From webhook-mailer at python.org Mon Nov 1 05:58:02 2021 From: webhook-mailer at python.org (pablogsal) Date: Mon, 01 Nov 2021 09:58:02 -0000 Subject: [Python-checkins] bpo-10572: Fixup Lib/test/libregrtest/pgo.py (GH-29327) Message-ID: https://github.com/python/cpython/commit/762a4dc9361f9563e158e373ba8d767b4449f23d commit: 762a4dc9361f9563e158e373ba8d767b4449f23d branch: main author: Erlend Egeberg Aasland committer: pablogsal date: 2021-11-01T09:57:28Z summary: bpo-10572: Fixup Lib/test/libregrtest/pgo.py (GH-29327) files: M Lib/test/libregrtest/pgo.py diff --git a/Lib/test/libregrtest/pgo.py b/Lib/test/libregrtest/pgo.py index 582e812e284cc..42ce5fba7a97c 100644 --- a/Lib/test/libregrtest/pgo.py +++ b/Lib/test/libregrtest/pgo.py @@ -40,7 +40,7 @@ 'test_pprint', 'test_re', 'test_set', - 'test_sqlite', + 'test_sqlite3', 'test_statistics', 'test_struct', 'test_tabnanny', From webhook-mailer at python.org Mon Nov 1 06:14:59 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 01 Nov 2021 10:14:59 -0000 Subject: [Python-checkins] bpo-45668: Fix PGO tests without test extensions (GH-29315) Message-ID: https://github.com/python/cpython/commit/e73283a20fb05b70da2990decefac0e011faec17 commit: e73283a20fb05b70da2990decefac0e011faec17 branch: main author: Christian Heimes committer: tiran date: 2021-11-01T11:14:53+01:00 summary: bpo-45668: Fix PGO tests without test extensions (GH-29315) files: A Misc/NEWS.d/next/Tests/2021-10-29-17-18-56.bpo-45668.MfAw4i.rst M Lib/test/datetimetester.py M Lib/test/string_tests.py M Lib/test/support/__init__.py M Lib/test/test_array.py M Lib/test/test_bytes.py M Lib/test/test_cmath.py M Lib/test/test_codecs.py M Lib/test/test_dict.py M Lib/test/test_embed.py M Lib/test/test_float.py M Lib/test/test_struct.py M Lib/test/test_unicode.py diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 9f551d9b9748d..810478c7db2be 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -31,7 +31,10 @@ from datetime import date, datetime import time as _time -import _testcapi +try: + import _testcapi +except ImportError: + _testcapi = None # Needed by test_datetime import _strptime @@ -5918,6 +5921,7 @@ class IranTest(ZoneInfoTest): zonename = 'Asia/Tehran' + at unittest.skipIf(_testcapi is None, 'need _testcapi module') class CapiTest(unittest.TestCase): def setUp(self): # Since the C API is not present in the _Pure tests, skip all tests diff --git a/Lib/test/string_tests.py b/Lib/test/string_tests.py index 089701c983a14..0d4c7ecf4a04f 100644 --- a/Lib/test/string_tests.py +++ b/Lib/test/string_tests.py @@ -4,6 +4,7 @@ import unittest, string, sys, struct from test import support +from test.support import import_helper from collections import UserList import random @@ -1328,17 +1329,17 @@ class X(object): pass @support.cpython_only def test_formatting_c_limits(self): - from _testcapi import PY_SSIZE_T_MAX, INT_MAX, UINT_MAX - SIZE_MAX = (1 << (PY_SSIZE_T_MAX.bit_length() + 1)) - 1 + _testcapi = import_helper.import_module('_testcapi') + SIZE_MAX = (1 << (_testcapi.PY_SSIZE_T_MAX.bit_length() + 1)) - 1 self.checkraises(OverflowError, '%*s', '__mod__', - (PY_SSIZE_T_MAX + 1, '')) + (_testcapi.PY_SSIZE_T_MAX + 1, '')) self.checkraises(OverflowError, '%.*f', '__mod__', - (INT_MAX + 1, 1. / 7)) + (_testcapi.INT_MAX + 1, 1. / 7)) # Issue 15989 self.checkraises(OverflowError, '%*s', '__mod__', (SIZE_MAX + 1, '')) self.checkraises(OverflowError, '%.*f', '__mod__', - (UINT_MAX + 1, 1. / 7)) + (_testcapi.UINT_MAX + 1, 1. / 7)) def test_floatformatting(self): # float formatting diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index fc3c99ec0ecc3..6d84a8bea420e 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -444,7 +444,10 @@ def requires_lzma(reason='requires lzma'): return unittest.skipUnless(lzma, reason) def has_no_debug_ranges(): - import _testinternalcapi + try: + import _testinternalcapi + except ImportError: + raise unittest.SkipTest("_testinternalcapi required") config = _testinternalcapi.get_config() return bool(config['no_debug_ranges']) @@ -692,7 +695,10 @@ def calcvobjsize(fmt): _TPFLAGS_HEAPTYPE = 1<<9 def check_sizeof(test, o, size): - import _testinternalcapi + try: + import _testinternalcapi + except ImportError: + raise unittest.SkipTest("_testinternalcapi required") result = sys.getsizeof(o) # add GC header size if ((type(o) == type) and (o.__flags__ & _TPFLAGS_HEAPTYPE) or\ diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py index 6a48c1cc97572..5b2c107a6044b 100755 --- a/Lib/test/test_array.py +++ b/Lib/test/test_array.py @@ -5,6 +5,7 @@ import collections.abc import unittest from test import support +from test.support import import_helper from test.support import os_helper from test.support import _2G import weakref @@ -1147,9 +1148,9 @@ def test_initialize_with_unicode(self): @support.cpython_only def test_obsolete_write_lock(self): - from _testcapi import getbuffer_with_null_view + _testcapi = import_helper.import_module('_testcapi') a = array.array('B', b"") - self.assertRaises(BufferError, getbuffer_with_null_view, a) + self.assertRaises(BufferError, _testcapi.getbuffer_with_null_view, a) def test_free_after_iterating(self): support.check_free_after_iterating(self, iter, array.array, diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py index c2fe2cc25420f..fd8e1d4bdc44c 100644 --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -1650,8 +1650,8 @@ def delslice(): @test.support.cpython_only def test_obsolete_write_lock(self): - from _testcapi import getbuffer_with_null_view - self.assertRaises(BufferError, getbuffer_with_null_view, bytearray()) + _testcapi = import_helper.import_module('_testcapi') + self.assertRaises(BufferError, _testcapi.getbuffer_with_null_view, bytearray()) def test_iterator_pickling2(self): orig = bytearray(b'abc') diff --git a/Lib/test/test_cmath.py b/Lib/test/test_cmath.py index 9bb939356144e..4bdec6d2d8384 100644 --- a/Lib/test/test_cmath.py +++ b/Lib/test/test_cmath.py @@ -1,4 +1,4 @@ -from test.support import requires_IEEE_754, cpython_only +from test.support import requires_IEEE_754, cpython_only, import_helper from test.test_math import parse_testfile, test_file import test.test_math as test_math import unittest @@ -452,13 +452,13 @@ def test_polar(self): @cpython_only def test_polar_errno(self): # Issue #24489: check a previously set C errno doesn't disturb polar() - from _testcapi import set_errno + _testcapi = import_helper.import_module('_testcapi') def polar_with_errno_set(z): - set_errno(11) + _testcapi.set_errno(11) try: return polar(z) finally: - set_errno(0) + _testcapi.set_errno(0) self.check_polar(polar_with_errno_set) def test_phase(self): diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py index 506b51c428fb5..f924826db9438 100644 --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -1970,6 +1970,7 @@ def test_basics(self): "encoding=%r" % encoding) @support.cpython_only + @unittest.skipIf(_testcapi is None, 'need _testcapi module') def test_basics_capi(self): s = "abc123" # all codecs should be able to encode these for encoding in all_unicode_encodings: diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py index b43c83abd0eeb..32ffd38f03576 100644 --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -8,6 +8,7 @@ import unittest import weakref from test import support +from test.support import import_helper class DictTest(unittest.TestCase): @@ -1541,7 +1542,8 @@ class CAPITest(unittest.TestCase): # Test _PyDict_GetItem_KnownHash() @support.cpython_only def test_getitem_knownhash(self): - from _testcapi import dict_getitem_knownhash + _testcapi = import_helper.import_module('_testcapi') + dict_getitem_knownhash = _testcapi.dict_getitem_knownhash d = {'x': 1, 'y': 2, 'z': 3} self.assertEqual(dict_getitem_knownhash(d, 'x', hash('x')), 1) diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index 7858f68d971cd..3a00efa5799b9 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -1494,6 +1494,7 @@ def test_init_use_frozen_modules(self): class SetConfigTests(unittest.TestCase): def test_set_config(self): # bpo-42260: Test _PyInterpreterState_SetConfig() + import_helper.import_module('_testcapi') cmd = [sys.executable, '-I', '-m', 'test._test_embed_set_config'] proc = subprocess.run(cmd, stdout=subprocess.PIPE, diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py index aba15839f1378..f033736917c65 100644 --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -8,6 +8,7 @@ import unittest from test import support +from test.support import import_helper from test.test_grammar import (VALID_UNDERSCORE_LITERALS, INVALID_UNDERSCORE_LITERALS) from math import isinf, isnan, copysign, ldexp @@ -714,7 +715,7 @@ def test_float_specials_do_unpack(self): @support.requires_IEEE_754 def test_serialized_float_rounding(self): - from _testcapi import FLT_MAX + FLT_MAX = import_helper.import_module('_testcapi').FLT_MAX self.assertEqual(struct.pack(" https://github.com/python/cpython/commit/401d25e92f62a9ef320a97542b3e63cb8c34e7e9 commit: 401d25e92f62a9ef320a97542b3e63cb8c34e7e9 branch: main author: Nikita Sobolev committer: Fidget-Spinner <28750310+Fidget-Spinner at users.noreply.github.com> date: 2021-11-01T20:11:34+08:00 summary: bpo-45666: Use `%S` for MSVC and `%s` elsewhere for `swprintf` in `_testembed.c` (GH-29341) Co-authored-by: Ken Jin <28750310+Fidget-Spinner at users.noreply.github.com> files: M Programs/_testembed.c diff --git a/Programs/_testembed.c b/Programs/_testembed.c index 1ed3bd00edff6..8077c470c07c5 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -1733,7 +1733,13 @@ static int check_use_frozen_modules(const char *rawval) if (rawval == NULL) { wcscpy(optval, L"frozen_modules"); } - else if (swprintf(optval, 100, L"frozen_modules=%S", rawval) < 0) { + else if (swprintf(optval, 100, +#if defined(_MSC_VER) + L"frozen_modules=%S", +#else + L"frozen_modules=%s", +#endif + rawval) < 0) { error("rawval is too long"); return -1; } From webhook-mailer at python.org Mon Nov 1 11:53:15 2021 From: webhook-mailer at python.org (ned-deily) Date: Mon, 01 Nov 2021 15:53:15 -0000 Subject: [Python-checkins] Update macOS installer to use Tk 8.6.12rc1 pre-release. (GH-29354) Message-ID: https://github.com/python/cpython/commit/e2063d6a1ebc3568e90a14ed163fa291b5977ae8 commit: e2063d6a1ebc3568e90a14ed163fa291b5977ae8 branch: main author: Ned Deily committer: ned-deily date: 2021-11-01T11:53:05-04:00 summary: Update macOS installer to use Tk 8.6.12rc1 pre-release. (GH-29354) files: D Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch M Mac/BuildScript/build-installer.py M Mac/BuildScript/resources/ReadMe.rtf M Mac/BuildScript/resources/Welcome.rtf diff --git a/Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch b/Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch deleted file mode 100644 index 1d06329fff3fb..0000000000000 --- a/Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch +++ /dev/null @@ -1,202 +0,0 @@ ---- tk8.6.11/macosx/tkMacOSXDialog.c 2020-12-31 01:46:07.000000000 +0000 -+++ tk8.6.11-patched/macosx/tkMacOSXDialog.c 2021-10-28 15:13:03.000000000 +0000 -@@ -221,7 +221,7 @@ - returnCode: (NSModalResponse) returnCode - contextInfo: (void *) contextInfo - { -- FilePanelCallbackInfo *callbackInfo = contextInfo; -+ FilePanelCallbackInfo *callbackInfo = (FilePanelCallbackInfo *)contextInfo; - - if (returnCode == modalOK) { - Tcl_Obj *resultObj; -@@ -266,7 +266,7 @@ - - (void) tkAlertDidEnd: (NSAlert *) alert returnCode: (NSInteger) returnCode - contextInfo: (void *) contextInfo - { -- AlertCallbackInfo *callbackInfo = contextInfo; -+ AlertCallbackInfo *callbackInfo = (AlertCallbackInfo *)contextInfo; - - if (returnCode >= NSAlertFirstButtonReturn) { - Tcl_Obj *resultObj = Tcl_NewStringObj(alertButtonStrings[ -@@ -350,49 +350,41 @@ - FilePanelCallbackInfo *callbackInfo) - { - NSInteger modalReturnCode; -+ int OSVersion = [NSApp macOSVersion]; - -- if (parent && ![parent attachedSheet]) { -- [panel beginSheetModalForWindow:parent -- completionHandler:^(NSModalResponse returnCode) { -- [NSApp tkFilePanelDidEnd:panel -- returnCode:returnCode -- contextInfo:callbackInfo ]; -- }]; -- -- /* -- * The sheet has been prepared, so now we have to run it as a modal -- * window. Using [NSApp runModalForWindow:] on macOS 10.15 or later -- * generates warnings on stderr. But using [NSOpenPanel runModal] or -- * [NSSavePanel runModal] on 10.14 or earler does not cause the -- * completion handler to run when the panel is closed. -- */ -+ /* -+ * Use a sheet if -parent is specified (unless there is already a sheet). -+ */ - -- if ([NSApp macOSVersion] > 101400) { -- modalReturnCode = [panel runModal]; -- } else { -+ if (parent && ![parent attachedSheet]) { -+ if (OSVersion < 101500) { -+ [panel beginSheetModalForWindow:parent -+ completionHandler:^(NSModalResponse returnCode) { -+ [NSApp tkFilePanelDidEnd:panel -+ returnCode:returnCode -+ contextInfo:callbackInfo ]; -+ }]; - modalReturnCode = [NSApp runModalForWindow:panel]; -- } -- } else { -- -- /* -- * For the standalone file dialog, completion handlers do not work -- * at all on macOS 10.14 and earlier. -- */ -- -- if ([NSApp macOSVersion] > 101400) { -- [panel beginWithCompletionHandler:^(NSModalResponse returnCode) { -+ } else if (OSVersion < 110000) { -+ [panel beginSheetModalForWindow:parent -+ completionHandler:^(NSModalResponse returnCode) { - [NSApp tkFilePanelDidEnd:panel -- returnCode:returnCode -- contextInfo:callbackInfo ]; -- }]; -+ returnCode:returnCode -+ contextInfo:callbackInfo ]; -+ }]; - modalReturnCode = [panel runModal]; - } else { -+ [parent beginSheet: panel completionHandler:nil]; - modalReturnCode = [panel runModal]; - [NSApp tkFilePanelDidEnd:panel -- returnCode:modalReturnCode -- contextInfo:callbackInfo ]; -- [panel close]; -+ returnCode:modalReturnCode -+ contextInfo:callbackInfo ]; - } -+ } else { -+ modalReturnCode = [panel runModal]; -+ [NSApp tkFilePanelDidEnd:panel -+ returnCode:modalReturnCode -+ contextInfo:callbackInfo ]; - } - return callbackInfo->cmdObj ? modalOther : modalReturnCode; - } -@@ -422,7 +414,7 @@ - Tcl_Obj *const objv[]) /* Argument objects. */ - { - int result = TCL_ERROR; -- Tk_Window parent, tkwin = clientData; -+ Tk_Window parent, tkwin = (Tk_Window)clientData; - const char *title = NULL; - int i; - NSColor *color = nil, *initialColor = nil; -@@ -677,7 +669,7 @@ - int objc, /* Number of arguments. */ - Tcl_Obj *const objv[]) /* Argument objects. */ - { -- Tk_Window tkwin = clientData; -+ Tk_Window tkwin = (Tk_Window)clientData; - char *str; - int i, result = TCL_ERROR, haveParentOption = 0; - int index, len, multiple = 0; -@@ -1679,10 +1671,10 @@ - if (!fontchooserInterp) { - return; - } -- fcdPtr = Tcl_GetAssocData(fontchooserInterp, "::tk::fontchooser", NULL); -+ fcdPtr = (FontchooserData *)Tcl_GetAssocData(fontchooserInterp, "::tk::fontchooser", NULL); - switch (kind) { - case FontchooserClosed: -- if (fcdPtr->parent != None) { -+ if (fcdPtr->parent != NULL) { - TkSendVirtualEvent(fcdPtr->parent, "TkFontchooserVisibility", NULL); - fontchooserInterp = NULL; - } -@@ -1738,7 +1730,7 @@ - - switch(optionIndex) { - case FontchooserParent: -- if (fcdPtr->parent != None) { -+ if (fcdPtr->parent != NULL) { - resObj = Tcl_NewStringObj( - ((TkWindow *)fcdPtr->parent)->pathName, -1); - } else { -@@ -1801,7 +1793,7 @@ - Tcl_Obj *const objv[]) - { - Tk_Window tkwin = (Tk_Window)clientData; -- FontchooserData *fcdPtr = Tcl_GetAssocData(interp, "::tk::fontchooser", -+ FontchooserData *fcdPtr = (FontchooserData *)Tcl_GetAssocData(interp, "::tk::fontchooser", - NULL); - int i, r = TCL_OK; - -@@ -1858,7 +1850,7 @@ - Tk_Window parent = Tk_NameToWindow(interp, - Tcl_GetString(objv[i+1]), tkwin); - -- if (parent == None) { -+ if (parent == NULL) { - return TCL_ERROR; - } - if (fcdPtr->parent) { -@@ -1885,7 +1877,7 @@ - fcdPtr->titleObj = NULL; - } - break; -- case FontchooserFont: -+ case FontchooserFont: { - Tcl_GetStringFromObj(objv[i+1], &len); - if (len) { - Tk_Font f = Tk_AllocFontFromObj(interp, tkwin, objv[i+1]); -@@ -1919,6 +1911,7 @@ - "TkFontchooserFontChanged", NULL); - } - break; -+ } - case FontchooserCmd: - if (fcdPtr->cmdObj) { - Tcl_DecrRefCount(fcdPtr->cmdObj); -@@ -1964,10 +1957,10 @@ - TCL_UNUSED(int), - TCL_UNUSED(Tcl_Obj *const *)) - { -- FontchooserData *fcdPtr = Tcl_GetAssocData(interp, "::tk::fontchooser", -+ FontchooserData *fcdPtr = (FontchooserData *)Tcl_GetAssocData(interp, "::tk::fontchooser", - NULL); - -- if (fcdPtr->parent == None) { -+ if (fcdPtr->parent == NULL) { - fcdPtr->parent = (Tk_Window)clientData; - Tk_CreateEventHandler(fcdPtr->parent, StructureNotifyMask, - FontchooserParentEventHandler, fcdPtr); -@@ -2042,7 +2035,7 @@ - ClientData clientData, - XEvent *eventPtr) - { -- FontchooserData *fcdPtr = clientData; -+ FontchooserData *fcdPtr = (FontchooserData *)clientData; - - if (eventPtr->type == DestroyNotify) { - Tk_DeleteEventHandler(fcdPtr->parent, StructureNotifyMask, -@@ -2074,7 +2067,7 @@ - ClientData clientData, - Tcl_Interp *interp) - { -- FontchooserData *fcdPtr = clientData; -+ FontchooserData *fcdPtr = (FontchooserData *)clientData; - - if (fcdPtr->titleObj) { - Tcl_DecrRefCount(fcdPtr->titleObj); diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index f366968a71d91..9db2616bc75ba 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -265,11 +265,11 @@ def library_recipes(): tk_patches = ['tk868_on_10_8_10_9.patch'] else: - tcl_tk_ver='8.6.11' - tcl_checksum='8a4c004f48984a03a7747e9ba06e4da4' + tcl_tk_ver='8.6.12rc1' + tcl_checksum='82fd1637c0f7d4b76cb909f8abc373ec' - tk_checksum='c7ee71a2d05bba78dfffd76528dc17c6' - tk_patches = ['bpo-44828-filedialog-crash-monterey.patch'] + tk_checksum='d63c3b91b86cd8b6fa54e83ef2c5153e' + tk_patches = [ ] result.extend([ @@ -729,6 +729,10 @@ def extractArchive(builddir, archiveName): if ((retval.startswith('tcl') or retval.startswith('tk')) and retval.endswith('-src')): retval = retval[:-4] + # Strip rcxx suffix from Tcl/Tk release candidates + retval_rc = retval.find('rc') + if retval_rc > 0: + retval = retval[:retval_rc] if os.path.exists(retval): shutil.rmtree(retval) fp = os.popen("tar zxf %s 2>&1"%(shellQuote(archiveName),), 'r') diff --git a/Mac/BuildScript/resources/ReadMe.rtf b/Mac/BuildScript/resources/ReadMe.rtf index a6bfeb9f164ea..2a954083bf127 100644 --- a/Mac/BuildScript/resources/ReadMe.rtf +++ b/Mac/BuildScript/resources/ReadMe.rtf @@ -11,7 +11,7 @@ \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\partightenfactor0 \f1\b \cf0 NOTE: -\f0\b0 This is a beta test preview of Python 3.10.0, the next feature release of Python 3. It is not intended for production use.\ +\f0\b0 This is an alpha preview of Python 3.11.0, the next feature release of Python 3. It is not intended for production use.\ \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0 \cf0 \ \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0 @@ -66,17 +66,9 @@ Due to new security checks on macOS 10.15 Catalina, when launching IDLE macOS ma \f0\b0 button to proceed.\ \ -\f1\b \ul macOS 11 (Big Sur) and Apple Silicon Mac support\ +\f1\b \ul Apple Silicon Mac support\ \f0\b0 \ulnone \ -For Python 3.10 releases, we provide a new -\f4 universal2 -\f0 installer variant that provides universal binaries for both -\f4 ARM64 -\f0 and -\f4 Intel 64 -\f0 architectures and is also supported on all Macs that support macOS 10.9 or later. Some of the advantages of the new installer variant: native ARM64 code on Apple Silicon Macs should run significantly faster than Rosetta2-emulated code; some operating system functions and options introduced in macOS releases since 10.9 are now exposed when available (primarily in the os module); and the new installer variant includes Tcl/Tk 8.6.11 rather than 8.6.8.\ -\ On Apple Silicon Macs, it is possible to run Python either with native ARM64 code or under Intel 64 emulation using Rosetta2. This option might be useful for testing or if binary wheels are not yet available with native ARM64 binaries. To easily force Python to run in emulation mode, invoke it from a command line shell with the \f4 python3-intel64 \f0 command instead of just diff --git a/Mac/BuildScript/resources/Welcome.rtf b/Mac/BuildScript/resources/Welcome.rtf index c65119b7fa2e2..e6ccfcb3fce96 100644 --- a/Mac/BuildScript/resources/Welcome.rtf +++ b/Mac/BuildScript/resources/Welcome.rtf @@ -3,7 +3,7 @@ } {\colortbl;\red255\green255\blue255;} {\*\expandedcolortbl;;} -\paperw11905\paperh16837\margl1440\margr1440\vieww12200\viewh10880\viewkind0 +\paperw11900\paperh16840\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 @@ -26,5 +26,5 @@ At the end of this install, click on \ \f1\b NOTE: -\f0\b0 This is a beta test preview of Python 3.10.0, the next feature release of Python 3. It is not intended for production use.\ +\f0\b0 This is an alpha test preview of Python 3.11.0, the next feature release of Python 3. It is not intended for production use.\ } \ No newline at end of file From webhook-mailer at python.org Mon Nov 1 18:51:03 2021 From: webhook-mailer at python.org (pablogsal) Date: Mon, 01 Nov 2021 22:51:03 -0000 Subject: [Python-checkins] bpo-45243: Add support for setting/getting `sqlite3` connection limits (GH-28463) Message-ID: https://github.com/python/cpython/commit/b6b38a82267ff70d2abaf2a8371327268887c97d commit: b6b38a82267ff70d2abaf2a8371327268887c97d branch: main author: Erlend Egeberg Aasland committer: pablogsal date: 2021-11-01T22:50:53Z summary: bpo-45243: Add support for setting/getting `sqlite3` connection limits (GH-28463) files: A Misc/NEWS.d/next/Library/2021-09-20-01-25-09.bpo-45243.0pJf0U.rst M Doc/library/sqlite3.rst M Doc/whatsnew/3.11.rst M Lib/test/test_sqlite3/test_dbapi.py M Modules/_sqlite/clinic/connection.c.h M Modules/_sqlite/connection.c M Modules/_sqlite/module.c diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index 19a4155542382..dcffc779cfba3 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -662,6 +662,40 @@ Connection Objects .. versionadded:: 3.7 + .. method:: getlimit(category, /) + + Get a connection run-time limit. *category* is the limit category to be + queried. + + Example, query the maximum length of an SQL statement:: + + import sqlite3 + con = sqlite3.connect(":memory:") + lim = con.getlimit(sqlite3.SQLITE_LIMIT_SQL_LENGTH) + print(f"SQLITE_LIMIT_SQL_LENGTH={lim}") + + .. versionadded:: 3.11 + + + .. method:: setlimit(category, limit, /) + + Set a connection run-time limit. *category* is the limit category to be + set. *limit* is the new limit. If the new limit is a negative number, the + limit is unchanged. + + Attempts to increase a limit above its hard upper bound are silently + truncated to the hard upper bound. Regardless of whether or not the limit + was changed, the prior value of the limit is returned. + + Example, limit the number of attached databases to 1:: + + import sqlite3 + con = sqlite3.connect(":memory:") + con.setlimit(sqlite3.SQLITE_LIMIT_ATTACHED, 1) + + .. versionadded:: 3.11 + + .. _sqlite3-cursor-objects: Cursor Objects diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 156bfbd9109ee..3500b1ba6b1cb 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -248,6 +248,12 @@ sqlite3 (Contributed by Aviv Palivoda, Daniel Shahaf, and Erlend E. Aasland in :issue:`16379`.) +* Add :meth:`~sqlite3.Connection.setlimit` and + :meth:`~sqlite3.Connection.getlimit` to :class:`sqlite3.Connection` for + setting and getting SQLite limits by connection basis. + (Contributed by Erlend E. Aasland in :issue:`45243`.) + + threading --------- diff --git a/Lib/test/test_sqlite3/test_dbapi.py b/Lib/test/test_sqlite3/test_dbapi.py index d82543663d18b..34895be018078 100644 --- a/Lib/test/test_sqlite3/test_dbapi.py +++ b/Lib/test/test_sqlite3/test_dbapi.py @@ -167,11 +167,25 @@ def test_module_constants(self): "SQLITE_TOOBIG", "SQLITE_TRANSACTION", "SQLITE_UPDATE", + # Run-time limit categories + "SQLITE_LIMIT_LENGTH", + "SQLITE_LIMIT_SQL_LENGTH", + "SQLITE_LIMIT_COLUMN", + "SQLITE_LIMIT_EXPR_DEPTH", + "SQLITE_LIMIT_COMPOUND_SELECT", + "SQLITE_LIMIT_VDBE_OP", + "SQLITE_LIMIT_FUNCTION_ARG", + "SQLITE_LIMIT_ATTACHED", + "SQLITE_LIMIT_LIKE_PATTERN_LENGTH", + "SQLITE_LIMIT_VARIABLE_NUMBER", + "SQLITE_LIMIT_TRIGGER_DEPTH", ] if sqlite.sqlite_version_info >= (3, 7, 17): consts += ["SQLITE_NOTICE", "SQLITE_WARNING"] if sqlite.sqlite_version_info >= (3, 8, 3): consts.append("SQLITE_RECURSIVE") + if sqlite.sqlite_version_info >= (3, 8, 7): + consts.append("SQLITE_LIMIT_WORKER_THREADS") consts += ["PARSE_DECLTYPES", "PARSE_COLNAMES"] for const in consts: with self.subTest(const=const): @@ -332,6 +346,28 @@ def test_drop_unused_refs(self): cu = self.cx.execute(f"select {n}") self.assertEqual(cu.fetchone()[0], n) + def test_connection_limits(self): + category = sqlite.SQLITE_LIMIT_SQL_LENGTH + saved_limit = self.cx.getlimit(category) + try: + new_limit = 10 + prev_limit = self.cx.setlimit(category, new_limit) + self.assertEqual(saved_limit, prev_limit) + self.assertEqual(self.cx.getlimit(category), new_limit) + msg = "string or blob too big" + self.assertRaisesRegex(sqlite.DataError, msg, + self.cx.execute, "select 1 as '16'") + finally: # restore saved limit + self.cx.setlimit(category, saved_limit) + + def test_connection_bad_limit_category(self): + msg = "'category' is out of bounds" + cat = 1111 + self.assertRaisesRegex(sqlite.ProgrammingError, msg, + self.cx.getlimit, cat) + self.assertRaisesRegex(sqlite.ProgrammingError, msg, + self.cx.setlimit, cat, 0) + class UninitialisedConnectionTests(unittest.TestCase): def setUp(self): @@ -767,6 +803,8 @@ def test_check_connection_thread(self): lambda: self.con.set_trace_callback(None), lambda: self.con.set_authorizer(None), lambda: self.con.create_collation("foo", None), + lambda: self.con.setlimit(sqlite.SQLITE_LIMIT_LENGTH, -1), + lambda: self.con.getlimit(sqlite.SQLITE_LIMIT_LENGTH), ] for fn in fns: with self.subTest(fn=fn): diff --git a/Misc/NEWS.d/next/Library/2021-09-20-01-25-09.bpo-45243.0pJf0U.rst b/Misc/NEWS.d/next/Library/2021-09-20-01-25-09.bpo-45243.0pJf0U.rst new file mode 100644 index 0000000000000..8292e86245f02 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-09-20-01-25-09.bpo-45243.0pJf0U.rst @@ -0,0 +1,4 @@ +Add :meth:`~sqlite3.Connection.setlimit` and +:meth:`~sqlite3.Connection.getlimit` to :class:`sqlite3.Connection` for +setting and getting SQLite limits by connection basis. Patch by Erlend E. +Aasland. diff --git a/Modules/_sqlite/clinic/connection.c.h b/Modules/_sqlite/clinic/connection.c.h index e9e3064ae0f89..f9323eb21d6f4 100644 --- a/Modules/_sqlite/clinic/connection.c.h +++ b/Modules/_sqlite/clinic/connection.c.h @@ -750,6 +750,83 @@ pysqlite_connection_exit(pysqlite_Connection *self, PyObject *const *args, Py_ss return return_value; } +PyDoc_STRVAR(setlimit__doc__, +"setlimit($self, category, limit, /)\n" +"--\n" +"\n" +"Set connection run-time limits.\n" +"\n" +" category\n" +" The limit category to be set.\n" +" limit\n" +" The new limit. If the new limit is a negative number, the limit is\n" +" unchanged.\n" +"\n" +"Attempts to increase a limit above its hard upper bound are silently truncated\n" +"to the hard upper bound. Regardless of whether or not the limit was changed,\n" +"the prior value of the limit is returned."); + +#define SETLIMIT_METHODDEF \ + {"setlimit", (PyCFunction)(void(*)(void))setlimit, METH_FASTCALL, setlimit__doc__}, + +static PyObject * +setlimit_impl(pysqlite_Connection *self, int category, int limit); + +static PyObject * +setlimit(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int category; + int limit; + + if (!_PyArg_CheckPositional("setlimit", nargs, 2, 2)) { + goto exit; + } + category = _PyLong_AsInt(args[0]); + if (category == -1 && PyErr_Occurred()) { + goto exit; + } + limit = _PyLong_AsInt(args[1]); + if (limit == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = setlimit_impl(self, category, limit); + +exit: + return return_value; +} + +PyDoc_STRVAR(getlimit__doc__, +"getlimit($self, category, /)\n" +"--\n" +"\n" +"Get connection run-time limits.\n" +"\n" +" category\n" +" The limit category to be queried."); + +#define GETLIMIT_METHODDEF \ + {"getlimit", (PyCFunction)getlimit, METH_O, getlimit__doc__}, + +static PyObject * +getlimit_impl(pysqlite_Connection *self, int category); + +static PyObject * +getlimit(pysqlite_Connection *self, PyObject *arg) +{ + PyObject *return_value = NULL; + int category; + + category = _PyLong_AsInt(arg); + if (category == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = getlimit_impl(self, category); + +exit: + return return_value; +} + #ifndef PYSQLITE_CONNECTION_ENABLE_LOAD_EXTENSION_METHODDEF #define PYSQLITE_CONNECTION_ENABLE_LOAD_EXTENSION_METHODDEF #endif /* !defined(PYSQLITE_CONNECTION_ENABLE_LOAD_EXTENSION_METHODDEF) */ @@ -757,4 +834,4 @@ pysqlite_connection_exit(pysqlite_Connection *self, PyObject *const *args, Py_ss #ifndef PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF #define PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF #endif /* !defined(PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF) */ -/*[clinic end generated code: output=7567e5d716309258 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0c3901153a3837a5 input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 94c38ad395440..f913267e1560e 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -1896,6 +1896,57 @@ pysqlite_connection_exit_impl(pysqlite_Connection *self, PyObject *exc_type, Py_RETURN_FALSE; } +/*[clinic input] +_sqlite3.Connection.setlimit as setlimit + + category: int + The limit category to be set. + limit: int + The new limit. If the new limit is a negative number, the limit is + unchanged. + / + +Set connection run-time limits. + +Attempts to increase a limit above its hard upper bound are silently truncated +to the hard upper bound. Regardless of whether or not the limit was changed, +the prior value of the limit is returned. +[clinic start generated code]*/ + +static PyObject * +setlimit_impl(pysqlite_Connection *self, int category, int limit) +/*[clinic end generated code: output=0d208213f8d68ccd input=9bd469537e195635]*/ +{ + if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { + return NULL; + } + + int old_limit = sqlite3_limit(self->db, category, limit); + if (old_limit < 0) { + PyErr_SetString(self->ProgrammingError, "'category' is out of bounds"); + return NULL; + } + return PyLong_FromLong(old_limit); +} + +/*[clinic input] +_sqlite3.Connection.getlimit as getlimit + + category: int + The limit category to be queried. + / + +Get connection run-time limits. +[clinic start generated code]*/ + +static PyObject * +getlimit_impl(pysqlite_Connection *self, int category) +/*[clinic end generated code: output=7c3f5d11f24cecb1 input=61e0849fb4fb058f]*/ +{ + return setlimit_impl(self, category, -1); +} + + static const char connection_doc[] = PyDoc_STR("SQLite database connection object."); @@ -1927,6 +1978,8 @@ static PyMethodDef connection_methods[] = { PYSQLITE_CONNECTION_SET_AUTHORIZER_METHODDEF PYSQLITE_CONNECTION_SET_PROGRESS_HANDLER_METHODDEF PYSQLITE_CONNECTION_SET_TRACE_CALLBACK_METHODDEF + SETLIMIT_METHODDEF + GETLIMIT_METHODDEF {NULL, NULL} }; diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c index 912851ba775dc..8666af171c8cb 100644 --- a/Modules/_sqlite/module.c +++ b/Modules/_sqlite/module.c @@ -395,6 +395,21 @@ add_integer_constants(PyObject *module) { ADD_INT(SQLITE_SAVEPOINT); #if SQLITE_VERSION_NUMBER >= 3008003 ADD_INT(SQLITE_RECURSIVE); +#endif + // Run-time limit categories + ADD_INT(SQLITE_LIMIT_LENGTH); + ADD_INT(SQLITE_LIMIT_SQL_LENGTH); + ADD_INT(SQLITE_LIMIT_COLUMN); + ADD_INT(SQLITE_LIMIT_EXPR_DEPTH); + ADD_INT(SQLITE_LIMIT_COMPOUND_SELECT); + ADD_INT(SQLITE_LIMIT_VDBE_OP); + ADD_INT(SQLITE_LIMIT_FUNCTION_ARG); + ADD_INT(SQLITE_LIMIT_ATTACHED); + ADD_INT(SQLITE_LIMIT_LIKE_PATTERN_LENGTH); + ADD_INT(SQLITE_LIMIT_VARIABLE_NUMBER); + ADD_INT(SQLITE_LIMIT_TRIGGER_DEPTH); +#if SQLITE_VERSION_NUMBER >= 3008007 + ADD_INT(SQLITE_LIMIT_WORKER_THREADS); #endif #undef ADD_INT return 0; From webhook-mailer at python.org Mon Nov 1 21:09:40 2021 From: webhook-mailer at python.org (gvanrossum) Date: Tue, 02 Nov 2021 01:09:40 -0000 Subject: [Python-checkins] Remove Programs/_freeze_importlib (#29357) Message-ID: https://github.com/python/cpython/commit/69a6173d64332cd4992024c5f6a9f3f5fd6523d5 commit: 69a6173d64332cd4992024c5f6a9f3f5fd6523d5 branch: main author: Brandt Bucher committer: gvanrossum date: 2021-11-01T18:09:26-07:00 summary: Remove Programs/_freeze_importlib (#29357) files: D Programs/_freeze_importlib diff --git a/Programs/_freeze_importlib b/Programs/_freeze_importlib deleted file mode 100755 index 817856481b449..0000000000000 Binary files a/Programs/_freeze_importlib and /dev/null differ From webhook-mailer at python.org Tue Nov 2 07:09:02 2021 From: webhook-mailer at python.org (tiran) Date: Tue, 02 Nov 2021 11:09:02 -0000 Subject: [Python-checkins] bpo-45688: Add _scproxy to sys.stdlib_module_names (GH-29358) Message-ID: https://github.com/python/cpython/commit/34098991289cb3e8eec012fa0243f30b9709666f commit: 34098991289cb3e8eec012fa0243f30b9709666f branch: main author: Christian Heimes committer: tiran date: 2021-11-02T12:08:40+01:00 summary: bpo-45688: Add _scproxy to sys.stdlib_module_names (GH-29358) files: A Misc/NEWS.d/next/Core and Builtins/2021-11-02-09-27-46.bpo-45688.v5Der1.rst M Python/stdlib_module_names.h M Tools/scripts/generate_stdlib_module_names.py diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-02-09-27-46.bpo-45688.v5Der1.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-02-09-27-46.bpo-45688.v5Der1.rst new file mode 100644 index 0000000000000..afd73a1266279 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-02-09-27-46.bpo-45688.v5Der1.rst @@ -0,0 +1,2 @@ +:data:`sys.stdlib_module_names` now contains the macOS-specific module +:mod:`_scproxy`. diff --git a/Python/stdlib_module_names.h b/Python/stdlib_module_names.h index 1743292593f36..754fa94e35eba 100644 --- a/Python/stdlib_module_names.h +++ b/Python/stdlib_module_names.h @@ -61,6 +61,7 @@ static const char* _Py_stdlib_module_names[] = { "_pyio", "_queue", "_random", +"_scproxy", "_sha1", "_sha256", "_sha3", diff --git a/Tools/scripts/generate_stdlib_module_names.py b/Tools/scripts/generate_stdlib_module_names.py index 50042f14fb62e..3e896ba737543 100644 --- a/Tools/scripts/generate_stdlib_module_names.py +++ b/Tools/scripts/generate_stdlib_module_names.py @@ -54,6 +54,10 @@ 'winsound' ) +# macOS extension modules +MACOS_MODULES = ( + '_scproxy', +) # Pure Python modules (Lib/*.py) def list_python_modules(names): @@ -136,7 +140,7 @@ def list_frozen(names): def list_modules(): - names = set(sys.builtin_module_names) | set(WINDOWS_MODULES) + names = set(sys.builtin_module_names) | set(WINDOWS_MODULES) | set(MACOS_MODULES) list_modules_setup_extensions(names) list_setup_extensions(names) list_packages(names) From webhook-mailer at python.org Tue Nov 2 07:25:18 2021 From: webhook-mailer at python.org (tiran) Date: Tue, 02 Nov 2021 11:25:18 -0000 Subject: [Python-checkins] bpo-43158: Use configure values for building _uuid extension (GH-29353) Message-ID: https://github.com/python/cpython/commit/77a1f8d94c29da7bda4bd43e5a9c2233573d46ee commit: 77a1f8d94c29da7bda4bd43e5a9c2233573d46ee branch: main author: Christian Heimes committer: tiran date: 2021-11-02T12:25:13+01:00 summary: bpo-43158: Use configure values for building _uuid extension (GH-29353) files: A Misc/NEWS.d/next/Build/2021-11-01-12-51-46.bpo-43158.fghS6w.rst M configure M configure.ac M pyconfig.h.in M setup.py diff --git a/Misc/NEWS.d/next/Build/2021-11-01-12-51-46.bpo-43158.fghS6w.rst b/Misc/NEWS.d/next/Build/2021-11-01-12-51-46.bpo-43158.fghS6w.rst new file mode 100644 index 0000000000000..3b1de478e7fd4 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-01-12-51-46.bpo-43158.fghS6w.rst @@ -0,0 +1,2 @@ +``setup.py`` now uses values from configure script to build the ``_uuid`` +extension module. Configure now detects util-linux's ``libuuid``, too. diff --git a/configure b/configure index a32c9100d9842..f0046ffab5eb0 100755 --- a/configure +++ b/configure @@ -10159,6 +10159,75 @@ $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +save_LIBS=$LIBS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing uuid_generate_time_safe" >&5 +$as_echo_n "checking for library containing uuid_generate_time_safe... " >&6; } +if ${ac_cv_search_uuid_generate_time_safe+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char uuid_generate_time_safe (); +int +main () +{ +return uuid_generate_time_safe (); + ; + return 0; +} +_ACEOF +for ac_lib in '' uuid; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_uuid_generate_time_safe=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_uuid_generate_time_safe+:} false; then : + break +fi +done +if ${ac_cv_search_uuid_generate_time_safe+:} false; then : + +else + ac_cv_search_uuid_generate_time_safe=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_uuid_generate_time_safe" >&5 +$as_echo "$ac_cv_search_uuid_generate_time_safe" >&6; } +ac_res=$ac_cv_search_uuid_generate_time_safe +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + + +$as_echo "#define HAVE_LIBUUID 1" >>confdefs.h +, + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi + +LIBS=$save_LIBS + # AIX provides support for RFC4122 (uuid) in libc.a starting with AIX 6.1 (anno 2007) # FreeBSD and OpenBSD provides support as well { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_create" >&5 diff --git a/configure.ac b/configure.ac index ccc5e1f74d83e..ea119085ab157 100644 --- a/configure.ac +++ b/configure.ac @@ -2945,8 +2945,13 @@ void *x = uuid_generate_time_safe [AC_MSG_RESULT(no)] ) +# check for libuuid from util-linux +save_LIBS=$LIBS +AC_CHECK_LIB([uuid], [uuid_generate_time]) +LIBS=$save_LIBS + # AIX provides support for RFC4122 (uuid) in libc.a starting with AIX 6.1 (anno 2007) -# FreeBSD and OpenBSD provides support as well +# FreeBSD and OpenBSD provides support in libc as well. AC_MSG_CHECKING(for uuid_create) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ #ifndef uuid_create diff --git a/pyconfig.h.in b/pyconfig.h.in index 3e3944a6ec208..108a13d8d2ca9 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -604,6 +604,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LIBUTIL_H +/* Define you have libuuid. */ +#undef HAVE_LIBUUID + /* Define if you have the 'link' function. */ #undef HAVE_LINK diff --git a/setup.py b/setup.py index 6fa8a674eda31..22c5ccf0a073a 100644 --- a/setup.py +++ b/setup.py @@ -1842,15 +1842,15 @@ def detect_multiprocessing(self): def detect_uuid(self): # Build the _uuid module if possible - uuid_incs = find_file("uuid.h", self.inc_dirs, ["/usr/include/uuid"]) - if uuid_incs is not None: - if self.compiler.find_library_file(self.lib_dirs, 'uuid'): - uuid_libs = ['uuid'] + uuid_h = sysconfig.get_config_var("HAVE_UUID_H") + uuid_uuid_h = sysconfig.get_config_var("HAVE_UUID_UUID_H") + if uuid_h or uuid_uuid_h: + if sysconfig.get_config_var("HAVE_LIBUUID"): + uuid_libs = ["uuid"] else: uuid_libs = [] self.add(Extension('_uuid', ['_uuidmodule.c'], - libraries=uuid_libs, - include_dirs=uuid_incs)) + libraries=uuid_libs)) else: self.missing.append('_uuid') From webhook-mailer at python.org Tue Nov 2 07:32:41 2021 From: webhook-mailer at python.org (tiran) Date: Tue, 02 Nov 2021 11:32:41 -0000 Subject: [Python-checkins] [3.10] bpo-45688: Add _scproxy to sys.stdlib_module_names (GH-29358) (GH-29361) Message-ID: https://github.com/python/cpython/commit/b2ae63161926527e31b9a9071b38836ad88e9a92 commit: b2ae63161926527e31b9a9071b38836ad88e9a92 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: tiran date: 2021-11-02T12:32:36+01:00 summary: [3.10] bpo-45688: Add _scproxy to sys.stdlib_module_names (GH-29358) (GH-29361) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Core and Builtins/2021-11-02-09-27-46.bpo-45688.v5Der1.rst M Python/stdlib_module_names.h M Tools/scripts/generate_stdlib_module_names.py diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-02-09-27-46.bpo-45688.v5Der1.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-02-09-27-46.bpo-45688.v5Der1.rst new file mode 100644 index 0000000000000..afd73a1266279 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-02-09-27-46.bpo-45688.v5Der1.rst @@ -0,0 +1,2 @@ +:data:`sys.stdlib_module_names` now contains the macOS-specific module +:mod:`_scproxy`. diff --git a/Python/stdlib_module_names.h b/Python/stdlib_module_names.h index b09b8dc7a394a..50cf340e543b4 100644 --- a/Python/stdlib_module_names.h +++ b/Python/stdlib_module_names.h @@ -61,6 +61,7 @@ static const char* _Py_stdlib_module_names[] = { "_pyio", "_queue", "_random", +"_scproxy", "_sha1", "_sha256", "_sha3", diff --git a/Tools/scripts/generate_stdlib_module_names.py b/Tools/scripts/generate_stdlib_module_names.py index 716a6d4b7a07f..dc6a074274715 100644 --- a/Tools/scripts/generate_stdlib_module_names.py +++ b/Tools/scripts/generate_stdlib_module_names.py @@ -51,6 +51,10 @@ 'winsound' ) +# macOS extension modules +MACOS_MODULES = ( + '_scproxy', +) # Pure Python modules (Lib/*.py) def list_python_modules(names): @@ -123,7 +127,7 @@ def list_frozen(names): def list_modules(): - names = set(sys.builtin_module_names) | set(WINDOWS_MODULES) + names = set(sys.builtin_module_names) | set(WINDOWS_MODULES) | set(MACOS_MODULES) list_modules_setup_extensions(names) list_setup_extensions(names) list_packages(names) From webhook-mailer at python.org Tue Nov 2 07:49:42 2021 From: webhook-mailer at python.org (tiran) Date: Tue, 02 Nov 2021 11:49:42 -0000 Subject: [Python-checkins] [3.10] bpo-43158: Use configure values for building _uuid extension (GH-29353) (GH-29362) Message-ID: https://github.com/python/cpython/commit/b71bc052454803aa8bd3e7edd2044e2d5e962243 commit: b71bc052454803aa8bd3e7edd2044e2d5e962243 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: tiran date: 2021-11-02T12:49:17+01:00 summary: [3.10] bpo-43158: Use configure values for building _uuid extension (GH-29353) (GH-29362) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Build/2021-11-01-12-51-46.bpo-43158.fghS6w.rst M configure M configure.ac M pyconfig.h.in M setup.py diff --git a/Misc/NEWS.d/next/Build/2021-11-01-12-51-46.bpo-43158.fghS6w.rst b/Misc/NEWS.d/next/Build/2021-11-01-12-51-46.bpo-43158.fghS6w.rst new file mode 100644 index 0000000000000..3b1de478e7fd4 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-01-12-51-46.bpo-43158.fghS6w.rst @@ -0,0 +1,2 @@ +``setup.py`` now uses values from configure script to build the ``_uuid`` +extension module. Configure now detects util-linux's ``libuuid``, too. diff --git a/configure b/configure index e79425d5b9d8e..b344445a80541 100755 --- a/configure +++ b/configure @@ -10120,6 +10120,75 @@ $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +save_LIBS=$LIBS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing uuid_generate_time_safe" >&5 +$as_echo_n "checking for library containing uuid_generate_time_safe... " >&6; } +if ${ac_cv_search_uuid_generate_time_safe+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char uuid_generate_time_safe (); +int +main () +{ +return uuid_generate_time_safe (); + ; + return 0; +} +_ACEOF +for ac_lib in '' uuid; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_uuid_generate_time_safe=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_uuid_generate_time_safe+:} false; then : + break +fi +done +if ${ac_cv_search_uuid_generate_time_safe+:} false; then : + +else + ac_cv_search_uuid_generate_time_safe=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_uuid_generate_time_safe" >&5 +$as_echo "$ac_cv_search_uuid_generate_time_safe" >&6; } +ac_res=$ac_cv_search_uuid_generate_time_safe +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + + +$as_echo "#define HAVE_LIBUUID 1" >>confdefs.h +, + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi + +LIBS=$save_LIBS + # AIX provides support for RFC4122 (uuid) in libc.a starting with AIX 6.1 (anno 2007) # FreeBSD and OpenBSD provides support as well { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_create" >&5 diff --git a/configure.ac b/configure.ac index 4c2ac5915a1cf..c0db1f41d3b7d 100644 --- a/configure.ac +++ b/configure.ac @@ -2911,8 +2911,13 @@ void *x = uuid_generate_time_safe [AC_MSG_RESULT(no)] ) +# check for libuuid from util-linux +save_LIBS=$LIBS +AC_CHECK_LIB([uuid], [uuid_generate_time]) +LIBS=$save_LIBS + # AIX provides support for RFC4122 (uuid) in libc.a starting with AIX 6.1 (anno 2007) -# FreeBSD and OpenBSD provides support as well +# FreeBSD and OpenBSD provides support in libc as well. AC_MSG_CHECKING(for uuid_create) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ #ifndef uuid_create diff --git a/pyconfig.h.in b/pyconfig.h.in index 0559274b4768c..41d3abbf536ca 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -628,6 +628,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LIBUTIL_H +/* Define you have libuuid. */ +#undef HAVE_LIBUUID + /* Define if you have the 'link' function. */ #undef HAVE_LINK diff --git a/setup.py b/setup.py index 74d5cefc60ee3..4802b6dd3e5e6 100644 --- a/setup.py +++ b/setup.py @@ -1863,15 +1863,15 @@ def detect_multiprocessing(self): def detect_uuid(self): # Build the _uuid module if possible - uuid_incs = find_file("uuid.h", self.inc_dirs, ["/usr/include/uuid"]) - if uuid_incs is not None: - if self.compiler.find_library_file(self.lib_dirs, 'uuid'): - uuid_libs = ['uuid'] + uuid_h = sysconfig.get_config_var("HAVE_UUID_H") + uuid_uuid_h = sysconfig.get_config_var("HAVE_UUID_UUID_H") + if uuid_h or uuid_uuid_h: + if sysconfig.get_config_var("HAVE_LIBUUID"): + uuid_libs = ["uuid"] else: uuid_libs = [] self.add(Extension('_uuid', ['_uuidmodule.c'], - libraries=uuid_libs, - include_dirs=uuid_incs)) + libraries=uuid_libs)) else: self.missing.append('_uuid') From webhook-mailer at python.org Tue Nov 2 07:52:47 2021 From: webhook-mailer at python.org (tiran) Date: Tue, 02 Nov 2021 11:52:47 -0000 Subject: [Python-checkins] [3.9] bpo-43158: Use configure values for building _uuid extension (GH-29353) (GH-29363) Message-ID: https://github.com/python/cpython/commit/91a51c5ffc3bd9da28a0000550530f6f2bcc25a2 commit: 91a51c5ffc3bd9da28a0000550530f6f2bcc25a2 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: tiran date: 2021-11-02T12:52:42+01:00 summary: [3.9] bpo-43158: Use configure values for building _uuid extension (GH-29353) (GH-29363) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Build/2021-11-01-12-51-46.bpo-43158.fghS6w.rst M configure M configure.ac M pyconfig.h.in M setup.py diff --git a/Misc/NEWS.d/next/Build/2021-11-01-12-51-46.bpo-43158.fghS6w.rst b/Misc/NEWS.d/next/Build/2021-11-01-12-51-46.bpo-43158.fghS6w.rst new file mode 100644 index 0000000000000..3b1de478e7fd4 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-01-12-51-46.bpo-43158.fghS6w.rst @@ -0,0 +1,2 @@ +``setup.py`` now uses values from configure script to build the ``_uuid`` +extension module. Configure now detects util-linux's ``libuuid``, too. diff --git a/configure b/configure index c0dfcd64c52a5..33ecb16f71452 100755 --- a/configure +++ b/configure @@ -9920,6 +9920,75 @@ $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +save_LIBS=$LIBS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing uuid_generate_time_safe" >&5 +$as_echo_n "checking for library containing uuid_generate_time_safe... " >&6; } +if ${ac_cv_search_uuid_generate_time_safe+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char uuid_generate_time_safe (); +int +main () +{ +return uuid_generate_time_safe (); + ; + return 0; +} +_ACEOF +for ac_lib in '' uuid; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_uuid_generate_time_safe=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_uuid_generate_time_safe+:} false; then : + break +fi +done +if ${ac_cv_search_uuid_generate_time_safe+:} false; then : + +else + ac_cv_search_uuid_generate_time_safe=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_uuid_generate_time_safe" >&5 +$as_echo "$ac_cv_search_uuid_generate_time_safe" >&6; } +ac_res=$ac_cv_search_uuid_generate_time_safe +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + + +$as_echo "#define HAVE_LIBUUID 1" >>confdefs.h +, + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi + +LIBS=$save_LIBS + # AIX provides support for RFC4122 (uuid) in libc.a starting with AIX 6.1 (anno 2007) # FreeBSD and OpenBSD provides support as well { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_create" >&5 diff --git a/configure.ac b/configure.ac index c9bf86b71a97f..823252be69425 100644 --- a/configure.ac +++ b/configure.ac @@ -2873,8 +2873,13 @@ void *x = uuid_generate_time_safe [AC_MSG_RESULT(no)] ) +# check for libuuid from util-linux +save_LIBS=$LIBS +AC_CHECK_LIB([uuid], [uuid_generate_time]) +LIBS=$save_LIBS + # AIX provides support for RFC4122 (uuid) in libc.a starting with AIX 6.1 (anno 2007) -# FreeBSD and OpenBSD provides support as well +# FreeBSD and OpenBSD provides support in libc as well. AC_MSG_CHECKING(for uuid_create) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ #ifndef uuid_create diff --git a/pyconfig.h.in b/pyconfig.h.in index b62e169255d99..63b013823cbf1 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -613,6 +613,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LIBUTIL_H +/* Define you have libuuid. */ +#undef HAVE_LIBUUID + /* Define if you have the 'link' function. */ #undef HAVE_LINK diff --git a/setup.py b/setup.py index 94ee77085113b..9a5887b59ffc4 100644 --- a/setup.py +++ b/setup.py @@ -1770,15 +1770,15 @@ def detect_multiprocessing(self): def detect_uuid(self): # Build the _uuid module if possible - uuid_incs = find_file("uuid.h", self.inc_dirs, ["/usr/include/uuid"]) - if uuid_incs is not None: - if self.compiler.find_library_file(self.lib_dirs, 'uuid'): - uuid_libs = ['uuid'] + uuid_h = sysconfig.get_config_var("HAVE_UUID_H") + uuid_uuid_h = sysconfig.get_config_var("HAVE_UUID_UUID_H") + if uuid_h or uuid_uuid_h: + if sysconfig.get_config_var("HAVE_LIBUUID"): + uuid_libs = ["uuid"] else: uuid_libs = [] self.add(Extension('_uuid', ['_uuidmodule.c'], - libraries=uuid_libs, - include_dirs=uuid_incs)) + libraries=uuid_libs)) else: self.missing.append('_uuid') From webhook-mailer at python.org Tue Nov 2 10:47:31 2021 From: webhook-mailer at python.org (Fidget-Spinner) Date: Tue, 02 Nov 2021 14:47:31 -0000 Subject: [Python-checkins] bpo-45633: Fix newtypes doc typo (GH-29318) Message-ID: https://github.com/python/cpython/commit/454cdb99abcda37413b15167cda564091fec2572 commit: 454cdb99abcda37413b15167cda564091fec2572 branch: main author: Dmitry Smirnov committer: Fidget-Spinner <28750310+Fidget-Spinner at users.noreply.github.com> date: 2021-11-02T22:47:06+08:00 summary: bpo-45633: Fix newtypes doc typo (GH-29318) files: M Doc/extending/newtypes.rst diff --git a/Doc/extending/newtypes.rst b/Doc/extending/newtypes.rst index 23ec8bce8c5ac..f75bee9e6f2a2 100644 --- a/Doc/extending/newtypes.rst +++ b/Doc/extending/newtypes.rst @@ -393,7 +393,7 @@ analogous to the :ref:`rich comparison methods `, like :c:func:`PyObject_RichCompareBool`. This function is called with two Python objects and the operator as arguments, -where the operator is one of ``Py_EQ``, ``Py_NE``, ``Py_LE``, ``Py_GT``, +where the operator is one of ``Py_EQ``, ``Py_NE``, ``Py_LE``, ``Py_GE``, ``Py_LT`` or ``Py_GT``. It should compare the two objects with respect to the specified operator and return ``Py_True`` or ``Py_False`` if the comparison is successful, ``Py_NotImplemented`` to indicate that comparison is not From webhook-mailer at python.org Tue Nov 2 11:36:07 2021 From: webhook-mailer at python.org (encukou) Date: Tue, 02 Nov 2021 15:36:07 -0000 Subject: [Python-checkins] bpo-42064: Adapt `sqlite3` to multi-phase init (PEP 489) (GH-29234) Message-ID: https://github.com/python/cpython/commit/401272e6e660445d6556d5cd4db88ed4267a50b3 commit: 401272e6e660445d6556d5cd4db88ed4267a50b3 branch: main author: Erlend Egeberg Aasland committer: encukou date: 2021-11-02T16:35:51+01:00 summary: bpo-42064: Adapt `sqlite3` to multi-phase init (PEP 489) (GH-29234) files: A Misc/NEWS.d/next/Library/2021-10-27-13-28-52.bpo-42064.UK4jgV.rst M Modules/_sqlite/module.c diff --git a/Misc/NEWS.d/next/Library/2021-10-27-13-28-52.bpo-42064.UK4jgV.rst b/Misc/NEWS.d/next/Library/2021-10-27-13-28-52.bpo-42064.UK4jgV.rst new file mode 100644 index 0000000000000..bcb3307d37bc2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-10-27-13-28-52.bpo-42064.UK4jgV.rst @@ -0,0 +1,2 @@ +Convert :mod:`sqlite3` to multi-phase initialisation (PEP 489). Patches by +Erlend E. Aasland. diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c index 8666af171c8cb..65229623b84d6 100644 --- a/Modules/_sqlite/module.c +++ b/Modules/_sqlite/module.c @@ -415,12 +415,75 @@ add_integer_constants(PyObject *module) { return 0; } -struct PyModuleDef _sqlite3module = { - .m_base = PyModuleDef_HEAD_INIT, - .m_name = "_sqlite3", - .m_size = sizeof(pysqlite_state), - .m_methods = module_methods, -}; +static int +module_traverse(PyObject *module, visitproc visit, void *arg) +{ + pysqlite_state *state = pysqlite_get_state(module); + + // Exceptions + Py_VISIT(state->DataError); + Py_VISIT(state->DatabaseError); + Py_VISIT(state->Error); + Py_VISIT(state->IntegrityError); + Py_VISIT(state->InterfaceError); + Py_VISIT(state->InternalError); + Py_VISIT(state->NotSupportedError); + Py_VISIT(state->OperationalError); + Py_VISIT(state->ProgrammingError); + Py_VISIT(state->Warning); + + // Types + Py_VISIT(state->ConnectionType); + Py_VISIT(state->CursorType); + Py_VISIT(state->PrepareProtocolType); + Py_VISIT(state->RowType); + Py_VISIT(state->StatementType); + + // Misc + Py_VISIT(state->converters); + Py_VISIT(state->lru_cache); + Py_VISIT(state->psyco_adapters); + + return 0; +} + +static int +module_clear(PyObject *module) +{ + pysqlite_state *state = pysqlite_get_state(module); + + // Exceptions + Py_CLEAR(state->DataError); + Py_CLEAR(state->DatabaseError); + Py_CLEAR(state->Error); + Py_CLEAR(state->IntegrityError); + Py_CLEAR(state->InterfaceError); + Py_CLEAR(state->InternalError); + Py_CLEAR(state->NotSupportedError); + Py_CLEAR(state->OperationalError); + Py_CLEAR(state->ProgrammingError); + Py_CLEAR(state->Warning); + + // Types + Py_CLEAR(state->ConnectionType); + Py_CLEAR(state->CursorType); + Py_CLEAR(state->PrepareProtocolType); + Py_CLEAR(state->RowType); + Py_CLEAR(state->StatementType); + + // Misc + Py_CLEAR(state->converters); + Py_CLEAR(state->lru_cache); + Py_CLEAR(state->psyco_adapters); + + return 0; +} + +static void +module_free(void *module) +{ + module_clear((PyObject *)module); +} #define ADD_TYPE(module, type) \ do { \ @@ -438,26 +501,21 @@ do { \ ADD_TYPE(module, (PyTypeObject *)state->exc); \ } while (0) -PyMODINIT_FUNC PyInit__sqlite3(void) +static int +module_exec(PyObject *module) { - PyObject *module; - if (sqlite3_libversion_number() < 3007015) { PyErr_SetString(PyExc_ImportError, MODULE_NAME ": SQLite 3.7.15 or higher required"); - return NULL; + return -1; } int rc = sqlite3_initialize(); if (rc != SQLITE_OK) { PyErr_SetString(PyExc_ImportError, sqlite3_errstr(rc)); - return NULL; + return -1; } - module = PyModule_Create(&_sqlite3module); - pysqlite_state *state = pysqlite_get_state(module); - - if (!module || - (pysqlite_row_setup_types(module) < 0) || + if ((pysqlite_row_setup_types(module) < 0) || (pysqlite_cursor_setup_types(module) < 0) || (pysqlite_connection_setup_types(module) < 0) || (pysqlite_statement_setup_types(module) < 0) || @@ -466,6 +524,7 @@ PyMODINIT_FUNC PyInit__sqlite3(void) goto error; } + pysqlite_state *state = pysqlite_get_state(module); ADD_TYPE(module, state->ConnectionType); ADD_TYPE(module, state->CursorType); ADD_TYPE(module, state->PrepareProtocolType); @@ -519,11 +578,31 @@ PyMODINIT_FUNC PyInit__sqlite3(void) goto error; } - return module; + return 0; error: sqlite3_shutdown(); - PyErr_SetString(PyExc_ImportError, MODULE_NAME ": init failed"); - Py_XDECREF(module); - return NULL; + return -1; +} + +static struct PyModuleDef_Slot module_slots[] = { + {Py_mod_exec, module_exec}, + {0, NULL}, +}; + +struct PyModuleDef _sqlite3module = { + .m_base = PyModuleDef_HEAD_INIT, + .m_name = "_sqlite3", + .m_size = sizeof(pysqlite_state), + .m_methods = module_methods, + .m_slots = module_slots, + .m_traverse = module_traverse, + .m_clear = module_clear, + .m_free = module_free, +}; + +PyMODINIT_FUNC +PyInit__sqlite3(void) +{ + return PyModuleDef_Init(&_sqlite3module); } From webhook-mailer at python.org Tue Nov 2 16:39:36 2021 From: webhook-mailer at python.org (ambv) Date: Tue, 02 Nov 2021 20:39:36 -0000 Subject: [Python-checkins] makefile: remove unused SGI_ABI variable (GH-29325) Message-ID: https://github.com/python/cpython/commit/38982ab13629a0802ea721a5917da0b98d0d5a0a commit: 38982ab13629a0802ea721a5917da0b98d0d5a0a branch: main author: Filipe La?ns committer: ambv date: 2021-11-02T21:39:27+01:00 summary: makefile: remove unused SGI_ABI variable (GH-29325) SGI_ABI support was removed in [1] but this variable was never removed from the makefile. Currently, it is just a bad variable that does not get replaced by the configure script. [1] https://github.com/python/cpython/pull/3294 Signed-off-by: Filipe La?ns files: M Makefile.pre.in diff --git a/Makefile.pre.in b/Makefile.pre.in index 7c3c046f711a5..7e959b01906bc 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -104,7 +104,6 @@ PY_CPPFLAGS= $(BASECPPFLAGS) -I. -I$(srcdir)/Include $(CONFIGURE_CPPFLAGS) $(CPP PY_LDFLAGS= $(CONFIGURE_LDFLAGS) $(LDFLAGS) PY_LDFLAGS_NODIST=$(CONFIGURE_LDFLAGS_NODIST) $(LDFLAGS_NODIST) NO_AS_NEEDED= @NO_AS_NEEDED@ -SGI_ABI= @SGI_ABI@ CCSHARED= @CCSHARED@ # LINKFORSHARED are the flags passed to the $(CC) command that links # the python executable -- this is only needed for a few systems From webhook-mailer at python.org Tue Nov 2 17:00:55 2021 From: webhook-mailer at python.org (ambv) Date: Tue, 02 Nov 2021 21:00:55 -0000 Subject: [Python-checkins] makefile: remove unused SGI_ABI variable (GH-29325) (GH-29368) Message-ID: https://github.com/python/cpython/commit/8d609b29c0f196ecf98f64c3f4b22237b561e6d7 commit: 8d609b29c0f196ecf98f64c3f4b22237b561e6d7 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-02T22:00:46+01:00 summary: makefile: remove unused SGI_ABI variable (GH-29325) (GH-29368) SGI_ABI support was removed in [1] but this variable was never removed from the makefile. Currently, it is just a bad variable that does not get replaced by the configure script. [1] https://github.com/python/cpython/pull/3294 Signed-off-by: Filipe La?ns (cherry picked from commit 38982ab13629a0802ea721a5917da0b98d0d5a0a) Co-authored-by: Filipe La?ns files: M Makefile.pre.in diff --git a/Makefile.pre.in b/Makefile.pre.in index 790d974b9685a..673e6efbf1e4f 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -103,7 +103,6 @@ PY_CPPFLAGS= $(BASECPPFLAGS) -I. -I$(srcdir)/Include $(CONFIGURE_CPPFLAGS) $(CPP PY_LDFLAGS= $(CONFIGURE_LDFLAGS) $(LDFLAGS) PY_LDFLAGS_NODIST=$(CONFIGURE_LDFLAGS_NODIST) $(LDFLAGS_NODIST) NO_AS_NEEDED= @NO_AS_NEEDED@ -SGI_ABI= @SGI_ABI@ CCSHARED= @CCSHARED@ # LINKFORSHARED are the flags passed to the $(CC) command that links # the python executable -- this is only needed for a few systems From webhook-mailer at python.org Tue Nov 2 17:01:41 2021 From: webhook-mailer at python.org (ned-deily) Date: Tue, 02 Nov 2021 21:01:41 -0000 Subject: [Python-checkins] bpo-44828: macOS installer: avoid leaving a zombie Save panel in Tk 8.6.12rc1 (GH-29367) Message-ID: https://github.com/python/cpython/commit/4a8b4051734fd2ce46e15e6369811132ac3a5697 commit: 4a8b4051734fd2ce46e15e6369811132ac3a5697 branch: main author: Ned Deily committer: ned-deily date: 2021-11-02T17:01:37-04:00 summary: bpo-44828: macOS installer: avoid leaving a zombie Save panel in Tk 8.6.12rc1 (GH-29367) files: A Mac/BuildScript/bpo-44828-filedialog-crash-monterey-8612rc1.patch M Mac/BuildScript/build-installer.py diff --git a/Mac/BuildScript/bpo-44828-filedialog-crash-monterey-8612rc1.patch b/Mac/BuildScript/bpo-44828-filedialog-crash-monterey-8612rc1.patch new file mode 100644 index 0000000000000..e70e2c35dc113 --- /dev/null +++ b/Mac/BuildScript/bpo-44828-filedialog-crash-monterey-8612rc1.patch @@ -0,0 +1,10 @@ +--- tk8.6.12/macosx/tkMacOSXDialog.c 2021-10-29 17:08:23.000000000 +0000 ++++ tk8.6.12-patched/macosx/tkMacOSXDialog.c 2021-11-02 19:04:59.000000000 +0000 +@@ -379,6 +379,7 @@ + [NSApp tkFilePanelDidEnd:panel + returnCode:modalReturnCode + contextInfo:callbackInfo ]; ++ [parent endSheet:panel]; + } + } else { + modalReturnCode = [panel runModal]; diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 9db2616bc75ba..1f6fcafc6f92c 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -269,7 +269,7 @@ def library_recipes(): tcl_checksum='82fd1637c0f7d4b76cb909f8abc373ec' tk_checksum='d63c3b91b86cd8b6fa54e83ef2c5153e' - tk_patches = [ ] + tk_patches = ['bpo-44828-filedialog-crash-monterey-8612rc1.patch'] result.extend([ From webhook-mailer at python.org Tue Nov 2 17:02:03 2021 From: webhook-mailer at python.org (ambv) Date: Tue, 02 Nov 2021 21:02:03 -0000 Subject: [Python-checkins] makefile: remove unused SGI_ABI variable (GH-29325) (GH-29370) Message-ID: https://github.com/python/cpython/commit/e312f38f7ba7b7bf1624fcb2a7bf64e02bacb5e9 commit: e312f38f7ba7b7bf1624fcb2a7bf64e02bacb5e9 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-02T22:01:59+01:00 summary: makefile: remove unused SGI_ABI variable (GH-29325) (GH-29370) SGI_ABI support was removed in [1] but this variable was never removed from the makefile. Currently, it is just a bad variable that does not get replaced by the configure script. [1] https://github.com/python/cpython/pull/3294 Signed-off-by: Filipe La?ns (cherry picked from commit 38982ab13629a0802ea721a5917da0b98d0d5a0a) Co-authored-by: Filipe La?ns files: M Makefile.pre.in diff --git a/Makefile.pre.in b/Makefile.pre.in index 6ce7a614dce23..11230fa563d16 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -103,7 +103,6 @@ PY_CPPFLAGS= $(BASECPPFLAGS) -I. -I$(srcdir)/Include $(CONFIGURE_CPPFLAGS) $(CPP PY_LDFLAGS= $(CONFIGURE_LDFLAGS) $(LDFLAGS) PY_LDFLAGS_NODIST=$(CONFIGURE_LDFLAGS_NODIST) $(LDFLAGS_NODIST) NO_AS_NEEDED= @NO_AS_NEEDED@ -SGI_ABI= @SGI_ABI@ CCSHARED= @CCSHARED@ # LINKFORSHARED are the flags passed to the $(CC) command that links # the python executable -- this is only needed for a few systems From webhook-mailer at python.org Tue Nov 2 17:03:03 2021 From: webhook-mailer at python.org (ned-deily) Date: Tue, 02 Nov 2021 21:03:03 -0000 Subject: [Python-checkins] bpo-44828: Avoid leaving a zombie Save panel. (GH-29369) Message-ID: https://github.com/python/cpython/commit/6681a77c52df41636feb213d63ba27a759c7e5f4 commit: 6681a77c52df41636feb213d63ba27a759c7e5f4 branch: 3.10 author: Ned Deily committer: ned-deily date: 2021-11-02T17:02:58-04:00 summary: bpo-44828: Avoid leaving a zombie Save panel. (GH-29369) Patch by Marc Culler of the Tk project. files: M Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch diff --git a/Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch b/Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch index 1d06329fff3fb..059149250f8c8 100644 --- a/Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch +++ b/Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch @@ -18,7 +18,7 @@ if (returnCode >= NSAlertFirstButtonReturn) { Tcl_Obj *resultObj = Tcl_NewStringObj(alertButtonStrings[ -@@ -350,49 +350,41 @@ +@@ -350,49 +350,42 @@ FilePanelCallbackInfo *callbackInfo) { NSInteger modalReturnCode; @@ -85,6 +85,7 @@ - [panel close]; + returnCode:modalReturnCode + contextInfo:callbackInfo ]; ++ [parent endSheet:panel]; } + } else { + modalReturnCode = [panel runModal]; From webhook-mailer at python.org Tue Nov 2 17:06:23 2021 From: webhook-mailer at python.org (ned-deily) Date: Tue, 02 Nov 2021 21:06:23 -0000 Subject: [Python-checkins] bpo-44828: Avoid leaving a zombie Save panel. (GH-29371) Message-ID: https://github.com/python/cpython/commit/d53d9e7f4f1656a13b030b17baca743455e511fd commit: d53d9e7f4f1656a13b030b17baca743455e511fd branch: 3.9 author: Ned Deily committer: ned-deily date: 2021-11-02T17:06:11-04:00 summary: bpo-44828: Avoid leaving a zombie Save panel. (GH-29371) Patch by Marc Culler of the Tk project. files: M Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch diff --git a/Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch b/Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch index 1d06329fff3fb..059149250f8c8 100644 --- a/Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch +++ b/Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch @@ -18,7 +18,7 @@ if (returnCode >= NSAlertFirstButtonReturn) { Tcl_Obj *resultObj = Tcl_NewStringObj(alertButtonStrings[ -@@ -350,49 +350,41 @@ +@@ -350,49 +350,42 @@ FilePanelCallbackInfo *callbackInfo) { NSInteger modalReturnCode; @@ -85,6 +85,7 @@ - [panel close]; + returnCode:modalReturnCode + contextInfo:callbackInfo ]; ++ [parent endSheet:panel]; } + } else { + modalReturnCode = [panel runModal]; From webhook-mailer at python.org Tue Nov 2 17:28:00 2021 From: webhook-mailer at python.org (ambv) Date: Tue, 02 Nov 2021 21:28:00 -0000 Subject: [Python-checkins] bpo-45457: Minor fix to documentation for SSLContext.load_default_certs. (GH-28947) Message-ID: https://github.com/python/cpython/commit/3551bf16ee5c25b6349209dd30e032f0f3b9ace3 commit: 3551bf16ee5c25b6349209dd30e032f0f3b9ace3 branch: main author: LincolnPuzey committer: ambv date: 2021-11-02T22:27:44+01:00 summary: bpo-45457: Minor fix to documentation for SSLContext.load_default_certs. (GH-28947) Specify that SSLContext.set_default_verify_paths is called on ALL systems. The code of SSLContext.load_default_certs was changed in bpo-22449 to do this, this fix corrects the documentation to match that change. files: M Doc/library/ssl.rst diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index c1167416e528d..eb33d7e1778a7 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -1576,7 +1576,7 @@ to speed up repeated connections from the same clients. Load a set of default "certification authority" (CA) certificates from default locations. On Windows it loads CA certs from the ``CA`` and - ``ROOT`` system stores. On other systems it calls + ``ROOT`` system stores. On all systems it calls :meth:`SSLContext.set_default_verify_paths`. In the future the method may load CA certificates from other locations, too. From webhook-mailer at python.org Tue Nov 2 17:34:10 2021 From: webhook-mailer at python.org (ambv) Date: Tue, 02 Nov 2021 21:34:10 -0000 Subject: [Python-checkins] [doc] Link to section File input (GH-28941) Message-ID: https://github.com/python/cpython/commit/48824fa1e26595ac97ffc96ee2c3d32ff130c420 commit: 48824fa1e26595ac97ffc96ee2c3d32ff130c420 branch: main author: Andre Delfino committer: ambv date: 2021-11-02T22:34:00+01:00 summary: [doc] Link to section File input (GH-28941) files: M Doc/library/functions.rst diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 09211681baf30..cf4a96097074f 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -557,7 +557,7 @@ are always available. They are listed here in alphabetical order. a suite of Python statements which is then executed (unless a syntax error occurs). [#]_ If it is a code object, it is simply executed. In all cases, the code that's executed is expected to be valid as file input (see the - section "File input" in the Reference Manual). Be aware that the + section :ref:`file-input` in the Reference Manual). Be aware that the :keyword:`nonlocal`, :keyword:`yield`, and :keyword:`return` statements may not be used outside of function definitions even within the context of code passed to the From webhook-mailer at python.org Tue Nov 2 17:48:01 2021 From: webhook-mailer at python.org (ambv) Date: Tue, 02 Nov 2021 21:48:01 -0000 Subject: [Python-checkins] bpo-45457: Minor fix to documentation for SSLContext.load_default_certs. (GH-28947) (GH-29373) Message-ID: https://github.com/python/cpython/commit/71f602b54c9c5346d22a542e186746b06cccfc8e commit: 71f602b54c9c5346d22a542e186746b06cccfc8e branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-02T22:47:50+01:00 summary: bpo-45457: Minor fix to documentation for SSLContext.load_default_certs. (GH-28947) (GH-29373) Specify that SSLContext.set_default_verify_paths is called on ALL systems. The code of SSLContext.load_default_certs was changed in bpo-22449 to do this, this fix corrects the documentation to match that change. (cherry picked from commit 3551bf16ee5c25b6349209dd30e032f0f3b9ace3) Co-authored-by: LincolnPuzey files: M Doc/library/ssl.rst diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 4d75616488b5f..a20f97a26535e 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -1576,7 +1576,7 @@ to speed up repeated connections from the same clients. Load a set of default "certification authority" (CA) certificates from default locations. On Windows it loads CA certs from the ``CA`` and - ``ROOT`` system stores. On other systems it calls + ``ROOT`` system stores. On all systems it calls :meth:`SSLContext.set_default_verify_paths`. In the future the method may load CA certificates from other locations, too. From webhook-mailer at python.org Tue Nov 2 17:53:51 2021 From: webhook-mailer at python.org (ambv) Date: Tue, 02 Nov 2021 21:53:51 -0000 Subject: [Python-checkins] bpo-45457: Minor fix to documentation for SSLContext.load_default_certs. (GH-28947) (GH-29374) Message-ID: https://github.com/python/cpython/commit/4ab6e524abd2d7f21c2d7a6eaee5be1f93baf140 commit: 4ab6e524abd2d7f21c2d7a6eaee5be1f93baf140 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-02T22:53:45+01:00 summary: bpo-45457: Minor fix to documentation for SSLContext.load_default_certs. (GH-28947) (GH-29374) Specify that SSLContext.set_default_verify_paths is called on ALL systems. The code of SSLContext.load_default_certs was changed in bpo-22449 to do this, this fix corrects the documentation to match that change. (cherry picked from commit 3551bf16ee5c25b6349209dd30e032f0f3b9ace3) Co-authored-by: LincolnPuzey files: M Doc/library/ssl.rst diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 58f0497878a85..0b231f170aa05 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -1522,7 +1522,7 @@ to speed up repeated connections from the same clients. Load a set of default "certification authority" (CA) certificates from default locations. On Windows it loads CA certs from the ``CA`` and - ``ROOT`` system stores. On other systems it calls + ``ROOT`` system stores. On all systems it calls :meth:`SSLContext.set_default_verify_paths`. In the future the method may load CA certificates from other locations, too. From webhook-mailer at python.org Tue Nov 2 17:54:58 2021 From: webhook-mailer at python.org (ambv) Date: Tue, 02 Nov 2021 21:54:58 -0000 Subject: [Python-checkins] [doc] Link to section File input (GH-28941) (GH-29375) Message-ID: https://github.com/python/cpython/commit/8af3090cb7af967ff699d82760ff36f978631b7a commit: 8af3090cb7af967ff699d82760ff36f978631b7a branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-02T22:54:53+01:00 summary: [doc] Link to section File input (GH-28941) (GH-29375) (cherry picked from commit 48824fa1e26595ac97ffc96ee2c3d32ff130c420) Co-authored-by: Andre Delfino files: M Doc/library/functions.rst diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 689455409eec3..47ebbd0b509a5 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -557,7 +557,7 @@ are always available. They are listed here in alphabetical order. a suite of Python statements which is then executed (unless a syntax error occurs). [#]_ If it is a code object, it is simply executed. In all cases, the code that's executed is expected to be valid as file input (see the - section "File input" in the Reference Manual). Be aware that the + section :ref:`file-input` in the Reference Manual). Be aware that the :keyword:`nonlocal`, :keyword:`yield`, and :keyword:`return` statements may not be used outside of function definitions even within the context of code passed to the From webhook-mailer at python.org Tue Nov 2 17:55:56 2021 From: webhook-mailer at python.org (ambv) Date: Tue, 02 Nov 2021 21:55:56 -0000 Subject: [Python-checkins] bpo-45406: make inspect.getmodule() return None when getabsfile() raises FileNotFoundError (GH-28824) Message-ID: https://github.com/python/cpython/commit/a459a81530de700b3d3faeb827b22ed1c9985812 commit: a459a81530de700b3d3faeb827b22ed1c9985812 branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: ambv date: 2021-11-02T22:55:51+01:00 summary: bpo-45406: make inspect.getmodule() return None when getabsfile() raises FileNotFoundError (GH-28824) files: A Misc/NEWS.d/next/Library/2021-10-08-19-24-48.bpo-45406.Qh_Mz4.rst M Lib/inspect.py M Lib/test/test_inspect.py diff --git a/Lib/inspect.py b/Lib/inspect.py index 14a42fda56c65..dd891112570c6 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -858,7 +858,7 @@ def getmodule(object, _filename=None): # Try the cache again with the absolute file name try: file = getabsfile(object, _filename) - except TypeError: + except (TypeError, FileNotFoundError): return None if file in modulesbyfile: return sys.modules.get(modulesbyfile[file]) diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 7479eb326e6f5..d43486a219158 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -493,6 +493,15 @@ def test_getmodule(self): # Check filename override self.assertEqual(inspect.getmodule(None, modfile), mod) + def test_getmodule_file_not_found(self): + # See bpo-45406 + def _getabsfile(obj, _filename): + raise FileNotFoundError('bad file') + with unittest.mock.patch('inspect.getabsfile', _getabsfile): + f = inspect.currentframe() + self.assertIsNone(inspect.getmodule(f)) + inspect.getouterframes(f) # smoke test + def test_getframeinfo_get_first_line(self): frame_info = inspect.getframeinfo(self.fodderModule.fr, 50) self.assertEqual(frame_info.code_context[0], "# line 1\n") diff --git a/Misc/NEWS.d/next/Library/2021-10-08-19-24-48.bpo-45406.Qh_Mz4.rst b/Misc/NEWS.d/next/Library/2021-10-08-19-24-48.bpo-45406.Qh_Mz4.rst new file mode 100644 index 0000000000000..2c3a8165aeb49 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-10-08-19-24-48.bpo-45406.Qh_Mz4.rst @@ -0,0 +1 @@ +Make :func:`inspect.getmodule` catch ``FileNotFoundError`` raised by :'func:`inspect.getabsfile`, and return ``None`` to indicate that the module could not be determined. \ No newline at end of file From webhook-mailer at python.org Tue Nov 2 17:59:50 2021 From: webhook-mailer at python.org (ambv) Date: Tue, 02 Nov 2021 21:59:50 -0000 Subject: [Python-checkins] [doc] Link to section File input (GH-28941) (GH-29376) Message-ID: https://github.com/python/cpython/commit/d3e775501566138347ca9d10ce57afdc1fcd3859 commit: d3e775501566138347ca9d10ce57afdc1fcd3859 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-02T22:59:42+01:00 summary: [doc] Link to section File input (GH-28941) (GH-29376) (cherry picked from commit 48824fa1e26595ac97ffc96ee2c3d32ff130c420) Co-authored-by: Andre Delfino files: M Doc/library/functions.rst diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 942ad6fab85c9..4acbc67b2d69b 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -507,7 +507,7 @@ are always available. They are listed here in alphabetical order. a suite of Python statements which is then executed (unless a syntax error occurs). [#]_ If it is a code object, it is simply executed. In all cases, the code that's executed is expected to be valid as file input (see the - section "File input" in the Reference Manual). Be aware that the + section :ref:`file-input` in the Reference Manual). Be aware that the :keyword:`nonlocal`, :keyword:`yield`, and :keyword:`return` statements may not be used outside of function definitions even within the context of code passed to the From webhook-mailer at python.org Tue Nov 2 18:23:58 2021 From: webhook-mailer at python.org (miss-islington) Date: Tue, 02 Nov 2021 22:23:58 -0000 Subject: [Python-checkins] bpo-45406: make inspect.getmodule() return None when getabsfile() raises FileNotFoundError (GH-28824) Message-ID: https://github.com/python/cpython/commit/cfdd7d26a72e7ae523039e40c11001c2d7ef36ba commit: cfdd7d26a72e7ae523039e40c11001c2d7ef36ba branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-02T15:23:43-07:00 summary: bpo-45406: make inspect.getmodule() return None when getabsfile() raises FileNotFoundError (GH-28824) (cherry picked from commit a459a81530de700b3d3faeb827b22ed1c9985812) Co-authored-by: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> files: A Misc/NEWS.d/next/Library/2021-10-08-19-24-48.bpo-45406.Qh_Mz4.rst M Lib/inspect.py M Lib/test/test_inspect.py diff --git a/Lib/inspect.py b/Lib/inspect.py index 531b891283b53..6d43d8dad46b9 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -859,7 +859,7 @@ def getmodule(object, _filename=None): # Try the cache again with the absolute file name try: file = getabsfile(object, _filename) - except TypeError: + except (TypeError, FileNotFoundError): return None if file in modulesbyfile: return sys.modules.get(modulesbyfile[file]) diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 4164634417b2a..93ff2f85df193 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -493,6 +493,15 @@ def test_getmodule(self): # Check filename override self.assertEqual(inspect.getmodule(None, modfile), mod) + def test_getmodule_file_not_found(self): + # See bpo-45406 + def _getabsfile(obj, _filename): + raise FileNotFoundError('bad file') + with unittest.mock.patch('inspect.getabsfile', _getabsfile): + f = inspect.currentframe() + self.assertIsNone(inspect.getmodule(f)) + inspect.getouterframes(f) # smoke test + def test_getframeinfo_get_first_line(self): frame_info = inspect.getframeinfo(self.fodderModule.fr, 50) self.assertEqual(frame_info.code_context[0], "# line 1\n") diff --git a/Misc/NEWS.d/next/Library/2021-10-08-19-24-48.bpo-45406.Qh_Mz4.rst b/Misc/NEWS.d/next/Library/2021-10-08-19-24-48.bpo-45406.Qh_Mz4.rst new file mode 100644 index 0000000000000..2c3a8165aeb49 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-10-08-19-24-48.bpo-45406.Qh_Mz4.rst @@ -0,0 +1 @@ +Make :func:`inspect.getmodule` catch ``FileNotFoundError`` raised by :'func:`inspect.getabsfile`, and return ``None`` to indicate that the module could not be determined. \ No newline at end of file From webhook-mailer at python.org Tue Nov 2 18:26:44 2021 From: webhook-mailer at python.org (miss-islington) Date: Tue, 02 Nov 2021 22:26:44 -0000 Subject: [Python-checkins] bpo-45406: make inspect.getmodule() return None when getabsfile() raises FileNotFoundError (GH-28824) Message-ID: https://github.com/python/cpython/commit/5f527caf15c52acc3f6e865721cdf781209f11ca commit: 5f527caf15c52acc3f6e865721cdf781209f11ca branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-02T15:26:40-07:00 summary: bpo-45406: make inspect.getmodule() return None when getabsfile() raises FileNotFoundError (GH-28824) (cherry picked from commit a459a81530de700b3d3faeb827b22ed1c9985812) Co-authored-by: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> files: A Misc/NEWS.d/next/Library/2021-10-08-19-24-48.bpo-45406.Qh_Mz4.rst M Lib/inspect.py M Lib/test/test_inspect.py diff --git a/Lib/inspect.py b/Lib/inspect.py index 64605c3cd3f6f..10b5d14eb37bf 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -736,7 +736,7 @@ def getmodule(object, _filename=None): # Try the cache again with the absolute file name try: file = getabsfile(object, _filename) - except TypeError: + except (TypeError, FileNotFoundError): return None if file in modulesbyfile: return sys.modules.get(modulesbyfile[file]) diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 8a8844e912ad2..08aed248b9665 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -488,6 +488,15 @@ def test_getmodule(self): # Check filename override self.assertEqual(inspect.getmodule(None, modfile), mod) + def test_getmodule_file_not_found(self): + # See bpo-45406 + def _getabsfile(obj, _filename): + raise FileNotFoundError('bad file') + with unittest.mock.patch('inspect.getabsfile', _getabsfile): + f = inspect.currentframe() + self.assertIsNone(inspect.getmodule(f)) + inspect.getouterframes(f) # smoke test + def test_getframeinfo_get_first_line(self): frame_info = inspect.getframeinfo(self.fodderModule.fr, 50) self.assertEqual(frame_info.code_context[0], "# line 1\n") diff --git a/Misc/NEWS.d/next/Library/2021-10-08-19-24-48.bpo-45406.Qh_Mz4.rst b/Misc/NEWS.d/next/Library/2021-10-08-19-24-48.bpo-45406.Qh_Mz4.rst new file mode 100644 index 0000000000000..2c3a8165aeb49 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-10-08-19-24-48.bpo-45406.Qh_Mz4.rst @@ -0,0 +1 @@ +Make :func:`inspect.getmodule` catch ``FileNotFoundError`` raised by :'func:`inspect.getabsfile`, and return ``None`` to indicate that the module could not be determined. \ No newline at end of file From webhook-mailer at python.org Tue Nov 2 19:49:47 2021 From: webhook-mailer at python.org (pablogsal) Date: Tue, 02 Nov 2021 23:49:47 -0000 Subject: [Python-checkins] bpo-24139: Add support for SQLite extended result codes (GH-28076) Message-ID: https://github.com/python/cpython/commit/456e27ac0ac6bc1cfd6da0191bd7802d8667457b commit: 456e27ac0ac6bc1cfd6da0191bd7802d8667457b branch: main author: Erlend Egeberg Aasland committer: pablogsal date: 2021-11-02T23:49:38Z summary: bpo-24139: Add support for SQLite extended result codes (GH-28076) files: A Misc/NEWS.d/next/Library/2021-08-30-23-10-48.bpo-24139.e38czf.rst M Doc/whatsnew/3.11.rst M Lib/test/test_sqlite3/test_dbapi.py M Modules/_sqlite/module.c M Modules/_sqlite/util.c diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 3500b1ba6b1cb..26d0dbb32af0b 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -242,11 +242,12 @@ sqlite3 now raise :exc:`UnicodeEncodeError` instead of :exc:`sqlite3.ProgrammingError`. (Contributed by Erlend E. Aasland in :issue:`44688`.) -* :mod:`sqlite3` exceptions now include the SQLite error code as +* :mod:`sqlite3` exceptions now include the SQLite extended error code as :attr:`~sqlite3.Error.sqlite_errorcode` and the SQLite error name as :attr:`~sqlite3.Error.sqlite_errorname`. (Contributed by Aviv Palivoda, Daniel Shahaf, and Erlend E. Aasland in - :issue:`16379`.) + :issue:`16379` and :issue:`24139`.) + * Add :meth:`~sqlite3.Connection.setlimit` and :meth:`~sqlite3.Connection.getlimit` to :class:`sqlite3.Connection` for diff --git a/Lib/test/test_sqlite3/test_dbapi.py b/Lib/test/test_sqlite3/test_dbapi.py index 34895be018078..0ba313d929830 100644 --- a/Lib/test/test_sqlite3/test_dbapi.py +++ b/Lib/test/test_sqlite3/test_dbapi.py @@ -157,6 +157,7 @@ def test_module_constants(self): "SQLITE_PERM", "SQLITE_PRAGMA", "SQLITE_PROTOCOL", + "SQLITE_RANGE", "SQLITE_READ", "SQLITE_READONLY", "SQLITE_REINDEX", @@ -187,18 +188,142 @@ def test_module_constants(self): if sqlite.sqlite_version_info >= (3, 8, 7): consts.append("SQLITE_LIMIT_WORKER_THREADS") consts += ["PARSE_DECLTYPES", "PARSE_COLNAMES"] + # Extended result codes + consts += [ + "SQLITE_ABORT_ROLLBACK", + "SQLITE_BUSY_RECOVERY", + "SQLITE_CANTOPEN_FULLPATH", + "SQLITE_CANTOPEN_ISDIR", + "SQLITE_CANTOPEN_NOTEMPDIR", + "SQLITE_CORRUPT_VTAB", + "SQLITE_IOERR_ACCESS", + "SQLITE_IOERR_BLOCKED", + "SQLITE_IOERR_CHECKRESERVEDLOCK", + "SQLITE_IOERR_CLOSE", + "SQLITE_IOERR_DELETE", + "SQLITE_IOERR_DELETE_NOENT", + "SQLITE_IOERR_DIR_CLOSE", + "SQLITE_IOERR_DIR_FSYNC", + "SQLITE_IOERR_FSTAT", + "SQLITE_IOERR_FSYNC", + "SQLITE_IOERR_LOCK", + "SQLITE_IOERR_NOMEM", + "SQLITE_IOERR_RDLOCK", + "SQLITE_IOERR_READ", + "SQLITE_IOERR_SEEK", + "SQLITE_IOERR_SHMLOCK", + "SQLITE_IOERR_SHMMAP", + "SQLITE_IOERR_SHMOPEN", + "SQLITE_IOERR_SHMSIZE", + "SQLITE_IOERR_SHORT_READ", + "SQLITE_IOERR_TRUNCATE", + "SQLITE_IOERR_UNLOCK", + "SQLITE_IOERR_WRITE", + "SQLITE_LOCKED_SHAREDCACHE", + "SQLITE_READONLY_CANTLOCK", + "SQLITE_READONLY_RECOVERY", + ] + if sqlite.version_info >= (3, 7, 16): + consts += [ + "SQLITE_CONSTRAINT_CHECK", + "SQLITE_CONSTRAINT_COMMITHOOK", + "SQLITE_CONSTRAINT_FOREIGNKEY", + "SQLITE_CONSTRAINT_FUNCTION", + "SQLITE_CONSTRAINT_NOTNULL", + "SQLITE_CONSTRAINT_PRIMARYKEY", + "SQLITE_CONSTRAINT_TRIGGER", + "SQLITE_CONSTRAINT_UNIQUE", + "SQLITE_CONSTRAINT_VTAB", + "SQLITE_READONLY_ROLLBACK", + ] + if sqlite.version_info >= (3, 7, 17): + consts += [ + "SQLITE_IOERR_MMAP", + "SQLITE_NOTICE_RECOVER_ROLLBACK", + "SQLITE_NOTICE_RECOVER_WAL", + ] + if sqlite.version_info >= (3, 8, 0): + consts += [ + "SQLITE_BUSY_SNAPSHOT", + "SQLITE_IOERR_GETTEMPPATH", + "SQLITE_WARNING_AUTOINDEX", + ] + if sqlite.version_info >= (3, 8, 1): + consts += ["SQLITE_CANTOPEN_CONVPATH", "SQLITE_IOERR_CONVPATH"] + if sqlite.version_info >= (3, 8, 2): + consts.append("SQLITE_CONSTRAINT_ROWID") + if sqlite.version_info >= (3, 8, 3): + consts.append("SQLITE_READONLY_DBMOVED") + if sqlite.version_info >= (3, 8, 7): + consts.append("SQLITE_AUTH_USER") + if sqlite.version_info >= (3, 9, 0): + consts.append("SQLITE_IOERR_VNODE") + if sqlite.version_info >= (3, 10, 0): + consts.append("SQLITE_IOERR_AUTH") + if sqlite.version_info >= (3, 14, 1): + consts.append("SQLITE_OK_LOAD_PERMANENTLY") + if sqlite.version_info >= (3, 21, 0): + consts += [ + "SQLITE_IOERR_BEGIN_ATOMIC", + "SQLITE_IOERR_COMMIT_ATOMIC", + "SQLITE_IOERR_ROLLBACK_ATOMIC", + ] + if sqlite.version_info >= (3, 22, 0): + consts += [ + "SQLITE_ERROR_MISSING_COLLSEQ", + "SQLITE_ERROR_RETRY", + "SQLITE_READONLY_CANTINIT", + "SQLITE_READONLY_DIRECTORY", + ] + if sqlite.version_info >= (3, 24, 0): + consts += ["SQLITE_CORRUPT_SEQUENCE", "SQLITE_LOCKED_VTAB"] + if sqlite.version_info >= (3, 25, 0): + consts += ["SQLITE_CANTOPEN_DIRTYWAL", "SQLITE_ERROR_SNAPSHOT"] + if sqlite.version_info >= (3, 31, 0): + consts += [ + "SQLITE_CANTOPEN_SYMLINK", + "SQLITE_CONSTRAINT_PINNED", + "SQLITE_OK_SYMLINK", + ] + if sqlite.version_info >= (3, 32, 0): + consts += [ + "SQLITE_BUSY_TIMEOUT", + "SQLITE_CORRUPT_INDEX", + "SQLITE_IOERR_DATA", + ] + if sqlite.version_info >= (3, 34, 0): + const.append("SQLITE_IOERR_CORRUPTFS") for const in consts: with self.subTest(const=const): self.assertTrue(hasattr(sqlite, const)) def test_error_code_on_exception(self): err_msg = "unable to open database file" + if sys.platform.startswith("win"): + err_code = sqlite.SQLITE_CANTOPEN_ISDIR + else: + err_code = sqlite.SQLITE_CANTOPEN + with temp_dir() as db: with self.assertRaisesRegex(sqlite.Error, err_msg) as cm: sqlite.connect(db) e = cm.exception - self.assertEqual(e.sqlite_errorcode, sqlite.SQLITE_CANTOPEN) - self.assertEqual(e.sqlite_errorname, "SQLITE_CANTOPEN") + self.assertEqual(e.sqlite_errorcode, err_code) + self.assertTrue(e.sqlite_errorname.startswith("SQLITE_CANTOPEN")) + + @unittest.skipIf(sqlite.sqlite_version_info <= (3, 7, 16), + "Requires SQLite 3.7.16 or newer") + def test_extended_error_code_on_exception(self): + with managed_connect(":memory:", in_mem=True) as con: + with con: + con.execute("create table t(t integer check(t > 0))") + errmsg = "CHECK constraint failed" + with self.assertRaisesRegex(sqlite.IntegrityError, errmsg) as cm: + con.execute("insert into t values(-1)") + exc = cm.exception + self.assertEqual(exc.sqlite_errorcode, + sqlite.SQLITE_CONSTRAINT_CHECK) + self.assertEqual(exc.sqlite_errorname, "SQLITE_CONSTRAINT_CHECK") # sqlite3_enable_shared_cache() is deprecated on macOS and calling it may raise # OperationalError on some buildbots. diff --git a/Misc/NEWS.d/next/Library/2021-08-30-23-10-48.bpo-24139.e38czf.rst b/Misc/NEWS.d/next/Library/2021-08-30-23-10-48.bpo-24139.e38czf.rst new file mode 100644 index 0000000000000..b44d0cf6e20e3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-08-30-23-10-48.bpo-24139.e38czf.rst @@ -0,0 +1,2 @@ +Add support for SQLite extended result codes in :exc:`sqlite3.Error`. Patch +by Erlend E. Aasland. diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c index 65229623b84d6..3bca33b8e8c27 100644 --- a/Modules/_sqlite/module.c +++ b/Modules/_sqlite/module.c @@ -280,7 +280,22 @@ static PyMethodDef module_methods[] = { {NULL, NULL} }; -/* SQLite API error codes */ +/* SQLite C API result codes. See also: + * - https://www.sqlite.org/c3ref/c_abort_rollback.html + * - https://sqlite.org/changes.html#version_3_3_8 + * - https://sqlite.org/changes.html#version_3_7_16 + * - https://sqlite.org/changes.html#version_3_7_17 + * - https://sqlite.org/changes.html#version_3_8_0 + * - https://sqlite.org/changes.html#version_3_8_3 + * - https://sqlite.org/changes.html#version_3_14 + * + * Note: the SQLite changelogs rarely mention new result codes, so in order to + * keep the 'error_codes' table in sync with SQLite, we must manually inspect + * sqlite3.h for every release. + * + * We keep the SQLITE_VERSION_NUMBER checks in order to easily declutter the + * code when we adjust the SQLite version requirement. + */ static const struct { const char *name; long value; @@ -311,6 +326,7 @@ static const struct { DECLARE_ERROR_CODE(SQLITE_OK), DECLARE_ERROR_CODE(SQLITE_PERM), DECLARE_ERROR_CODE(SQLITE_PROTOCOL), + DECLARE_ERROR_CODE(SQLITE_RANGE), DECLARE_ERROR_CODE(SQLITE_READONLY), DECLARE_ERROR_CODE(SQLITE_ROW), DECLARE_ERROR_CODE(SQLITE_SCHEMA), @@ -318,6 +334,115 @@ static const struct { #if SQLITE_VERSION_NUMBER >= 3007017 DECLARE_ERROR_CODE(SQLITE_NOTICE), DECLARE_ERROR_CODE(SQLITE_WARNING), +#endif + // Extended result code list + DECLARE_ERROR_CODE(SQLITE_ABORT_ROLLBACK), + DECLARE_ERROR_CODE(SQLITE_BUSY_RECOVERY), + DECLARE_ERROR_CODE(SQLITE_CANTOPEN_FULLPATH), + DECLARE_ERROR_CODE(SQLITE_CANTOPEN_ISDIR), + DECLARE_ERROR_CODE(SQLITE_CANTOPEN_NOTEMPDIR), + DECLARE_ERROR_CODE(SQLITE_CORRUPT_VTAB), + DECLARE_ERROR_CODE(SQLITE_IOERR_ACCESS), + DECLARE_ERROR_CODE(SQLITE_IOERR_BLOCKED), + DECLARE_ERROR_CODE(SQLITE_IOERR_CHECKRESERVEDLOCK), + DECLARE_ERROR_CODE(SQLITE_IOERR_CLOSE), + DECLARE_ERROR_CODE(SQLITE_IOERR_DELETE), + DECLARE_ERROR_CODE(SQLITE_IOERR_DELETE_NOENT), + DECLARE_ERROR_CODE(SQLITE_IOERR_DIR_CLOSE), + DECLARE_ERROR_CODE(SQLITE_IOERR_DIR_FSYNC), + DECLARE_ERROR_CODE(SQLITE_IOERR_FSTAT), + DECLARE_ERROR_CODE(SQLITE_IOERR_FSYNC), + DECLARE_ERROR_CODE(SQLITE_IOERR_LOCK), + DECLARE_ERROR_CODE(SQLITE_IOERR_NOMEM), + DECLARE_ERROR_CODE(SQLITE_IOERR_RDLOCK), + DECLARE_ERROR_CODE(SQLITE_IOERR_READ), + DECLARE_ERROR_CODE(SQLITE_IOERR_SEEK), + DECLARE_ERROR_CODE(SQLITE_IOERR_SHMLOCK), + DECLARE_ERROR_CODE(SQLITE_IOERR_SHMMAP), + DECLARE_ERROR_CODE(SQLITE_IOERR_SHMOPEN), + DECLARE_ERROR_CODE(SQLITE_IOERR_SHMSIZE), + DECLARE_ERROR_CODE(SQLITE_IOERR_SHORT_READ), + DECLARE_ERROR_CODE(SQLITE_IOERR_TRUNCATE), + DECLARE_ERROR_CODE(SQLITE_IOERR_UNLOCK), + DECLARE_ERROR_CODE(SQLITE_IOERR_WRITE), + DECLARE_ERROR_CODE(SQLITE_LOCKED_SHAREDCACHE), + DECLARE_ERROR_CODE(SQLITE_READONLY_CANTLOCK), + DECLARE_ERROR_CODE(SQLITE_READONLY_RECOVERY), +#if SQLITE_VERSION_NUMBER >= 3007016 + DECLARE_ERROR_CODE(SQLITE_CONSTRAINT_CHECK), + DECLARE_ERROR_CODE(SQLITE_CONSTRAINT_COMMITHOOK), + DECLARE_ERROR_CODE(SQLITE_CONSTRAINT_FOREIGNKEY), + DECLARE_ERROR_CODE(SQLITE_CONSTRAINT_FUNCTION), + DECLARE_ERROR_CODE(SQLITE_CONSTRAINT_NOTNULL), + DECLARE_ERROR_CODE(SQLITE_CONSTRAINT_PRIMARYKEY), + DECLARE_ERROR_CODE(SQLITE_CONSTRAINT_TRIGGER), + DECLARE_ERROR_CODE(SQLITE_CONSTRAINT_UNIQUE), + DECLARE_ERROR_CODE(SQLITE_CONSTRAINT_VTAB), + DECLARE_ERROR_CODE(SQLITE_READONLY_ROLLBACK), +#endif +#if SQLITE_VERSION_NUMBER >= 3007017 + DECLARE_ERROR_CODE(SQLITE_IOERR_MMAP), + DECLARE_ERROR_CODE(SQLITE_NOTICE_RECOVER_ROLLBACK), + DECLARE_ERROR_CODE(SQLITE_NOTICE_RECOVER_WAL), +#endif +#if SQLITE_VERSION_NUMBER >= 3008000 + DECLARE_ERROR_CODE(SQLITE_BUSY_SNAPSHOT), + DECLARE_ERROR_CODE(SQLITE_IOERR_GETTEMPPATH), + DECLARE_ERROR_CODE(SQLITE_WARNING_AUTOINDEX), +#endif +#if SQLITE_VERSION_NUMBER >= 3008001 + DECLARE_ERROR_CODE(SQLITE_CANTOPEN_CONVPATH), + DECLARE_ERROR_CODE(SQLITE_IOERR_CONVPATH), +#endif +#if SQLITE_VERSION_NUMBER >= 3008002 + DECLARE_ERROR_CODE(SQLITE_CONSTRAINT_ROWID), +#endif +#if SQLITE_VERSION_NUMBER >= 3008003 + DECLARE_ERROR_CODE(SQLITE_READONLY_DBMOVED), +#endif +#if SQLITE_VERSION_NUMBER >= 3008007 + DECLARE_ERROR_CODE(SQLITE_AUTH_USER), +#endif +#if SQLITE_VERSION_NUMBER >= 3009000 + DECLARE_ERROR_CODE(SQLITE_IOERR_VNODE), +#endif +#if SQLITE_VERSION_NUMBER >= 3010000 + DECLARE_ERROR_CODE(SQLITE_IOERR_AUTH), +#endif +#if SQLITE_VERSION_NUMBER >= 3014001 + DECLARE_ERROR_CODE(SQLITE_OK_LOAD_PERMANENTLY), +#endif +#if SQLITE_VERSION_NUMBER >= 3021000 + DECLARE_ERROR_CODE(SQLITE_IOERR_BEGIN_ATOMIC), + DECLARE_ERROR_CODE(SQLITE_IOERR_COMMIT_ATOMIC), + DECLARE_ERROR_CODE(SQLITE_IOERR_ROLLBACK_ATOMIC), +#endif +#if SQLITE_VERSION_NUMBER >= 3022000 + DECLARE_ERROR_CODE(SQLITE_ERROR_MISSING_COLLSEQ), + DECLARE_ERROR_CODE(SQLITE_ERROR_RETRY), + DECLARE_ERROR_CODE(SQLITE_READONLY_CANTINIT), + DECLARE_ERROR_CODE(SQLITE_READONLY_DIRECTORY), +#endif +#if SQLITE_VERSION_NUMBER >= 3024000 + DECLARE_ERROR_CODE(SQLITE_CORRUPT_SEQUENCE), + DECLARE_ERROR_CODE(SQLITE_LOCKED_VTAB), +#endif +#if SQLITE_VERSION_NUMBER >= 3025000 + DECLARE_ERROR_CODE(SQLITE_CANTOPEN_DIRTYWAL), + DECLARE_ERROR_CODE(SQLITE_ERROR_SNAPSHOT), +#endif +#if SQLITE_VERSION_NUMBER >= 3031000 + DECLARE_ERROR_CODE(SQLITE_CANTOPEN_SYMLINK), + DECLARE_ERROR_CODE(SQLITE_CONSTRAINT_PINNED), + DECLARE_ERROR_CODE(SQLITE_OK_SYMLINK), +#endif +#if SQLITE_VERSION_NUMBER >= 3032000 + DECLARE_ERROR_CODE(SQLITE_BUSY_TIMEOUT), + DECLARE_ERROR_CODE(SQLITE_CORRUPT_INDEX), + DECLARE_ERROR_CODE(SQLITE_IOERR_DATA), +#endif +#if SQLITE_VERSION_NUMBER >= 3034000 + DECLARE_ERROR_CODE(SQLITE_IOERR_CORRUPTFS), #endif #undef DECLARE_ERROR_CODE {NULL, 0}, diff --git a/Modules/_sqlite/util.c b/Modules/_sqlite/util.c index cfd189dfc3360..113b581bfac73 100644 --- a/Modules/_sqlite/util.c +++ b/Modules/_sqlite/util.c @@ -72,6 +72,8 @@ get_exception_class(pysqlite_state *state, int errorcode) return state->IntegrityError; case SQLITE_MISUSE: return state->ProgrammingError; + case SQLITE_RANGE: + return state->InterfaceError; default: return state->DatabaseError; } @@ -139,9 +141,10 @@ _pysqlite_seterror(pysqlite_state *state, sqlite3 *db) } /* Create and set the exception. */ + int extended_errcode = sqlite3_extended_errcode(db); const char *errmsg = sqlite3_errmsg(db); - raise_exception(exc_class, errorcode, errmsg); - return errorcode; + raise_exception(exc_class, extended_errcode, errmsg); + return extended_errcode; } #ifdef WORDS_BIGENDIAN From webhook-mailer at python.org Wed Nov 3 05:29:24 2021 From: webhook-mailer at python.org (Fidget-Spinner) Date: Wed, 03 Nov 2021 09:29:24 -0000 Subject: [Python-checkins] [3.9] bpo-45679: Fix caching of multi-value typing.Literal (GH-29334) (GH-29342) Message-ID: https://github.com/python/cpython/commit/bbcf06bf95b448810f1b6f4f119c32e871bfb84c commit: bbcf06bf95b448810f1b6f4f119c32e871bfb84c branch: 3.9 author: Serhiy Storchaka committer: Fidget-Spinner <28750310+Fidget-Spinner at users.noreply.github.com> date: 2021-11-03T17:28:55+08:00 summary: [3.9] bpo-45679: Fix caching of multi-value typing.Literal (GH-29334) (GH-29342) Literal[True, 2] is no longer equal to Literal[1, 2].. (cherry picked from commit 634984d7dbdd91e0a51a793eed4d870e139ae1e0) Co-authored-by: Serhiy Storchaka files: A Misc/NEWS.d/next/Library/2021-10-30-21-11-37.bpo-45679.Dq8Cpu.rst M Lib/test/test_typing.py M Lib/typing.py diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 1163d6f70aef1..19c38ec833c67 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -562,6 +562,8 @@ def test_equal(self): self.assertNotEqual(Literal[True], Literal[1]) self.assertNotEqual(Literal[1], Literal[2]) self.assertNotEqual(Literal[1, True], Literal[1]) + self.assertNotEqual(Literal[1, True], Literal[1, 1]) + self.assertNotEqual(Literal[1, 2], Literal[True, 2]) self.assertEqual(Literal[1], Literal[1]) self.assertEqual(Literal[1, 2], Literal[2, 1]) self.assertEqual(Literal[1, 2, 3], Literal[1, 2, 3, 3]) diff --git a/Lib/typing.py b/Lib/typing.py index 747f6b25e5be8..da70d4115fa23 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -355,9 +355,10 @@ def __getitem__(self, parameters): class _LiteralSpecialForm(_SpecialForm, _root=True): - @_tp_cache(typed=True) def __getitem__(self, parameters): - return self._getitem(self, parameters) + if not isinstance(parameters, tuple): + parameters = (parameters,) + return self._getitem(self, *parameters) @_SpecialForm @@ -478,7 +479,8 @@ def Optional(self, parameters): return Union[arg, type(None)] @_LiteralSpecialForm -def Literal(self, parameters): + at _tp_cache(typed=True) +def Literal(self, *parameters): """Special typing form to define literal types (a.k.a. value types). This form can be used to indicate to type checkers that the corresponding @@ -501,9 +503,6 @@ def open_helper(file: str, mode: MODE) -> str: """ # There is no '_type_check' call because arguments to Literal[...] are # values, not types. - if not isinstance(parameters, tuple): - parameters = (parameters,) - parameters = _flatten_literal_params(parameters) try: diff --git a/Misc/NEWS.d/next/Library/2021-10-30-21-11-37.bpo-45679.Dq8Cpu.rst b/Misc/NEWS.d/next/Library/2021-10-30-21-11-37.bpo-45679.Dq8Cpu.rst new file mode 100644 index 0000000000000..a644492a12d17 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-10-30-21-11-37.bpo-45679.Dq8Cpu.rst @@ -0,0 +1,2 @@ +Fix caching of multi-value :data:`typing.Literal`. ``Literal[True, 2]`` is no +longer equal to ``Literal[1, 2]``. From webhook-mailer at python.org Wed Nov 3 05:30:07 2021 From: webhook-mailer at python.org (Fidget-Spinner) Date: Wed, 03 Nov 2021 09:30:07 -0000 Subject: [Python-checkins] bpo-45633: Fix newtypes doc typo (GH-29318) (GH-29364) Message-ID: https://github.com/python/cpython/commit/06247061798a1ac402940d6ec04604ffa0be6c7a commit: 06247061798a1ac402940d6ec04604ffa0be6c7a branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Fidget-Spinner <28750310+Fidget-Spinner at users.noreply.github.com> date: 2021-11-03T17:30:02+08:00 summary: bpo-45633: Fix newtypes doc typo (GH-29318) (GH-29364) (cherry picked from commit 454cdb99abcda37413b15167cda564091fec2572) Co-authored-by: Dmitry Smirnov files: M Doc/extending/newtypes.rst diff --git a/Doc/extending/newtypes.rst b/Doc/extending/newtypes.rst index 23ec8bce8c5ac..f75bee9e6f2a2 100644 --- a/Doc/extending/newtypes.rst +++ b/Doc/extending/newtypes.rst @@ -393,7 +393,7 @@ analogous to the :ref:`rich comparison methods `, like :c:func:`PyObject_RichCompareBool`. This function is called with two Python objects and the operator as arguments, -where the operator is one of ``Py_EQ``, ``Py_NE``, ``Py_LE``, ``Py_GT``, +where the operator is one of ``Py_EQ``, ``Py_NE``, ``Py_LE``, ``Py_GE``, ``Py_LT`` or ``Py_GT``. It should compare the two objects with respect to the specified operator and return ``Py_True`` or ``Py_False`` if the comparison is successful, ``Py_NotImplemented`` to indicate that comparison is not From webhook-mailer at python.org Wed Nov 3 05:31:03 2021 From: webhook-mailer at python.org (Fidget-Spinner) Date: Wed, 03 Nov 2021 09:31:03 -0000 Subject: [Python-checkins] bpo-45633: Fix newtypes doc typo (GH-29318) (GH-29365) Message-ID: https://github.com/python/cpython/commit/3a93c669f50f090a227e964eb26ce8a3d1dc1202 commit: 3a93c669f50f090a227e964eb26ce8a3d1dc1202 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Fidget-Spinner <28750310+Fidget-Spinner at users.noreply.github.com> date: 2021-11-03T17:30:59+08:00 summary: bpo-45633: Fix newtypes doc typo (GH-29318) (GH-29365) (cherry picked from commit 454cdb99abcda37413b15167cda564091fec2572) Co-authored-by: Dmitry Smirnov files: M Doc/extending/newtypes.rst diff --git a/Doc/extending/newtypes.rst b/Doc/extending/newtypes.rst index 638b00a4c0f68..7c51d8e29cd42 100644 --- a/Doc/extending/newtypes.rst +++ b/Doc/extending/newtypes.rst @@ -388,7 +388,7 @@ analogous to the :ref:`rich comparison methods `, like :c:func:`PyObject_RichCompareBool`. This function is called with two Python objects and the operator as arguments, -where the operator is one of ``Py_EQ``, ``Py_NE``, ``Py_LE``, ``Py_GT``, +where the operator is one of ``Py_EQ``, ``Py_NE``, ``Py_LE``, ``Py_GE``, ``Py_LT`` or ``Py_GT``. It should compare the two objects with respect to the specified operator and return ``Py_True`` or ``Py_False`` if the comparison is successful, ``Py_NotImplemented`` to indicate that comparison is not From webhook-mailer at python.org Wed Nov 3 05:35:47 2021 From: webhook-mailer at python.org (Fidget-Spinner) Date: Wed, 03 Nov 2021 09:35:47 -0000 Subject: [Python-checkins] bpo-24139: Fix test_sqlite3 `test_extended_error_code_on_exception()` on s390x RHEL buildbots (GH-29382) Message-ID: https://github.com/python/cpython/commit/0dfb8c4afee65f9e185882efd57f7012120da74c commit: 0dfb8c4afee65f9e185882efd57f7012120da74c branch: main author: Erlend Egeberg Aasland committer: Fidget-Spinner <28750310+Fidget-Spinner at users.noreply.github.com> date: 2021-11-03T17:35:42+08:00 summary: bpo-24139: Fix test_sqlite3 `test_extended_error_code_on_exception()` on s390x RHEL buildbots (GH-29382) files: M Lib/test/test_sqlite3/test_dbapi.py diff --git a/Lib/test/test_sqlite3/test_dbapi.py b/Lib/test/test_sqlite3/test_dbapi.py index 0ba313d929830..998b7cb8c7fc0 100644 --- a/Lib/test/test_sqlite3/test_dbapi.py +++ b/Lib/test/test_sqlite3/test_dbapi.py @@ -317,7 +317,7 @@ def test_extended_error_code_on_exception(self): with managed_connect(":memory:", in_mem=True) as con: with con: con.execute("create table t(t integer check(t > 0))") - errmsg = "CHECK constraint failed" + errmsg = "constraint failed" with self.assertRaisesRegex(sqlite.IntegrityError, errmsg) as cm: con.execute("insert into t values(-1)") exc = cm.exception From webhook-mailer at python.org Wed Nov 3 09:55:48 2021 From: webhook-mailer at python.org (ambv) Date: Wed, 03 Nov 2021 13:55:48 -0000 Subject: [Python-checkins] bpo-45578: add tests for `dis.distb` (GH-29332) Message-ID: https://github.com/python/cpython/commit/e346f196819aeb02a8a94205ce3e1536c4c2f105 commit: e346f196819aeb02a8a94205ce3e1536c4c2f105 branch: main author: Nikita Sobolev committer: ambv date: 2021-11-03T14:55:42+01:00 summary: bpo-45578: add tests for `dis.distb` (GH-29332) files: A Misc/NEWS.d/next/Tests/2021-10-30-19-00-25.bpo-45578.bvu6X2.rst M Lib/test/test_dis.py diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index 4755e3f3a1724..2a0e3b4e84981 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -1359,5 +1359,45 @@ def test__find_store_names(self): self.assertEqual(res, expected) +class TestDisTraceback(unittest.TestCase): + def setUp(self) -> None: + try: # We need to clean up existing tracebacks + del sys.last_traceback + except AttributeError: + pass + return super().setUp() + + def get_disassembly(self, tb): + output = io.StringIO() + with contextlib.redirect_stdout(output): + dis.distb(tb) + return output.getvalue() + + def test_distb_empty(self): + with self.assertRaises(RuntimeError): + dis.distb() + + def test_distb_last_traceback(self): + # We need to have an existing last traceback in `sys`: + tb = get_tb() + sys.last_traceback = tb + + self.assertEqual(self.get_disassembly(None), dis_traceback) + + def test_distb_explicit_arg(self): + tb = get_tb() + + self.assertEqual(self.get_disassembly(tb), dis_traceback) + + +class TestDisTracebackWithFile(TestDisTraceback): + # Run the `distb` tests again, using the file arg instead of print + def get_disassembly(self, tb): + output = io.StringIO() + with contextlib.redirect_stdout(output): + dis.distb(tb, file=output) + return output.getvalue() + + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Tests/2021-10-30-19-00-25.bpo-45578.bvu6X2.rst b/Misc/NEWS.d/next/Tests/2021-10-30-19-00-25.bpo-45578.bvu6X2.rst new file mode 100644 index 0000000000000..3d0e0ca3f04a1 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-10-30-19-00-25.bpo-45578.bvu6X2.rst @@ -0,0 +1 @@ +Add tests for :func:`dis.distb` From webhook-mailer at python.org Wed Nov 3 11:53:54 2021 From: webhook-mailer at python.org (ambv) Date: Wed, 03 Nov 2021 15:53:54 -0000 Subject: [Python-checkins] [3.10] bpo-45578: add tests for `dis.distb` (GH-29332) (GH-29385) Message-ID: https://github.com/python/cpython/commit/fd6b70d6b715c2403a194a2b3eae3210e2e81742 commit: fd6b70d6b715c2403a194a2b3eae3210e2e81742 branch: 3.10 author: ?ukasz Langa committer: ambv date: 2021-11-03T16:53:36+01:00 summary: [3.10] bpo-45578: add tests for `dis.distb` (GH-29332) (GH-29385) (cherry picked from commit e346f196819aeb02a8a94205ce3e1536c4c2f105) Co-authored-by: Nikita Sobolev files: A Misc/NEWS.d/next/Tests/2021-10-30-19-00-25.bpo-45578.bvu6X2.rst M Lib/test/test_dis.py diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index edda967ce1e1c..2cb2eff9a6c3f 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -1244,5 +1244,46 @@ def test_assert_not_in_with_arg_in_bytecode(self): with self.assertRaises(AssertionError): self.assertNotInBytecode(code, "LOAD_CONST", 1) + +class TestDisTraceback(unittest.TestCase): + def setUp(self) -> None: + try: # We need to clean up existing tracebacks + del sys.last_traceback + except AttributeError: + pass + return super().setUp() + + def get_disassembly(self, tb): + output = io.StringIO() + with contextlib.redirect_stdout(output): + dis.distb(tb) + return output.getvalue() + + def test_distb_empty(self): + with self.assertRaises(RuntimeError): + dis.distb() + + def test_distb_last_traceback(self): + # We need to have an existing last traceback in `sys`: + tb = get_tb() + sys.last_traceback = tb + + self.assertEqual(self.get_disassembly(None), dis_traceback) + + def test_distb_explicit_arg(self): + tb = get_tb() + + self.assertEqual(self.get_disassembly(tb), dis_traceback) + + +class TestDisTracebackWithFile(TestDisTraceback): + # Run the `distb` tests again, using the file arg instead of print + def get_disassembly(self, tb): + output = io.StringIO() + with contextlib.redirect_stdout(output): + dis.distb(tb, file=output) + return output.getvalue() + + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Tests/2021-10-30-19-00-25.bpo-45578.bvu6X2.rst b/Misc/NEWS.d/next/Tests/2021-10-30-19-00-25.bpo-45578.bvu6X2.rst new file mode 100644 index 0000000000000..3d0e0ca3f04a1 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-10-30-19-00-25.bpo-45578.bvu6X2.rst @@ -0,0 +1 @@ +Add tests for :func:`dis.distb` From webhook-mailer at python.org Wed Nov 3 12:12:11 2021 From: webhook-mailer at python.org (ambv) Date: Wed, 03 Nov 2021 16:12:11 -0000 Subject: [Python-checkins] bpo-45678: Add ``functools.singledispatchmethod`` tests (GH-29328) Message-ID: https://github.com/python/cpython/commit/5a14929a6e4fab672e2f83a86773618e973b22a6 commit: 5a14929a6e4fab672e2f83a86773618e973b22a6 branch: main author: Alex Waygood committer: ambv date: 2021-11-03T17:12:02+01:00 summary: bpo-45678: Add ``functools.singledispatchmethod`` tests (GH-29328) files: A Misc/NEWS.d/next/Tests/2021-10-30-13-12-20.bpo-45678.bKrYeS.rst M Lib/test/test_functools.py diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index bdb4ddcc60cac..1a3c921509d5e 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -2411,7 +2411,7 @@ def _(cls, arg): self.assertEqual(A.t(0.0).arg, "base") def test_abstractmethod_register(self): - class Abstract(abc.ABCMeta): + class Abstract(metaclass=abc.ABCMeta): @functools.singledispatchmethod @abc.abstractmethod @@ -2419,6 +2419,10 @@ def add(self, x, y): pass self.assertTrue(Abstract.add.__isabstractmethod__) + self.assertTrue(Abstract.__dict__['add'].__isabstractmethod__) + + with self.assertRaises(TypeError): + Abstract() def test_type_ann_register(self): class A: @@ -2479,6 +2483,42 @@ def _(cls, arg: str): self.assertEqual(A.t('').arg, "str") self.assertEqual(A.t(0.0).arg, "base") + def test_method_wrapping_attributes(self): + class A: + @functools.singledispatchmethod + def func(self, arg: int) -> str: + """My function docstring""" + return str(arg) + @functools.singledispatchmethod + @classmethod + def cls_func(cls, arg: int) -> str: + """My function docstring""" + return str(arg) + @functools.singledispatchmethod + @staticmethod + def static_func(arg: int) -> str: + """My function docstring""" + return str(arg) + + for meth in ( + A.func, + A().func, + A.cls_func, + A().cls_func, + A.static_func, + A().static_func + ): + with self.subTest(meth=meth): + self.assertEqual(meth.__doc__, 'My function docstring') + self.assertEqual(meth.__annotations__['arg'], int) + + self.assertEqual(A.func.__name__, 'func') + self.assertEqual(A().func.__name__, 'func') + self.assertEqual(A.cls_func.__name__, 'cls_func') + self.assertEqual(A().cls_func.__name__, 'cls_func') + self.assertEqual(A.static_func.__name__, 'static_func') + self.assertEqual(A().static_func.__name__, 'static_func') + def test_invalid_registrations(self): msg_prefix = "Invalid first argument to `register()`: " msg_suffix = ( diff --git a/Misc/NEWS.d/next/Tests/2021-10-30-13-12-20.bpo-45678.bKrYeS.rst b/Misc/NEWS.d/next/Tests/2021-10-30-13-12-20.bpo-45678.bKrYeS.rst new file mode 100644 index 0000000000000..885b2fa64ad0f --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-10-30-13-12-20.bpo-45678.bKrYeS.rst @@ -0,0 +1,2 @@ +Add tests to ensure that ``functools.singledispatchmethod`` correctly wraps +the attributes of the target function. From webhook-mailer at python.org Wed Nov 3 12:22:42 2021 From: webhook-mailer at python.org (markshannon) Date: Wed, 03 Nov 2021 16:22:42 -0000 Subject: [Python-checkins] bpo-45691: Make array of small ints static to fix use-after-free error. (GH-29366) Message-ID: https://github.com/python/cpython/commit/acc89db9233abf4d903af9a7595a2ed7478fe7d3 commit: acc89db9233abf4d903af9a7595a2ed7478fe7d3 branch: main author: Mark Shannon committer: markshannon date: 2021-11-03T16:22:32Z summary: bpo-45691: Make array of small ints static to fix use-after-free error. (GH-29366) files: M Include/internal/pycore_interp.h M Include/internal/pycore_long.h M Include/internal/pycore_runtime.h M Objects/longobject.c diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index 8bd3dc064eea3..18f21432008d9 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -247,14 +247,6 @@ struct type_cache { /* interpreter state */ -#define _PY_NSMALLPOSINTS 257 -#define _PY_NSMALLNEGINTS 5 - -// _PyLong_GetZero() and _PyLong_GetOne() must always be available -#if _PY_NSMALLPOSINTS < 2 -# error "_PY_NSMALLPOSINTS must be greater than 1" -#endif - // The PyInterpreterState typedef is in Include/pystate.h. struct _is { @@ -330,12 +322,6 @@ struct _is { PyObject *audit_hooks; - /* Small integers are preallocated in this array so that they - can be shared. - The integers that are preallocated are those in the range - -_PY_NSMALLNEGINTS (inclusive) to _PY_NSMALLPOSINTS (not inclusive). - */ - PyLongObject small_ints[_PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS]; struct _Py_bytes_state bytes; struct _Py_unicode_state unicode; struct _Py_float_state float_state; diff --git a/Include/internal/pycore_long.h b/Include/internal/pycore_long.h index 773025b4a5add..2f786083e4527 100644 --- a/Include/internal/pycore_long.h +++ b/Include/internal/pycore_long.h @@ -11,28 +11,15 @@ extern "C" { #include "pycore_interp.h" // PyInterpreterState.small_ints #include "pycore_pystate.h" // _PyThreadState_GET() -// Don't call this function but _PyLong_GetZero() and _PyLong_GetOne() -static inline PyObject* __PyLong_GetSmallInt_internal(int value) -{ - PyInterpreterState *interp = _PyInterpreterState_GET(); - assert(-_PY_NSMALLNEGINTS <= value && value < _PY_NSMALLPOSINTS); - size_t index = _PY_NSMALLNEGINTS + value; - PyObject *obj = (PyObject*)&interp->small_ints[index]; - // _PyLong_GetZero(), _PyLong_GetOne() and get_small_int() must not be - // called before _PyLong_Init() nor after _PyLong_Fini(). - assert(obj != NULL); - return obj; -} - // Return a borrowed reference to the zero singleton. // The function cannot return NULL. static inline PyObject* _PyLong_GetZero(void) -{ return __PyLong_GetSmallInt_internal(0); } +{ return (PyObject *)&_PyRuntime.small_ints[_PY_NSMALLNEGINTS]; } // Return a borrowed reference to the one singleton. // The function cannot return NULL. static inline PyObject* _PyLong_GetOne(void) -{ return __PyLong_GetSmallInt_internal(1); } +{ return (PyObject *)&_PyRuntime.small_ints[_PY_NSMALLNEGINTS+1]; } PyObject *_PyLong_Add(PyLongObject *left, PyLongObject *right); PyObject *_PyLong_Multiply(PyLongObject *left, PyLongObject *right); diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h index bcd710c4496bd..9df833c270193 100644 --- a/Include/internal/pycore_runtime.h +++ b/Include/internal/pycore_runtime.h @@ -11,6 +11,14 @@ extern "C" { #include "pycore_atomic.h" /* _Py_atomic_address */ #include "pycore_gil.h" // struct _gil_runtime_state +#define _PY_NSMALLPOSINTS 257 +#define _PY_NSMALLNEGINTS 5 + +// _PyLong_GetZero() and _PyLong_GetOne() must always be available +#if _PY_NSMALLPOSINTS < 2 +# error "_PY_NSMALLPOSINTS must be greater than 1" +#endif + /* ceval state */ struct _ceval_runtime_state { @@ -100,6 +108,13 @@ typedef struct pyruntimestate { unsigned long main_thread; + /* Small integers are preallocated in this array so that they + * can be shared. + * The integers that are preallocated are those in the range + *-_PY_NSMALLNEGINTS (inclusive) to _PY_NSMALLPOSINTS (not inclusive). + */ + PyLongObject small_ints[_PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS]; + #define NEXITFUNCS 32 void (*exitfuncs[NEXITFUNCS])(void); int nexitfuncs; diff --git a/Objects/longobject.c b/Objects/longobject.c index b7392e50e7f6c..a4d90b1704321 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -4,8 +4,8 @@ #include "Python.h" #include "pycore_bitutils.h" // _Py_popcount32() -#include "pycore_interp.h" // _PY_NSMALLPOSINTS -#include "pycore_long.h" // __PyLong_GetSmallInt_internal() +#include "pycore_runtime.h" // _PY_NSMALLPOSINTS +#include "pycore_long.h" // _Py_SmallInts #include "pycore_object.h" // _PyObject_InitVar() #include "pycore_pystate.h" // _Py_IsMainInterpreter() @@ -20,9 +20,6 @@ class int "PyObject *" "&PyLong_Type" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=ec0275e3422a36e3]*/ -#define NSMALLNEGINTS _PY_NSMALLNEGINTS -#define NSMALLPOSINTS _PY_NSMALLPOSINTS - _Py_IDENTIFIER(little); _Py_IDENTIFIER(big); @@ -37,8 +34,8 @@ medium_value(PyLongObject *x) return ((stwodigits)Py_SIZE(x)) * x->ob_digit[0]; } -#define IS_SMALL_INT(ival) (-NSMALLNEGINTS <= (ival) && (ival) < NSMALLPOSINTS) -#define IS_SMALL_UINT(ival) ((ival) < NSMALLPOSINTS) +#define IS_SMALL_INT(ival) (-_PY_NSMALLNEGINTS <= (ival) && (ival) < _PY_NSMALLPOSINTS) +#define IS_SMALL_UINT(ival) ((ival) < _PY_NSMALLPOSINTS) static inline int is_medium_int(stwodigits x) { @@ -51,7 +48,7 @@ static PyObject * get_small_int(sdigit ival) { assert(IS_SMALL_INT(ival)); - PyObject *v = __PyLong_GetSmallInt_internal(ival); + PyObject *v = (PyObject *)&_PyRuntime.small_ints[_PY_NSMALLNEGINTS + ival]; Py_INCREF(v); return v; } @@ -5830,17 +5827,18 @@ PyLong_GetInfo(void) void _PyLong_Init(PyInterpreterState *interp) { - for (Py_ssize_t i=0; i < NSMALLNEGINTS + NSMALLPOSINTS; i++) { - sdigit ival = (sdigit)i - NSMALLNEGINTS; - int size = (ival < 0) ? -1 : ((ival == 0) ? 0 : 1); - interp->small_ints[i].ob_base.ob_base.ob_refcnt = 1; - interp->small_ints[i].ob_base.ob_base.ob_type = &PyLong_Type; - interp->small_ints[i].ob_base.ob_size = size; - interp->small_ints[i].ob_digit[0] = (digit)abs(ival); + if (_PyRuntime.small_ints[0].ob_base.ob_base.ob_refcnt == 0) { + for (Py_ssize_t i=0; i < _PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS; i++) { + sdigit ival = (sdigit)i - _PY_NSMALLNEGINTS; + int size = (ival < 0) ? -1 : ((ival == 0) ? 0 : 1); + _PyRuntime.small_ints[i].ob_base.ob_base.ob_refcnt = 1; + _PyRuntime.small_ints[i].ob_base.ob_base.ob_type = &PyLong_Type; + _PyRuntime.small_ints[i].ob_base.ob_size = size; + _PyRuntime.small_ints[i].ob_digit[0] = (digit)abs(ival); + } } } - int _PyLong_InitTypes(void) { From webhook-mailer at python.org Wed Nov 3 12:45:40 2021 From: webhook-mailer at python.org (ambv) Date: Wed, 03 Nov 2021 16:45:40 -0000 Subject: [Python-checkins] bpo-45678: Add ``functools.singledispatchmethod`` tests (GH-29328) (GH-29390) Message-ID: https://github.com/python/cpython/commit/f1918385cccf3ef51d339dfa1f3654005508f307 commit: f1918385cccf3ef51d339dfa1f3654005508f307 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-03T17:45:20+01:00 summary: bpo-45678: Add ``functools.singledispatchmethod`` tests (GH-29328) (GH-29390) (cherry picked from commit 5a14929a6e4fab672e2f83a86773618e973b22a6) Co-authored-by: Alex Waygood files: A Misc/NEWS.d/next/Tests/2021-10-30-13-12-20.bpo-45678.bKrYeS.rst M Lib/test/test_functools.py diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index bdb4ddcc60cac..1a3c921509d5e 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -2411,7 +2411,7 @@ def _(cls, arg): self.assertEqual(A.t(0.0).arg, "base") def test_abstractmethod_register(self): - class Abstract(abc.ABCMeta): + class Abstract(metaclass=abc.ABCMeta): @functools.singledispatchmethod @abc.abstractmethod @@ -2419,6 +2419,10 @@ def add(self, x, y): pass self.assertTrue(Abstract.add.__isabstractmethod__) + self.assertTrue(Abstract.__dict__['add'].__isabstractmethod__) + + with self.assertRaises(TypeError): + Abstract() def test_type_ann_register(self): class A: @@ -2479,6 +2483,42 @@ def _(cls, arg: str): self.assertEqual(A.t('').arg, "str") self.assertEqual(A.t(0.0).arg, "base") + def test_method_wrapping_attributes(self): + class A: + @functools.singledispatchmethod + def func(self, arg: int) -> str: + """My function docstring""" + return str(arg) + @functools.singledispatchmethod + @classmethod + def cls_func(cls, arg: int) -> str: + """My function docstring""" + return str(arg) + @functools.singledispatchmethod + @staticmethod + def static_func(arg: int) -> str: + """My function docstring""" + return str(arg) + + for meth in ( + A.func, + A().func, + A.cls_func, + A().cls_func, + A.static_func, + A().static_func + ): + with self.subTest(meth=meth): + self.assertEqual(meth.__doc__, 'My function docstring') + self.assertEqual(meth.__annotations__['arg'], int) + + self.assertEqual(A.func.__name__, 'func') + self.assertEqual(A().func.__name__, 'func') + self.assertEqual(A.cls_func.__name__, 'cls_func') + self.assertEqual(A().cls_func.__name__, 'cls_func') + self.assertEqual(A.static_func.__name__, 'static_func') + self.assertEqual(A().static_func.__name__, 'static_func') + def test_invalid_registrations(self): msg_prefix = "Invalid first argument to `register()`: " msg_suffix = ( diff --git a/Misc/NEWS.d/next/Tests/2021-10-30-13-12-20.bpo-45678.bKrYeS.rst b/Misc/NEWS.d/next/Tests/2021-10-30-13-12-20.bpo-45678.bKrYeS.rst new file mode 100644 index 0000000000000..885b2fa64ad0f --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-10-30-13-12-20.bpo-45678.bKrYeS.rst @@ -0,0 +1,2 @@ +Add tests to ensure that ``functools.singledispatchmethod`` correctly wraps +the attributes of the target function. From webhook-mailer at python.org Wed Nov 3 12:47:13 2021 From: webhook-mailer at python.org (ambv) Date: Wed, 03 Nov 2021 16:47:13 -0000 Subject: [Python-checkins] [3.9] bpo-45578: add tests for `dis.distb` (GH-29332) (#29386) Message-ID: https://github.com/python/cpython/commit/8198617bcce885c280ba5f8acd066c71b311b1ac commit: 8198617bcce885c280ba5f8acd066c71b311b1ac branch: 3.9 author: ?ukasz Langa committer: ambv date: 2021-11-03T17:47:04+01:00 summary: [3.9] bpo-45578: add tests for `dis.distb` (GH-29332) (#29386) (cherry picked from commit e346f196819aeb02a8a94205ce3e1536c4c2f105) Co-authored-by: Nikita Sobolev files: A Misc/NEWS.d/next/Tests/2021-10-30-19-00-25.bpo-45578.bvu6X2.rst M Lib/test/test_dis.py diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index ac5836d288978..54bab568ab8a3 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -1202,5 +1202,46 @@ def test_from_traceback_dis(self): b = dis.Bytecode.from_traceback(tb) self.assertEqual(b.dis(), dis_traceback) + +class TestDisTraceback(unittest.TestCase): + def setUp(self) -> None: + try: # We need to clean up existing tracebacks + del sys.last_traceback + except AttributeError: + pass + return super().setUp() + + def get_disassembly(self, tb): + output = io.StringIO() + with contextlib.redirect_stdout(output): + dis.distb(tb) + return output.getvalue() + + def test_distb_empty(self): + with self.assertRaises(RuntimeError): + dis.distb() + + def test_distb_last_traceback(self): + # We need to have an existing last traceback in `sys`: + tb = get_tb() + sys.last_traceback = tb + + self.assertEqual(self.get_disassembly(None), dis_traceback) + + def test_distb_explicit_arg(self): + tb = get_tb() + + self.assertEqual(self.get_disassembly(tb), dis_traceback) + + +class TestDisTracebackWithFile(TestDisTraceback): + # Run the `distb` tests again, using the file arg instead of print + def get_disassembly(self, tb): + output = io.StringIO() + with contextlib.redirect_stdout(output): + dis.distb(tb, file=output) + return output.getvalue() + + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Tests/2021-10-30-19-00-25.bpo-45578.bvu6X2.rst b/Misc/NEWS.d/next/Tests/2021-10-30-19-00-25.bpo-45578.bvu6X2.rst new file mode 100644 index 0000000000000..3d0e0ca3f04a1 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-10-30-19-00-25.bpo-45578.bvu6X2.rst @@ -0,0 +1 @@ +Add tests for :func:`dis.distb` From webhook-mailer at python.org Wed Nov 3 13:47:26 2021 From: webhook-mailer at python.org (ericsnowcurrently) Date: Wed, 03 Nov 2021 17:47:26 -0000 Subject: [Python-checkins] bpo-45506: Stop skipping test_embed. (gh-29300) Message-ID: https://github.com/python/cpython/commit/7b438282d39e742b2628a32e7c6699a140ff4cfb commit: 7b438282d39e742b2628a32e7c6699a140ff4cfb branch: main author: Eric Snow committer: ericsnowcurrently date: 2021-11-03T11:47:16-06:00 summary: bpo-45506: Stop skipping test_embed. (gh-29300) In gh-29063 I ended up disabling test_embed on non-Windows by accident. This gets it running again. https://bugs.python.org/issue45506 files: M Lib/test/test_embed.py diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index 3a00efa5799b9..a0d61504f427d 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -58,10 +58,12 @@ def setUp(self): ext = ("_d" if debug_build(sys.executable) else "") + ".exe" exename += ext exepath = builddir + expecteddir = support.REPO_ROOT else: exepath = os.path.join(builddir, 'Programs') + expecteddir = os.path.join(support.REPO_ROOT, 'Programs') self.test_exe = exe = os.path.join(exepath, exename) - if exepath != support.REPO_ROOT or not os.path.exists(exe): + if exepath != expecteddir or not os.path.exists(exe): self.skipTest("%r doesn't exist" % exe) # This is needed otherwise we get a fatal error: # "Py_Initialize: Unable to get the locale encoding From webhook-mailer at python.org Wed Nov 3 16:57:54 2021 From: webhook-mailer at python.org (pablogsal) Date: Wed, 03 Nov 2021 20:57:54 -0000 Subject: [Python-checkins] bpo-44257: fix "assigment_expr" typo + regenerate the grammar, and remove unused imports (GH-29393) Message-ID: https://github.com/python/cpython/commit/762173c6709f5cf3b59cbbe47d4e6fafbfe7ec2a commit: 762173c6709f5cf3b59cbbe47d4e6fafbfe7ec2a branch: main author: wim glenn committer: pablogsal date: 2021-11-03T20:57:40Z summary: bpo-44257: fix "assigment_expr" typo + regenerate the grammar, and remove unused imports (GH-29393) Co-authored-by: Wim Glenn files: M Grammar/python.gram M Parser/parser.c M Tools/peg_generator/pegen/python_generator.py diff --git a/Grammar/python.gram b/Grammar/python.gram index 4443a5fda7c24..a8c693d74075a 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -642,11 +642,11 @@ star_named_expression[expr_ty]: | '*' a=bitwise_or { _PyAST_Starred(a, Load, EXTRA) } | named_expression -assigment_expression[expr_ty]: +assignment_expression[expr_ty]: | a=NAME ':=' ~ b=expression { _PyAST_NamedExpr(CHECK(expr_ty, _PyPegen_set_expr_context(p, a, Store)), b, EXTRA) } named_expression[expr_ty]: - | assigment_expression + | assignment_expression | invalid_named_expression | expression !':=' @@ -903,7 +903,7 @@ setcomp[expr_ty]: | invalid_comprehension genexp[expr_ty]: - | '(' a=( assigment_expression | expression !':=') b=for_if_clauses ')' { _PyAST_GeneratorExp(a, b, EXTRA) } + | '(' a=( assignment_expression | expression !':=') b=for_if_clauses ')' { _PyAST_GeneratorExp(a, b, EXTRA) } | invalid_comprehension dictcomp[expr_ty]: @@ -918,7 +918,7 @@ arguments[expr_ty] (memo): | invalid_arguments args[expr_ty]: - | a[asdl_expr_seq*]=','.(starred_expression | ( assigment_expression | expression !':=') !'=')+ b=[',' k=kwargs {k}] { + | a[asdl_expr_seq*]=','.(starred_expression | ( assignment_expression | expression !':=') !'=')+ b=[',' k=kwargs {k}] { _PyPegen_collect_call_seqs(p, a, b, EXTRA) } | a=kwargs { _PyAST_Call(_PyPegen_dummy_name(p), CHECK_NULL_ALLOWED(asdl_expr_seq*, _PyPegen_seq_extract_starred_exprs(p, a)), diff --git a/Parser/parser.c b/Parser/parser.c index 47722f3baf1e6..42f6f733326b3 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -172,7 +172,7 @@ static char *soft_keywords[] = { #define star_expression_type 1098 #define star_named_expressions_type 1099 #define star_named_expression_type 1100 -#define assigment_expression_type 1101 +#define assignment_expression_type 1101 #define named_expression_type 1102 #define disjunction_type 1103 #define conjunction_type 1104 @@ -599,7 +599,7 @@ static expr_ty star_expressions_rule(Parser *p); static expr_ty star_expression_rule(Parser *p); static asdl_expr_seq* star_named_expressions_rule(Parser *p); static expr_ty star_named_expression_rule(Parser *p); -static expr_ty assigment_expression_rule(Parser *p); +static expr_ty assignment_expression_rule(Parser *p); static expr_ty named_expression_rule(Parser *p); static expr_ty disjunction_rule(Parser *p); static expr_ty conjunction_rule(Parser *p); @@ -10289,9 +10289,9 @@ star_named_expression_rule(Parser *p) return _res; } -// assigment_expression: NAME ':=' ~ expression +// assignment_expression: NAME ':=' ~ expression static expr_ty -assigment_expression_rule(Parser *p) +assignment_expression_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -10314,7 +10314,7 @@ assigment_expression_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> assigment_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME ':=' ~ expression")); + D(fprintf(stderr, "%*c> assignment_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME ':=' ~ expression")); int _cut_var = 0; Token * _literal; expr_ty a; @@ -10329,7 +10329,7 @@ assigment_expression_rule(Parser *p) (b = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ assigment_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME ':=' ~ expression")); + D(fprintf(stderr, "%*c+ assignment_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME ':=' ~ expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { D(p->level--); @@ -10348,7 +10348,7 @@ assigment_expression_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s assigment_expression[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s assignment_expression[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME ':=' ~ expression")); if (_cut_var) { D(p->level--); @@ -10361,7 +10361,7 @@ assigment_expression_rule(Parser *p) return _res; } -// named_expression: assigment_expression | invalid_named_expression | expression !':=' +// named_expression: assignment_expression | invalid_named_expression | expression !':=' static expr_ty named_expression_rule(Parser *p) { @@ -10372,24 +10372,24 @@ named_expression_rule(Parser *p) } expr_ty _res = NULL; int _mark = p->mark; - { // assigment_expression + { // assignment_expression if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assigment_expression")); - expr_ty assigment_expression_var; + D(fprintf(stderr, "%*c> named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + expr_ty assignment_expression_var; if ( - (assigment_expression_var = assigment_expression_rule(p)) // assigment_expression + (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression ) { - D(fprintf(stderr, "%*c+ named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assigment_expression")); - _res = assigment_expression_var; + D(fprintf(stderr, "%*c+ named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + _res = assignment_expression_var; goto done; } p->mark = _mark; D(fprintf(stderr, "%*c%s named_expression[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assigment_expression")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); } if (p->call_invalid_rules) { // invalid_named_expression if (p->error_indicator) { @@ -15231,7 +15231,7 @@ setcomp_rule(Parser *p) } // genexp: -// | '(' (assigment_expression | expression !':=') for_if_clauses ')' +// | '(' (assignment_expression | expression !':=') for_if_clauses ')' // | invalid_comprehension static expr_ty genexp_rule(Parser *p) @@ -15252,12 +15252,12 @@ genexp_rule(Parser *p) UNUSED(_start_lineno); // Only used by EXTRA macro int _start_col_offset = p->tokens[_mark]->col_offset; UNUSED(_start_col_offset); // Only used by EXTRA macro - { // '(' (assigment_expression | expression !':=') for_if_clauses ')' + { // '(' (assignment_expression | expression !':=') for_if_clauses ')' if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> genexp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' (assigment_expression | expression !':=') for_if_clauses ')'")); + D(fprintf(stderr, "%*c> genexp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' (assignment_expression | expression !':=') for_if_clauses ')'")); Token * _literal; Token * _literal_1; void *a; @@ -15265,14 +15265,14 @@ genexp_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (a = _tmp_113_rule(p)) // assigment_expression | expression !':=' + (a = _tmp_113_rule(p)) // assignment_expression | expression !':=' && (b = for_if_clauses_rule(p)) // for_if_clauses && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ genexp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' (assigment_expression | expression !':=') for_if_clauses ')'")); + D(fprintf(stderr, "%*c+ genexp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' (assignment_expression | expression !':=') for_if_clauses ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { D(p->level--); @@ -15292,7 +15292,7 @@ genexp_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s genexp[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' (assigment_expression | expression !':=') for_if_clauses ')'")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' (assignment_expression | expression !':=') for_if_clauses ')'")); } if (p->call_invalid_rules) { // invalid_comprehension if (p->error_indicator) { @@ -15478,7 +15478,7 @@ arguments_rule(Parser *p) } // args: -// | ','.(starred_expression | (assigment_expression | expression !':=') !'=')+ [',' kwargs] +// | ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs] // | kwargs static expr_ty args_rule(Parser *p) @@ -15499,21 +15499,21 @@ args_rule(Parser *p) UNUSED(_start_lineno); // Only used by EXTRA macro int _start_col_offset = p->tokens[_mark]->col_offset; UNUSED(_start_col_offset); // Only used by EXTRA macro - { // ','.(starred_expression | (assigment_expression | expression !':=') !'=')+ [',' kwargs] + { // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs] if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> args[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assigment_expression | expression !':=') !'=')+ [',' kwargs]")); + D(fprintf(stderr, "%*c> args[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs]")); asdl_expr_seq* a; void *b; if ( - (a = (asdl_expr_seq*)_gather_114_rule(p)) // ','.(starred_expression | (assigment_expression | expression !':=') !'=')+ + (a = (asdl_expr_seq*)_gather_114_rule(p)) // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ && (b = _tmp_116_rule(p), !p->error_indicator) // [',' kwargs] ) { - D(fprintf(stderr, "%*c+ args[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assigment_expression | expression !':=') !'=')+ [',' kwargs]")); + D(fprintf(stderr, "%*c+ args[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { D(p->level--); @@ -15533,7 +15533,7 @@ args_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s args[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','.(starred_expression | (assigment_expression | expression !':=') !'=')+ [',' kwargs]")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs]")); } { // kwargs if (p->error_indicator) { @@ -28047,7 +28047,7 @@ _loop0_112_rule(Parser *p) return _seq; } -// _tmp_113: assigment_expression | expression !':=' +// _tmp_113: assignment_expression | expression !':=' static void * _tmp_113_rule(Parser *p) { @@ -28058,24 +28058,24 @@ _tmp_113_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // assigment_expression + { // assignment_expression if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assigment_expression")); - expr_ty assigment_expression_var; + D(fprintf(stderr, "%*c> _tmp_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + expr_ty assignment_expression_var; if ( - (assigment_expression_var = assigment_expression_rule(p)) // assigment_expression + (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression ) { - D(fprintf(stderr, "%*c+ _tmp_113[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assigment_expression")); - _res = assigment_expression_var; + D(fprintf(stderr, "%*c+ _tmp_113[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + _res = assignment_expression_var; goto done; } p->mark = _mark; D(fprintf(stderr, "%*c%s _tmp_113[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assigment_expression")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); } { // expression !':=' if (p->error_indicator) { @@ -28104,7 +28104,7 @@ _tmp_113_rule(Parser *p) return _res; } -// _loop0_115: ',' (starred_expression | (assigment_expression | expression !':=') !'=') +// _loop0_115: ',' (starred_expression | (assignment_expression | expression !':=') !'=') static asdl_seq * _loop0_115_rule(Parser *p) { @@ -28125,18 +28125,18 @@ _loop0_115_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // ',' (starred_expression | (assigment_expression | expression !':=') !'=') + { // ',' (starred_expression | (assignment_expression | expression !':=') !'=') if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | (assigment_expression | expression !':=') !'=')")); + D(fprintf(stderr, "%*c> _loop0_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_190_rule(p)) // starred_expression | (assigment_expression | expression !':=') !'=' + (elem = _tmp_190_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' ) { _res = elem; @@ -28162,7 +28162,7 @@ _loop0_115_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s _loop0_115[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (starred_expression | (assigment_expression | expression !':=') !'=')")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -28180,7 +28180,7 @@ _loop0_115_rule(Parser *p) } // _gather_114: -// | (starred_expression | (assigment_expression | expression !':=') !'=') _loop0_115 +// | (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_115 static asdl_seq * _gather_114_rule(Parser *p) { @@ -28191,27 +28191,27 @@ _gather_114_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (starred_expression | (assigment_expression | expression !':=') !'=') _loop0_115 + { // (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_115 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assigment_expression | expression !':=') !'=') _loop0_115")); + D(fprintf(stderr, "%*c> _gather_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_115")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_190_rule(p)) // starred_expression | (assigment_expression | expression !':=') !'=' + (elem = _tmp_190_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' && (seq = _loop0_115_rule(p)) // _loop0_115 ) { - D(fprintf(stderr, "%*c+ _gather_114[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assigment_expression | expression !':=') !'=') _loop0_115")); + D(fprintf(stderr, "%*c+ _gather_114[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_115")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; D(fprintf(stderr, "%*c%s _gather_114[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression | (assigment_expression | expression !':=') !'=') _loop0_115")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_115")); } _res = NULL; done: @@ -32352,7 +32352,7 @@ _tmp_189_rule(Parser *p) return _res; } -// _tmp_190: starred_expression | (assigment_expression | expression !':=') !'=' +// _tmp_190: starred_expression | (assignment_expression | expression !':=') !'=' static void * _tmp_190_rule(Parser *p) { @@ -32382,26 +32382,26 @@ _tmp_190_rule(Parser *p) D(fprintf(stderr, "%*c%s _tmp_190[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression")); } - { // (assigment_expression | expression !':=') !'=' + { // (assignment_expression | expression !':=') !'=' if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_190[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assigment_expression | expression !':=') !'='")); + D(fprintf(stderr, "%*c> _tmp_190[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); void *_tmp_201_var; if ( - (_tmp_201_var = _tmp_201_rule(p)) // assigment_expression | expression !':=' + (_tmp_201_var = _tmp_201_rule(p)) // assignment_expression | expression !':=' && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_190[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assigment_expression | expression !':=') !'='")); + D(fprintf(stderr, "%*c+ _tmp_190[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); _res = _tmp_201_var; goto done; } p->mark = _mark; D(fprintf(stderr, "%*c%s _tmp_190[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(assigment_expression | expression !':=') !'='")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(assignment_expression | expression !':=') !'='")); } _res = NULL; done: @@ -32845,7 +32845,7 @@ _tmp_200_rule(Parser *p) return _res; } -// _tmp_201: assigment_expression | expression !':=' +// _tmp_201: assignment_expression | expression !':=' static void * _tmp_201_rule(Parser *p) { @@ -32856,24 +32856,24 @@ _tmp_201_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // assigment_expression + { // assignment_expression if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assigment_expression")); - expr_ty assigment_expression_var; + D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + expr_ty assignment_expression_var; if ( - (assigment_expression_var = assigment_expression_rule(p)) // assigment_expression + (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression ) { - D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assigment_expression")); - _res = assigment_expression_var; + D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + _res = assignment_expression_var; goto done; } p->mark = _mark; D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assigment_expression")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); } { // expression !':=' if (p->error_indicator) { diff --git a/Tools/peg_generator/pegen/python_generator.py b/Tools/peg_generator/pegen/python_generator.py index 7aa730ae1c953..25a48bfab5d6c 100644 --- a/Tools/peg_generator/pegen/python_generator.py +++ b/Tools/peg_generator/pegen/python_generator.py @@ -1,5 +1,3 @@ -import ast -import re import token from typing import IO, Any, Dict, Optional, Sequence, Set, Text, Tuple From webhook-mailer at python.org Wed Nov 3 17:01:47 2021 From: webhook-mailer at python.org (pablogsal) Date: Wed, 03 Nov 2021 21:01:47 -0000 Subject: [Python-checkins] bpo-45613: Set `sqlite3.threadsafety` dynamically (GH-29227) Message-ID: https://github.com/python/cpython/commit/c2739867113a2b650db300c03ef06cf18dcee3f4 commit: c2739867113a2b650db300c03ef06cf18dcee3f4 branch: main author: Erlend Egeberg Aasland committer: pablogsal date: 2021-11-03T21:01:37Z summary: bpo-45613: Set `sqlite3.threadsafety` dynamically (GH-29227) Use the compile-time selected default SQLite threaded mode to set the DB-API 2.0 attribute 'threadsafety' Mappings: - SQLITE_THREADSAFE=0 => threadsafety=0 - SQLITE_THREADSAFE=1 => threadsafety=3 - SQLITE_THREADSAFE=2 => threadsafety=1 files: A Misc/NEWS.d/next/Library/2021-10-26-14-29-54.bpo-45613.55Ie3c.rst M Doc/library/sqlite3.rst M Doc/whatsnew/3.11.rst M Lib/sqlite3/dbapi2.py M Lib/test/test_sqlite3/test_dbapi.py M Modules/_sqlite/module.c diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index dcffc779cfba3..91bf7b0e7c879 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -159,23 +159,41 @@ Module functions and constants .. data:: threadsafety - Integer constant required by the DB-API, stating the level of thread safety - the :mod:`sqlite3` module supports. Currently hard-coded to ``1``, meaning - *"Threads may share the module, but not connections."* However, this may not - always be true. You can check the underlying SQLite library's compile-time - threaded mode using the following query:: - - import sqlite3 - con = sqlite3.connect(":memory:") - con.execute(""" - select * from pragma_compile_options - where compile_options like 'THREADSAFE=%' - """).fetchall() - - Note that the `SQLITE_THREADSAFE levels - `_ do not match the DB-API 2.0 - ``threadsafety`` levels. - + Integer constant required by the DB-API 2.0, stating the level of thread + safety the :mod:`sqlite3` module supports. This attribute is set based on + the default `threading mode `_ the + underlying SQLite library is compiled with. The SQLite threading modes are: + + 1. **Single-thread**: In this mode, all mutexes are disabled and SQLite is + unsafe to use in more than a single thread at once. + 2. **Multi-thread**: In this mode, SQLite can be safely used by multiple + threads provided that no single database connection is used + simultaneously in two or more threads. + 3. **Serialized**: In serialized mode, SQLite can be safely used by + multiple threads with no restriction. + + The mappings from SQLite threading modes to DB-API 2.0 threadsafety levels + are as follows: + + +------------------+-----------------+----------------------+-------------------------------+ + | SQLite threading | `threadsafety`_ | `SQLITE_THREADSAFE`_ | DB-API 2.0 meaning | + | mode | | | | + +==================+=================+======================+===============================+ + | single-thread | 0 | 0 | Threads may not share the | + | | | | module | + +------------------+-----------------+----------------------+-------------------------------+ + | multi-thread | 1 | 2 | Threads may share the module, | + | | | | but not connections | + +------------------+-----------------+----------------------+-------------------------------+ + | serialized | 3 | 1 | Threads may share the module, | + | | | | connections and cursors | + +------------------+-----------------+----------------------+-------------------------------+ + + .. _threadsafety: https://www.python.org/dev/peps/pep-0249/#threadsafety + .. _SQLITE_THREADSAFE: https://sqlite.org/compile.html#threadsafe + + .. versionchanged:: 3.11 + Set *threadsafety* dynamically instead of hard-coding it to ``1``. .. data:: PARSE_DECLTYPES diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 26d0dbb32af0b..7b15ace403170 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -254,6 +254,10 @@ sqlite3 setting and getting SQLite limits by connection basis. (Contributed by Erlend E. Aasland in :issue:`45243`.) +* :mod:`sqlite3` now sets :attr:`sqlite3.threadsafety` based on the default + threading mode the underlying SQLite library has been compiled with. + (Contributed by Erlend E. Aasland in :issue:`45613`.) + threading --------- diff --git a/Lib/sqlite3/dbapi2.py b/Lib/sqlite3/dbapi2.py index cfe6225f46efc..7cf4dd32d541d 100644 --- a/Lib/sqlite3/dbapi2.py +++ b/Lib/sqlite3/dbapi2.py @@ -28,8 +28,6 @@ paramstyle = "qmark" -threadsafety = 1 - apilevel = "2.0" Date = datetime.date diff --git a/Lib/test/test_sqlite3/test_dbapi.py b/Lib/test/test_sqlite3/test_dbapi.py index 998b7cb8c7fc0..ba3652a04a2d8 100644 --- a/Lib/test/test_sqlite3/test_dbapi.py +++ b/Lib/test/test_sqlite3/test_dbapi.py @@ -54,8 +54,9 @@ def test_api_level(self): "apilevel is %s, should be 2.0" % sqlite.apilevel) def test_thread_safety(self): - self.assertEqual(sqlite.threadsafety, 1, - "threadsafety is %d, should be 1" % sqlite.threadsafety) + self.assertIn(sqlite.threadsafety, {0, 1, 3}, + "threadsafety is %d, should be 0, 1 or 3" % + sqlite.threadsafety) def test_param_style(self): self.assertEqual(sqlite.paramstyle, "qmark", diff --git a/Misc/NEWS.d/next/Library/2021-10-26-14-29-54.bpo-45613.55Ie3c.rst b/Misc/NEWS.d/next/Library/2021-10-26-14-29-54.bpo-45613.55Ie3c.rst new file mode 100644 index 0000000000000..ac0937b54aeea --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-10-26-14-29-54.bpo-45613.55Ie3c.rst @@ -0,0 +1,3 @@ +:mod:`sqlite3` now sets :attr:`sqlite3.threadsafety` based on the default +threading mode the underlying SQLite library has been compiled with. Patch by +Erlend E. Aasland. diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c index 3bca33b8e8c27..3b9f79799b5c5 100644 --- a/Modules/_sqlite/module.c +++ b/Modules/_sqlite/module.c @@ -540,6 +540,28 @@ add_integer_constants(PyObject *module) { return 0; } +/* Convert SQLite default threading mode (as set by the compile-time constant + * SQLITE_THREADSAFE) to the corresponding DB-API 2.0 (PEP 249) threadsafety + * level. */ +static int +get_threadsafety(pysqlite_state *state) +{ + int mode = sqlite3_threadsafe(); + switch (mode) { + case 0: // Single-thread mode; threads may not share the module. + return 0; + case 1: // Serialized mode; threads may share the module, + return 3; // connections, and cursors. + case 2: // Multi-thread mode; threads may share the module, but not + return 1; // connections. + default: + PyErr_Format(state->InterfaceError, + "Unable to interpret SQLite threadsafety mode. Got %d, " + "expected 0, 1, or 2", mode); + return -1; + } +} + static int module_traverse(PyObject *module, visitproc visit, void *arg) { @@ -689,6 +711,14 @@ module_exec(PyObject *module) goto error; } + int threadsafety = get_threadsafety(state); + if (threadsafety < 0) { + goto error; + } + if (PyModule_AddIntConstant(module, "threadsafety", threadsafety) < 0) { + goto error; + } + /* initialize microprotocols layer */ if (pysqlite_microprotocols_init(module) < 0) { goto error; From webhook-mailer at python.org Thu Nov 4 00:06:43 2021 From: webhook-mailer at python.org (Fidget-Spinner) Date: Thu, 04 Nov 2021 04:06:43 -0000 Subject: [Python-checkins] bpo-45680: ``typing`` docs: improve links to docs on ``GenericAlias``/``__class_getitem__`` (GH-29387) Message-ID: https://github.com/python/cpython/commit/e03e50377d6f8f212af60fed4ae405ebeb73237d commit: e03e50377d6f8f212af60fed4ae405ebeb73237d branch: main author: Alex Waygood committer: Fidget-Spinner <28750310+Fidget-Spinner at users.noreply.github.com> date: 2021-11-04T12:06:34+08:00 summary: bpo-45680: ``typing`` docs: improve links to docs on ``GenericAlias``/``__class_getitem__`` (GH-29387) files: A Misc/NEWS.d/next/Documentation/2021-11-03-14-51-03.bpo-45680.9_NTFU.rst M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index eb95af378d45f..79ca2e96431a6 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -49,8 +49,8 @@ annotations. These include: *Introducing* :class:`Protocol` and the :func:`@runtime_checkable` decorator * :pep:`585`: Type Hinting Generics In Standard Collections - *Introducing* the ability to use builtin collections and ABCs as - :term:`generic types` + *Introducing* :class:`types.GenericAlias` and the ability to use standard + library classes as :ref:`generic types` * :pep:`586`: Literal Types *Introducing* :data:`Literal` * :pep:`589`: TypedDict: Type Hints for Dictionaries with a Fixed Set of Keys @@ -291,8 +291,8 @@ A user-defined class can be defined as a generic class. single type parameter ``T`` . This also makes ``T`` valid as a type within the class body. -The :class:`Generic` base class defines :meth:`__class_getitem__` so that -``LoggedVar[t]`` is valid as a type:: +The :class:`Generic` base class defines :meth:`~object.__class_getitem__` so +that ``LoggedVar[t]`` is valid as a type:: from collections.abc import Iterable diff --git a/Misc/NEWS.d/next/Documentation/2021-11-03-14-51-03.bpo-45680.9_NTFU.rst b/Misc/NEWS.d/next/Documentation/2021-11-03-14-51-03.bpo-45680.9_NTFU.rst new file mode 100644 index 0000000000000..79ea6e308e54a --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-03-14-51-03.bpo-45680.9_NTFU.rst @@ -0,0 +1,3 @@ +Amend the docs on ``GenericAlias`` objects to clarify that non-container +classes can also implement ``__class_getitem__``. Patch contributed by Alex +Waygood. From webhook-mailer at python.org Thu Nov 4 00:27:56 2021 From: webhook-mailer at python.org (miss-islington) Date: Thu, 04 Nov 2021 04:27:56 -0000 Subject: [Python-checkins] bpo-45680: ``typing`` docs: improve links to docs on ``GenericAlias``/``__class_getitem__`` (GH-29387) Message-ID: https://github.com/python/cpython/commit/c10896696f47a8348e6d9ea3c1d96fa6ba131a31 commit: c10896696f47a8348e6d9ea3c1d96fa6ba131a31 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-03T21:27:47-07:00 summary: bpo-45680: ``typing`` docs: improve links to docs on ``GenericAlias``/``__class_getitem__`` (GH-29387) (cherry picked from commit e03e50377d6f8f212af60fed4ae405ebeb73237d) Co-authored-by: Alex Waygood files: A Misc/NEWS.d/next/Documentation/2021-11-03-14-51-03.bpo-45680.9_NTFU.rst M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 7652c87827220..db9ad1154f2f4 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -49,8 +49,8 @@ annotations. These include: *Introducing* :class:`Protocol` and the :func:`@runtime_checkable` decorator * :pep:`585`: Type Hinting Generics In Standard Collections - *Introducing* the ability to use builtin collections and ABCs as - :term:`generic types` + *Introducing* :class:`types.GenericAlias` and the ability to use standard + library classes as :ref:`generic types` * :pep:`586`: Literal Types *Introducing* :data:`Literal` * :pep:`589`: TypedDict: Type Hints for Dictionaries with a Fixed Set of Keys @@ -291,8 +291,8 @@ A user-defined class can be defined as a generic class. single type parameter ``T`` . This also makes ``T`` valid as a type within the class body. -The :class:`Generic` base class defines :meth:`__class_getitem__` so that -``LoggedVar[t]`` is valid as a type:: +The :class:`Generic` base class defines :meth:`~object.__class_getitem__` so +that ``LoggedVar[t]`` is valid as a type:: from collections.abc import Iterable diff --git a/Misc/NEWS.d/next/Documentation/2021-11-03-14-51-03.bpo-45680.9_NTFU.rst b/Misc/NEWS.d/next/Documentation/2021-11-03-14-51-03.bpo-45680.9_NTFU.rst new file mode 100644 index 0000000000000..79ea6e308e54a --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-03-14-51-03.bpo-45680.9_NTFU.rst @@ -0,0 +1,3 @@ +Amend the docs on ``GenericAlias`` objects to clarify that non-container +classes can also implement ``__class_getitem__``. Patch contributed by Alex +Waygood. From webhook-mailer at python.org Thu Nov 4 00:34:41 2021 From: webhook-mailer at python.org (miss-islington) Date: Thu, 04 Nov 2021 04:34:41 -0000 Subject: [Python-checkins] bpo-45680: ``typing`` docs: improve links to docs on ``GenericAlias``/``__class_getitem__`` (GH-29387) Message-ID: https://github.com/python/cpython/commit/e813dd4d7bb0ecfabc7dae75e13f58164bcf8da6 commit: e813dd4d7bb0ecfabc7dae75e13f58164bcf8da6 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-03T21:34:31-07:00 summary: bpo-45680: ``typing`` docs: improve links to docs on ``GenericAlias``/``__class_getitem__`` (GH-29387) (cherry picked from commit e03e50377d6f8f212af60fed4ae405ebeb73237d) Co-authored-by: Alex Waygood files: A Misc/NEWS.d/next/Documentation/2021-11-03-14-51-03.bpo-45680.9_NTFU.rst M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 295f2ae8905af..068112d8d9451 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -49,8 +49,8 @@ annotations. These include: *Introducing* :class:`Protocol` and the :func:`@runtime_checkable` decorator * :pep:`585`: Type Hinting Generics In Standard Collections - *Introducing* the ability to use builtin collections and ABCs as - :term:`generic types` + *Introducing* :class:`types.GenericAlias` and the ability to use standard + library classes as :ref:`generic types` * :pep:`586`: Literal Types *Introducing* :class:`Literal` * :pep:`589`: TypedDict: Type Hints for Dictionaries with a Fixed Set of Keys @@ -258,8 +258,8 @@ A user-defined class can be defined as a generic class. single type parameter ``T`` . This also makes ``T`` valid as a type within the class body. -The :class:`Generic` base class defines :meth:`__class_getitem__` so that -``LoggedVar[t]`` is valid as a type:: +The :class:`Generic` base class defines :meth:`~object.__class_getitem__` so +that ``LoggedVar[t]`` is valid as a type:: from collections.abc import Iterable diff --git a/Misc/NEWS.d/next/Documentation/2021-11-03-14-51-03.bpo-45680.9_NTFU.rst b/Misc/NEWS.d/next/Documentation/2021-11-03-14-51-03.bpo-45680.9_NTFU.rst new file mode 100644 index 0000000000000..79ea6e308e54a --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-03-14-51-03.bpo-45680.9_NTFU.rst @@ -0,0 +1,3 @@ +Amend the docs on ``GenericAlias`` objects to clarify that non-container +classes can also implement ``__class_getitem__``. Patch contributed by Alex +Waygood. From webhook-mailer at python.org Thu Nov 4 06:40:22 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Thu, 04 Nov 2021 10:40:22 -0000 Subject: [Python-checkins] bpo-45697: Use PyObject_TypeCheck in type_call (GH-29392) Message-ID: https://github.com/python/cpython/commit/2c045bd5673d56c3fdde7536da9df1c7d6f270f0 commit: 2c045bd5673d56c3fdde7536da9df1c7d6f270f0 branch: main author: Itamar Ostricher committer: serhiy-storchaka date: 2021-11-04T12:39:50+02:00 summary: bpo-45697: Use PyObject_TypeCheck in type_call (GH-29392) files: M Objects/typeobject.c diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 18bea476ea9f2..51ec93d875271 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1121,7 +1121,7 @@ type_call(PyTypeObject *type, PyObject *args, PyObject *kwds) /* If the returned object is not an instance of type, it won't be initialized. */ - if (!PyType_IsSubtype(Py_TYPE(obj), type)) + if (!PyObject_TypeCheck(obj, type)) return obj; type = Py_TYPE(obj); From webhook-mailer at python.org Thu Nov 4 07:48:48 2021 From: webhook-mailer at python.org (Fidget-Spinner) Date: Thu, 04 Nov 2021 11:48:48 -0000 Subject: [Python-checkins] Remove reference to ``Tuple`` at top of ``typing`` docs (GH-29401) Message-ID: https://github.com/python/cpython/commit/87032cfa3dc975d7442fd57dea2c6a56d31c911a commit: 87032cfa3dc975d7442fd57dea2c6a56d31c911a branch: main author: Alex Waygood committer: Fidget-Spinner <28750310+Fidget-Spinner at users.noreply.github.com> date: 2021-11-04T19:48:40+08:00 summary: Remove reference to ``Tuple`` at top of ``typing`` docs (GH-29401) ``typing.Tuple`` has been deprecated since Python 3.9, so it makes no sense to mention it so prominently in the documentation for the ``typing`` module. files: M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 79ca2e96431a6..c37e97eb3e730 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -18,10 +18,9 @@ -------------- This module provides runtime support for type hints. The most fundamental -support consists of the types :data:`Any`, :data:`Union`, :data:`Tuple`, -:data:`Callable`, :class:`TypeVar`, and :class:`Generic`. For a full -specification, please see :pep:`484`. For a simplified introduction to type -hints, see :pep:`483`. +support consists of the types :data:`Any`, :data:`Union`, :data:`Callable`, +:class:`TypeVar`, and :class:`Generic`. For a full specification, please see +:pep:`484`. For a simplified introduction to type hints, see :pep:`483`. The function below takes and returns a string and is annotated as follows:: From webhook-mailer at python.org Thu Nov 4 08:11:24 2021 From: webhook-mailer at python.org (miss-islington) Date: Thu, 04 Nov 2021 12:11:24 -0000 Subject: [Python-checkins] Remove reference to ``Tuple`` at top of ``typing`` docs (GH-29401) Message-ID: https://github.com/python/cpython/commit/75ed2ce9e86a7f213fa54e6f8cbbb3ab6f25b5a2 commit: 75ed2ce9e86a7f213fa54e6f8cbbb3ab6f25b5a2 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-04T05:11:14-07:00 summary: Remove reference to ``Tuple`` at top of ``typing`` docs (GH-29401) ``typing.Tuple`` has been deprecated since Python 3.9, so it makes no sense to mention it so prominently in the documentation for the ``typing`` module. (cherry picked from commit 87032cfa3dc975d7442fd57dea2c6a56d31c911a) Co-authored-by: Alex Waygood files: M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index db9ad1154f2f4..c59afdd5e9025 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -18,10 +18,9 @@ -------------- This module provides runtime support for type hints. The most fundamental -support consists of the types :data:`Any`, :data:`Union`, :data:`Tuple`, -:data:`Callable`, :class:`TypeVar`, and :class:`Generic`. For a full -specification, please see :pep:`484`. For a simplified introduction to type -hints, see :pep:`483`. +support consists of the types :data:`Any`, :data:`Union`, :data:`Callable`, +:class:`TypeVar`, and :class:`Generic`. For a full specification, please see +:pep:`484`. For a simplified introduction to type hints, see :pep:`483`. The function below takes and returns a string and is annotated as follows:: From webhook-mailer at python.org Thu Nov 4 08:13:35 2021 From: webhook-mailer at python.org (miss-islington) Date: Thu, 04 Nov 2021 12:13:35 -0000 Subject: [Python-checkins] Remove reference to ``Tuple`` at top of ``typing`` docs (GH-29401) Message-ID: https://github.com/python/cpython/commit/7e244fc80434584d082c0c7a3d9a92e69aa30061 commit: 7e244fc80434584d082c0c7a3d9a92e69aa30061 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-04T05:13:24-07:00 summary: Remove reference to ``Tuple`` at top of ``typing`` docs (GH-29401) ``typing.Tuple`` has been deprecated since Python 3.9, so it makes no sense to mention it so prominently in the documentation for the ``typing`` module. (cherry picked from commit 87032cfa3dc975d7442fd57dea2c6a56d31c911a) Co-authored-by: Alex Waygood files: M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 068112d8d9451..3b50d76c5a8fe 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -18,10 +18,9 @@ -------------- This module provides runtime support for type hints. The most fundamental -support consists of the types :data:`Any`, :data:`Union`, :data:`Tuple`, -:data:`Callable`, :class:`TypeVar`, and :class:`Generic`. For a full -specification, please see :pep:`484`. For a simplified introduction to type -hints, see :pep:`483`. +support consists of the types :data:`Any`, :data:`Union`, :data:`Callable`, +:class:`TypeVar`, and :class:`Generic`. For a full specification, please see +:pep:`484`. For a simplified introduction to type hints, see :pep:`483`. The function below takes and returns a string and is annotated as follows:: From webhook-mailer at python.org Thu Nov 4 12:39:26 2021 From: webhook-mailer at python.org (zooba) Date: Thu, 04 Nov 2021 16:39:26 -0000 Subject: [Python-checkins] bpo-43652: Actually update to Tcl/Tk 8.6.11 on Windows (GH-29397) Message-ID: https://github.com/python/cpython/commit/36b4f9e2a7d5ed55c441eb6dfe5c13baa483b9d4 commit: 36b4f9e2a7d5ed55c441eb6dfe5c13baa483b9d4 branch: main author: Steve Dower committer: zooba date: 2021-11-04T16:39:07Z summary: bpo-43652: Actually update to Tcl/Tk 8.6.11 on Windows (GH-29397) files: A Misc/NEWS.d/next/Windows/2021-11-04-00-41-50.bpo-43652.RnqV7I.rst M PCbuild/get_externals.bat M PCbuild/tcltk.props diff --git a/Misc/NEWS.d/next/Windows/2021-11-04-00-41-50.bpo-43652.RnqV7I.rst b/Misc/NEWS.d/next/Windows/2021-11-04-00-41-50.bpo-43652.RnqV7I.rst new file mode 100644 index 0000000000000..7da8fc79a9dab --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2021-11-04-00-41-50.bpo-43652.RnqV7I.rst @@ -0,0 +1,2 @@ +Update Tcl/Tk to 8.6.11, actually this time. The previous update incorrectly +included 8.6.10. diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index b3e557e2a1314..484543d5999b8 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -55,8 +55,8 @@ set libraries=%libraries% bzip2-1.0.6 if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.4.2 if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1l set libraries=%libraries% sqlite-3.36.0.0 -if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.11.0 -if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.11.0 +if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.11.1 +if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.11.1 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tix-8.4.3.6 set libraries=%libraries% xz-5.2.2 set libraries=%libraries% zlib-1.2.11 @@ -78,7 +78,7 @@ echo.Fetching external binaries... set binaries= if NOT "%IncludeLibffi%"=="false" set binaries=%binaries% libffi-3.4.2 if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.1l -if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.11.0 +if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.11.1 if NOT "%IncludeSSLSrc%"=="false" set binaries=%binaries% nasm-2.11.06 for %%b in (%binaries%) do ( diff --git a/PCbuild/tcltk.props b/PCbuild/tcltk.props index 1101796bb3604..228efb34d7399 100644 --- a/PCbuild/tcltk.props +++ b/PCbuild/tcltk.props @@ -5,7 +5,7 @@ 8 6 11 - 0 + 1 $(TclMajorVersion) $(TclMinorVersion) $(TclPatchLevel) From webhook-mailer at python.org Thu Nov 4 12:39:41 2021 From: webhook-mailer at python.org (zooba) Date: Thu, 04 Nov 2021 16:39:41 -0000 Subject: [Python-checkins] bpo-45220: Remove invalid include from resource definition files on Windows (GH-29396) Message-ID: https://github.com/python/cpython/commit/fd0c84dc28d00d68e4f43034dc41786a682390fd commit: fd0c84dc28d00d68e4f43034dc41786a682390fd branch: main author: Steve Dower committer: zooba date: 2021-11-04T16:39:36Z summary: bpo-45220: Remove invalid include from resource definition files on Windows (GH-29396) files: M PC/pylauncher.rc M PC/pyshellext.rc M PC/python_exe.rc M PC/python_nt.rc M PC/pythonw_exe.rc M PC/sqlite3.rc M PCbuild/python.props diff --git a/PC/pylauncher.rc b/PC/pylauncher.rc index 92987af7138dd..d21f9b6e9d2ab 100644 --- a/PC/pylauncher.rc +++ b/PC/pylauncher.rc @@ -4,7 +4,6 @@ // Include the manifest file that indicates we support all // current versions of Windows. -#include 1 RT_MANIFEST "python.manifest" #if defined(PY_ICON) diff --git a/PC/pyshellext.rc b/PC/pyshellext.rc index e5924a42dabe2..fc607e97840fb 100644 --- a/PC/pyshellext.rc +++ b/PC/pyshellext.rc @@ -4,7 +4,6 @@ // Include the manifest file that indicates we support all // current versions of Windows. -#include 1 RT_MANIFEST "python.manifest" ///////////////////////////////////////////////////////////////////////////// diff --git a/PC/python_exe.rc b/PC/python_exe.rc index ae0b029b8070a..5eba89962b475 100644 --- a/PC/python_exe.rc +++ b/PC/python_exe.rc @@ -4,7 +4,6 @@ // Include the manifest file that indicates we support all // current versions of Windows. -#include 1 RT_MANIFEST "python.manifest" 1 ICON DISCARDABLE "icons\python.ico" diff --git a/PC/python_nt.rc b/PC/python_nt.rc index b5fb58f26b202..6fd872c1a03cc 100644 --- a/PC/python_nt.rc +++ b/PC/python_nt.rc @@ -4,7 +4,6 @@ // Include the manifest file that indicates we support all // current versions of Windows. -#include 2 RT_MANIFEST "python.manifest" ///////////////////////////////////////////////////////////////////////////// diff --git a/PC/pythonw_exe.rc b/PC/pythonw_exe.rc index 88bf3592e1812..562652be18471 100644 --- a/PC/pythonw_exe.rc +++ b/PC/pythonw_exe.rc @@ -4,7 +4,6 @@ // Include the manifest file that indicates we support all // current versions of Windows. -#include 1 RT_MANIFEST "python.manifest" 1 ICON DISCARDABLE "icons\pythonw.ico" diff --git a/PC/sqlite3.rc b/PC/sqlite3.rc index 84bd87d9d575d..d2c18f8add8b2 100644 --- a/PC/sqlite3.rc +++ b/PC/sqlite3.rc @@ -4,7 +4,6 @@ // Include the manifest file that indicates we support all // current versions of Windows. -#include 2 RT_MANIFEST "python.manifest" ///////////////////////////////////////////////////////////////////////////// diff --git a/PCbuild/python.props b/PCbuild/python.props index 142c12acd7709..b739e417fbaa5 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -107,9 +107,6 @@ <_RegistryVersion Condition="$(_RegistryVersion) != '' and !$(_RegistryVersion.EndsWith('.0'))">$(_RegistryVersion).0 - - <_RegistryVersion Condition="$([System.Version]::Parse($(_RegistryVersion))) >= $([System.Version]::Parse(`10.0.22000.0`))">10.0.19041.0 - 10.0.10586.0 $(_RegistryVersion) From webhook-mailer at python.org Thu Nov 4 13:01:28 2021 From: webhook-mailer at python.org (miss-islington) Date: Thu, 04 Nov 2021 17:01:28 -0000 Subject: [Python-checkins] bpo-45220: Remove invalid include from resource definition files on Windows (GH-29396) Message-ID: https://github.com/python/cpython/commit/1a44d27e6f8a06cb7d56e39be48852f0c3f4502b commit: 1a44d27e6f8a06cb7d56e39be48852f0c3f4502b branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-04T10:01:19-07:00 summary: bpo-45220: Remove invalid include from resource definition files on Windows (GH-29396) (cherry picked from commit fd0c84dc28d00d68e4f43034dc41786a682390fd) Co-authored-by: Steve Dower files: M PC/pylauncher.rc M PC/pyshellext.rc M PC/python_exe.rc M PC/python_nt.rc M PC/pythonw_exe.rc M PC/sqlite3.rc M PCbuild/python.props diff --git a/PC/pylauncher.rc b/PC/pylauncher.rc index 92987af7138dd..d21f9b6e9d2ab 100644 --- a/PC/pylauncher.rc +++ b/PC/pylauncher.rc @@ -4,7 +4,6 @@ // Include the manifest file that indicates we support all // current versions of Windows. -#include 1 RT_MANIFEST "python.manifest" #if defined(PY_ICON) diff --git a/PC/pyshellext.rc b/PC/pyshellext.rc index e5924a42dabe2..fc607e97840fb 100644 --- a/PC/pyshellext.rc +++ b/PC/pyshellext.rc @@ -4,7 +4,6 @@ // Include the manifest file that indicates we support all // current versions of Windows. -#include 1 RT_MANIFEST "python.manifest" ///////////////////////////////////////////////////////////////////////////// diff --git a/PC/python_exe.rc b/PC/python_exe.rc index ae0b029b8070a..5eba89962b475 100644 --- a/PC/python_exe.rc +++ b/PC/python_exe.rc @@ -4,7 +4,6 @@ // Include the manifest file that indicates we support all // current versions of Windows. -#include 1 RT_MANIFEST "python.manifest" 1 ICON DISCARDABLE "icons\python.ico" diff --git a/PC/python_nt.rc b/PC/python_nt.rc index b5fb58f26b202..6fd872c1a03cc 100644 --- a/PC/python_nt.rc +++ b/PC/python_nt.rc @@ -4,7 +4,6 @@ // Include the manifest file that indicates we support all // current versions of Windows. -#include 2 RT_MANIFEST "python.manifest" ///////////////////////////////////////////////////////////////////////////// diff --git a/PC/pythonw_exe.rc b/PC/pythonw_exe.rc index 88bf3592e1812..562652be18471 100644 --- a/PC/pythonw_exe.rc +++ b/PC/pythonw_exe.rc @@ -4,7 +4,6 @@ // Include the manifest file that indicates we support all // current versions of Windows. -#include 1 RT_MANIFEST "python.manifest" 1 ICON DISCARDABLE "icons\pythonw.ico" diff --git a/PC/sqlite3.rc b/PC/sqlite3.rc index 84bd87d9d575d..d2c18f8add8b2 100644 --- a/PC/sqlite3.rc +++ b/PC/sqlite3.rc @@ -4,7 +4,6 @@ // Include the manifest file that indicates we support all // current versions of Windows. -#include 2 RT_MANIFEST "python.manifest" ///////////////////////////////////////////////////////////////////////////// diff --git a/PCbuild/python.props b/PCbuild/python.props index 888de37caaa25..42c67de4afa34 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -107,9 +107,6 @@ <_RegistryVersion Condition="$(_RegistryVersion) != '' and !$(_RegistryVersion.EndsWith('.0'))">$(_RegistryVersion).0 - - <_RegistryVersion Condition="$([System.Version]::Parse($(_RegistryVersion))) >= $([System.Version]::Parse(`10.0.22000.0`))">10.0.19041.0 - 10.0.10586.0 $(_RegistryVersion) From webhook-mailer at python.org Thu Nov 4 13:28:06 2021 From: webhook-mailer at python.org (zooba) Date: Thu, 04 Nov 2021 17:28:06 -0000 Subject: [Python-checkins] bpo-43652: Actually update to Tcl/Tk 8.6.11 on Windows (GH-29397) Message-ID: https://github.com/python/cpython/commit/6340ba7f2c1bef94939dcab0d5babc256ffd7485 commit: 6340ba7f2c1bef94939dcab0d5babc256ffd7485 branch: 3.10 author: Steve Dower committer: zooba date: 2021-11-04T17:27:57Z summary: bpo-43652: Actually update to Tcl/Tk 8.6.11 on Windows (GH-29397) files: A Misc/NEWS.d/next/Windows/2021-11-04-00-41-50.bpo-43652.RnqV7I.rst M PCbuild/get_externals.bat M PCbuild/tcltk.props diff --git a/Misc/NEWS.d/next/Windows/2021-11-04-00-41-50.bpo-43652.RnqV7I.rst b/Misc/NEWS.d/next/Windows/2021-11-04-00-41-50.bpo-43652.RnqV7I.rst new file mode 100644 index 0000000000000..7da8fc79a9dab --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2021-11-04-00-41-50.bpo-43652.RnqV7I.rst @@ -0,0 +1,2 @@ +Update Tcl/Tk to 8.6.11, actually this time. The previous update incorrectly +included 8.6.10. diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index ea85d98e12bbd..53bedf1cd9200 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -55,8 +55,8 @@ set libraries=%libraries% bzip2-1.0.6 if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.3.0 if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1l set libraries=%libraries% sqlite-3.35.5.0 -if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.11.0 -if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.11.0 +if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.11.1 +if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.11.1 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tix-8.4.3.6 set libraries=%libraries% xz-5.2.2 set libraries=%libraries% zlib-1.2.11 @@ -78,7 +78,7 @@ echo.Fetching external binaries... set binaries= if NOT "%IncludeLibffi%"=="false" set binaries=%binaries% libffi-3.3.0 if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.1l -if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.11.0 +if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.11.1 if NOT "%IncludeSSLSrc%"=="false" set binaries=%binaries% nasm-2.11.06 for %%b in (%binaries%) do ( diff --git a/PCbuild/tcltk.props b/PCbuild/tcltk.props index 1101796bb3604..228efb34d7399 100644 --- a/PCbuild/tcltk.props +++ b/PCbuild/tcltk.props @@ -5,7 +5,7 @@ 8 6 11 - 0 + 1 $(TclMajorVersion) $(TclMinorVersion) $(TclPatchLevel) From webhook-mailer at python.org Thu Nov 4 15:09:51 2021 From: webhook-mailer at python.org (ambv) Date: Thu, 04 Nov 2021 19:09:51 -0000 Subject: [Python-checkins] Add generated artifacts in Mac/ to .gitignore; update copyright (GH-29408) Message-ID: https://github.com/python/cpython/commit/3167df16212e27f8aac1e5f39c0644a97b593406 commit: 3167df16212e27f8aac1e5f39c0644a97b593406 branch: main author: ?ukasz Langa committer: ambv date: 2021-11-04T20:09:46+01:00 summary: Add generated artifacts in Mac/ to .gitignore; update copyright (GH-29408) files: M .gitignore M Mac/Resources/framework/Info.plist.in diff --git a/.gitignore b/.gitignore index b2ad76689f12b..98a3d58dcd172 100644 --- a/.gitignore +++ b/.gitignore @@ -61,6 +61,15 @@ Lib/test/data/* !Lib/test/data/README /Makefile /Makefile.pre +Mac/Makefile +Mac/PythonLauncher/Info.plist +Mac/PythonLauncher/Makefile +Mac/PythonLauncher/Python Launcher +Mac/PythonLauncher/Python Launcher.app/* +Mac/Resources/app/Info.plist +Mac/Resources/framework/Info.plist +Mac/pythonw +/*.framework/ Misc/python.pc Misc/python-embed.pc Misc/python-config.sh diff --git a/Mac/Resources/framework/Info.plist.in b/Mac/Resources/framework/Info.plist.in index 0dc2e17156f18..863b45238fe4d 100644 --- a/Mac/Resources/framework/Info.plist.in +++ b/Mac/Resources/framework/Info.plist.in @@ -17,9 +17,9 @@ CFBundlePackageType FMWK CFBundleShortVersionString - %VERSION%, (c) 2001-2019 Python Software Foundation. + %VERSION%, (c) 2001-2021 Python Software Foundation. CFBundleLongVersionString - %VERSION%, (c) 2001-2019 Python Software Foundation. + %VERSION%, (c) 2001-2021 Python Software Foundation. CFBundleSignature ???? CFBundleVersion From webhook-mailer at python.org Thu Nov 4 15:31:48 2021 From: webhook-mailer at python.org (ambv) Date: Thu, 04 Nov 2021 19:31:48 -0000 Subject: [Python-checkins] Add generated artifacts in Mac/ to .gitignore; update copyright (GH-29408) (GH-29410) Message-ID: https://github.com/python/cpython/commit/9a4604bf03b03d4c66d84f63c19d6893cc16392a commit: 9a4604bf03b03d4c66d84f63c19d6893cc16392a branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-04T20:31:39+01:00 summary: Add generated artifacts in Mac/ to .gitignore; update copyright (GH-29408) (GH-29410) (cherry picked from commit 3167df16212e27f8aac1e5f39c0644a97b593406) Co-authored-by: ?ukasz Langa files: M .gitignore M Mac/Resources/framework/Info.plist.in diff --git a/.gitignore b/.gitignore index a96be67962217..d0b608892a87c 100644 --- a/.gitignore +++ b/.gitignore @@ -61,6 +61,15 @@ Lib/test/data/* !Lib/test/data/README /Makefile /Makefile.pre +Mac/Makefile +Mac/PythonLauncher/Info.plist +Mac/PythonLauncher/Makefile +Mac/PythonLauncher/Python Launcher +Mac/PythonLauncher/Python Launcher.app/* +Mac/Resources/app/Info.plist +Mac/Resources/framework/Info.plist +Mac/pythonw +/*.framework/ Misc/python.pc Misc/python-embed.pc Misc/python-config.sh diff --git a/Mac/Resources/framework/Info.plist.in b/Mac/Resources/framework/Info.plist.in index 0dc2e17156f18..863b45238fe4d 100644 --- a/Mac/Resources/framework/Info.plist.in +++ b/Mac/Resources/framework/Info.plist.in @@ -17,9 +17,9 @@ CFBundlePackageType FMWK CFBundleShortVersionString - %VERSION%, (c) 2001-2019 Python Software Foundation. + %VERSION%, (c) 2001-2021 Python Software Foundation. CFBundleLongVersionString - %VERSION%, (c) 2001-2019 Python Software Foundation. + %VERSION%, (c) 2001-2021 Python Software Foundation. CFBundleSignature ???? CFBundleVersion From webhook-mailer at python.org Thu Nov 4 15:32:08 2021 From: webhook-mailer at python.org (ambv) Date: Thu, 04 Nov 2021 19:32:08 -0000 Subject: [Python-checkins] Add generated artifacts in Mac/ to .gitignore; update copyright (GH-29408) (GH-29409) Message-ID: https://github.com/python/cpython/commit/d729c8097910fc8c6d15927ab6176b0bae12674a commit: d729c8097910fc8c6d15927ab6176b0bae12674a branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-04T20:32:03+01:00 summary: Add generated artifacts in Mac/ to .gitignore; update copyright (GH-29408) (GH-29409) (cherry picked from commit 3167df16212e27f8aac1e5f39c0644a97b593406) Co-authored-by: ?ukasz Langa files: M .gitignore M Mac/Resources/framework/Info.plist.in diff --git a/.gitignore b/.gitignore index a96be67962217..d0b608892a87c 100644 --- a/.gitignore +++ b/.gitignore @@ -61,6 +61,15 @@ Lib/test/data/* !Lib/test/data/README /Makefile /Makefile.pre +Mac/Makefile +Mac/PythonLauncher/Info.plist +Mac/PythonLauncher/Makefile +Mac/PythonLauncher/Python Launcher +Mac/PythonLauncher/Python Launcher.app/* +Mac/Resources/app/Info.plist +Mac/Resources/framework/Info.plist +Mac/pythonw +/*.framework/ Misc/python.pc Misc/python-embed.pc Misc/python-config.sh diff --git a/Mac/Resources/framework/Info.plist.in b/Mac/Resources/framework/Info.plist.in index 0dc2e17156f18..863b45238fe4d 100644 --- a/Mac/Resources/framework/Info.plist.in +++ b/Mac/Resources/framework/Info.plist.in @@ -17,9 +17,9 @@ CFBundlePackageType FMWK CFBundleShortVersionString - %VERSION%, (c) 2001-2019 Python Software Foundation. + %VERSION%, (c) 2001-2021 Python Software Foundation. CFBundleLongVersionString - %VERSION%, (c) 2001-2019 Python Software Foundation. + %VERSION%, (c) 2001-2021 Python Software Foundation. CFBundleSignature ???? CFBundleVersion From webhook-mailer at python.org Thu Nov 4 15:34:22 2021 From: webhook-mailer at python.org (ambv) Date: Thu, 04 Nov 2021 19:34:22 -0000 Subject: [Python-checkins] [3.9] bpo-45678: Fix `singledispatchmethod` `classmethod`/`staticmethod` bug (GH-29394) Message-ID: https://github.com/python/cpython/commit/effb72fa0f6f8f8ec92687fc6a29d63bbdb7e98d commit: effb72fa0f6f8f8ec92687fc6a29d63bbdb7e98d branch: 3.9 author: Alex Waygood committer: ambv date: 2021-11-04T20:34:14+01:00 summary: [3.9] bpo-45678: Fix `singledispatchmethod` `classmethod`/`staticmethod` bug (GH-29394) This PR fixes a bug in the 3.9 branch where ``functools.singledispatchmethod`` did not properly wrap attributes such as ``__name__``, ``__doc__`` and ``__module__`` of the target method. It also backports tests already merged into the 3.11 and 3.10 branches in #29328 and #29390. Co-authored-by: ?ukasz Langa files: A Misc/NEWS.d/next/Library/2021-11-03-17-28-43.bpo-45678.Zj_O8j.rst M Lib/functools.py M Lib/test/test_functools.py diff --git a/Lib/functools.py b/Lib/functools.py index 5054e281ad281..1a290e1c02461 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -901,6 +901,13 @@ def __init__(self, func): self.dispatcher = singledispatch(func) self.func = func + # bpo-45678: special-casing for classmethod/staticmethod in Python <=3.9, + # as functools.update_wrapper doesn't work properly in singledispatchmethod.__get__ + # if it is applied to an unbound classmethod/staticmethod + if isinstance(func, (staticmethod, classmethod)): + self._wrapped_func = func.__func__ + else: + self._wrapped_func = func def register(self, cls, method=None): """generic_method.register(cls, func) -> func @@ -921,7 +928,7 @@ def _method(*args, **kwargs): _method.__isabstractmethod__ = self.__isabstractmethod__ _method.register = self.register - update_wrapper(_method, self.func) + update_wrapper(_method, self._wrapped_func) return _method @property diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 96e93ed8eab34..b2a7e5a88b422 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -2401,7 +2401,7 @@ def _(cls, arg): self.assertEqual(A.t(0.0).arg, "base") def test_abstractmethod_register(self): - class Abstract(abc.ABCMeta): + class Abstract(metaclass=abc.ABCMeta): @functools.singledispatchmethod @abc.abstractmethod @@ -2409,6 +2409,10 @@ def add(self, x, y): pass self.assertTrue(Abstract.add.__isabstractmethod__) + self.assertTrue(Abstract.__dict__['add'].__isabstractmethod__) + + with self.assertRaises(TypeError): + Abstract() def test_type_ann_register(self): class A: @@ -2469,6 +2473,141 @@ def _(cls, arg: str): self.assertEqual(A.t('').arg, "str") self.assertEqual(A.t(0.0).arg, "base") + def test_method_wrapping_attributes(self): + class A: + @functools.singledispatchmethod + def func(self, arg: int) -> str: + """My function docstring""" + return str(arg) + @functools.singledispatchmethod + @classmethod + def cls_func(cls, arg: int) -> str: + """My function docstring""" + return str(arg) + @functools.singledispatchmethod + @staticmethod + def static_func(arg: int) -> str: + """My function docstring""" + return str(arg) + + for meth in ( + A.func, + A().func, + A.cls_func, + A().cls_func, + A.static_func, + A().static_func + ): + with self.subTest(meth=meth): + self.assertEqual(meth.__doc__, 'My function docstring') + self.assertEqual(meth.__annotations__['arg'], int) + + self.assertEqual(A.func.__name__, 'func') + self.assertEqual(A().func.__name__, 'func') + self.assertEqual(A.cls_func.__name__, 'cls_func') + self.assertEqual(A().cls_func.__name__, 'cls_func') + self.assertEqual(A.static_func.__name__, 'static_func') + self.assertEqual(A().static_func.__name__, 'static_func') + + def test_double_wrapped_methods(self): + def classmethod_friendly_decorator(func): + wrapped = func.__func__ + @classmethod + @functools.wraps(wrapped) + def wrapper(*args, **kwargs): + return wrapped(*args, **kwargs) + return wrapper + + class WithoutSingleDispatch: + @classmethod + @contextlib.contextmanager + def cls_context_manager(cls, arg: int) -> str: + try: + yield str(arg) + finally: + return 'Done' + + @classmethod_friendly_decorator + @classmethod + def decorated_classmethod(cls, arg: int) -> str: + return str(arg) + + class WithSingleDispatch: + @functools.singledispatchmethod + @classmethod + @contextlib.contextmanager + def cls_context_manager(cls, arg: int) -> str: + """My function docstring""" + try: + yield str(arg) + finally: + return 'Done' + + @functools.singledispatchmethod + @classmethod_friendly_decorator + @classmethod + def decorated_classmethod(cls, arg: int) -> str: + """My function docstring""" + return str(arg) + + # These are sanity checks + # to test the test itself is working as expected + with WithoutSingleDispatch.cls_context_manager(5) as foo: + without_single_dispatch_foo = foo + + with WithSingleDispatch.cls_context_manager(5) as foo: + single_dispatch_foo = foo + + self.assertEqual(without_single_dispatch_foo, single_dispatch_foo) + self.assertEqual(single_dispatch_foo, '5') + + self.assertEqual( + WithoutSingleDispatch.decorated_classmethod(5), + WithSingleDispatch.decorated_classmethod(5) + ) + + self.assertEqual(WithSingleDispatch.decorated_classmethod(5), '5') + + # Behavioural checks now follow + for method_name in ('cls_context_manager', 'decorated_classmethod'): + with self.subTest(method=method_name): + self.assertEqual( + getattr(WithSingleDispatch, method_name).__name__, + getattr(WithoutSingleDispatch, method_name).__name__ + ) + + self.assertEqual( + getattr(WithSingleDispatch(), method_name).__name__, + getattr(WithoutSingleDispatch(), method_name).__name__ + ) + + for meth in ( + WithSingleDispatch.cls_context_manager, + WithSingleDispatch().cls_context_manager, + WithSingleDispatch.decorated_classmethod, + WithSingleDispatch().decorated_classmethod + ): + with self.subTest(meth=meth): + self.assertEqual(meth.__doc__, 'My function docstring') + self.assertEqual(meth.__annotations__['arg'], int) + + self.assertEqual( + WithSingleDispatch.cls_context_manager.__name__, + 'cls_context_manager' + ) + self.assertEqual( + WithSingleDispatch().cls_context_manager.__name__, + 'cls_context_manager' + ) + self.assertEqual( + WithSingleDispatch.decorated_classmethod.__name__, + 'decorated_classmethod' + ) + self.assertEqual( + WithSingleDispatch().decorated_classmethod.__name__, + 'decorated_classmethod' + ) + def test_invalid_registrations(self): msg_prefix = "Invalid first argument to `register()`: " msg_suffix = ( diff --git a/Misc/NEWS.d/next/Library/2021-11-03-17-28-43.bpo-45678.Zj_O8j.rst b/Misc/NEWS.d/next/Library/2021-11-03-17-28-43.bpo-45678.Zj_O8j.rst new file mode 100644 index 0000000000000..f00707ca0099e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-03-17-28-43.bpo-45678.Zj_O8j.rst @@ -0,0 +1,2 @@ +Fix bug in Python 3.9 that meant ``functools.singledispatchmethod`` failed +to properly wrap the attributes of the target method. Patch by Alex Waygood. From webhook-mailer at python.org Thu Nov 4 16:17:17 2021 From: webhook-mailer at python.org (ambv) Date: Thu, 04 Nov 2021 20:17:17 -0000 Subject: [Python-checkins] bpo-45220: Remove invalid include from resource definition files on Windows (GH-29396) (GH-29406) Message-ID: https://github.com/python/cpython/commit/c0f3281d6ca5c59d4a11698364463d968b9ddd3c commit: c0f3281d6ca5c59d4a11698364463d968b9ddd3c branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-04T21:17:08+01:00 summary: bpo-45220: Remove invalid include from resource definition files on Windows (GH-29396) (GH-29406) (cherry picked from commit fd0c84dc28d00d68e4f43034dc41786a682390fd) Co-authored-by: Steve Dower files: M PC/pylauncher.rc M PC/pyshellext.rc M PC/python_exe.rc M PC/python_nt.rc M PC/pythonw_exe.rc M PC/sqlite3.rc M PCbuild/python.props diff --git a/PC/pylauncher.rc b/PC/pylauncher.rc index 92987af7138dd..d21f9b6e9d2ab 100644 --- a/PC/pylauncher.rc +++ b/PC/pylauncher.rc @@ -4,7 +4,6 @@ // Include the manifest file that indicates we support all // current versions of Windows. -#include 1 RT_MANIFEST "python.manifest" #if defined(PY_ICON) diff --git a/PC/pyshellext.rc b/PC/pyshellext.rc index e5924a42dabe2..fc607e97840fb 100644 --- a/PC/pyshellext.rc +++ b/PC/pyshellext.rc @@ -4,7 +4,6 @@ // Include the manifest file that indicates we support all // current versions of Windows. -#include 1 RT_MANIFEST "python.manifest" ///////////////////////////////////////////////////////////////////////////// diff --git a/PC/python_exe.rc b/PC/python_exe.rc index ae0b029b8070a..5eba89962b475 100644 --- a/PC/python_exe.rc +++ b/PC/python_exe.rc @@ -4,7 +4,6 @@ // Include the manifest file that indicates we support all // current versions of Windows. -#include 1 RT_MANIFEST "python.manifest" 1 ICON DISCARDABLE "icons\python.ico" diff --git a/PC/python_nt.rc b/PC/python_nt.rc index b5fb58f26b202..6fd872c1a03cc 100644 --- a/PC/python_nt.rc +++ b/PC/python_nt.rc @@ -4,7 +4,6 @@ // Include the manifest file that indicates we support all // current versions of Windows. -#include 2 RT_MANIFEST "python.manifest" ///////////////////////////////////////////////////////////////////////////// diff --git a/PC/pythonw_exe.rc b/PC/pythonw_exe.rc index 88bf3592e1812..562652be18471 100644 --- a/PC/pythonw_exe.rc +++ b/PC/pythonw_exe.rc @@ -4,7 +4,6 @@ // Include the manifest file that indicates we support all // current versions of Windows. -#include 1 RT_MANIFEST "python.manifest" 1 ICON DISCARDABLE "icons\pythonw.ico" diff --git a/PC/sqlite3.rc b/PC/sqlite3.rc index 84bd87d9d575d..d2c18f8add8b2 100644 --- a/PC/sqlite3.rc +++ b/PC/sqlite3.rc @@ -4,7 +4,6 @@ // Include the manifest file that indicates we support all // current versions of Windows. -#include 2 RT_MANIFEST "python.manifest" ///////////////////////////////////////////////////////////////////////////// diff --git a/PCbuild/python.props b/PCbuild/python.props index 888de37caaa25..42c67de4afa34 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -107,9 +107,6 @@ <_RegistryVersion Condition="$(_RegistryVersion) != '' and !$(_RegistryVersion.EndsWith('.0'))">$(_RegistryVersion).0 - - <_RegistryVersion Condition="$([System.Version]::Parse($(_RegistryVersion))) >= $([System.Version]::Parse(`10.0.22000.0`))">10.0.19041.0 - 10.0.10586.0 $(_RegistryVersion) From webhook-mailer at python.org Thu Nov 4 16:20:26 2021 From: webhook-mailer at python.org (ambv) Date: Thu, 04 Nov 2021 20:20:26 -0000 Subject: [Python-checkins] bpo-30570: Use Py_EnterRecursiveCall() in issubclass() (GH-29048) (GH-29178) Message-ID: https://github.com/python/cpython/commit/1e29dce1138a39e095ba47ab4c1e445fd08716e2 commit: 1e29dce1138a39e095ba47ab4c1e445fd08716e2 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-04T21:20:21+01:00 summary: bpo-30570: Use Py_EnterRecursiveCall() in issubclass() (GH-29048) (GH-29178) * Use Py_EnterRecursiveCall() in issubclass() Reviewed-by: Gregory P. Smith [Google] (cherry picked from commit 423fa1c1817abfa8c3d1bc308ddbbd8f28b69d68) Co-authored-by: Dennis Sweeney <36520290+sweeneyde at users.noreply.github.com> files: A Misc/NEWS.d/next/Core and Builtins/2021-10-19-01-04-08.bpo-30570._G30Ms.rst M Lib/test/test_isinstance.py M Objects/abstract.c diff --git a/Lib/test/test_isinstance.py b/Lib/test/test_isinstance.py index 31b38996930cc..34082a1a4b361 100644 --- a/Lib/test/test_isinstance.py +++ b/Lib/test/test_isinstance.py @@ -281,6 +281,36 @@ def __bases__(self): self.assertRaises(RecursionError, issubclass, int, X()) self.assertRaises(RecursionError, isinstance, 1, X()) + def test_infinite_recursion_via_bases_tuple(self): + """Regression test for bpo-30570.""" + class Failure(object): + def __getattr__(self, attr): + return (self, None) + + with self.assertRaises(RecursionError): + issubclass(Failure(), int) + + def test_infinite_cycle_in_bases(self): + """Regression test for bpo-30570.""" + class X: + @property + def __bases__(self): + return (self, self, self) + self.assertRaises(RecursionError, issubclass, X(), int) + + def test_infinitely_many_bases(self): + """Regression test for bpo-30570.""" + class X: + def __getattr__(self, attr): + self.assertEqual(attr, "__bases__") + class A: + pass + class B: + pass + A.__getattr__ = B.__getattr__ = X.__getattr__ + return (A(), B()) + self.assertRaises(RecursionError, issubclass, X(), int) + def blowstack(fxn, arg, compare_to): # Make sure that calling isinstance with a deeply nested tuple for its diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-19-01-04-08.bpo-30570._G30Ms.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-19-01-04-08.bpo-30570._G30Ms.rst new file mode 100644 index 0000000000000..d9ab60cd08f56 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-10-19-01-04-08.bpo-30570._G30Ms.rst @@ -0,0 +1 @@ +Fixed a crash in ``issubclass()`` from infinite recursion when searching pathological ``__bases__`` tuples. \ No newline at end of file diff --git a/Objects/abstract.c b/Objects/abstract.c index 1922619ad85db..a5cbb12ff87c6 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2417,14 +2417,22 @@ abstract_issubclass(PyObject *derived, PyObject *cls) derived = PyTuple_GET_ITEM(bases, 0); continue; } - for (i = 0; i < n; i++) { - r = abstract_issubclass(PyTuple_GET_ITEM(bases, i), cls); - if (r != 0) - break; - } + break; + } + assert(n >= 2); + if (Py_EnterRecursiveCall(" in __issubclass__")) { Py_DECREF(bases); - return r; + return -1; } + for (i = 0; i < n; i++) { + r = abstract_issubclass(PyTuple_GET_ITEM(bases, i), cls); + if (r != 0) { + break; + } + } + Py_LeaveRecursiveCall(); + Py_DECREF(bases); + return r; } static int From webhook-mailer at python.org Thu Nov 4 16:21:33 2021 From: webhook-mailer at python.org (ambv) Date: Thu, 04 Nov 2021 20:21:33 -0000 Subject: [Python-checkins] bpo-44828: Avoid leaving a zombie Save panel (GH-29372) Message-ID: https://github.com/python/cpython/commit/10b0c671580a2f8dd013b6345c1dc9789d5bd95c commit: 10b0c671580a2f8dd013b6345c1dc9789d5bd95c branch: 3.8 author: Ned Deily committer: ambv date: 2021-11-04T21:21:25+01:00 summary: bpo-44828: Avoid leaving a zombie Save panel (GH-29372) Patch by Marc Culler of the Tk project. files: M Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch diff --git a/Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch b/Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch index 1d06329fff3fb..059149250f8c8 100644 --- a/Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch +++ b/Mac/BuildScript/bpo-44828-filedialog-crash-monterey.patch @@ -18,7 +18,7 @@ if (returnCode >= NSAlertFirstButtonReturn) { Tcl_Obj *resultObj = Tcl_NewStringObj(alertButtonStrings[ -@@ -350,49 +350,41 @@ +@@ -350,49 +350,42 @@ FilePanelCallbackInfo *callbackInfo) { NSInteger modalReturnCode; @@ -85,6 +85,7 @@ - [panel close]; + returnCode:modalReturnCode + contextInfo:callbackInfo ]; ++ [parent endSheet:panel]; } + } else { + modalReturnCode = [panel runModal]; From webhook-mailer at python.org Thu Nov 4 16:45:15 2021 From: webhook-mailer at python.org (miss-islington) Date: Thu, 04 Nov 2021 20:45:15 -0000 Subject: [Python-checkins] bpo-30570: Fix segfault on buildbots caused by stack overflow from recursion in tests (GH-29258) Message-ID: https://github.com/python/cpython/commit/1f3ae5c1ca5a8e7696bad414c1de38e0f5f1e2c3 commit: 1f3ae5c1ca5a8e7696bad414c1de38e0f5f1e2c3 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-04T13:45:05-07:00 summary: bpo-30570: Fix segfault on buildbots caused by stack overflow from recursion in tests (GH-29258) * Don't stackoveflow on debug builds * Also catch the pickletester case (cherry picked from commit d56375a0dd4cee162081b173310298a3d32af293) Co-authored-by: Dennis Sweeney <36520290+sweeneyde at users.noreply.github.com> files: M Lib/test/pickletester.py M Lib/test/test_isinstance.py diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py index 3e2c781caa11a..f13d42f664880 100644 --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -2383,7 +2383,8 @@ def test_bad_getattr(self): # Issue #3514: crash when there is an infinite loop in __getattr__ x = BadGetattr() for proto in protocols: - self.assertRaises(RuntimeError, self.dumps, x, proto) + with support.infinite_recursion(): + self.assertRaises(RuntimeError, self.dumps, x, proto) def test_reduce_bad_iterator(self): # Issue4176: crash when 4th and 5th items of __reduce__() diff --git a/Lib/test/test_isinstance.py b/Lib/test/test_isinstance.py index 6ab44be9a26ba..9d37cff990338 100644 --- a/Lib/test/test_isinstance.py +++ b/Lib/test/test_isinstance.py @@ -5,6 +5,7 @@ import unittest import sys import typing +from test import support @@ -266,12 +267,14 @@ def test_subclass_tuple(self): def test_subclass_recursion_limit(self): # make sure that issubclass raises RecursionError before the C stack is # blown - self.assertRaises(RecursionError, blowstack, issubclass, str, str) + with support.infinite_recursion(): + self.assertRaises(RecursionError, blowstack, issubclass, str, str) def test_isinstance_recursion_limit(self): # make sure that issubclass raises RecursionError before the C stack is # blown - self.assertRaises(RecursionError, blowstack, isinstance, '', str) + with support.infinite_recursion(): + self.assertRaises(RecursionError, blowstack, isinstance, '', str) def test_subclass_with_union(self): self.assertTrue(issubclass(int, int | float | int)) @@ -308,19 +311,19 @@ class X: @property def __bases__(self): return self.__bases__ - - self.assertRaises(RecursionError, issubclass, X(), int) - self.assertRaises(RecursionError, issubclass, int, X()) - self.assertRaises(RecursionError, isinstance, 1, X()) + with support.infinite_recursion(): + self.assertRaises(RecursionError, issubclass, X(), int) + self.assertRaises(RecursionError, issubclass, int, X()) + self.assertRaises(RecursionError, isinstance, 1, X()) def test_infinite_recursion_via_bases_tuple(self): """Regression test for bpo-30570.""" class Failure(object): def __getattr__(self, attr): return (self, None) - - with self.assertRaises(RecursionError): - issubclass(Failure(), int) + with support.infinite_recursion(): + with self.assertRaises(RecursionError): + issubclass(Failure(), int) def test_infinite_cycle_in_bases(self): """Regression test for bpo-30570.""" @@ -328,7 +331,8 @@ class X: @property def __bases__(self): return (self, self, self) - self.assertRaises(RecursionError, issubclass, X(), int) + with support.infinite_recursion(): + self.assertRaises(RecursionError, issubclass, X(), int) def test_infinitely_many_bases(self): """Regression test for bpo-30570.""" @@ -341,7 +345,8 @@ class B: pass A.__getattr__ = B.__getattr__ = X.__getattr__ return (A(), B()) - self.assertRaises(RecursionError, issubclass, X(), int) + with support.infinite_recursion(): + self.assertRaises(RecursionError, issubclass, X(), int) def blowstack(fxn, arg, compare_to): From webhook-mailer at python.org Thu Nov 4 16:52:39 2021 From: webhook-mailer at python.org (ambv) Date: Thu, 04 Nov 2021 20:52:39 -0000 Subject: [Python-checkins] [3.9] bpo-30570: Fix segfault on buildbots caused by stack overflow from recursion in tests (GH-29258) (GH-29415) Message-ID: https://github.com/python/cpython/commit/f701237db2611140e578cebbdfef91ae4714af4e commit: f701237db2611140e578cebbdfef91ae4714af4e branch: 3.9 author: ?ukasz Langa committer: ambv date: 2021-11-04T21:52:26+01:00 summary: [3.9] bpo-30570: Fix segfault on buildbots caused by stack overflow from recursion in tests (GH-29258) (GH-29415) (cherry picked from commit d56375a0dd4cee162081b173310298a3d32af293) Co-authored-by: Dennis Sweeney <36520290+sweeneyde at users.noreply.github.com> files: M Lib/test/pickletester.py M Lib/test/test_isinstance.py diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py index e86847c5f13d8..4684c9e68994b 100644 --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -2371,7 +2371,8 @@ def test_bad_getattr(self): # Issue #3514: crash when there is an infinite loop in __getattr__ x = BadGetattr() for proto in protocols: - self.assertRaises(RuntimeError, self.dumps, x, proto) + with support.infinite_recursion(): + self.assertRaises(RuntimeError, self.dumps, x, proto) def test_reduce_bad_iterator(self): # Issue4176: crash when 4th and 5th items of __reduce__() diff --git a/Lib/test/test_isinstance.py b/Lib/test/test_isinstance.py index 34082a1a4b361..70dbe7166fd57 100644 --- a/Lib/test/test_isinstance.py +++ b/Lib/test/test_isinstance.py @@ -4,6 +4,7 @@ import unittest import sys +from test import support @@ -244,12 +245,14 @@ def test_subclass_tuple(self): def test_subclass_recursion_limit(self): # make sure that issubclass raises RecursionError before the C stack is # blown - self.assertRaises(RecursionError, blowstack, issubclass, str, str) + with support.infinite_recursion(): + self.assertRaises(RecursionError, blowstack, issubclass, str, str) def test_isinstance_recursion_limit(self): # make sure that issubclass raises RecursionError before the C stack is # blown - self.assertRaises(RecursionError, blowstack, isinstance, '', str) + with support.infinite_recursion(): + self.assertRaises(RecursionError, blowstack, isinstance, '', str) def test_issubclass_refcount_handling(self): # bpo-39382: abstract_issubclass() didn't hold item reference while @@ -276,19 +279,19 @@ class X: @property def __bases__(self): return self.__bases__ - - self.assertRaises(RecursionError, issubclass, X(), int) - self.assertRaises(RecursionError, issubclass, int, X()) - self.assertRaises(RecursionError, isinstance, 1, X()) + with support.infinite_recursion(): + self.assertRaises(RecursionError, issubclass, X(), int) + self.assertRaises(RecursionError, issubclass, int, X()) + self.assertRaises(RecursionError, isinstance, 1, X()) def test_infinite_recursion_via_bases_tuple(self): """Regression test for bpo-30570.""" class Failure(object): def __getattr__(self, attr): return (self, None) - - with self.assertRaises(RecursionError): - issubclass(Failure(), int) + with support.infinite_recursion(): + with self.assertRaises(RecursionError): + issubclass(Failure(), int) def test_infinite_cycle_in_bases(self): """Regression test for bpo-30570.""" @@ -296,7 +299,8 @@ class X: @property def __bases__(self): return (self, self, self) - self.assertRaises(RecursionError, issubclass, X(), int) + with support.infinite_recursion(): + self.assertRaises(RecursionError, issubclass, X(), int) def test_infinitely_many_bases(self): """Regression test for bpo-30570.""" @@ -309,7 +313,8 @@ class B: pass A.__getattr__ = B.__getattr__ = X.__getattr__ return (A(), B()) - self.assertRaises(RecursionError, issubclass, X(), int) + with support.infinite_recursion(): + self.assertRaises(RecursionError, issubclass, X(), int) def blowstack(fxn, arg, compare_to): From webhook-mailer at python.org Thu Nov 4 19:19:37 2021 From: webhook-mailer at python.org (ambv) Date: Thu, 04 Nov 2021 23:19:37 -0000 Subject: [Python-checkins] [3.10] bpo-44257: fix "assigment_expr" typo + regenerate the grammar, and remove unused imports (GH-29393) (GH-29395) Message-ID: https://github.com/python/cpython/commit/0e34a5918c74c3cc2284cd77a2eba4108b0d6fb0 commit: 0e34a5918c74c3cc2284cd77a2eba4108b0d6fb0 branch: 3.10 author: Pablo Galindo Salgado committer: ambv date: 2021-11-05T00:19:27+01:00 summary: [3.10] bpo-44257: fix "assigment_expr" typo + regenerate the grammar, and remove unused imports (GH-29393) (GH-29395) Co-authored-by: Wim Glenn . (cherry picked from commit 762173c6709f5cf3b59cbbe47d4e6fafbfe7ec2a) Co-authored-by: wim glenn files: M Grammar/python.gram M Parser/parser.c diff --git a/Grammar/python.gram b/Grammar/python.gram index 76c0b4e67ec05..24f5fb43f7870 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -512,11 +512,11 @@ star_named_expression[expr_ty]: | named_expression -assigment_expression[expr_ty]: +assignment_expression[expr_ty]: | a=NAME ':=' ~ b=expression { _PyAST_NamedExpr(CHECK(expr_ty, _PyPegen_set_expr_context(p, a, Store)), b, EXTRA) } named_expression[expr_ty]: - | assigment_expression + | assignment_expression | invalid_named_expression | expression !':=' @@ -708,7 +708,7 @@ group[expr_ty]: | '(' a=(yield_expr | named_expression) ')' { a } | invalid_group genexp[expr_ty]: - | '(' a=( assigment_expression | expression !':=') b=for_if_clauses ')' { _PyAST_GeneratorExp(a, b, EXTRA) } + | '(' a=( assignment_expression | expression !':=') b=for_if_clauses ')' { _PyAST_GeneratorExp(a, b, EXTRA) } | invalid_comprehension set[expr_ty]: '{' a=star_named_expressions '}' { _PyAST_Set(a, EXTRA) } setcomp[expr_ty]: @@ -747,7 +747,7 @@ arguments[expr_ty] (memo): | a=args [','] &')' { a } | invalid_arguments args[expr_ty]: - | a[asdl_expr_seq*]=','.(starred_expression | ( assigment_expression | expression !':=') !'=')+ b=[',' k=kwargs {k}] { + | a[asdl_expr_seq*]=','.(starred_expression | ( assignment_expression | expression !':=') !'=')+ b=[',' k=kwargs {k}] { _PyPegen_collect_call_seqs(p, a, b, EXTRA) } | a=kwargs { _PyAST_Call(_PyPegen_dummy_name(p), CHECK_NULL_ALLOWED(asdl_expr_seq*, _PyPegen_seq_extract_starred_exprs(p, a)), diff --git a/Parser/parser.c b/Parser/parser.c index eccf104d679a8..fc0347135ff3f 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -170,7 +170,7 @@ static char *soft_keywords[] = { #define star_expression_type 1096 #define star_named_expressions_type 1097 #define star_named_expression_type 1098 -#define assigment_expression_type 1099 +#define assignment_expression_type 1099 #define named_expression_type 1100 #define annotated_rhs_type 1101 #define expressions_type 1102 @@ -598,7 +598,7 @@ static expr_ty star_expressions_rule(Parser *p); static expr_ty star_expression_rule(Parser *p); static asdl_expr_seq* star_named_expressions_rule(Parser *p); static expr_ty star_named_expression_rule(Parser *p); -static expr_ty assigment_expression_rule(Parser *p); +static expr_ty assignment_expression_rule(Parser *p); static expr_ty named_expression_rule(Parser *p); static expr_ty annotated_rhs_rule(Parser *p); static expr_ty expressions_rule(Parser *p); @@ -10210,9 +10210,9 @@ star_named_expression_rule(Parser *p) return _res; } -// assigment_expression: NAME ':=' ~ expression +// assignment_expression: NAME ':=' ~ expression static expr_ty -assigment_expression_rule(Parser *p) +assignment_expression_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -10235,7 +10235,7 @@ assigment_expression_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> assigment_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME ':=' ~ expression")); + D(fprintf(stderr, "%*c> assignment_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME ':=' ~ expression")); int _cut_var = 0; Token * _literal; expr_ty a; @@ -10250,7 +10250,7 @@ assigment_expression_rule(Parser *p) (b = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ assigment_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME ':=' ~ expression")); + D(fprintf(stderr, "%*c+ assignment_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME ':=' ~ expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { D(p->level--); @@ -10269,7 +10269,7 @@ assigment_expression_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s assigment_expression[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s assignment_expression[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME ':=' ~ expression")); if (_cut_var) { D(p->level--); @@ -10282,7 +10282,7 @@ assigment_expression_rule(Parser *p) return _res; } -// named_expression: assigment_expression | invalid_named_expression | expression !':=' +// named_expression: assignment_expression | invalid_named_expression | expression !':=' static expr_ty named_expression_rule(Parser *p) { @@ -10293,24 +10293,24 @@ named_expression_rule(Parser *p) } expr_ty _res = NULL; int _mark = p->mark; - { // assigment_expression + { // assignment_expression if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assigment_expression")); - expr_ty assigment_expression_var; + D(fprintf(stderr, "%*c> named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + expr_ty assignment_expression_var; if ( - (assigment_expression_var = assigment_expression_rule(p)) // assigment_expression + (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression ) { - D(fprintf(stderr, "%*c+ named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assigment_expression")); - _res = assigment_expression_var; + D(fprintf(stderr, "%*c+ named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + _res = assignment_expression_var; goto done; } p->mark = _mark; D(fprintf(stderr, "%*c%s named_expression[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assigment_expression")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); } if (p->call_invalid_rules) { // invalid_named_expression if (p->error_indicator) { @@ -14919,7 +14919,7 @@ group_rule(Parser *p) } // genexp: -// | '(' (assigment_expression | expression !':=') for_if_clauses ')' +// | '(' (assignment_expression | expression !':=') for_if_clauses ')' // | invalid_comprehension static expr_ty genexp_rule(Parser *p) @@ -14940,12 +14940,12 @@ genexp_rule(Parser *p) UNUSED(_start_lineno); // Only used by EXTRA macro int _start_col_offset = p->tokens[_mark]->col_offset; UNUSED(_start_col_offset); // Only used by EXTRA macro - { // '(' (assigment_expression | expression !':=') for_if_clauses ')' + { // '(' (assignment_expression | expression !':=') for_if_clauses ')' if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> genexp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' (assigment_expression | expression !':=') for_if_clauses ')'")); + D(fprintf(stderr, "%*c> genexp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' (assignment_expression | expression !':=') for_if_clauses ')'")); Token * _literal; Token * _literal_1; void *a; @@ -14953,14 +14953,14 @@ genexp_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (a = _tmp_117_rule(p)) // assigment_expression | expression !':=' + (a = _tmp_117_rule(p)) // assignment_expression | expression !':=' && (b = for_if_clauses_rule(p)) // for_if_clauses && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ genexp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' (assigment_expression | expression !':=') for_if_clauses ')'")); + D(fprintf(stderr, "%*c+ genexp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' (assignment_expression | expression !':=') for_if_clauses ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { D(p->level--); @@ -14980,7 +14980,7 @@ genexp_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s genexp[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' (assigment_expression | expression !':=') for_if_clauses ')'")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' (assignment_expression | expression !':=') for_if_clauses ')'")); } if (p->call_invalid_rules) { // invalid_comprehension if (p->error_indicator) { @@ -15833,7 +15833,7 @@ arguments_rule(Parser *p) } // args: -// | ','.(starred_expression | (assigment_expression | expression !':=') !'=')+ [',' kwargs] +// | ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs] // | kwargs static expr_ty args_rule(Parser *p) @@ -15854,21 +15854,21 @@ args_rule(Parser *p) UNUSED(_start_lineno); // Only used by EXTRA macro int _start_col_offset = p->tokens[_mark]->col_offset; UNUSED(_start_col_offset); // Only used by EXTRA macro - { // ','.(starred_expression | (assigment_expression | expression !':=') !'=')+ [',' kwargs] + { // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs] if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> args[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assigment_expression | expression !':=') !'=')+ [',' kwargs]")); + D(fprintf(stderr, "%*c> args[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs]")); asdl_expr_seq* a; void *b; if ( - (a = (asdl_expr_seq*)_gather_123_rule(p)) // ','.(starred_expression | (assigment_expression | expression !':=') !'=')+ + (a = (asdl_expr_seq*)_gather_123_rule(p)) // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ && (b = _tmp_125_rule(p), !p->error_indicator) // [',' kwargs] ) { - D(fprintf(stderr, "%*c+ args[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assigment_expression | expression !':=') !'=')+ [',' kwargs]")); + D(fprintf(stderr, "%*c+ args[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { D(p->level--); @@ -15888,7 +15888,7 @@ args_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s args[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','.(starred_expression | (assigment_expression | expression !':=') !'=')+ [',' kwargs]")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs]")); } { // kwargs if (p->error_indicator) { @@ -28292,7 +28292,7 @@ _tmp_116_rule(Parser *p) return _res; } -// _tmp_117: assigment_expression | expression !':=' +// _tmp_117: assignment_expression | expression !':=' static void * _tmp_117_rule(Parser *p) { @@ -28303,24 +28303,24 @@ _tmp_117_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // assigment_expression + { // assignment_expression if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assigment_expression")); - expr_ty assigment_expression_var; + D(fprintf(stderr, "%*c> _tmp_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + expr_ty assignment_expression_var; if ( - (assigment_expression_var = assigment_expression_rule(p)) // assigment_expression + (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression ) { - D(fprintf(stderr, "%*c+ _tmp_117[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assigment_expression")); - _res = assigment_expression_var; + D(fprintf(stderr, "%*c+ _tmp_117[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + _res = assignment_expression_var; goto done; } p->mark = _mark; D(fprintf(stderr, "%*c%s _tmp_117[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assigment_expression")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); } { // expression !':=' if (p->error_indicator) { @@ -28666,7 +28666,7 @@ _loop0_122_rule(Parser *p) return _seq; } -// _loop0_124: ',' (starred_expression | (assigment_expression | expression !':=') !'=') +// _loop0_124: ',' (starred_expression | (assignment_expression | expression !':=') !'=') static asdl_seq * _loop0_124_rule(Parser *p) { @@ -28687,18 +28687,18 @@ _loop0_124_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // ',' (starred_expression | (assigment_expression | expression !':=') !'=') + { // ',' (starred_expression | (assignment_expression | expression !':=') !'=') if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | (assigment_expression | expression !':=') !'=')")); + D(fprintf(stderr, "%*c> _loop0_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_190_rule(p)) // starred_expression | (assigment_expression | expression !':=') !'=' + (elem = _tmp_190_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' ) { _res = elem; @@ -28724,7 +28724,7 @@ _loop0_124_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s _loop0_124[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (starred_expression | (assigment_expression | expression !':=') !'=')")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -28742,7 +28742,7 @@ _loop0_124_rule(Parser *p) } // _gather_123: -// | (starred_expression | (assigment_expression | expression !':=') !'=') _loop0_124 +// | (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124 static asdl_seq * _gather_123_rule(Parser *p) { @@ -28753,27 +28753,27 @@ _gather_123_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (starred_expression | (assigment_expression | expression !':=') !'=') _loop0_124 + { // (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assigment_expression | expression !':=') !'=') _loop0_124")); + D(fprintf(stderr, "%*c> _gather_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_190_rule(p)) // starred_expression | (assigment_expression | expression !':=') !'=' + (elem = _tmp_190_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' && (seq = _loop0_124_rule(p)) // _loop0_124 ) { - D(fprintf(stderr, "%*c+ _gather_123[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assigment_expression | expression !':=') !'=') _loop0_124")); + D(fprintf(stderr, "%*c+ _gather_123[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; D(fprintf(stderr, "%*c%s _gather_123[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression | (assigment_expression | expression !':=') !'=') _loop0_124")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124")); } _res = NULL; done: @@ -32419,7 +32419,7 @@ _tmp_189_rule(Parser *p) return _res; } -// _tmp_190: starred_expression | (assigment_expression | expression !':=') !'=' +// _tmp_190: starred_expression | (assignment_expression | expression !':=') !'=' static void * _tmp_190_rule(Parser *p) { @@ -32449,26 +32449,26 @@ _tmp_190_rule(Parser *p) D(fprintf(stderr, "%*c%s _tmp_190[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression")); } - { // (assigment_expression | expression !':=') !'=' + { // (assignment_expression | expression !':=') !'=' if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_190[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assigment_expression | expression !':=') !'='")); + D(fprintf(stderr, "%*c> _tmp_190[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); void *_tmp_201_var; if ( - (_tmp_201_var = _tmp_201_rule(p)) // assigment_expression | expression !':=' + (_tmp_201_var = _tmp_201_rule(p)) // assignment_expression | expression !':=' && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_190[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assigment_expression | expression !':=') !'='")); + D(fprintf(stderr, "%*c+ _tmp_190[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); _res = _tmp_201_var; goto done; } p->mark = _mark; D(fprintf(stderr, "%*c%s _tmp_190[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(assigment_expression | expression !':=') !'='")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(assignment_expression | expression !':=') !'='")); } _res = NULL; done: @@ -32912,7 +32912,7 @@ _tmp_200_rule(Parser *p) return _res; } -// _tmp_201: assigment_expression | expression !':=' +// _tmp_201: assignment_expression | expression !':=' static void * _tmp_201_rule(Parser *p) { @@ -32923,24 +32923,24 @@ _tmp_201_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // assigment_expression + { // assignment_expression if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assigment_expression")); - expr_ty assigment_expression_var; + D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + expr_ty assignment_expression_var; if ( - (assigment_expression_var = assigment_expression_rule(p)) // assigment_expression + (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression ) { - D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assigment_expression")); - _res = assigment_expression_var; + D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + _res = assignment_expression_var; goto done; } p->mark = _mark; D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assigment_expression")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); } { // expression !':=' if (p->error_indicator) { From webhook-mailer at python.org Fri Nov 5 04:52:04 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 05 Nov 2021 08:52:04 -0000 Subject: [Python-checkins] bpo-45160: Fix refleak in test_ttk_guionly introduced in GH-28291 (GH-29416) Message-ID: https://github.com/python/cpython/commit/54d1e3f72ed1ad8e860888c30ee7a285b931c0d1 commit: 54d1e3f72ed1ad8e860888c30ee7a285b931c0d1 branch: main author: ?ukasz Langa committer: ambv date: 2021-11-05T09:51:31+01:00 summary: bpo-45160: Fix refleak in test_ttk_guionly introduced in GH-28291 (GH-29416) files: M Lib/tkinter/test/test_ttk/test_extensions.py diff --git a/Lib/tkinter/test/test_ttk/test_extensions.py b/Lib/tkinter/test/test_ttk/test_extensions.py index cddd1f2e84834..7fc1ebb95c970 100644 --- a/Lib/tkinter/test/test_ttk/test_extensions.py +++ b/Lib/tkinter/test/test_ttk/test_extensions.py @@ -310,9 +310,12 @@ def cb_test(*args): self.assertEqual(textvar.get(), items[1]) success.append(True) optmenu = ttk.OptionMenu(self.root, textvar, "a", *items) - textvar.trace("w", cb_test) + optmenu.pack() + cb_name = textvar.trace("w", cb_test) optmenu['menu'].invoke(1) self.assertEqual(success, [True]) + textvar.trace_vdelete("w", cb_name) + optmenu.destroy() class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase): From webhook-mailer at python.org Fri Nov 5 04:53:18 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 05 Nov 2021 08:53:18 -0000 Subject: [Python-checkins] bpo-27313: Fix ttk_guionly tests failing on Framework builds on macOS (GH-29411) Message-ID: https://github.com/python/cpython/commit/e52f9bee802aa7a7fbd405dcc43bc2d1bea884d9 commit: e52f9bee802aa7a7fbd405dcc43bc2d1bea884d9 branch: main author: ?ukasz Langa committer: ambv date: 2021-11-05T09:53:13+01:00 summary: bpo-27313: Fix ttk_guionly tests failing on Framework builds on macOS (GH-29411) files: M Lib/tkinter/test/test_ttk/test_widgets.py diff --git a/Lib/tkinter/test/test_ttk/test_widgets.py b/Lib/tkinter/test/test_ttk/test_widgets.py index 935be3d7f1b5a..1cb7e74c66ec7 100644 --- a/Lib/tkinter/test/test_ttk/test_widgets.py +++ b/Lib/tkinter/test/test_ttk/test_widgets.py @@ -61,7 +61,6 @@ def setUp(self): self.widget = ttk.Button(self.root, width=0, text="Text") self.widget.pack() - def test_identify(self): self.widget.update() self.assertEqual(self.widget.identify( @@ -74,7 +73,6 @@ def test_identify(self): self.assertRaises(tkinter.TclError, self.widget.identify, 5, None) self.assertRaises(tkinter.TclError, self.widget.identify, 5, '') - def test_widget_state(self): # XXX not sure about the portability of all these tests self.assertEqual(self.widget.state(), ()) @@ -287,6 +285,7 @@ class EntryTest(AbstractWidgetTest, unittest.TestCase): 'show', 'state', 'style', 'takefocus', 'textvariable', 'validate', 'validatecommand', 'width', 'xscrollcommand', ) + IDENTIFY_AS = 'Entry.field' if sys.platform == 'darwin' else 'textarea' def setUp(self): super().setUp() @@ -319,30 +318,23 @@ def test_configure_validatecommand(self): widget = self.create() self.checkCommandParam(widget, 'validatecommand') - def test_bbox(self): self.assertIsBoundingBox(self.entry.bbox(0)) self.assertRaises(tkinter.TclError, self.entry.bbox, 'noindex') self.assertRaises(tkinter.TclError, self.entry.bbox, None) - def test_identify(self): self.entry.pack() self.entry.update() # bpo-27313: macOS Cocoa widget differs from X, allow either - if sys.platform == 'darwin': - self.assertIn(self.entry.identify(5, 5), - ("textarea", "Combobox.button") ) - else: - self.assertEqual(self.entry.identify(5, 5), "textarea") + self.assertEqual(self.entry.identify(5, 5), self.IDENTIFY_AS) self.assertEqual(self.entry.identify(-1, -1), "") self.assertRaises(tkinter.TclError, self.entry.identify, None, 5) self.assertRaises(tkinter.TclError, self.entry.identify, 5, None) self.assertRaises(tkinter.TclError, self.entry.identify, 5, '') - def test_validation_options(self): success = [] test_invalid = lambda: success.append(True) @@ -370,7 +362,6 @@ def test_validation_options(self): self.entry['validatecommand'] = True self.assertRaises(tkinter.TclError, self.entry.validate) - def test_validation(self): validation = [] def validate(to_insert): @@ -388,7 +379,6 @@ def validate(to_insert): self.assertEqual(validation, [False, True]) self.assertEqual(self.entry.get(), 'a') - def test_revalidation(self): def validate(content): for letter in content: @@ -424,6 +414,7 @@ class ComboboxTest(EntryTest, unittest.TestCase): 'validate', 'validatecommand', 'values', 'width', 'xscrollcommand', ) + IDENTIFY_AS = 'Combobox.button' if sys.platform == 'darwin' else 'textarea' def setUp(self): super().setUp() @@ -439,7 +430,8 @@ def test_configure_height(self): def _show_drop_down_listbox(self): width = self.combo.winfo_width() x, y = width - 5, 5 - self.assertRegex(self.combo.identify(x, y), r'.*downarrow\Z') + if sys.platform != 'darwin': # there's no down arrow on macOS + self.assertRegex(self.combo.identify(x, y), r'.*downarrow\Z') self.combo.event_generate('', x=x, y=y) self.combo.event_generate('', x=x, y=y) self.combo.update_idletasks() @@ -461,7 +453,6 @@ def test_virtual_event(self): self.assertTrue(success) - def test_configure_postcommand(self): success = [] @@ -477,7 +468,6 @@ def test_configure_postcommand(self): self._show_drop_down_listbox() self.assertEqual(len(success), 1) - def test_configure_values(self): def check_get_current(getval, currval): self.assertEqual(self.combo.get(), getval) @@ -592,7 +582,6 @@ def test_add(self): other_child.destroy() self.assertRaises(tkinter.TclError, self.paned.pane, 0) - def test_forget(self): self.assertRaises(tkinter.TclError, self.paned.forget, None) self.assertRaises(tkinter.TclError, self.paned.forget, 0) @@ -601,7 +590,6 @@ def test_forget(self): self.paned.forget(0) self.assertRaises(tkinter.TclError, self.paned.forget, 0) - def test_insert(self): self.assertRaises(tkinter.TclError, self.paned.insert, None, 0) self.assertRaises(tkinter.TclError, self.paned.insert, 0, None) @@ -636,7 +624,6 @@ def test_insert(self): self.assertEqual(self.paned.panes(), (str(child3), str(child2), str(child))) - def test_pane(self): self.assertRaises(tkinter.TclError, self.paned.pane, 0) @@ -653,7 +640,6 @@ def test_pane(self): self.assertRaises(tkinter.TclError, self.paned.pane, 0, badoption='somevalue') - def test_sashpos(self): self.assertRaises(tkinter.TclError, self.paned.sashpos, None) self.assertRaises(tkinter.TclError, self.paned.sashpos, '') @@ -801,7 +787,6 @@ def test_custom_event(self): self.assertFalse(failure) - def test_get(self): if self.wantobjects: conv = lambda x: x @@ -819,7 +804,6 @@ def test_get(self): self.assertRaises(tkinter.TclError, self.scale.get, '', 0) self.assertRaises(tkinter.TclError, self.scale.get, 0, '') - def test_set(self): if self.wantobjects: conv = lambda x: x @@ -952,7 +936,6 @@ def test_tab_identifiers(self): else: self.fail("Tab with text 'a' not found") - def test_add_and_hidden(self): self.assertRaises(tkinter.TclError, self.nb.hide, -1) self.assertRaises(tkinter.TclError, self.nb.hide, 'hi') @@ -981,7 +964,6 @@ def test_add_and_hidden(self): # but the tab next to it (not hidden) is the one selected now self.assertEqual(self.nb.index('current'), curr + 1) - def test_forget(self): self.assertRaises(tkinter.TclError, self.nb.forget, -1) self.assertRaises(tkinter.TclError, self.nb.forget, 'hi') @@ -997,7 +979,6 @@ def test_forget(self): self.assertEqual(self.nb.index(self.child1), 1) self.assertNotEqual(child1_index, self.nb.index(self.child1)) - def test_index(self): self.assertRaises(tkinter.TclError, self.nb.index, -1) self.assertRaises(tkinter.TclError, self.nb.index, None) @@ -1007,7 +988,6 @@ def test_index(self): self.assertEqual(self.nb.index(self.child2), 1) self.assertEqual(self.nb.index('end'), 2) - def test_insert(self): # moving tabs tabs = self.nb.tabs() @@ -1040,7 +1020,6 @@ def test_insert(self): self.assertRaises(tkinter.TclError, self.nb.insert, None, 0) self.assertRaises(tkinter.TclError, self.nb.insert, None, None) - def test_select(self): self.nb.pack() self.nb.update() @@ -1060,7 +1039,6 @@ def test_select(self): self.nb.update() self.assertTrue(tab_changed) - def test_tab(self): self.assertRaises(tkinter.TclError, self.nb.tab, -1) self.assertRaises(tkinter.TclError, self.nb.tab, 'notab') @@ -1074,7 +1052,6 @@ def test_tab(self): self.assertEqual(self.nb.tab(self.child1, text=None), 'abc') self.assertEqual(self.nb.tab(self.child1, 'text'), 'abc') - def test_configure_tabs(self): self.assertEqual(len(self.nb.tabs()), 2) @@ -1083,14 +1060,14 @@ def test_configure_tabs(self): self.assertEqual(self.nb.tabs(), ()) - def test_traversal(self): self.nb.pack() self.nb.update() self.nb.select(0) - self.assertEqual(self.nb.identify(5, 5), 'focus') + focus_identify_as = 'focus' if sys.platform != 'darwin' else '' + self.assertEqual(self.nb.identify(5, 5), focus_identify_as) simulate_mouse_click(self.nb, 5, 5) self.nb.focus_force() self.nb.event_generate('') @@ -1103,15 +1080,24 @@ def test_traversal(self): self.assertEqual(self.nb.select(), str(self.child2)) self.nb.tab(self.child1, text='a', underline=0) + self.nb.tab(self.child2, text='e', underline=0) self.nb.enable_traversal() self.nb.focus_force() - self.assertEqual(self.nb.identify(5, 5), 'focus') + self.assertEqual(self.nb.identify(5, 5), focus_identify_as) simulate_mouse_click(self.nb, 5, 5) + # on macOS Emacs-style keyboard shortcuts are region-dependent; + # let's use the regular arrow keys instead if sys.platform == 'darwin': - self.nb.event_generate('') + begin = '' + end = '' else: - self.nb.event_generate('') + begin = '' + end = '' + self.nb.event_generate(begin) self.assertEqual(self.nb.select(), str(self.child1)) + self.nb.event_generate(end) + self.assertEqual(self.nb.select(), str(self.child2)) + @add_standard_options(IntegerSizeTests, StandardTtkOptionsTests) class SpinboxTest(EntryTest, unittest.TestCase): @@ -1122,6 +1108,7 @@ class SpinboxTest(EntryTest, unittest.TestCase): 'takefocus', 'textvariable', 'to', 'validate', 'validatecommand', 'values', 'width', 'wrap', 'xscrollcommand', ) + IDENTIFY_AS = 'Spinbox.field' if sys.platform == 'darwin' else 'textarea' def setUp(self): super().setUp() @@ -1370,7 +1357,6 @@ def test_bbox(self): child1 = self.tv.insert(item_id, 'end') self.assertEqual(self.tv.bbox(child1), '') - def test_children(self): # no children yet, should get an empty tuple self.assertEqual(self.tv.get_children(), ()) @@ -1398,7 +1384,6 @@ def test_children(self): self.tv.set_children('') self.assertEqual(self.tv.get_children(), ()) - def test_column(self): # return a dict with all options/values self.assertIsInstance(self.tv.column('#0'), dict) @@ -1424,7 +1409,6 @@ def test_column(self): self.assertRaises(tkinter.TclError, self.tv.column, '#0', **kw) - def test_delete(self): self.assertRaises(tkinter.TclError, self.tv.delete, '#0') @@ -1448,7 +1432,6 @@ def test_delete(self): self.tv.delete(item1, item2) self.assertFalse(self.tv.get_children()) - def test_detach_reattach(self): item_id = self.tv.insert('', 'end') item2 = self.tv.insert(item_id, 'end') @@ -1490,7 +1473,6 @@ def test_detach_reattach(self): self.assertEqual(self.tv.get_children(), ()) self.assertEqual(self.tv.get_children(item_id), ()) - def test_exists(self): self.assertEqual(self.tv.exists('something'), False) self.assertEqual(self.tv.exists(''), True) @@ -1501,7 +1483,6 @@ def test_exists(self): # in the tcl interpreter since tk requires an item. self.assertRaises(tkinter.TclError, self.tv.exists, None) - def test_focus(self): # nothing is focused right now self.assertEqual(self.tv.focus(), '') @@ -1516,7 +1497,6 @@ def test_focus(self): # try focusing inexistent item self.assertRaises(tkinter.TclError, self.tv.focus, 'hi') - def test_heading(self): # check a dict is returned self.assertIsInstance(self.tv.heading('#0'), dict) @@ -1568,7 +1548,6 @@ def simulate_heading_click(x, y): #self.tv.heading('#0', command='I dont exist') #simulate_heading_click(5, 5) - def test_index(self): # item 'what' doesn't exist self.assertRaises(tkinter.TclError, self.tv.index, 'what') @@ -1599,7 +1578,6 @@ def test_index(self): self.tv.delete(item1) self.assertRaises(tkinter.TclError, self.tv.index, c2) - def test_insert_item(self): # parent 'none' doesn't exist self.assertRaises(tkinter.TclError, self.tv.insert, 'none', 'end') @@ -1676,7 +1654,6 @@ def test_insert_item(self): self.assertRaises(tkinter.TclError, self.tv.insert, '', 'end', False) self.assertRaises(tkinter.TclError, self.tv.insert, '', 'end', '') - def test_selection(self): self.assertRaises(TypeError, self.tv.selection, 'spam') # item 'none' doesn't exist @@ -1747,7 +1724,6 @@ def test_selection(self): self.tv.selection_toggle((c1, c3)) self.assertEqual(self.tv.selection(), (c3, item2)) - def test_set(self): self.tv['columns'] = ['A', 'B'] item = self.tv.insert('', 'end', values=['a', 'b']) @@ -1780,7 +1756,6 @@ def test_set(self): # inexistent item self.assertRaises(tkinter.TclError, self.tv.set, 'notme') - def test_tag_bind(self): events = [] item1 = self.tv.insert('', 'end', tags=['call']) @@ -1813,7 +1788,6 @@ def test_tag_bind(self): for evt in zip(events[::2], events[1::2]): self.assertEqual(evt, (1, 2)) - def test_tag_configure(self): # Just testing parameter passing for now self.assertRaises(TypeError, self.tv.tag_configure) From webhook-mailer at python.org Fri Nov 5 05:39:51 2021 From: webhook-mailer at python.org (iritkatriel) Date: Fri, 05 Nov 2021 09:39:51 -0000 Subject: [Python-checkins] bpo-45292: [PEP 654] Update traceback display code to work with exception groups (GH-29207) Message-ID: https://github.com/python/cpython/commit/3509b26c916707363c71a1df040855e395cf4817 commit: 3509b26c916707363c71a1df040855e395cf4817 branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-11-05T09:39:18Z summary: bpo-45292: [PEP 654] Update traceback display code to work with exception groups (GH-29207) files: M Include/internal/pycore_traceback.h M Lib/test/test_traceback.py M Lib/traceback.py M Misc/NEWS.d/next/Core and Builtins/2021-09-26-18-18-50.bpo-45292.aX5HVr.rst M Python/pythonrun.c M Python/traceback.c diff --git a/Include/internal/pycore_traceback.h b/Include/internal/pycore_traceback.h index c01a47639d5e3..84dbe27044fd3 100644 --- a/Include/internal/pycore_traceback.h +++ b/Include/internal/pycore_traceback.h @@ -87,6 +87,17 @@ PyAPI_FUNC(PyObject*) _PyTraceBack_FromFrame( PyObject *tb_next, PyFrameObject *frame); +#define EXCEPTION_TB_HEADER "Traceback (most recent call last):\n" +#define EXCEPTION_GROUP_TB_HEADER "Exception Group Traceback (most recent call last):\n" + +/* Write the traceback tb to file f. Prefix each line with + indent spaces followed by the margin (if it is not NULL). */ +PyAPI_FUNC(int) _PyTraceBack_Print_Indented( + PyObject *tb, int indent, const char* margin, + const char *header_margin, const char *header, PyObject *f); +PyAPI_FUNC(int) _Py_WriteIndentedMargin(int, const char*, PyObject *); +PyAPI_FUNC(int) _Py_WriteIndent(int, PyObject *); + #ifdef __cplusplus } #endif diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index 1c7db9d3d4737..d88851ddda431 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -987,6 +987,35 @@ def __eq__(self, other): self.assertIn('UnhashableException: ex2', tb[4]) self.assertIn('UnhashableException: ex1', tb[12]) + def deep_eg(self): + e = TypeError(1) + for i in range(2000): + e = ExceptionGroup('eg', [e]) + return e + + @cpython_only + def test_exception_group_deep_recursion_capi(self): + from _testcapi import exception_print + LIMIT = 75 + eg = self.deep_eg() + with captured_output("stderr") as stderr_f: + with support.infinite_recursion(max_depth=LIMIT): + exception_print(eg) + output = stderr_f.getvalue() + self.assertIn('ExceptionGroup', output) + self.assertLessEqual(output.count('ExceptionGroup'), LIMIT) + + def test_exception_group_deep_recursion_traceback(self): + LIMIT = 75 + eg = self.deep_eg() + with captured_output("stderr") as stderr_f: + with support.infinite_recursion(max_depth=LIMIT): + traceback.print_exception(type(eg), eg, eg.__traceback__) + output = stderr_f.getvalue() + self.assertIn('ExceptionGroup', output) + self.assertLessEqual(output.count('ExceptionGroup'), LIMIT) + + cause_message = ( "\nThe above exception was the direct cause " "of the following exception:\n\n") @@ -998,7 +1027,6 @@ def __eq__(self, other): boundaries = re.compile( '(%s|%s)' % (re.escape(cause_message), re.escape(context_message))) - class BaseExceptionReportingTests: def get_exception(self, exception_or_callable): @@ -1009,6 +1037,8 @@ def get_exception(self, exception_or_callable): except Exception as e: return e + callable_line = get_exception.__code__.co_firstlineno + 4 + def zero_div(self): 1/0 # In zero_div @@ -1234,6 +1264,298 @@ def __str__(self): self.assertEqual(err, f"{str_name}: {str_value}\n") + # #### Exception Groups #### + + def test_exception_group_basic(self): + def exc(): + raise ExceptionGroup("eg", [ValueError(1), TypeError(2)]) + + expected = ( + f' + Exception Group Traceback (most recent call last):\n' + f' | File "{__file__}", line {self.callable_line}, in get_exception\n' + f' | exception_or_callable()\n' + f' | ^^^^^^^^^^^^^^^^^^^^^^^\n' + f' | File "{__file__}", line {exc.__code__.co_firstlineno + 1}, in exc\n' + f' | raise ExceptionGroup("eg", [ValueError(1), TypeError(2)])\n' + f' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' + f' | ExceptionGroup: eg\n' + f' +-+---------------- 1 ----------------\n' + f' | ValueError: 1\n' + f' +---------------- 2 ----------------\n' + f' | TypeError: 2\n' + f' +------------------------------------\n') + + report = self.get_report(exc) + self.assertEqual(report, expected) + + def test_exception_group_cause(self): + def exc(): + EG = ExceptionGroup + try: + raise EG("eg1", [ValueError(1), TypeError(2)]) + except Exception as e: + raise EG("eg2", [ValueError(3), TypeError(4)]) from e + + expected = (f' + Exception Group Traceback (most recent call last):\n' + f' | File "{__file__}", line {exc.__code__.co_firstlineno + 3}, in exc\n' + f' | raise EG("eg1", [ValueError(1), TypeError(2)])\n' + f' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' + f' | ExceptionGroup: eg1\n' + f' +-+---------------- 1 ----------------\n' + f' | ValueError: 1\n' + f' +---------------- 2 ----------------\n' + f' | TypeError: 2\n' + f' +------------------------------------\n' + f'\n' + f'The above exception was the direct cause of the following exception:\n' + f'\n' + f' + Exception Group Traceback (most recent call last):\n' + f' | File "{__file__}", line {self.callable_line}, in get_exception\n' + f' | exception_or_callable()\n' + f' | ^^^^^^^^^^^^^^^^^^^^^^^\n' + f' | File "{__file__}", line {exc.__code__.co_firstlineno + 5}, in exc\n' + f' | raise EG("eg2", [ValueError(3), TypeError(4)]) from e\n' + f' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' + f' | ExceptionGroup: eg2\n' + f' +-+---------------- 1 ----------------\n' + f' | ValueError: 3\n' + f' +---------------- 2 ----------------\n' + f' | TypeError: 4\n' + f' +------------------------------------\n') + + report = self.get_report(exc) + self.assertEqual(report, expected) + + def test_exception_group_context_with_context(self): + def exc(): + EG = ExceptionGroup + try: + try: + raise EG("eg1", [ValueError(1), TypeError(2)]) + except: + raise EG("eg2", [ValueError(3), TypeError(4)]) + except: + raise ImportError(5) + + expected = ( + f' + Exception Group Traceback (most recent call last):\n' + f' | File "{__file__}", line {exc.__code__.co_firstlineno + 4}, in exc\n' + f' | raise EG("eg1", [ValueError(1), TypeError(2)])\n' + f' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' + f' | ExceptionGroup: eg1\n' + f' +-+---------------- 1 ----------------\n' + f' | ValueError: 1\n' + f' +---------------- 2 ----------------\n' + f' | TypeError: 2\n' + f' +------------------------------------\n' + f'\n' + f'During handling of the above exception, another exception occurred:\n' + f'\n' + f' + Exception Group Traceback (most recent call last):\n' + f' | File "{__file__}", line {exc.__code__.co_firstlineno + 6}, in exc\n' + f' | raise EG("eg2", [ValueError(3), TypeError(4)])\n' + f' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' + f' | ExceptionGroup: eg2\n' + f' +-+---------------- 1 ----------------\n' + f' | ValueError: 3\n' + f' +---------------- 2 ----------------\n' + f' | TypeError: 4\n' + f' +------------------------------------\n' + f'\n' + f'During handling of the above exception, another exception occurred:\n' + f'\n' + f'Traceback (most recent call last):\n' + f' File "{__file__}", line {self.callable_line}, in get_exception\n' + f' exception_or_callable()\n' + f' ^^^^^^^^^^^^^^^^^^^^^^^\n' + f' File "{__file__}", line {exc.__code__.co_firstlineno + 8}, in exc\n' + f' raise ImportError(5)\n' + f' ^^^^^^^^^^^^^^^^^^^^\n' + f'ImportError: 5\n') + + report = self.get_report(exc) + self.assertEqual(report, expected) + + def test_exception_group_nested(self): + def exc(): + EG = ExceptionGroup + VE = ValueError + TE = TypeError + try: + try: + raise EG("nested", [TE(2), TE(3)]) + except Exception as e: + exc = e + raise EG("eg", [VE(1), exc, VE(4)]) + except: + raise EG("top", [VE(5)]) + + expected = (f' + Exception Group Traceback (most recent call last):\n' + f' | File "{__file__}", line {exc.__code__.co_firstlineno + 9}, in exc\n' + f' | raise EG("eg", [VE(1), exc, VE(4)])\n' + f' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' + f' | ExceptionGroup: eg\n' + f' +-+---------------- 1 ----------------\n' + f' | ValueError: 1\n' + f' +---------------- 2 ----------------\n' + f' | Exception Group Traceback (most recent call last):\n' + f' | File "{__file__}", line {exc.__code__.co_firstlineno + 6}, in exc\n' + f' | raise EG("nested", [TE(2), TE(3)])\n' + f' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n' + f' | ExceptionGroup: nested\n' + f' +-+---------------- 1 ----------------\n' + f' | TypeError: 2\n' + f' +---------------- 2 ----------------\n' + f' | TypeError: 3\n' + f' +------------------------------------\n' + f' +---------------- 3 ----------------\n' + f' | ValueError: 4\n' + f' +------------------------------------\n' + f'\n' + f'During handling of the above exception, another exception occurred:\n' + f'\n' + f' + Exception Group Traceback (most recent call last):\n' + f' | File "{__file__}", line {self.callable_line}, in get_exception\n' + f' | exception_or_callable()\n' + f' | ^^^^^^^^^^^^^^^^^^^^^^^\n' + f' | File "{__file__}", line {exc.__code__.co_firstlineno + 11}, in exc\n' + f' | raise EG("top", [VE(5)])\n' + f' | ^^^^^^^^^^^^^^^^^^^^^^^^\n' + f' | ExceptionGroup: top\n' + f' +-+---------------- 1 ----------------\n' + f' | ValueError: 5\n' + f' +------------------------------------\n') + + report = self.get_report(exc) + self.assertEqual(report, expected) + + def test_exception_group_width_limit(self): + excs = [] + for i in range(1000): + excs.append(ValueError(i)) + eg = ExceptionGroup('eg', excs) + + expected = (' | ExceptionGroup: eg\n' + ' +-+---------------- 1 ----------------\n' + ' | ValueError: 0\n' + ' +---------------- 2 ----------------\n' + ' | ValueError: 1\n' + ' +---------------- 3 ----------------\n' + ' | ValueError: 2\n' + ' +---------------- 4 ----------------\n' + ' | ValueError: 3\n' + ' +---------------- 5 ----------------\n' + ' | ValueError: 4\n' + ' +---------------- 6 ----------------\n' + ' | ValueError: 5\n' + ' +---------------- 7 ----------------\n' + ' | ValueError: 6\n' + ' +---------------- 8 ----------------\n' + ' | ValueError: 7\n' + ' +---------------- 9 ----------------\n' + ' | ValueError: 8\n' + ' +---------------- 10 ----------------\n' + ' | ValueError: 9\n' + ' +---------------- 11 ----------------\n' + ' | ValueError: 10\n' + ' +---------------- 12 ----------------\n' + ' | ValueError: 11\n' + ' +---------------- 13 ----------------\n' + ' | ValueError: 12\n' + ' +---------------- 14 ----------------\n' + ' | ValueError: 13\n' + ' +---------------- 15 ----------------\n' + ' | ValueError: 14\n' + ' +---------------- ... ----------------\n' + ' | and 985 more exceptions\n' + ' +------------------------------------\n') + + report = self.get_report(eg) + self.assertEqual(report, expected) + + def test_exception_group_depth_limit(self): + exc = TypeError('bad type') + for i in range(1000): + exc = ExceptionGroup( + f'eg{i}', + [ValueError(i), exc, ValueError(-i)]) + + expected = (' | ExceptionGroup: eg999\n' + ' +-+---------------- 1 ----------------\n' + ' | ValueError: 999\n' + ' +---------------- 2 ----------------\n' + ' | ExceptionGroup: eg998\n' + ' +-+---------------- 1 ----------------\n' + ' | ValueError: 998\n' + ' +---------------- 2 ----------------\n' + ' | ExceptionGroup: eg997\n' + ' +-+---------------- 1 ----------------\n' + ' | ValueError: 997\n' + ' +---------------- 2 ----------------\n' + ' | ExceptionGroup: eg996\n' + ' +-+---------------- 1 ----------------\n' + ' | ValueError: 996\n' + ' +---------------- 2 ----------------\n' + ' | ExceptionGroup: eg995\n' + ' +-+---------------- 1 ----------------\n' + ' | ValueError: 995\n' + ' +---------------- 2 ----------------\n' + ' | ExceptionGroup: eg994\n' + ' +-+---------------- 1 ----------------\n' + ' | ValueError: 994\n' + ' +---------------- 2 ----------------\n' + ' | ExceptionGroup: eg993\n' + ' +-+---------------- 1 ----------------\n' + ' | ValueError: 993\n' + ' +---------------- 2 ----------------\n' + ' | ExceptionGroup: eg992\n' + ' +-+---------------- 1 ----------------\n' + ' | ValueError: 992\n' + ' +---------------- 2 ----------------\n' + ' | ExceptionGroup: eg991\n' + ' +-+---------------- 1 ----------------\n' + ' | ValueError: 991\n' + ' +---------------- 2 ----------------\n' + ' | ExceptionGroup: eg990\n' + ' +-+---------------- 1 ----------------\n' + ' | ValueError: 990\n' + ' +---------------- 2 ----------------\n' + ' | ... (max_group_depth is 10)\n' + ' +---------------- 3 ----------------\n' + ' | ValueError: -990\n' + ' +------------------------------------\n' + ' +---------------- 3 ----------------\n' + ' | ValueError: -991\n' + ' +------------------------------------\n' + ' +---------------- 3 ----------------\n' + ' | ValueError: -992\n' + ' +------------------------------------\n' + ' +---------------- 3 ----------------\n' + ' | ValueError: -993\n' + ' +------------------------------------\n' + ' +---------------- 3 ----------------\n' + ' | ValueError: -994\n' + ' +------------------------------------\n' + ' +---------------- 3 ----------------\n' + ' | ValueError: -995\n' + ' +------------------------------------\n' + ' +---------------- 3 ----------------\n' + ' | ValueError: -996\n' + ' +------------------------------------\n' + ' +---------------- 3 ----------------\n' + ' | ValueError: -997\n' + ' +------------------------------------\n' + ' +---------------- 3 ----------------\n' + ' | ValueError: -998\n' + ' +------------------------------------\n' + ' +---------------- 3 ----------------\n' + ' | ValueError: -999\n' + ' +------------------------------------\n') + + report = self.get_report(exc) + self.assertEqual(report, expected) + + class PyExcReportingTests(BaseExceptionReportingTests, unittest.TestCase): # # This checks reporting through the 'traceback' module, with both @@ -1913,6 +2235,197 @@ def f(): '']) +class TestTracebackException_ExceptionGroups(unittest.TestCase): + def setUp(self): + super().setUp() + self.eg_info = self._get_exception_group() + + def _get_exception_group(self): + def f(): + 1/0 + + def g(v): + raise ValueError(v) + + self.lno_f = f.__code__.co_firstlineno + self.lno_g = g.__code__.co_firstlineno + + try: + try: + try: + f() + except Exception as e: + exc1 = e + try: + g(42) + except Exception as e: + exc2 = e + raise ExceptionGroup("eg1", [exc1, exc2]) + except ExceptionGroup as e: + exc3 = e + try: + g(24) + except Exception as e: + exc4 = e + raise ExceptionGroup("eg2", [exc3, exc4]) + except ExceptionGroup: + return sys.exc_info() + self.fail('Exception Not Raised') + + def test_exception_group_construction(self): + eg_info = self.eg_info + teg1 = traceback.TracebackException(*eg_info) + teg2 = traceback.TracebackException.from_exception(eg_info[1]) + self.assertIsNot(teg1, teg2) + self.assertEqual(teg1, teg2) + + def test_exception_group_format_exception_only(self): + teg = traceback.TracebackException(*self.eg_info) + formatted = ''.join(teg.format_exception_only()).split('\n') + expected = "ExceptionGroup: eg2\n".split('\n') + + self.assertEqual(formatted, expected) + + def test_exception_group_format(self): + teg = traceback.TracebackException(*self.eg_info) + + formatted = ''.join(teg.format()).split('\n') + lno_f = self.lno_f + lno_g = self.lno_g + + expected = [ + f' + Exception Group Traceback (most recent call last):', + f' | File "{__file__}", line {lno_g+23}, in _get_exception_group', + f' | raise ExceptionGroup("eg2", [exc3, exc4])', + f' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^', + f' | ExceptionGroup: eg2', + f' +-+---------------- 1 ----------------', + f' | Exception Group Traceback (most recent call last):', + f' | File "{__file__}", line {lno_g+16}, in _get_exception_group', + f' | raise ExceptionGroup("eg1", [exc1, exc2])', + f' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^', + f' | ExceptionGroup: eg1', + f' +-+---------------- 1 ----------------', + f' | Traceback (most recent call last):', + f' | File "{__file__}", line {lno_g+9}, in _get_exception_group', + f' | f()', + f' | ^^^', + f' | File "{__file__}", line {lno_f+1}, in f', + f' | 1/0', + f' | ~^~', + f' | ZeroDivisionError: division by zero', + f' +---------------- 2 ----------------', + f' | Traceback (most recent call last):', + f' | File "{__file__}", line {lno_g+13}, in _get_exception_group', + f' | g(42)', + f' | ^^^^^', + f' | File "{__file__}", line {lno_g+1}, in g', + f' | raise ValueError(v)', + f' | ^^^^^^^^^^^^^^^^^^^', + f' | ValueError: 42', + f' +------------------------------------', + f' +---------------- 2 ----------------', + f' | Traceback (most recent call last):', + f' | File "{__file__}", line {lno_g+20}, in _get_exception_group', + f' | g(24)', + f' | ^^^^^', + f' | File "{__file__}", line {lno_g+1}, in g', + f' | raise ValueError(v)', + f' | ^^^^^^^^^^^^^^^^^^^', + f' | ValueError: 24', + f' +------------------------------------', + f''] + + self.assertEqual(formatted, expected) + + def test_max_group_width(self): + excs1 = [] + excs2 = [] + for i in range(3): + excs1.append(ValueError(i)) + for i in range(10): + excs2.append(TypeError(i)) + + EG = ExceptionGroup + eg = EG('eg', [EG('eg1', excs1), EG('eg2', excs2)]) + + teg = traceback.TracebackException.from_exception(eg, max_group_width=2) + formatted = ''.join(teg.format()).split('\n') + + expected = [ + f' | ExceptionGroup: eg', + f' +-+---------------- 1 ----------------', + f' | ExceptionGroup: eg1', + f' +-+---------------- 1 ----------------', + f' | ValueError: 0', + f' +---------------- 2 ----------------', + f' | ValueError: 1', + f' +---------------- ... ----------------', + f' | and 1 more exception', + f' +------------------------------------', + f' +---------------- 2 ----------------', + f' | ExceptionGroup: eg2', + f' +-+---------------- 1 ----------------', + f' | TypeError: 0', + f' +---------------- 2 ----------------', + f' | TypeError: 1', + f' +---------------- ... ----------------', + f' | and 8 more exceptions', + f' +------------------------------------', + f''] + + self.assertEqual(formatted, expected) + + def test_max_group_depth(self): + exc = TypeError('bad type') + for i in range(3): + exc = ExceptionGroup('exc', [ValueError(-i), exc, ValueError(i)]) + + teg = traceback.TracebackException.from_exception(exc, max_group_depth=2) + formatted = ''.join(teg.format()).split('\n') + + expected = [ + f' | ExceptionGroup: exc', + f' +-+---------------- 1 ----------------', + f' | ValueError: -2', + f' +---------------- 2 ----------------', + f' | ExceptionGroup: exc', + f' +-+---------------- 1 ----------------', + f' | ValueError: -1', + f' +---------------- 2 ----------------', + f' | ... (max_group_depth is 2)', + f' +---------------- 3 ----------------', + f' | ValueError: 1', + f' +------------------------------------', + f' +---------------- 3 ----------------', + f' | ValueError: 2', + f' +------------------------------------', + f''] + + self.assertEqual(formatted, expected) + + def test_comparison(self): + try: + raise self.eg_info[1] + except ExceptionGroup: + exc_info = sys.exc_info() + for _ in range(5): + try: + raise exc_info[1] + except: + exc_info = sys.exc_info() + exc = traceback.TracebackException(*exc_info) + exc2 = traceback.TracebackException(*exc_info) + exc3 = traceback.TracebackException(*exc_info, limit=300) + ne = traceback.TracebackException(*exc_info, limit=3) + self.assertIsNot(exc, exc2) + self.assertEqual(exc, exc2) + self.assertEqual(exc, exc3) + self.assertNotEqual(exc, ne) + self.assertNotEqual(exc, object()) + self.assertEqual(exc, ALWAYS_EQ) + + class MiscTest(unittest.TestCase): def test_all(self): diff --git a/Lib/traceback.py b/Lib/traceback.py index 568f3ff28c29b..97caa1372f478 100644 --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -4,6 +4,7 @@ import itertools import linecache import sys +import textwrap from contextlib import suppress __all__ = ['extract_stack', 'extract_tb', 'format_exception', @@ -601,6 +602,29 @@ def _extract_caret_anchors_from_line_segment(segment): return None +class _ExceptionPrintContext: + def __init__(self): + self.seen = set() + self.exception_group_depth = 0 + self.need_close = False + + def indent(self): + return ' ' * (2 * self.exception_group_depth) + + def emit(self, text_gen, margin_char=None): + if margin_char is None: + margin_char = '|' + indent_str = self.indent() + if self.exception_group_depth: + indent_str += margin_char + ' ' + + if isinstance(text_gen, str): + yield textwrap.indent(text_gen, indent_str, lambda line: True) + else: + for text in text_gen: + yield textwrap.indent(text, indent_str, lambda line: True) + + class TracebackException: """An exception ready for rendering. @@ -608,6 +632,11 @@ class TracebackException: to this intermediary form to ensure that no references are held, while still being able to fully print or format it. + max_group_width and max_group_depth control the formatting of exception + groups. The depth refers to the nesting level of the group, and the width + refers to the size of a single exception group's exceptions array. The + formatted output is truncated when either limit is exceeded. + Use `from_exception` to create TracebackException instances from exception objects, or the constructor to create TracebackException instances from individual components. @@ -635,7 +664,7 @@ class TracebackException: def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None, lookup_lines=True, capture_locals=False, compact=False, - _seen=None): + max_group_width=15, max_group_depth=10, _seen=None): # NB: we need to accept exc_traceback, exc_value, exc_traceback to # permit backwards compat with the existing API, otherwise we # need stub thunk objects just to glue it together. @@ -645,7 +674,9 @@ def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None, _seen = set() _seen.add(id(exc_value)) - # TODO: locals. + self.max_group_width = max_group_width + self.max_group_depth = max_group_depth + self.stack = StackSummary._extract_from_extended_frame_gen( _walk_tb_with_full_positions(exc_traceback), limit=limit, lookup_lines=lookup_lines, @@ -685,6 +716,8 @@ def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None, limit=limit, lookup_lines=lookup_lines, capture_locals=capture_locals, + max_group_width=max_group_width, + max_group_depth=max_group_depth, _seen=_seen) else: cause = None @@ -704,15 +737,38 @@ def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None, limit=limit, lookup_lines=lookup_lines, capture_locals=capture_locals, + max_group_width=max_group_width, + max_group_depth=max_group_depth, _seen=_seen) else: context = None + + if e and isinstance(e, BaseExceptionGroup): + exceptions = [] + for exc in e.exceptions: + texc = TracebackException( + type(exc), + exc, + exc.__traceback__, + limit=limit, + lookup_lines=lookup_lines, + capture_locals=capture_locals, + max_group_width=max_group_width, + max_group_depth=max_group_depth, + _seen=_seen) + exceptions.append(texc) + else: + exceptions = None + te.__cause__ = cause te.__context__ = context + te.exceptions = exceptions if cause: queue.append((te.__cause__, e.__cause__)) if context: queue.append((te.__context__, e.__context__)) + if exceptions: + queue.extend(zip(te.exceptions, e.exceptions)) @classmethod def from_exception(cls, exc, *args, **kwargs): @@ -795,7 +851,7 @@ def _format_syntax_error(self, stype): msg = self.msg or "" yield "{}: {}{}\n".format(stype, msg, filename_suffix) - def format(self, *, chain=True): + def format(self, *, chain=True, _ctx=None): """Format the exception. If chain is not *True*, *__cause__* and *__context__* will not be formatted. @@ -808,10 +864,13 @@ def format(self, *, chain=True): string in the output. """ + if _ctx is None: + _ctx = _ExceptionPrintContext() + output = [] exc = self - while exc: - if chain: + if chain: + while exc: if exc.__cause__ is not None: chained_msg = _cause_message chained_exc = exc.__cause__ @@ -825,17 +884,73 @@ def format(self, *, chain=True): output.append((chained_msg, exc)) exc = chained_exc - else: - output.append((None, exc)) - exc = None + else: + output.append((None, exc)) for msg, exc in reversed(output): if msg is not None: - yield msg - if exc.stack: - yield 'Traceback (most recent call last):\n' - yield from exc.stack.format() - yield from exc.format_exception_only() + yield from _ctx.emit(msg) + if exc.exceptions is None: + if exc.stack: + yield from _ctx.emit('Traceback (most recent call last):\n') + yield from _ctx.emit(exc.stack.format()) + yield from _ctx.emit(exc.format_exception_only()) + elif _ctx.exception_group_depth > self.max_group_depth: + # exception group, but depth exceeds limit + yield from _ctx.emit( + f"... (max_group_depth is {self.max_group_depth})\n") + else: + # format exception group + is_toplevel = (_ctx.exception_group_depth == 0) + if is_toplevel: + _ctx.exception_group_depth += 1 + + if exc.stack: + yield from _ctx.emit( + 'Exception Group Traceback (most recent call last):\n', + margin_char = '+' if is_toplevel else None) + yield from _ctx.emit(exc.stack.format()) + + yield from _ctx.emit(exc.format_exception_only()) + num_excs = len(exc.exceptions) + if num_excs <= self.max_group_width: + n = num_excs + else: + n = self.max_group_width + 1 + _ctx.need_close = False + for i in range(n): + last_exc = (i == n-1) + if last_exc: + # The closing frame may be added by a recursive call + _ctx.need_close = True + + if self.max_group_width is not None: + truncated = (i >= self.max_group_width) + else: + truncated = False + title = f'{i+1}' if not truncated else '...' + yield (_ctx.indent() + + ('+-' if i==0 else ' ') + + f'+---------------- {title} ----------------\n') + _ctx.exception_group_depth += 1 + if not truncated: + yield from exc.exceptions[i].format(chain=chain, _ctx=_ctx) + else: + remaining = num_excs - self.max_group_width + plural = 's' if remaining > 1 else '' + yield from _ctx.emit( + f"and {remaining} more exception{plural}\n") + + if last_exc and _ctx.need_close: + yield (_ctx.indent() + + "+------------------------------------\n") + _ctx.need_close = False + _ctx.exception_group_depth -= 1 + + if is_toplevel: + assert _ctx.exception_group_depth == 1 + _ctx.exception_group_depth = 0 + def print(self, *, file=None, chain=True): """Print the result of self.format(chain=chain) to 'file'.""" diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-26-18-18-50.bpo-45292.aX5HVr.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-26-18-18-50.bpo-45292.aX5HVr.rst index ee48b6d5105c5..55ca14f2259f0 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2021-09-26-18-18-50.bpo-45292.aX5HVr.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2021-09-26-18-18-50.bpo-45292.aX5HVr.rst @@ -1 +1 @@ -Implement :pep:`654` Add :class:`ExceptionGroup` and :class:`BaseExceptionGroup`. +Implement :pep:`654`. Add :class:`ExceptionGroup` and :class:`BaseExceptionGroup`. Update traceback display code. diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 6cecef9793228..2c0950ee17e8a 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -8,6 +8,8 @@ /* TODO: Cull includes following phase split */ +#include + #include "Python.h" #include "pycore_ast.h" // PyAST_mod2obj @@ -19,6 +21,7 @@ #include "pycore_pylifecycle.h" // _Py_UnhandledKeyboardInterrupt #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_sysmodule.h" // _PySys_Audit() +#include "pycore_traceback.h" // _PyTraceBack_Print_Indented() #include "token.h" // INDENT #include "errcode.h" // E_EOF @@ -886,19 +889,50 @@ PyErr_Print(void) PyErr_PrintEx(1); } +struct exception_print_context +{ + PyObject *file; + PyObject *seen; // Prevent cycles in recursion + int exception_group_depth; // nesting level of current exception group + bool need_close; // Need a closing bottom frame + int max_group_width; // Maximum number of children of each EG + int max_group_depth; // Maximum nesting level of EGs +}; + +#define EXC_MARGIN(ctx) ((ctx)->exception_group_depth ? "| " : "") +#define EXC_INDENT(ctx) (2 * (ctx)->exception_group_depth) + +static int +write_indented_margin(struct exception_print_context *ctx, PyObject *f) +{ + return _Py_WriteIndentedMargin(EXC_INDENT(ctx), EXC_MARGIN(ctx), f); +} + static void -print_exception(PyObject *f, PyObject *value) +print_exception(struct exception_print_context *ctx, PyObject *value) { int err = 0; PyObject *type, *tb, *tmp; + PyObject *f = ctx->file; + _Py_IDENTIFIER(print_file_and_line); if (!PyExceptionInstance_Check(value)) { - err = PyFile_WriteString("TypeError: print_exception(): Exception expected for value, ", f); - err += PyFile_WriteString(Py_TYPE(value)->tp_name, f); - err += PyFile_WriteString(" found\n", f); - if (err) + if (err == 0) { + err = _Py_WriteIndent(EXC_INDENT(ctx), f); + } + if (err == 0) { + err = PyFile_WriteString("TypeError: print_exception(): Exception expected for value, ", f); + } + if (err == 0) { + err = PyFile_WriteString(Py_TYPE(value)->tp_name, f); + } + if (err == 0) { + err = PyFile_WriteString(" found\n", f); + } + if (err != 0) { PyErr_Clear(); + } return; } @@ -906,8 +940,18 @@ print_exception(PyObject *f, PyObject *value) fflush(stdout); type = (PyObject *) Py_TYPE(value); tb = PyException_GetTraceback(value); - if (tb && tb != Py_None) - err = PyTraceBack_Print(tb, f); + if (tb && tb != Py_None) { + const char *header = EXCEPTION_TB_HEADER; + const char *header_margin = EXC_MARGIN(ctx); + if (_PyBaseExceptionGroup_Check(value)) { + header = EXCEPTION_GROUP_TB_HEADER; + if (ctx->exception_group_depth == 1) { + header_margin = "+ "; + } + } + err = _PyTraceBack_Print_Indented( + tb, EXC_INDENT(ctx), EXC_MARGIN(ctx), header_margin, header, f); + } if (err == 0 && (err = _PyObject_LookupAttrId(value, &PyId_print_file_and_line, &tmp)) > 0) { @@ -917,8 +961,9 @@ print_exception(PyObject *f, PyObject *value) Py_DECREF(tmp); if (!parse_syntax_error(value, &message, &filename, &lineno, &offset, - &end_lineno, &end_offset, &text)) + &end_lineno, &end_offset, &text)) { PyErr_Clear(); + } else { PyObject *line; @@ -929,7 +974,10 @@ print_exception(PyObject *f, PyObject *value) filename, lineno); Py_DECREF(filename); if (line != NULL) { - PyFile_WriteObject(line, f, Py_PRINT_RAW); + err = write_indented_margin(ctx, f); + if (err == 0) { + err = PyFile_WriteObject(line, f, Py_PRINT_RAW); + } Py_DECREF(line); } @@ -958,7 +1006,7 @@ print_exception(PyObject *f, PyObject *value) err = -1; } } - if (err) { + if (err != 0) { /* Don't do anything else */ } else { @@ -967,21 +1015,26 @@ print_exception(PyObject *f, PyObject *value) _Py_IDENTIFIER(__module__); assert(PyExceptionClass_Check(type)); - modulename = _PyObject_GetAttrId(type, &PyId___module__); - if (modulename == NULL || !PyUnicode_Check(modulename)) - { - Py_XDECREF(modulename); - PyErr_Clear(); - err = PyFile_WriteString("", f); - } - else { - if (!_PyUnicode_EqualToASCIIId(modulename, &PyId_builtins) && - !_PyUnicode_EqualToASCIIId(modulename, &PyId___main__)) + err = write_indented_margin(ctx, f); + if (err == 0) { + modulename = _PyObject_GetAttrId(type, &PyId___module__); + if (modulename == NULL || !PyUnicode_Check(modulename)) { - err = PyFile_WriteObject(modulename, f, Py_PRINT_RAW); - err += PyFile_WriteString(".", f); + Py_XDECREF(modulename); + PyErr_Clear(); + err = PyFile_WriteString("", f); + } + else { + if (!_PyUnicode_EqualToASCIIId(modulename, &PyId_builtins) && + !_PyUnicode_EqualToASCIIId(modulename, &PyId___main__)) + { + err = PyFile_WriteObject(modulename, f, Py_PRINT_RAW); + if (err == 0) { + err = PyFile_WriteString(".", f); + } + } + Py_DECREF(modulename); } - Py_DECREF(modulename); } if (err == 0) { PyObject* qualname = PyType_GetQualName((PyTypeObject *)type); @@ -1039,26 +1092,67 @@ print_exception(PyObject *f, PyObject *value) } static const char cause_message[] = - "\nThe above exception was the direct cause " - "of the following exception:\n\n"; + "The above exception was the direct cause " + "of the following exception:\n"; static const char context_message[] = - "\nDuring handling of the above exception, " - "another exception occurred:\n\n"; + "During handling of the above exception, " + "another exception occurred:\n"; + +static void +print_exception_recursive(struct exception_print_context*, PyObject*); + +static int +print_chained(struct exception_print_context* ctx, PyObject *value, + const char * message, const char *tag) +{ + PyObject *f = ctx->file; + bool need_close = ctx->need_close; + + int err = Py_EnterRecursiveCall(" in print_chained"); + if (err == 0) { + print_exception_recursive(ctx, value); + Py_LeaveRecursiveCall(); + + if (err == 0) { + err = write_indented_margin(ctx, f); + } + if (err == 0) { + err = PyFile_WriteString("\n", f); + } + if (err == 0) { + err = write_indented_margin(ctx, f); + } + if (err == 0) { + err = PyFile_WriteString(message, f); + } + if (err == 0) { + err = write_indented_margin(ctx, f); + } + if (err == 0) { + err = PyFile_WriteString("\n", f); + } + } + + ctx->need_close = need_close; + + return err; +} static void -print_exception_recursive(PyObject *f, PyObject *value, PyObject *seen) +print_exception_recursive(struct exception_print_context* ctx, PyObject *value) { int err = 0, res; PyObject *cause, *context; - if (seen != NULL) { + if (ctx->seen != NULL) { /* Exception chaining */ PyObject *value_id = PyLong_FromVoidPtr(value); - if (value_id == NULL || PySet_Add(seen, value_id) == -1) + if (value_id == NULL || PySet_Add(ctx->seen, value_id) == -1) PyErr_Clear(); else if (PyExceptionInstance_Check(value)) { PyObject *check_id = NULL; + cause = PyException_GetCause(value); context = PyException_GetContext(value); if (cause) { @@ -1066,16 +1160,13 @@ print_exception_recursive(PyObject *f, PyObject *value, PyObject *seen) if (check_id == NULL) { res = -1; } else { - res = PySet_Contains(seen, check_id); + res = PySet_Contains(ctx->seen, check_id); Py_DECREF(check_id); } if (res == -1) PyErr_Clear(); if (res == 0) { - print_exception_recursive( - f, cause, seen); - err |= PyFile_WriteString( - cause_message, f); + err = print_chained(ctx, cause, cause_message, "cause"); } } else if (context && @@ -1084,16 +1175,13 @@ print_exception_recursive(PyObject *f, PyObject *value, PyObject *seen) if (check_id == NULL) { res = -1; } else { - res = PySet_Contains(seen, check_id); + res = PySet_Contains(ctx->seen, check_id); Py_DECREF(check_id); } if (res == -1) PyErr_Clear(); if (res == 0) { - print_exception_recursive( - f, context, seen); - err |= PyFile_WriteString( - context_message, f); + err = print_chained(ctx, context, context_message, "context"); } } Py_XDECREF(context); @@ -1101,17 +1189,146 @@ print_exception_recursive(PyObject *f, PyObject *value, PyObject *seen) } Py_XDECREF(value_id); } - print_exception(f, value); + if (err) { + /* don't do anything else */ + } + else if (!_PyBaseExceptionGroup_Check(value)) { + print_exception(ctx, value); + } + else if (ctx->exception_group_depth > ctx->max_group_depth) { + /* exception group but depth exceeds limit */ + + PyObject *line = PyUnicode_FromFormat( + "... (max_group_depth is %d)\n", ctx->max_group_depth); + + if (line) { + PyObject *f = ctx->file; + if (err == 0) { + err = write_indented_margin(ctx, f); + } + if (err == 0) { + err = PyFile_WriteObject(line, f, Py_PRINT_RAW); + } + Py_DECREF(line); + } + else { + err = -1; + } + } + else { + /* format exception group */ + + if (ctx->exception_group_depth == 0) { + ctx->exception_group_depth += 1; + } + print_exception(ctx, value); + + PyObject *excs = ((PyBaseExceptionGroupObject *)value)->excs; + assert(excs && PyTuple_Check(excs)); + Py_ssize_t num_excs = PyTuple_GET_SIZE(excs); + assert(num_excs > 0); + Py_ssize_t n; + if (num_excs <= ctx->max_group_width) { + n = num_excs; + } + else { + n = ctx->max_group_width + 1; + } + + PyObject *f = ctx->file; + + ctx->need_close = false; + for (Py_ssize_t i = 0; i < n; i++) { + int last_exc = (i == n - 1); + if (last_exc) { + // The closing frame may be added in a recursive call + ctx->need_close = true; + } + PyObject *line; + bool truncated = (i >= ctx->max_group_width); + if (!truncated) { + line = PyUnicode_FromFormat( + "%s+---------------- %zd ----------------\n", + (i == 0) ? "+-" : " ", i + 1); + } + else { + line = PyUnicode_FromFormat( + "%s+---------------- ... ----------------\n", + (i == 0) ? "+-" : " "); + } + + if (line) { + if (err == 0) { + err = _Py_WriteIndent(EXC_INDENT(ctx), f); + } + if (err == 0) { + err = PyFile_WriteObject(line, f, Py_PRINT_RAW); + } + Py_DECREF(line); + } + else { + err = -1; + } + + if (err == 0) { + ctx->exception_group_depth += 1; + PyObject *exc = PyTuple_GET_ITEM(excs, i); + + if (!truncated) { + if (!Py_EnterRecursiveCall(" in print_exception_recursive")) { + print_exception_recursive(ctx, exc); + Py_LeaveRecursiveCall(); + } + else { + err = -1; + } + } + else { + Py_ssize_t excs_remaining = num_excs - ctx->max_group_width; + PyObject *line = PyUnicode_FromFormat( + "and %zd more exception%s\n", + excs_remaining, excs_remaining > 1 ? "s" : ""); + + if (line) { + if (err == 0) { + err = write_indented_margin(ctx, f); + } + if (err == 0) { + err = PyFile_WriteObject(line, f, Py_PRINT_RAW); + } + Py_DECREF(line); + } + else { + err = -1; + } + } + + if (err == 0 && last_exc && ctx->need_close) { + err = _Py_WriteIndent(EXC_INDENT(ctx), f); + if (err == 0) { + err = PyFile_WriteString( + "+------------------------------------\n", f); + } + ctx->need_close = false; + } + ctx->exception_group_depth -= 1; + } + } + if (ctx->exception_group_depth == 1) { + ctx->exception_group_depth -= 1; + } + } if (err != 0) PyErr_Clear(); } +#define PyErr_MAX_GROUP_WIDTH 15 +#define PyErr_MAX_GROUP_DEPTH 10 + void _PyErr_Display(PyObject *file, PyObject *exception, PyObject *value, PyObject *tb) { assert(file != NULL && file != Py_None); - - PyObject *seen; if (PyExceptionInstance_Check(value) && tb != NULL && PyTraceBack_Check(tb)) { /* Put the traceback on the exception, otherwise it won't get @@ -1123,15 +1340,21 @@ _PyErr_Display(PyObject *file, PyObject *exception, PyObject *value, PyObject *t Py_DECREF(cur_tb); } + struct exception_print_context ctx; + ctx.file = file; + ctx.exception_group_depth = 0; + ctx.max_group_width = PyErr_MAX_GROUP_WIDTH; + ctx.max_group_depth = PyErr_MAX_GROUP_DEPTH; + /* We choose to ignore seen being possibly NULL, and report at least the main exception (it could be a MemoryError). */ - seen = PySet_New(NULL); - if (seen == NULL) { + ctx.seen = PySet_New(NULL); + if (ctx.seen == NULL) { PyErr_Clear(); } - print_exception_recursive(file, value, seen); - Py_XDECREF(seen); + print_exception_recursive(&ctx, value); + Py_XDECREF(ctx.seen); /* Call file.flush() */ PyObject *res = _PyObject_CallMethodIdNoArgs(file, &PyId_flush); diff --git a/Python/traceback.c b/Python/traceback.c index 22a0922c255b3..67f995a759980 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -14,6 +14,7 @@ #include "pycore_pyarena.h" // _PyArena_Free() #include "pycore_pyerrors.h" // _PyErr_Fetch() #include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_traceback.h" // EXCEPTION_TB_HEADER #include "../Parser/pegen.h" // _PyPegen_byte_offset_to_character_offset() #include "structmember.h" // PyMemberDef #include "osdefs.h" // SEP @@ -379,8 +380,44 @@ _Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject * return result; } +/* Writes indent spaces. Returns 0 on success and non-zero on failure. + */ +int +_Py_WriteIndent(int indent, PyObject *f) +{ + int err = 0; + char buf[11] = " "; + assert(strlen(buf) == 10); + while (indent > 0) { + if (indent < 10) { + buf[indent] = '\0'; + } + err = PyFile_WriteString(buf, f); + if (err != 0) { + return err; + } + indent -= 10; + } + return 0; +} + +/* Writes indent spaces, followed by the margin if it is not `\0`. + Returns 0 on success and non-zero on failure. + */ int -_Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent, int *truncation, PyObject **line) +_Py_WriteIndentedMargin(int indent, const char *margin, PyObject *f) +{ + int err = _Py_WriteIndent(indent, f); + if (err == 0 && margin) { + err = PyFile_WriteString(margin, f); + } + return err; +} + +static int +display_source_line_with_margin(PyObject *f, PyObject *filename, int lineno, int indent, + int margin_indent, const char *margin, + int *truncation, PyObject **line) { int err = 0; int fd; @@ -508,27 +545,33 @@ _Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent, i *truncation = i - indent; } + if (err == 0) { + err = _Py_WriteIndentedMargin(margin_indent, margin, f); + } /* Write some spaces before the line */ - strcpy(buf, " "); - assert (strlen(buf) == 10); - while (indent > 0) { - if (indent < 10) - buf[indent] = '\0'; - err = PyFile_WriteString(buf, f); - if (err != 0) - break; - indent -= 10; + if (err == 0) { + err = _Py_WriteIndent(indent, f); } /* finally display the line */ - if (err == 0) + if (err == 0) { err = PyFile_WriteObject(lineobj, f, Py_PRINT_RAW); + } Py_DECREF(lineobj); - if (err == 0) + if (err == 0) { err = PyFile_WriteString("\n", f); + } return err; } +int +_Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent, + int *truncation, PyObject **line) +{ + return display_source_line_with_margin(f, filename, lineno, indent, 0, + NULL, truncation, line); +} + /* AST based Traceback Specialization * * When displaying a new traceback line, for certain syntactical constructs @@ -697,7 +740,7 @@ print_error_location_carets(PyObject *f, int offset, Py_ssize_t start_offset, Py static int tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int lineno, - PyFrameObject *frame, PyObject *name) + PyFrameObject *frame, PyObject *name, int margin_indent, const char *margin) { int err; PyObject *line; @@ -708,15 +751,20 @@ tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int linen filename, lineno, name); if (line == NULL) return -1; - err = PyFile_WriteObject(line, f, Py_PRINT_RAW); + err = _Py_WriteIndentedMargin(margin_indent, margin, f); + if (err == 0) { + err = PyFile_WriteObject(line, f, Py_PRINT_RAW); + } Py_DECREF(line); if (err != 0) return err; int truncation = _TRACEBACK_SOURCE_LINE_INDENT; PyObject* source_line = NULL; - if (_Py_DisplaySourceLine(f, filename, lineno, _TRACEBACK_SOURCE_LINE_INDENT, - &truncation, &source_line) != 0 || !source_line) { + int rc = display_source_line_with_margin( + f, filename, lineno, _TRACEBACK_SOURCE_LINE_INDENT, + margin_indent, margin, &truncation, &source_line); + if (rc != 0 || !source_line) { /* ignore errors since we can't report them, can we? */ err = ignore_source_errors(); goto done; @@ -801,9 +849,12 @@ tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int linen end_offset = i + 1; } - err = print_error_location_carets(f, truncation, start_offset, end_offset, - right_start_offset, left_end_offset, - primary_error_char, secondary_error_char); + err = _Py_WriteIndentedMargin(margin_indent, margin, f); + if (err == 0) { + err = print_error_location_carets(f, truncation, start_offset, end_offset, + right_start_offset, left_end_offset, + primary_error_char, secondary_error_char); + } done: Py_XDECREF(source_line); @@ -830,7 +881,8 @@ tb_print_line_repeated(PyObject *f, long cnt) } static int -tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit) +tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit, + int indent, const char *margin) { int err = 0; Py_ssize_t depth = 0; @@ -864,7 +916,7 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit) cnt++; if (err == 0 && cnt <= TB_RECURSIVE_CUTOFF) { err = tb_displayline(tb, f, code->co_filename, tb->tb_lineno, - tb->tb_frame, code->co_name); + tb->tb_frame, code->co_name, indent, margin); if (err == 0) { err = PyErr_CheckSignals(); } @@ -881,7 +933,8 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit) #define PyTraceBack_LIMIT 1000 int -PyTraceBack_Print(PyObject *v, PyObject *f) +_PyTraceBack_Print_Indented(PyObject *v, int indent, const char *margin, + const char *header_margin, const char *header, PyObject *f) { int err; PyObject *limitv; @@ -904,12 +957,27 @@ PyTraceBack_Print(PyObject *v, PyObject *f) return 0; } } - err = PyFile_WriteString("Traceback (most recent call last):\n", f); - if (!err) - err = tb_printinternal((PyTracebackObject *)v, f, limit); + err = _Py_WriteIndentedMargin(indent, header_margin, f); + if (err == 0) { + err = PyFile_WriteString(header, f); + } + if (err == 0) { + err = tb_printinternal((PyTracebackObject *)v, f, limit, indent, margin); + } return err; } +int +PyTraceBack_Print(PyObject *v, PyObject *f) +{ + int indent = 0; + const char *margin = NULL; + const char *header_margin = NULL; + const char *header = EXCEPTION_TB_HEADER; + + return _PyTraceBack_Print_Indented(v, indent, margin, header_margin, header, f); +} + /* Format an integer in range [0; 0xffffffff] to decimal and write it into the file fd. From webhook-mailer at python.org Fri Nov 5 05:59:39 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 05 Nov 2021 09:59:39 -0000 Subject: [Python-checkins] bpo-27313: Fix ttk_guionly tests failing on Framework builds on macOS (GH-29411) (GH-29422) Message-ID: https://github.com/python/cpython/commit/363ecb36da273ddb0c80ad14f3f1aa5101223bc2 commit: 363ecb36da273ddb0c80ad14f3f1aa5101223bc2 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-05T10:59:34+01:00 summary: bpo-27313: Fix ttk_guionly tests failing on Framework builds on macOS (GH-29411) (GH-29422) (cherry picked from commit e52f9bee802aa7a7fbd405dcc43bc2d1bea884d9) Co-authored-by: ?ukasz Langa files: M Lib/tkinter/test/test_ttk/test_widgets.py diff --git a/Lib/tkinter/test/test_ttk/test_widgets.py b/Lib/tkinter/test/test_ttk/test_widgets.py index 935be3d7f1b5a..1cb7e74c66ec7 100644 --- a/Lib/tkinter/test/test_ttk/test_widgets.py +++ b/Lib/tkinter/test/test_ttk/test_widgets.py @@ -61,7 +61,6 @@ def setUp(self): self.widget = ttk.Button(self.root, width=0, text="Text") self.widget.pack() - def test_identify(self): self.widget.update() self.assertEqual(self.widget.identify( @@ -74,7 +73,6 @@ def test_identify(self): self.assertRaises(tkinter.TclError, self.widget.identify, 5, None) self.assertRaises(tkinter.TclError, self.widget.identify, 5, '') - def test_widget_state(self): # XXX not sure about the portability of all these tests self.assertEqual(self.widget.state(), ()) @@ -287,6 +285,7 @@ class EntryTest(AbstractWidgetTest, unittest.TestCase): 'show', 'state', 'style', 'takefocus', 'textvariable', 'validate', 'validatecommand', 'width', 'xscrollcommand', ) + IDENTIFY_AS = 'Entry.field' if sys.platform == 'darwin' else 'textarea' def setUp(self): super().setUp() @@ -319,30 +318,23 @@ def test_configure_validatecommand(self): widget = self.create() self.checkCommandParam(widget, 'validatecommand') - def test_bbox(self): self.assertIsBoundingBox(self.entry.bbox(0)) self.assertRaises(tkinter.TclError, self.entry.bbox, 'noindex') self.assertRaises(tkinter.TclError, self.entry.bbox, None) - def test_identify(self): self.entry.pack() self.entry.update() # bpo-27313: macOS Cocoa widget differs from X, allow either - if sys.platform == 'darwin': - self.assertIn(self.entry.identify(5, 5), - ("textarea", "Combobox.button") ) - else: - self.assertEqual(self.entry.identify(5, 5), "textarea") + self.assertEqual(self.entry.identify(5, 5), self.IDENTIFY_AS) self.assertEqual(self.entry.identify(-1, -1), "") self.assertRaises(tkinter.TclError, self.entry.identify, None, 5) self.assertRaises(tkinter.TclError, self.entry.identify, 5, None) self.assertRaises(tkinter.TclError, self.entry.identify, 5, '') - def test_validation_options(self): success = [] test_invalid = lambda: success.append(True) @@ -370,7 +362,6 @@ def test_validation_options(self): self.entry['validatecommand'] = True self.assertRaises(tkinter.TclError, self.entry.validate) - def test_validation(self): validation = [] def validate(to_insert): @@ -388,7 +379,6 @@ def validate(to_insert): self.assertEqual(validation, [False, True]) self.assertEqual(self.entry.get(), 'a') - def test_revalidation(self): def validate(content): for letter in content: @@ -424,6 +414,7 @@ class ComboboxTest(EntryTest, unittest.TestCase): 'validate', 'validatecommand', 'values', 'width', 'xscrollcommand', ) + IDENTIFY_AS = 'Combobox.button' if sys.platform == 'darwin' else 'textarea' def setUp(self): super().setUp() @@ -439,7 +430,8 @@ def test_configure_height(self): def _show_drop_down_listbox(self): width = self.combo.winfo_width() x, y = width - 5, 5 - self.assertRegex(self.combo.identify(x, y), r'.*downarrow\Z') + if sys.platform != 'darwin': # there's no down arrow on macOS + self.assertRegex(self.combo.identify(x, y), r'.*downarrow\Z') self.combo.event_generate('', x=x, y=y) self.combo.event_generate('', x=x, y=y) self.combo.update_idletasks() @@ -461,7 +453,6 @@ def test_virtual_event(self): self.assertTrue(success) - def test_configure_postcommand(self): success = [] @@ -477,7 +468,6 @@ def test_configure_postcommand(self): self._show_drop_down_listbox() self.assertEqual(len(success), 1) - def test_configure_values(self): def check_get_current(getval, currval): self.assertEqual(self.combo.get(), getval) @@ -592,7 +582,6 @@ def test_add(self): other_child.destroy() self.assertRaises(tkinter.TclError, self.paned.pane, 0) - def test_forget(self): self.assertRaises(tkinter.TclError, self.paned.forget, None) self.assertRaises(tkinter.TclError, self.paned.forget, 0) @@ -601,7 +590,6 @@ def test_forget(self): self.paned.forget(0) self.assertRaises(tkinter.TclError, self.paned.forget, 0) - def test_insert(self): self.assertRaises(tkinter.TclError, self.paned.insert, None, 0) self.assertRaises(tkinter.TclError, self.paned.insert, 0, None) @@ -636,7 +624,6 @@ def test_insert(self): self.assertEqual(self.paned.panes(), (str(child3), str(child2), str(child))) - def test_pane(self): self.assertRaises(tkinter.TclError, self.paned.pane, 0) @@ -653,7 +640,6 @@ def test_pane(self): self.assertRaises(tkinter.TclError, self.paned.pane, 0, badoption='somevalue') - def test_sashpos(self): self.assertRaises(tkinter.TclError, self.paned.sashpos, None) self.assertRaises(tkinter.TclError, self.paned.sashpos, '') @@ -801,7 +787,6 @@ def test_custom_event(self): self.assertFalse(failure) - def test_get(self): if self.wantobjects: conv = lambda x: x @@ -819,7 +804,6 @@ def test_get(self): self.assertRaises(tkinter.TclError, self.scale.get, '', 0) self.assertRaises(tkinter.TclError, self.scale.get, 0, '') - def test_set(self): if self.wantobjects: conv = lambda x: x @@ -952,7 +936,6 @@ def test_tab_identifiers(self): else: self.fail("Tab with text 'a' not found") - def test_add_and_hidden(self): self.assertRaises(tkinter.TclError, self.nb.hide, -1) self.assertRaises(tkinter.TclError, self.nb.hide, 'hi') @@ -981,7 +964,6 @@ def test_add_and_hidden(self): # but the tab next to it (not hidden) is the one selected now self.assertEqual(self.nb.index('current'), curr + 1) - def test_forget(self): self.assertRaises(tkinter.TclError, self.nb.forget, -1) self.assertRaises(tkinter.TclError, self.nb.forget, 'hi') @@ -997,7 +979,6 @@ def test_forget(self): self.assertEqual(self.nb.index(self.child1), 1) self.assertNotEqual(child1_index, self.nb.index(self.child1)) - def test_index(self): self.assertRaises(tkinter.TclError, self.nb.index, -1) self.assertRaises(tkinter.TclError, self.nb.index, None) @@ -1007,7 +988,6 @@ def test_index(self): self.assertEqual(self.nb.index(self.child2), 1) self.assertEqual(self.nb.index('end'), 2) - def test_insert(self): # moving tabs tabs = self.nb.tabs() @@ -1040,7 +1020,6 @@ def test_insert(self): self.assertRaises(tkinter.TclError, self.nb.insert, None, 0) self.assertRaises(tkinter.TclError, self.nb.insert, None, None) - def test_select(self): self.nb.pack() self.nb.update() @@ -1060,7 +1039,6 @@ def test_select(self): self.nb.update() self.assertTrue(tab_changed) - def test_tab(self): self.assertRaises(tkinter.TclError, self.nb.tab, -1) self.assertRaises(tkinter.TclError, self.nb.tab, 'notab') @@ -1074,7 +1052,6 @@ def test_tab(self): self.assertEqual(self.nb.tab(self.child1, text=None), 'abc') self.assertEqual(self.nb.tab(self.child1, 'text'), 'abc') - def test_configure_tabs(self): self.assertEqual(len(self.nb.tabs()), 2) @@ -1083,14 +1060,14 @@ def test_configure_tabs(self): self.assertEqual(self.nb.tabs(), ()) - def test_traversal(self): self.nb.pack() self.nb.update() self.nb.select(0) - self.assertEqual(self.nb.identify(5, 5), 'focus') + focus_identify_as = 'focus' if sys.platform != 'darwin' else '' + self.assertEqual(self.nb.identify(5, 5), focus_identify_as) simulate_mouse_click(self.nb, 5, 5) self.nb.focus_force() self.nb.event_generate('') @@ -1103,15 +1080,24 @@ def test_traversal(self): self.assertEqual(self.nb.select(), str(self.child2)) self.nb.tab(self.child1, text='a', underline=0) + self.nb.tab(self.child2, text='e', underline=0) self.nb.enable_traversal() self.nb.focus_force() - self.assertEqual(self.nb.identify(5, 5), 'focus') + self.assertEqual(self.nb.identify(5, 5), focus_identify_as) simulate_mouse_click(self.nb, 5, 5) + # on macOS Emacs-style keyboard shortcuts are region-dependent; + # let's use the regular arrow keys instead if sys.platform == 'darwin': - self.nb.event_generate('') + begin = '' + end = '' else: - self.nb.event_generate('') + begin = '' + end = '' + self.nb.event_generate(begin) self.assertEqual(self.nb.select(), str(self.child1)) + self.nb.event_generate(end) + self.assertEqual(self.nb.select(), str(self.child2)) + @add_standard_options(IntegerSizeTests, StandardTtkOptionsTests) class SpinboxTest(EntryTest, unittest.TestCase): @@ -1122,6 +1108,7 @@ class SpinboxTest(EntryTest, unittest.TestCase): 'takefocus', 'textvariable', 'to', 'validate', 'validatecommand', 'values', 'width', 'wrap', 'xscrollcommand', ) + IDENTIFY_AS = 'Spinbox.field' if sys.platform == 'darwin' else 'textarea' def setUp(self): super().setUp() @@ -1370,7 +1357,6 @@ def test_bbox(self): child1 = self.tv.insert(item_id, 'end') self.assertEqual(self.tv.bbox(child1), '') - def test_children(self): # no children yet, should get an empty tuple self.assertEqual(self.tv.get_children(), ()) @@ -1398,7 +1384,6 @@ def test_children(self): self.tv.set_children('') self.assertEqual(self.tv.get_children(), ()) - def test_column(self): # return a dict with all options/values self.assertIsInstance(self.tv.column('#0'), dict) @@ -1424,7 +1409,6 @@ def test_column(self): self.assertRaises(tkinter.TclError, self.tv.column, '#0', **kw) - def test_delete(self): self.assertRaises(tkinter.TclError, self.tv.delete, '#0') @@ -1448,7 +1432,6 @@ def test_delete(self): self.tv.delete(item1, item2) self.assertFalse(self.tv.get_children()) - def test_detach_reattach(self): item_id = self.tv.insert('', 'end') item2 = self.tv.insert(item_id, 'end') @@ -1490,7 +1473,6 @@ def test_detach_reattach(self): self.assertEqual(self.tv.get_children(), ()) self.assertEqual(self.tv.get_children(item_id), ()) - def test_exists(self): self.assertEqual(self.tv.exists('something'), False) self.assertEqual(self.tv.exists(''), True) @@ -1501,7 +1483,6 @@ def test_exists(self): # in the tcl interpreter since tk requires an item. self.assertRaises(tkinter.TclError, self.tv.exists, None) - def test_focus(self): # nothing is focused right now self.assertEqual(self.tv.focus(), '') @@ -1516,7 +1497,6 @@ def test_focus(self): # try focusing inexistent item self.assertRaises(tkinter.TclError, self.tv.focus, 'hi') - def test_heading(self): # check a dict is returned self.assertIsInstance(self.tv.heading('#0'), dict) @@ -1568,7 +1548,6 @@ def simulate_heading_click(x, y): #self.tv.heading('#0', command='I dont exist') #simulate_heading_click(5, 5) - def test_index(self): # item 'what' doesn't exist self.assertRaises(tkinter.TclError, self.tv.index, 'what') @@ -1599,7 +1578,6 @@ def test_index(self): self.tv.delete(item1) self.assertRaises(tkinter.TclError, self.tv.index, c2) - def test_insert_item(self): # parent 'none' doesn't exist self.assertRaises(tkinter.TclError, self.tv.insert, 'none', 'end') @@ -1676,7 +1654,6 @@ def test_insert_item(self): self.assertRaises(tkinter.TclError, self.tv.insert, '', 'end', False) self.assertRaises(tkinter.TclError, self.tv.insert, '', 'end', '') - def test_selection(self): self.assertRaises(TypeError, self.tv.selection, 'spam') # item 'none' doesn't exist @@ -1747,7 +1724,6 @@ def test_selection(self): self.tv.selection_toggle((c1, c3)) self.assertEqual(self.tv.selection(), (c3, item2)) - def test_set(self): self.tv['columns'] = ['A', 'B'] item = self.tv.insert('', 'end', values=['a', 'b']) @@ -1780,7 +1756,6 @@ def test_set(self): # inexistent item self.assertRaises(tkinter.TclError, self.tv.set, 'notme') - def test_tag_bind(self): events = [] item1 = self.tv.insert('', 'end', tags=['call']) @@ -1813,7 +1788,6 @@ def test_tag_bind(self): for evt in zip(events[::2], events[1::2]): self.assertEqual(evt, (1, 2)) - def test_tag_configure(self): # Just testing parameter passing for now self.assertRaises(TypeError, self.tv.tag_configure) From webhook-mailer at python.org Fri Nov 5 05:59:55 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 05 Nov 2021 09:59:55 -0000 Subject: [Python-checkins] bpo-27313: Fix ttk_guionly tests failing on Framework builds on macOS (GH-29411) (GH-29423) Message-ID: https://github.com/python/cpython/commit/885e57c148d0b2c34daa2b7e5162dc57cf7e4469 commit: 885e57c148d0b2c34daa2b7e5162dc57cf7e4469 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-05T10:59:50+01:00 summary: bpo-27313: Fix ttk_guionly tests failing on Framework builds on macOS (GH-29411) (GH-29423) (cherry picked from commit e52f9bee802aa7a7fbd405dcc43bc2d1bea884d9) Co-authored-by: ?ukasz Langa files: M Lib/tkinter/test/test_ttk/test_widgets.py diff --git a/Lib/tkinter/test/test_ttk/test_widgets.py b/Lib/tkinter/test/test_ttk/test_widgets.py index 935be3d7f1b5a..1cb7e74c66ec7 100644 --- a/Lib/tkinter/test/test_ttk/test_widgets.py +++ b/Lib/tkinter/test/test_ttk/test_widgets.py @@ -61,7 +61,6 @@ def setUp(self): self.widget = ttk.Button(self.root, width=0, text="Text") self.widget.pack() - def test_identify(self): self.widget.update() self.assertEqual(self.widget.identify( @@ -74,7 +73,6 @@ def test_identify(self): self.assertRaises(tkinter.TclError, self.widget.identify, 5, None) self.assertRaises(tkinter.TclError, self.widget.identify, 5, '') - def test_widget_state(self): # XXX not sure about the portability of all these tests self.assertEqual(self.widget.state(), ()) @@ -287,6 +285,7 @@ class EntryTest(AbstractWidgetTest, unittest.TestCase): 'show', 'state', 'style', 'takefocus', 'textvariable', 'validate', 'validatecommand', 'width', 'xscrollcommand', ) + IDENTIFY_AS = 'Entry.field' if sys.platform == 'darwin' else 'textarea' def setUp(self): super().setUp() @@ -319,30 +318,23 @@ def test_configure_validatecommand(self): widget = self.create() self.checkCommandParam(widget, 'validatecommand') - def test_bbox(self): self.assertIsBoundingBox(self.entry.bbox(0)) self.assertRaises(tkinter.TclError, self.entry.bbox, 'noindex') self.assertRaises(tkinter.TclError, self.entry.bbox, None) - def test_identify(self): self.entry.pack() self.entry.update() # bpo-27313: macOS Cocoa widget differs from X, allow either - if sys.platform == 'darwin': - self.assertIn(self.entry.identify(5, 5), - ("textarea", "Combobox.button") ) - else: - self.assertEqual(self.entry.identify(5, 5), "textarea") + self.assertEqual(self.entry.identify(5, 5), self.IDENTIFY_AS) self.assertEqual(self.entry.identify(-1, -1), "") self.assertRaises(tkinter.TclError, self.entry.identify, None, 5) self.assertRaises(tkinter.TclError, self.entry.identify, 5, None) self.assertRaises(tkinter.TclError, self.entry.identify, 5, '') - def test_validation_options(self): success = [] test_invalid = lambda: success.append(True) @@ -370,7 +362,6 @@ def test_validation_options(self): self.entry['validatecommand'] = True self.assertRaises(tkinter.TclError, self.entry.validate) - def test_validation(self): validation = [] def validate(to_insert): @@ -388,7 +379,6 @@ def validate(to_insert): self.assertEqual(validation, [False, True]) self.assertEqual(self.entry.get(), 'a') - def test_revalidation(self): def validate(content): for letter in content: @@ -424,6 +414,7 @@ class ComboboxTest(EntryTest, unittest.TestCase): 'validate', 'validatecommand', 'values', 'width', 'xscrollcommand', ) + IDENTIFY_AS = 'Combobox.button' if sys.platform == 'darwin' else 'textarea' def setUp(self): super().setUp() @@ -439,7 +430,8 @@ def test_configure_height(self): def _show_drop_down_listbox(self): width = self.combo.winfo_width() x, y = width - 5, 5 - self.assertRegex(self.combo.identify(x, y), r'.*downarrow\Z') + if sys.platform != 'darwin': # there's no down arrow on macOS + self.assertRegex(self.combo.identify(x, y), r'.*downarrow\Z') self.combo.event_generate('', x=x, y=y) self.combo.event_generate('', x=x, y=y) self.combo.update_idletasks() @@ -461,7 +453,6 @@ def test_virtual_event(self): self.assertTrue(success) - def test_configure_postcommand(self): success = [] @@ -477,7 +468,6 @@ def test_configure_postcommand(self): self._show_drop_down_listbox() self.assertEqual(len(success), 1) - def test_configure_values(self): def check_get_current(getval, currval): self.assertEqual(self.combo.get(), getval) @@ -592,7 +582,6 @@ def test_add(self): other_child.destroy() self.assertRaises(tkinter.TclError, self.paned.pane, 0) - def test_forget(self): self.assertRaises(tkinter.TclError, self.paned.forget, None) self.assertRaises(tkinter.TclError, self.paned.forget, 0) @@ -601,7 +590,6 @@ def test_forget(self): self.paned.forget(0) self.assertRaises(tkinter.TclError, self.paned.forget, 0) - def test_insert(self): self.assertRaises(tkinter.TclError, self.paned.insert, None, 0) self.assertRaises(tkinter.TclError, self.paned.insert, 0, None) @@ -636,7 +624,6 @@ def test_insert(self): self.assertEqual(self.paned.panes(), (str(child3), str(child2), str(child))) - def test_pane(self): self.assertRaises(tkinter.TclError, self.paned.pane, 0) @@ -653,7 +640,6 @@ def test_pane(self): self.assertRaises(tkinter.TclError, self.paned.pane, 0, badoption='somevalue') - def test_sashpos(self): self.assertRaises(tkinter.TclError, self.paned.sashpos, None) self.assertRaises(tkinter.TclError, self.paned.sashpos, '') @@ -801,7 +787,6 @@ def test_custom_event(self): self.assertFalse(failure) - def test_get(self): if self.wantobjects: conv = lambda x: x @@ -819,7 +804,6 @@ def test_get(self): self.assertRaises(tkinter.TclError, self.scale.get, '', 0) self.assertRaises(tkinter.TclError, self.scale.get, 0, '') - def test_set(self): if self.wantobjects: conv = lambda x: x @@ -952,7 +936,6 @@ def test_tab_identifiers(self): else: self.fail("Tab with text 'a' not found") - def test_add_and_hidden(self): self.assertRaises(tkinter.TclError, self.nb.hide, -1) self.assertRaises(tkinter.TclError, self.nb.hide, 'hi') @@ -981,7 +964,6 @@ def test_add_and_hidden(self): # but the tab next to it (not hidden) is the one selected now self.assertEqual(self.nb.index('current'), curr + 1) - def test_forget(self): self.assertRaises(tkinter.TclError, self.nb.forget, -1) self.assertRaises(tkinter.TclError, self.nb.forget, 'hi') @@ -997,7 +979,6 @@ def test_forget(self): self.assertEqual(self.nb.index(self.child1), 1) self.assertNotEqual(child1_index, self.nb.index(self.child1)) - def test_index(self): self.assertRaises(tkinter.TclError, self.nb.index, -1) self.assertRaises(tkinter.TclError, self.nb.index, None) @@ -1007,7 +988,6 @@ def test_index(self): self.assertEqual(self.nb.index(self.child2), 1) self.assertEqual(self.nb.index('end'), 2) - def test_insert(self): # moving tabs tabs = self.nb.tabs() @@ -1040,7 +1020,6 @@ def test_insert(self): self.assertRaises(tkinter.TclError, self.nb.insert, None, 0) self.assertRaises(tkinter.TclError, self.nb.insert, None, None) - def test_select(self): self.nb.pack() self.nb.update() @@ -1060,7 +1039,6 @@ def test_select(self): self.nb.update() self.assertTrue(tab_changed) - def test_tab(self): self.assertRaises(tkinter.TclError, self.nb.tab, -1) self.assertRaises(tkinter.TclError, self.nb.tab, 'notab') @@ -1074,7 +1052,6 @@ def test_tab(self): self.assertEqual(self.nb.tab(self.child1, text=None), 'abc') self.assertEqual(self.nb.tab(self.child1, 'text'), 'abc') - def test_configure_tabs(self): self.assertEqual(len(self.nb.tabs()), 2) @@ -1083,14 +1060,14 @@ def test_configure_tabs(self): self.assertEqual(self.nb.tabs(), ()) - def test_traversal(self): self.nb.pack() self.nb.update() self.nb.select(0) - self.assertEqual(self.nb.identify(5, 5), 'focus') + focus_identify_as = 'focus' if sys.platform != 'darwin' else '' + self.assertEqual(self.nb.identify(5, 5), focus_identify_as) simulate_mouse_click(self.nb, 5, 5) self.nb.focus_force() self.nb.event_generate('') @@ -1103,15 +1080,24 @@ def test_traversal(self): self.assertEqual(self.nb.select(), str(self.child2)) self.nb.tab(self.child1, text='a', underline=0) + self.nb.tab(self.child2, text='e', underline=0) self.nb.enable_traversal() self.nb.focus_force() - self.assertEqual(self.nb.identify(5, 5), 'focus') + self.assertEqual(self.nb.identify(5, 5), focus_identify_as) simulate_mouse_click(self.nb, 5, 5) + # on macOS Emacs-style keyboard shortcuts are region-dependent; + # let's use the regular arrow keys instead if sys.platform == 'darwin': - self.nb.event_generate('') + begin = '' + end = '' else: - self.nb.event_generate('') + begin = '' + end = '' + self.nb.event_generate(begin) self.assertEqual(self.nb.select(), str(self.child1)) + self.nb.event_generate(end) + self.assertEqual(self.nb.select(), str(self.child2)) + @add_standard_options(IntegerSizeTests, StandardTtkOptionsTests) class SpinboxTest(EntryTest, unittest.TestCase): @@ -1122,6 +1108,7 @@ class SpinboxTest(EntryTest, unittest.TestCase): 'takefocus', 'textvariable', 'to', 'validate', 'validatecommand', 'values', 'width', 'wrap', 'xscrollcommand', ) + IDENTIFY_AS = 'Spinbox.field' if sys.platform == 'darwin' else 'textarea' def setUp(self): super().setUp() @@ -1370,7 +1357,6 @@ def test_bbox(self): child1 = self.tv.insert(item_id, 'end') self.assertEqual(self.tv.bbox(child1), '') - def test_children(self): # no children yet, should get an empty tuple self.assertEqual(self.tv.get_children(), ()) @@ -1398,7 +1384,6 @@ def test_children(self): self.tv.set_children('') self.assertEqual(self.tv.get_children(), ()) - def test_column(self): # return a dict with all options/values self.assertIsInstance(self.tv.column('#0'), dict) @@ -1424,7 +1409,6 @@ def test_column(self): self.assertRaises(tkinter.TclError, self.tv.column, '#0', **kw) - def test_delete(self): self.assertRaises(tkinter.TclError, self.tv.delete, '#0') @@ -1448,7 +1432,6 @@ def test_delete(self): self.tv.delete(item1, item2) self.assertFalse(self.tv.get_children()) - def test_detach_reattach(self): item_id = self.tv.insert('', 'end') item2 = self.tv.insert(item_id, 'end') @@ -1490,7 +1473,6 @@ def test_detach_reattach(self): self.assertEqual(self.tv.get_children(), ()) self.assertEqual(self.tv.get_children(item_id), ()) - def test_exists(self): self.assertEqual(self.tv.exists('something'), False) self.assertEqual(self.tv.exists(''), True) @@ -1501,7 +1483,6 @@ def test_exists(self): # in the tcl interpreter since tk requires an item. self.assertRaises(tkinter.TclError, self.tv.exists, None) - def test_focus(self): # nothing is focused right now self.assertEqual(self.tv.focus(), '') @@ -1516,7 +1497,6 @@ def test_focus(self): # try focusing inexistent item self.assertRaises(tkinter.TclError, self.tv.focus, 'hi') - def test_heading(self): # check a dict is returned self.assertIsInstance(self.tv.heading('#0'), dict) @@ -1568,7 +1548,6 @@ def simulate_heading_click(x, y): #self.tv.heading('#0', command='I dont exist') #simulate_heading_click(5, 5) - def test_index(self): # item 'what' doesn't exist self.assertRaises(tkinter.TclError, self.tv.index, 'what') @@ -1599,7 +1578,6 @@ def test_index(self): self.tv.delete(item1) self.assertRaises(tkinter.TclError, self.tv.index, c2) - def test_insert_item(self): # parent 'none' doesn't exist self.assertRaises(tkinter.TclError, self.tv.insert, 'none', 'end') @@ -1676,7 +1654,6 @@ def test_insert_item(self): self.assertRaises(tkinter.TclError, self.tv.insert, '', 'end', False) self.assertRaises(tkinter.TclError, self.tv.insert, '', 'end', '') - def test_selection(self): self.assertRaises(TypeError, self.tv.selection, 'spam') # item 'none' doesn't exist @@ -1747,7 +1724,6 @@ def test_selection(self): self.tv.selection_toggle((c1, c3)) self.assertEqual(self.tv.selection(), (c3, item2)) - def test_set(self): self.tv['columns'] = ['A', 'B'] item = self.tv.insert('', 'end', values=['a', 'b']) @@ -1780,7 +1756,6 @@ def test_set(self): # inexistent item self.assertRaises(tkinter.TclError, self.tv.set, 'notme') - def test_tag_bind(self): events = [] item1 = self.tv.insert('', 'end', tags=['call']) @@ -1813,7 +1788,6 @@ def test_tag_bind(self): for evt in zip(events[::2], events[1::2]): self.assertEqual(evt, (1, 2)) - def test_tag_configure(self): # Just testing parameter passing for now self.assertRaises(TypeError, self.tv.tag_configure) From webhook-mailer at python.org Fri Nov 5 06:00:10 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 05 Nov 2021 10:00:10 -0000 Subject: [Python-checkins] bpo-45160: Fix refleak in test_ttk_guionly introduced in GH-28291 (GH-29416) (GH-29420) Message-ID: https://github.com/python/cpython/commit/276a3a6a16ebf489607db31ad86c58dd89567306 commit: 276a3a6a16ebf489607db31ad86c58dd89567306 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-05T11:00:05+01:00 summary: bpo-45160: Fix refleak in test_ttk_guionly introduced in GH-28291 (GH-29416) (GH-29420) (cherry picked from commit 54d1e3f72ed1ad8e860888c30ee7a285b931c0d1) Co-authored-by: ?ukasz Langa files: M Lib/tkinter/test/test_ttk/test_extensions.py diff --git a/Lib/tkinter/test/test_ttk/test_extensions.py b/Lib/tkinter/test/test_ttk/test_extensions.py index cddd1f2e84834..7fc1ebb95c970 100644 --- a/Lib/tkinter/test/test_ttk/test_extensions.py +++ b/Lib/tkinter/test/test_ttk/test_extensions.py @@ -310,9 +310,12 @@ def cb_test(*args): self.assertEqual(textvar.get(), items[1]) success.append(True) optmenu = ttk.OptionMenu(self.root, textvar, "a", *items) - textvar.trace("w", cb_test) + optmenu.pack() + cb_name = textvar.trace("w", cb_test) optmenu['menu'].invoke(1) self.assertEqual(success, [True]) + textvar.trace_vdelete("w", cb_name) + optmenu.destroy() class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase): From webhook-mailer at python.org Fri Nov 5 06:00:23 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 05 Nov 2021 10:00:23 -0000 Subject: [Python-checkins] bpo-45160: Fix refleak in test_ttk_guionly introduced in GH-28291 (GH-29416) (GH-29421) Message-ID: https://github.com/python/cpython/commit/099a94fba3f9437e29d16ed54215ec8cf65de868 commit: 099a94fba3f9437e29d16ed54215ec8cf65de868 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-05T11:00:18+01:00 summary: bpo-45160: Fix refleak in test_ttk_guionly introduced in GH-28291 (GH-29416) (GH-29421) (cherry picked from commit 54d1e3f72ed1ad8e860888c30ee7a285b931c0d1) Co-authored-by: ?ukasz Langa files: M Lib/tkinter/test/test_ttk/test_extensions.py diff --git a/Lib/tkinter/test/test_ttk/test_extensions.py b/Lib/tkinter/test/test_ttk/test_extensions.py index cddd1f2e84834..7fc1ebb95c970 100644 --- a/Lib/tkinter/test/test_ttk/test_extensions.py +++ b/Lib/tkinter/test/test_ttk/test_extensions.py @@ -310,9 +310,12 @@ def cb_test(*args): self.assertEqual(textvar.get(), items[1]) success.append(True) optmenu = ttk.OptionMenu(self.root, textvar, "a", *items) - textvar.trace("w", cb_test) + optmenu.pack() + cb_name = textvar.trace("w", cb_test) optmenu['menu'].invoke(1) self.assertEqual(success, [True]) + textvar.trace_vdelete("w", cb_name) + optmenu.destroy() class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase): From webhook-mailer at python.org Fri Nov 5 06:06:27 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 05 Nov 2021 10:06:27 -0000 Subject: [Python-checkins] bpo-45678: Add more ``singledispatchmethod`` tests (GH-29412) Message-ID: https://github.com/python/cpython/commit/32f55d1a5de66f9a86964fc0655d7a006a9d90b9 commit: 32f55d1a5de66f9a86964fc0655d7a006a9d90b9 branch: main author: Alex Waygood committer: ambv date: 2021-11-05T11:06:18+01:00 summary: bpo-45678: Add more ``singledispatchmethod`` tests (GH-29412) In order to fix a bug in the 3.9 branch in #29394, more tests were added to ``test_functools.py`` to ensure that ``singledispatchmethod`` still correctly wrapped a target method, even if the target method had already been wrapped by multiple other decorators. This PR brings the new tests into the 3.11 and 3.10 branches as well. files: A Misc/NEWS.d/next/Tests/2021-11-04-20-03-32.bpo-45678.1xNMjN.rst M Lib/test/test_functools.py diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 1a3c921509d5e..7bc355ff7213e 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -2519,6 +2519,105 @@ def static_func(arg: int) -> str: self.assertEqual(A.static_func.__name__, 'static_func') self.assertEqual(A().static_func.__name__, 'static_func') + def test_double_wrapped_methods(self): + def classmethod_friendly_decorator(func): + wrapped = func.__func__ + @classmethod + @functools.wraps(wrapped) + def wrapper(*args, **kwargs): + return wrapped(*args, **kwargs) + return wrapper + + class WithoutSingleDispatch: + @classmethod + @contextlib.contextmanager + def cls_context_manager(cls, arg: int) -> str: + try: + yield str(arg) + finally: + return 'Done' + + @classmethod_friendly_decorator + @classmethod + def decorated_classmethod(cls, arg: int) -> str: + return str(arg) + + class WithSingleDispatch: + @functools.singledispatchmethod + @classmethod + @contextlib.contextmanager + def cls_context_manager(cls, arg: int) -> str: + """My function docstring""" + try: + yield str(arg) + finally: + return 'Done' + + @functools.singledispatchmethod + @classmethod_friendly_decorator + @classmethod + def decorated_classmethod(cls, arg: int) -> str: + """My function docstring""" + return str(arg) + + # These are sanity checks + # to test the test itself is working as expected + with WithoutSingleDispatch.cls_context_manager(5) as foo: + without_single_dispatch_foo = foo + + with WithSingleDispatch.cls_context_manager(5) as foo: + single_dispatch_foo = foo + + self.assertEqual(without_single_dispatch_foo, single_dispatch_foo) + self.assertEqual(single_dispatch_foo, '5') + + self.assertEqual( + WithoutSingleDispatch.decorated_classmethod(5), + WithSingleDispatch.decorated_classmethod(5) + ) + + self.assertEqual(WithSingleDispatch.decorated_classmethod(5), '5') + + # Behavioural checks now follow + for method_name in ('cls_context_manager', 'decorated_classmethod'): + with self.subTest(method=method_name): + self.assertEqual( + getattr(WithSingleDispatch, method_name).__name__, + getattr(WithoutSingleDispatch, method_name).__name__ + ) + + self.assertEqual( + getattr(WithSingleDispatch(), method_name).__name__, + getattr(WithoutSingleDispatch(), method_name).__name__ + ) + + for meth in ( + WithSingleDispatch.cls_context_manager, + WithSingleDispatch().cls_context_manager, + WithSingleDispatch.decorated_classmethod, + WithSingleDispatch().decorated_classmethod + ): + with self.subTest(meth=meth): + self.assertEqual(meth.__doc__, 'My function docstring') + self.assertEqual(meth.__annotations__['arg'], int) + + self.assertEqual( + WithSingleDispatch.cls_context_manager.__name__, + 'cls_context_manager' + ) + self.assertEqual( + WithSingleDispatch().cls_context_manager.__name__, + 'cls_context_manager' + ) + self.assertEqual( + WithSingleDispatch.decorated_classmethod.__name__, + 'decorated_classmethod' + ) + self.assertEqual( + WithSingleDispatch().decorated_classmethod.__name__, + 'decorated_classmethod' + ) + def test_invalid_registrations(self): msg_prefix = "Invalid first argument to `register()`: " msg_suffix = ( diff --git a/Misc/NEWS.d/next/Tests/2021-11-04-20-03-32.bpo-45678.1xNMjN.rst b/Misc/NEWS.d/next/Tests/2021-11-04-20-03-32.bpo-45678.1xNMjN.rst new file mode 100644 index 0000000000000..736d5f65f961b --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-11-04-20-03-32.bpo-45678.1xNMjN.rst @@ -0,0 +1,3 @@ +Add tests for scenarios in which :class:`functools.singledispatchmethod` is +stacked on top of a method that has already been wrapped by two other +decorators. Patch by Alex Waygood. From webhook-mailer at python.org Fri Nov 5 09:55:11 2021 From: webhook-mailer at python.org (pablogsal) Date: Fri, 05 Nov 2021 13:55:11 -0000 Subject: [Python-checkins] bpo-45716: Improve the error message when using True/False/None as keywords in a call (GH-29413) Message-ID: https://github.com/python/cpython/commit/e2d65630f36712dbdbf7711520c985c526a5cc25 commit: e2d65630f36712dbdbf7711520c985c526a5cc25 branch: main author: Pablo Galindo Salgado committer: pablogsal date: 2021-11-05T13:54:55Z summary: bpo-45716: Improve the error message when using True/False/None as keywords in a call (GH-29413) files: A Misc/NEWS.d/next/Core and Builtins/2021-11-04-20-19-07.bpo-45716.5C0pA1.rst M Grammar/python.gram M Lib/test/test_syntax.py M Parser/parser.c diff --git a/Grammar/python.gram b/Grammar/python.gram index a8c693d74075a..ffe035f037101 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -1062,6 +1062,8 @@ invalid_arguments: RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, asdl_seq_GET(b, b->size-1)->target, "Generator expression must be parenthesized") } | a=args ',' args { _PyPegen_arguments_parsing_error(p, a) } invalid_kwarg: + | a[Token*]=('True'|'False'|'None') b='=' { + RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "cannot assign to %s", PyBytes_AS_STRING(a->bytes)) } | a=NAME b='=' expression for_if_clauses { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "invalid syntax. Maybe you meant '==' or ':=' instead of '='?")} | !(NAME '=') a=expression b='=' { diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 3ce362788da6e..014a30aa2a612 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -524,9 +524,15 @@ >>> f((x)=2) Traceback (most recent call last): SyntaxError: expression cannot contain assignment, perhaps you meant "=="? ->>> f(True=2) +>>> f(True=1) Traceback (most recent call last): -SyntaxError: expression cannot contain assignment, perhaps you meant "=="? +SyntaxError: cannot assign to True +>>> f(False=1) +Traceback (most recent call last): +SyntaxError: cannot assign to False +>>> f(None=1) +Traceback (most recent call last): +SyntaxError: cannot assign to None >>> f(__debug__=1) Traceback (most recent call last): SyntaxError: cannot assign to __debug__ diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-04-20-19-07.bpo-45716.5C0pA1.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-04-20-19-07.bpo-45716.5C0pA1.rst new file mode 100644 index 0000000000000..682900c295416 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-04-20-19-07.bpo-45716.5C0pA1.rst @@ -0,0 +1,2 @@ +Improve the :exc:`SyntaxError` message when using ``True``, ``None`` or +``False`` as keywords in a function call. Patch by Pablo Galindo. diff --git a/Parser/parser.c b/Parser/parser.c index 42f6f733326b3..8ef7980d66b59 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -11,18 +11,18 @@ static KeywordToken *reserved_keywords[] = { (KeywordToken[]) {{NULL, -1}}, (KeywordToken[]) {{NULL, -1}}, (KeywordToken[]) { - {"if", 624}, - {"as", 622}, - {"in", 631}, + {"if", 627}, + {"as", 625}, + {"in", 634}, {"or", 571}, {"is", 579}, {NULL, -1}, }, (KeywordToken[]) { - {"del", 597}, - {"def", 632}, - {"for", 630}, - {"try", 609}, + {"del", 600}, + {"def", 635}, + {"for", 633}, + {"try", 612}, {"and", 572}, {"not", 578}, {NULL, -1}, @@ -30,20 +30,20 @@ static KeywordToken *reserved_keywords[] = { (KeywordToken[]) { {"from", 569}, {"pass", 504}, - {"with", 606}, - {"elif", 626}, - {"else", 627}, - {"None", 595}, - {"True", 594}, + {"with", 609}, + {"elif", 629}, + {"else", 630}, + {"None", 598}, + {"True", 597}, {NULL, -1}, }, (KeywordToken[]) { {"raise", 522}, {"yield", 570}, {"break", 508}, - {"class", 633}, - {"while", 629}, - {"False", 596}, + {"class", 636}, + {"while", 632}, + {"False", 599}, {NULL, -1}, }, (KeywordToken[]) { @@ -51,12 +51,12 @@ static KeywordToken *reserved_keywords[] = { {"import", 531}, {"assert", 526}, {"global", 523}, - {"except", 620}, + {"except", 623}, {"lambda", 583}, {NULL, -1}, }, (KeywordToken[]) { - {"finally", 617}, + {"finally", 620}, {NULL, -1}, }, (KeywordToken[]) { @@ -439,38 +439,38 @@ static char *soft_keywords[] = { #define _tmp_145_type 1365 #define _tmp_146_type 1366 #define _tmp_147_type 1367 -#define _loop0_148_type 1368 +#define _tmp_148_type 1368 #define _loop0_149_type 1369 #define _loop0_150_type 1370 -#define _tmp_151_type 1371 +#define _loop0_151_type 1371 #define _tmp_152_type 1372 #define _tmp_153_type 1373 #define _tmp_154_type 1374 -#define _loop0_155_type 1375 -#define _loop1_156_type 1376 -#define _loop0_157_type 1377 -#define _loop1_158_type 1378 -#define _tmp_159_type 1379 +#define _tmp_155_type 1375 +#define _loop0_156_type 1376 +#define _loop1_157_type 1377 +#define _loop0_158_type 1378 +#define _loop1_159_type 1379 #define _tmp_160_type 1380 #define _tmp_161_type 1381 -#define _loop0_163_type 1382 -#define _gather_162_type 1383 -#define _loop0_165_type 1384 -#define _gather_164_type 1385 -#define _loop0_167_type 1386 -#define _gather_166_type 1387 -#define _loop0_169_type 1388 -#define _gather_168_type 1389 -#define _tmp_170_type 1390 +#define _tmp_162_type 1382 +#define _loop0_164_type 1383 +#define _gather_163_type 1384 +#define _loop0_166_type 1385 +#define _gather_165_type 1386 +#define _loop0_168_type 1387 +#define _gather_167_type 1388 +#define _loop0_170_type 1389 +#define _gather_169_type 1390 #define _tmp_171_type 1391 #define _tmp_172_type 1392 #define _tmp_173_type 1393 #define _tmp_174_type 1394 #define _tmp_175_type 1395 #define _tmp_176_type 1396 -#define _loop0_178_type 1397 -#define _gather_177_type 1398 -#define _tmp_179_type 1399 +#define _tmp_177_type 1397 +#define _loop0_179_type 1398 +#define _gather_178_type 1399 #define _tmp_180_type 1400 #define _tmp_181_type 1401 #define _tmp_182_type 1402 @@ -497,6 +497,7 @@ static char *soft_keywords[] = { #define _tmp_203_type 1423 #define _tmp_204_type 1424 #define _tmp_205_type 1425 +#define _tmp_206_type 1426 static mod_ty file_rule(Parser *p); static mod_ty interactive_rule(Parser *p); @@ -866,38 +867,38 @@ static void *_tmp_144_rule(Parser *p); static void *_tmp_145_rule(Parser *p); static void *_tmp_146_rule(Parser *p); static void *_tmp_147_rule(Parser *p); -static asdl_seq *_loop0_148_rule(Parser *p); +static void *_tmp_148_rule(Parser *p); static asdl_seq *_loop0_149_rule(Parser *p); static asdl_seq *_loop0_150_rule(Parser *p); -static void *_tmp_151_rule(Parser *p); +static asdl_seq *_loop0_151_rule(Parser *p); static void *_tmp_152_rule(Parser *p); static void *_tmp_153_rule(Parser *p); static void *_tmp_154_rule(Parser *p); -static asdl_seq *_loop0_155_rule(Parser *p); -static asdl_seq *_loop1_156_rule(Parser *p); -static asdl_seq *_loop0_157_rule(Parser *p); -static asdl_seq *_loop1_158_rule(Parser *p); -static void *_tmp_159_rule(Parser *p); +static void *_tmp_155_rule(Parser *p); +static asdl_seq *_loop0_156_rule(Parser *p); +static asdl_seq *_loop1_157_rule(Parser *p); +static asdl_seq *_loop0_158_rule(Parser *p); +static asdl_seq *_loop1_159_rule(Parser *p); static void *_tmp_160_rule(Parser *p); static void *_tmp_161_rule(Parser *p); -static asdl_seq *_loop0_163_rule(Parser *p); -static asdl_seq *_gather_162_rule(Parser *p); -static asdl_seq *_loop0_165_rule(Parser *p); -static asdl_seq *_gather_164_rule(Parser *p); -static asdl_seq *_loop0_167_rule(Parser *p); -static asdl_seq *_gather_166_rule(Parser *p); -static asdl_seq *_loop0_169_rule(Parser *p); -static asdl_seq *_gather_168_rule(Parser *p); -static void *_tmp_170_rule(Parser *p); +static void *_tmp_162_rule(Parser *p); +static asdl_seq *_loop0_164_rule(Parser *p); +static asdl_seq *_gather_163_rule(Parser *p); +static asdl_seq *_loop0_166_rule(Parser *p); +static asdl_seq *_gather_165_rule(Parser *p); +static asdl_seq *_loop0_168_rule(Parser *p); +static asdl_seq *_gather_167_rule(Parser *p); +static asdl_seq *_loop0_170_rule(Parser *p); +static asdl_seq *_gather_169_rule(Parser *p); static void *_tmp_171_rule(Parser *p); static void *_tmp_172_rule(Parser *p); static void *_tmp_173_rule(Parser *p); static void *_tmp_174_rule(Parser *p); static void *_tmp_175_rule(Parser *p); static void *_tmp_176_rule(Parser *p); -static asdl_seq *_loop0_178_rule(Parser *p); -static asdl_seq *_gather_177_rule(Parser *p); -static void *_tmp_179_rule(Parser *p); +static void *_tmp_177_rule(Parser *p); +static asdl_seq *_loop0_179_rule(Parser *p); +static asdl_seq *_gather_178_rule(Parser *p); static void *_tmp_180_rule(Parser *p); static void *_tmp_181_rule(Parser *p); static void *_tmp_182_rule(Parser *p); @@ -924,6 +925,7 @@ static void *_tmp_202_rule(Parser *p); static void *_tmp_203_rule(Parser *p); static void *_tmp_204_rule(Parser *p); static void *_tmp_205_rule(Parser *p); +static void *_tmp_206_rule(Parser *p); // file: statements? $ @@ -1658,7 +1660,7 @@ simple_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'del' del_stmt")); stmt_ty del_stmt_var; if ( - _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 597) // token='del' + _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 600) // token='del' && (del_stmt_var = del_stmt_rule(p)) // del_stmt ) @@ -1876,7 +1878,7 @@ compound_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'if' if_stmt")); stmt_ty if_stmt_var; if ( - _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 624) // token='if' + _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 627) // token='if' && (if_stmt_var = if_stmt_rule(p)) // if_stmt ) @@ -1960,7 +1962,7 @@ compound_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'try' try_stmt")); stmt_ty try_stmt_var; if ( - _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 609) // token='try' + _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 612) // token='try' && (try_stmt_var = try_stmt_rule(p)) // try_stmt ) @@ -1981,7 +1983,7 @@ compound_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'while' while_stmt")); stmt_ty while_stmt_var; if ( - _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 629) // token='while' + _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 632) // token='while' && (while_stmt_var = while_stmt_rule(p)) // while_stmt ) @@ -2950,7 +2952,7 @@ del_stmt_rule(Parser *p) Token * _keyword; asdl_expr_seq* a; if ( - (_keyword = _PyPegen_expect_token(p, 597)) // token='del' + (_keyword = _PyPegen_expect_token(p, 600)) // token='del' && (a = del_targets_rule(p)) // del_targets && @@ -4051,7 +4053,7 @@ class_def_raw_rule(Parser *p) void *b; asdl_stmt_seq* c; if ( - (_keyword = _PyPegen_expect_token(p, 633)) // token='class' + (_keyword = _PyPegen_expect_token(p, 636)) // token='class' && (a = _PyPegen_name_token(p)) // NAME && @@ -4211,7 +4213,7 @@ function_def_raw_rule(Parser *p) void *params; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 632)) // token='def' + (_keyword = _PyPegen_expect_token(p, 635)) // token='def' && (n = _PyPegen_name_token(p)) // NAME && @@ -4271,7 +4273,7 @@ function_def_raw_rule(Parser *p) if ( (async_var = _PyPegen_expect_token(p, ASYNC)) // token='ASYNC' && - (_keyword = _PyPegen_expect_token(p, 632)) // token='def' + (_keyword = _PyPegen_expect_token(p, 635)) // token='def' && (n = _PyPegen_name_token(p)) // NAME && @@ -5319,7 +5321,7 @@ if_stmt_rule(Parser *p) asdl_stmt_seq* b; stmt_ty c; if ( - (_keyword = _PyPegen_expect_token(p, 624)) // token='if' + (_keyword = _PyPegen_expect_token(p, 627)) // token='if' && (a = named_expression_rule(p)) // named_expression && @@ -5364,7 +5366,7 @@ if_stmt_rule(Parser *p) asdl_stmt_seq* b; void *c; if ( - (_keyword = _PyPegen_expect_token(p, 624)) // token='if' + (_keyword = _PyPegen_expect_token(p, 627)) // token='if' && (a = named_expression_rule(p)) // named_expression && @@ -5457,7 +5459,7 @@ elif_stmt_rule(Parser *p) asdl_stmt_seq* b; stmt_ty c; if ( - (_keyword = _PyPegen_expect_token(p, 626)) // token='elif' + (_keyword = _PyPegen_expect_token(p, 629)) // token='elif' && (a = named_expression_rule(p)) // named_expression && @@ -5502,7 +5504,7 @@ elif_stmt_rule(Parser *p) asdl_stmt_seq* b; void *c; if ( - (_keyword = _PyPegen_expect_token(p, 626)) // token='elif' + (_keyword = _PyPegen_expect_token(p, 629)) // token='elif' && (a = named_expression_rule(p)) // named_expression && @@ -5581,7 +5583,7 @@ else_block_rule(Parser *p) Token * _literal; asdl_stmt_seq* b; if ( - (_keyword = _PyPegen_expect_token(p, 627)) // token='else' + (_keyword = _PyPegen_expect_token(p, 630)) // token='else' && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && @@ -5658,7 +5660,7 @@ while_stmt_rule(Parser *p) asdl_stmt_seq* b; void *c; if ( - (_keyword = _PyPegen_expect_token(p, 629)) // token='while' + (_keyword = _PyPegen_expect_token(p, 632)) // token='while' && (a = named_expression_rule(p)) // named_expression && @@ -5756,11 +5758,11 @@ for_stmt_rule(Parser *p) expr_ty t; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 630)) // token='for' + (_keyword = _PyPegen_expect_token(p, 633)) // token='for' && (t = star_targets_rule(p)) // star_targets && - (_keyword_1 = _PyPegen_expect_token(p, 631)) // token='in' + (_keyword_1 = _PyPegen_expect_token(p, 634)) // token='in' && (_cut_var = 1) && @@ -5820,11 +5822,11 @@ for_stmt_rule(Parser *p) if ( (async_var = _PyPegen_expect_token(p, ASYNC)) // token='ASYNC' && - (_keyword = _PyPegen_expect_token(p, 630)) // token='for' + (_keyword = _PyPegen_expect_token(p, 633)) // token='for' && (t = star_targets_rule(p)) // star_targets && - (_keyword_1 = _PyPegen_expect_token(p, 631)) // token='in' + (_keyword_1 = _PyPegen_expect_token(p, 634)) // token='in' && (_cut_var = 1) && @@ -5950,7 +5952,7 @@ with_stmt_rule(Parser *p) asdl_withitem_seq* a; asdl_stmt_seq* b; if ( - (_keyword = _PyPegen_expect_token(p, 606)) // token='with' + (_keyword = _PyPegen_expect_token(p, 609)) // token='with' && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && @@ -5999,7 +6001,7 @@ with_stmt_rule(Parser *p) asdl_stmt_seq* b; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 606)) // token='with' + (_keyword = _PyPegen_expect_token(p, 609)) // token='with' && (a = (asdl_withitem_seq*)_gather_52_rule(p)) // ','.with_item+ && @@ -6050,7 +6052,7 @@ with_stmt_rule(Parser *p) if ( (async_var = _PyPegen_expect_token(p, ASYNC)) // token='ASYNC' && - (_keyword = _PyPegen_expect_token(p, 606)) // token='with' + (_keyword = _PyPegen_expect_token(p, 609)) // token='with' && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && @@ -6102,7 +6104,7 @@ with_stmt_rule(Parser *p) if ( (async_var = _PyPegen_expect_token(p, ASYNC)) // token='ASYNC' && - (_keyword = _PyPegen_expect_token(p, 606)) // token='with' + (_keyword = _PyPegen_expect_token(p, 609)) // token='with' && (a = (asdl_withitem_seq*)_gather_56_rule(p)) // ','.with_item+ && @@ -6186,7 +6188,7 @@ with_item_rule(Parser *p) if ( (e = expression_rule(p)) // expression && - (_keyword = _PyPegen_expect_token(p, 622)) // token='as' + (_keyword = _PyPegen_expect_token(p, 625)) // token='as' && (t = star_target_rule(p)) // star_target && @@ -6308,7 +6310,7 @@ try_stmt_rule(Parser *p) asdl_stmt_seq* b; asdl_stmt_seq* f; if ( - (_keyword = _PyPegen_expect_token(p, 609)) // token='try' + (_keyword = _PyPegen_expect_token(p, 612)) // token='try' && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && @@ -6352,7 +6354,7 @@ try_stmt_rule(Parser *p) asdl_excepthandler_seq* ex; void *f; if ( - (_keyword = _PyPegen_expect_token(p, 609)) // token='try' + (_keyword = _PyPegen_expect_token(p, 612)) // token='try' && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && @@ -6448,7 +6450,7 @@ except_block_rule(Parser *p) expr_ty e; void *t; if ( - (_keyword = _PyPegen_expect_token(p, 620)) // token='except' + (_keyword = _PyPegen_expect_token(p, 623)) // token='except' && (e = expression_rule(p)) // expression && @@ -6491,7 +6493,7 @@ except_block_rule(Parser *p) Token * _literal; asdl_stmt_seq* b; if ( - (_keyword = _PyPegen_expect_token(p, 620)) // token='except' + (_keyword = _PyPegen_expect_token(p, 623)) // token='except' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -6585,7 +6587,7 @@ finally_block_rule(Parser *p) Token * _literal; asdl_stmt_seq* a; if ( - (_keyword = _PyPegen_expect_token(p, 617)) // token='finally' + (_keyword = _PyPegen_expect_token(p, 620)) // token='finally' && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && @@ -6885,7 +6887,7 @@ guard_rule(Parser *p) Token * _keyword; expr_ty guard; if ( - (_keyword = _PyPegen_expect_token(p, 624)) // token='if' + (_keyword = _PyPegen_expect_token(p, 627)) // token='if' && (guard = named_expression_rule(p)) // named_expression ) @@ -7074,7 +7076,7 @@ as_pattern_rule(Parser *p) if ( (pattern = or_pattern_rule(p)) // or_pattern && - (_keyword = _PyPegen_expect_token(p, 622)) // token='as' + (_keyword = _PyPegen_expect_token(p, 625)) // token='as' && (target = pattern_capture_target_rule(p)) // pattern_capture_target ) @@ -7497,7 +7499,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 595)) // token='None' + (_keyword = _PyPegen_expect_token(p, 598)) // token='None' ) { D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); @@ -7530,7 +7532,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 594)) // token='True' + (_keyword = _PyPegen_expect_token(p, 597)) // token='True' ) { D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); @@ -7563,7 +7565,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 596)) // token='False' + (_keyword = _PyPegen_expect_token(p, 599)) // token='False' ) { D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); @@ -7687,7 +7689,7 @@ literal_expr_rule(Parser *p) D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 595)) // token='None' + (_keyword = _PyPegen_expect_token(p, 598)) // token='None' ) { D(fprintf(stderr, "%*c+ literal_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); @@ -7720,7 +7722,7 @@ literal_expr_rule(Parser *p) D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 594)) // token='True' + (_keyword = _PyPegen_expect_token(p, 597)) // token='True' ) { D(fprintf(stderr, "%*c+ literal_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); @@ -7753,7 +7755,7 @@ literal_expr_rule(Parser *p) D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 596)) // token='False' + (_keyword = _PyPegen_expect_token(p, 599)) // token='False' ) { D(fprintf(stderr, "%*c+ literal_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); @@ -9776,11 +9778,11 @@ expression_rule(Parser *p) if ( (a = disjunction_rule(p)) // disjunction && - (_keyword = _PyPegen_expect_token(p, 624)) // token='if' + (_keyword = _PyPegen_expect_token(p, 627)) // token='if' && (b = disjunction_rule(p)) // disjunction && - (_keyword_1 = _PyPegen_expect_token(p, 627)) // token='else' + (_keyword_1 = _PyPegen_expect_token(p, 630)) // token='else' && (c = expression_rule(p)) // expression ) @@ -11280,7 +11282,7 @@ notin_bitwise_or_rule(Parser *p) if ( (_keyword = _PyPegen_expect_token(p, 578)) // token='not' && - (_keyword_1 = _PyPegen_expect_token(p, 631)) // token='in' + (_keyword_1 = _PyPegen_expect_token(p, 634)) // token='in' && (a = bitwise_or_rule(p)) // bitwise_or ) @@ -11324,7 +11326,7 @@ in_bitwise_or_rule(Parser *p) Token * _keyword; expr_ty a; if ( - (_keyword = _PyPegen_expect_token(p, 631)) // token='in' + (_keyword = _PyPegen_expect_token(p, 634)) // token='in' && (a = bitwise_or_rule(p)) // bitwise_or ) @@ -13196,7 +13198,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 594)) // token='True' + (_keyword = _PyPegen_expect_token(p, 597)) // token='True' ) { D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); @@ -13229,7 +13231,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 596)) // token='False' + (_keyword = _PyPegen_expect_token(p, 599)) // token='False' ) { D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); @@ -13262,7 +13264,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 595)) // token='None' + (_keyword = _PyPegen_expect_token(p, 598)) // token='None' ) { D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); @@ -14958,11 +14960,11 @@ for_if_clause_rule(Parser *p) if ( (async_var = _PyPegen_expect_token(p, ASYNC)) // token='ASYNC' && - (_keyword = _PyPegen_expect_token(p, 630)) // token='for' + (_keyword = _PyPegen_expect_token(p, 633)) // token='for' && (a = star_targets_rule(p)) // star_targets && - (_keyword_1 = _PyPegen_expect_token(p, 631)) // token='in' + (_keyword_1 = _PyPegen_expect_token(p, 634)) // token='in' && (_cut_var = 1) && @@ -15001,11 +15003,11 @@ for_if_clause_rule(Parser *p) expr_ty b; asdl_expr_seq* c; if ( - (_keyword = _PyPegen_expect_token(p, 630)) // token='for' + (_keyword = _PyPegen_expect_token(p, 633)) // token='for' && (a = star_targets_rule(p)) // star_targets && - (_keyword_1 = _PyPegen_expect_token(p, 631)) // token='in' + (_keyword_1 = _PyPegen_expect_token(p, 634)) // token='in' && (_cut_var = 1) && @@ -17969,7 +17971,10 @@ invalid_arguments_rule(Parser *p) return _res; } -// invalid_kwarg: NAME '=' expression for_if_clauses | !(NAME '=') expression '=' +// invalid_kwarg: +// | ('True' | 'False' | 'None') '=' +// | NAME '=' expression for_if_clauses +// | !(NAME '=') expression '=' static void * invalid_kwarg_rule(Parser *p) { @@ -17980,6 +17985,33 @@ invalid_kwarg_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; + { // ('True' | 'False' | 'None') '=' + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> invalid_kwarg[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('True' | 'False' | 'None') '='")); + Token* a; + Token * b; + if ( + (a = (Token*)_tmp_142_rule(p)) // 'True' | 'False' | 'None' + && + (b = _PyPegen_expect_token(p, 22)) // token='=' + ) + { + D(fprintf(stderr, "%*c+ invalid_kwarg[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "('True' | 'False' | 'None') '='")); + _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot assign to %s" , PyBytes_AS_STRING ( a -> bytes ) ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + D(p->level--); + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s invalid_kwarg[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('True' | 'False' | 'None') '='")); + } { // NAME '=' expression for_if_clauses if (p->error_indicator) { D(p->level--); @@ -18022,7 +18054,7 @@ invalid_kwarg_rule(Parser *p) expr_ty a; Token * b; if ( - _PyPegen_lookahead(0, _tmp_142_rule, p) + _PyPegen_lookahead(0, _tmp_143_rule, p) && (a = expression_rule(p)) // expression && @@ -18085,11 +18117,11 @@ expression_without_invalid_rule(Parser *p) if ( (a = disjunction_rule(p)) // disjunction && - (_keyword = _PyPegen_expect_token(p, 624)) // token='if' + (_keyword = _PyPegen_expect_token(p, 627)) // token='if' && (b = disjunction_rule(p)) // disjunction && - (_keyword_1 = _PyPegen_expect_token(p, 627)) // token='else' + (_keyword_1 = _PyPegen_expect_token(p, 630)) // token='else' && (c = expression_rule(p)) // expression ) @@ -18248,7 +18280,7 @@ invalid_expression_rule(Parser *p) expr_ty a; expr_ty b; if ( - _PyPegen_lookahead(0, _tmp_143_rule, p) + _PyPegen_lookahead(0, _tmp_144_rule, p) && (a = disjunction_rule(p)) // disjunction && @@ -18280,11 +18312,11 @@ invalid_expression_rule(Parser *p) if ( (a = disjunction_rule(p)) // disjunction && - (_keyword = _PyPegen_expect_token(p, 624)) // token='if' + (_keyword = _PyPegen_expect_token(p, 627)) // token='if' && (b = disjunction_rule(p)) // disjunction && - _PyPegen_lookahead(0, _tmp_144_rule, p) + _PyPegen_lookahead(0, _tmp_145_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction !('else' | ':')")); @@ -18366,7 +18398,7 @@ invalid_named_expression_rule(Parser *p) && (b = bitwise_or_rule(p)) // bitwise_or && - _PyPegen_lookahead(0, _tmp_145_rule, p) + _PyPegen_lookahead(0, _tmp_146_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' bitwise_or !('=' | ':=')")); @@ -18392,7 +18424,7 @@ invalid_named_expression_rule(Parser *p) Token * b; expr_ty bitwise_or_var; if ( - _PyPegen_lookahead(0, _tmp_146_rule, p) + _PyPegen_lookahead(0, _tmp_147_rule, p) && (a = bitwise_or_rule(p)) // bitwise_or && @@ -18400,7 +18432,7 @@ invalid_named_expression_rule(Parser *p) && (bitwise_or_var = bitwise_or_rule(p)) // bitwise_or && - _PyPegen_lookahead(0, _tmp_147_rule, p) + _PyPegen_lookahead(0, _tmp_148_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!(list | tuple | genexp | 'True' | 'None' | 'False') bitwise_or '=' bitwise_or !('=' | ':=')")); @@ -18477,7 +18509,7 @@ invalid_assignment_rule(Parser *p) D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions* ':' expression")); Token * _literal; Token * _literal_1; - asdl_seq * _loop0_148_var; + asdl_seq * _loop0_149_var; expr_ty a; expr_ty expression_var; if ( @@ -18485,7 +18517,7 @@ invalid_assignment_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_loop0_148_var = _loop0_148_rule(p)) // star_named_expressions* + (_loop0_149_var = _loop0_149_rule(p)) // star_named_expressions* && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -18542,10 +18574,10 @@ invalid_assignment_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* star_expressions '='")); Token * _literal; - asdl_seq * _loop0_149_var; + asdl_seq * _loop0_150_var; expr_ty a; if ( - (_loop0_149_var = _loop0_149_rule(p)) // ((star_targets '='))* + (_loop0_150_var = _loop0_150_rule(p)) // ((star_targets '='))* && (a = star_expressions_rule(p)) // star_expressions && @@ -18572,10 +18604,10 @@ invalid_assignment_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* yield_expr '='")); Token * _literal; - asdl_seq * _loop0_150_var; + asdl_seq * _loop0_151_var; expr_ty a; if ( - (_loop0_150_var = _loop0_150_rule(p)) // ((star_targets '='))* + (_loop0_151_var = _loop0_151_rule(p)) // ((star_targets '='))* && (a = yield_expr_rule(p)) // yield_expr && @@ -18601,7 +18633,7 @@ invalid_assignment_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions augassign (yield_expr | star_expressions)")); - void *_tmp_151_var; + void *_tmp_152_var; expr_ty a; AugOperator* augassign_var; if ( @@ -18609,7 +18641,7 @@ invalid_assignment_rule(Parser *p) && (augassign_var = augassign_rule(p)) // augassign && - (_tmp_151_var = _tmp_151_rule(p)) // yield_expr | star_expressions + (_tmp_152_var = _tmp_152_rule(p)) // yield_expr | star_expressions ) { D(fprintf(stderr, "%*c+ invalid_assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions augassign (yield_expr | star_expressions)")); @@ -18736,7 +18768,7 @@ invalid_del_stmt_rule(Parser *p) Token * _keyword; expr_ty a; if ( - (_keyword = _PyPegen_expect_token(p, 597)) // token='del' + (_keyword = _PyPegen_expect_token(p, 600)) // token='del' && (a = star_expressions_rule(p)) // star_expressions ) @@ -18823,11 +18855,11 @@ invalid_comprehension_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '(' | '{') starred_expression for_if_clauses")); - void *_tmp_152_var; + void *_tmp_153_var; expr_ty a; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_152_var = _tmp_152_rule(p)) // '[' | '(' | '{' + (_tmp_153_var = _tmp_153_rule(p)) // '[' | '(' | '{' && (a = starred_expression_rule(p)) // starred_expression && @@ -18854,12 +18886,12 @@ invalid_comprehension_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '{') star_named_expression ',' star_named_expressions for_if_clauses")); Token * _literal; - void *_tmp_153_var; + void *_tmp_154_var; expr_ty a; asdl_expr_seq* b; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_153_var = _tmp_153_rule(p)) // '[' | '{' + (_tmp_154_var = _tmp_154_rule(p)) // '[' | '{' && (a = star_named_expression_rule(p)) // star_named_expression && @@ -18889,12 +18921,12 @@ invalid_comprehension_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '{') star_named_expression ',' for_if_clauses")); - void *_tmp_154_var; + void *_tmp_155_var; expr_ty a; Token * b; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_154_var = _tmp_154_rule(p)) // '[' | '{' + (_tmp_155_var = _tmp_155_rule(p)) // '[' | '{' && (a = star_named_expression_rule(p)) // star_named_expression && @@ -18992,11 +19024,11 @@ invalid_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* invalid_parameters_helper param_no_default")); - asdl_seq * _loop0_155_var; + asdl_seq * _loop0_156_var; arg_ty a; void *invalid_parameters_helper_var; if ( - (_loop0_155_var = _loop0_155_rule(p)) // param_no_default* + (_loop0_156_var = _loop0_156_rule(p)) // param_no_default* && (invalid_parameters_helper_var = invalid_parameters_helper_rule(p)) // invalid_parameters_helper && @@ -19063,13 +19095,13 @@ invalid_parameters_helper_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default+")); - asdl_seq * _loop1_156_var; + asdl_seq * _loop1_157_var; if ( - (_loop1_156_var = _loop1_156_rule(p)) // param_with_default+ + (_loop1_157_var = _loop1_157_rule(p)) // param_with_default+ ) { D(fprintf(stderr, "%*c+ invalid_parameters_helper[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_with_default+")); - _res = _loop1_156_var; + _res = _loop1_157_var; goto done; } p->mark = _mark; @@ -19100,11 +19132,11 @@ invalid_lambda_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* invalid_lambda_parameters_helper lambda_param_no_default")); - asdl_seq * _loop0_157_var; + asdl_seq * _loop0_158_var; arg_ty a; void *invalid_lambda_parameters_helper_var; if ( - (_loop0_157_var = _loop0_157_rule(p)) // lambda_param_no_default* + (_loop0_158_var = _loop0_158_rule(p)) // lambda_param_no_default* && (invalid_lambda_parameters_helper_var = invalid_lambda_parameters_helper_rule(p)) // invalid_lambda_parameters_helper && @@ -19173,13 +19205,13 @@ invalid_lambda_parameters_helper_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+")); - asdl_seq * _loop1_158_var; + asdl_seq * _loop1_159_var; if ( - (_loop1_158_var = _loop1_158_rule(p)) // lambda_param_with_default+ + (_loop1_159_var = _loop1_159_rule(p)) // lambda_param_with_default+ ) { D(fprintf(stderr, "%*c+ invalid_lambda_parameters_helper[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+")); - _res = _loop1_158_var; + _res = _loop1_159_var; goto done; } p->mark = _mark; @@ -19209,12 +19241,12 @@ invalid_star_etc_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))")); - void *_tmp_159_var; + void *_tmp_160_var; Token * a; if ( (a = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_159_var = _tmp_159_rule(p)) // ')' | ',' (')' | '**') + (_tmp_160_var = _tmp_160_rule(p)) // ')' | ',' (')' | '**') ) { D(fprintf(stderr, "%*c+ invalid_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))")); @@ -19284,11 +19316,11 @@ invalid_lambda_star_etc_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))")); Token * _literal; - void *_tmp_160_var; + void *_tmp_161_var; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_160_var = _tmp_160_rule(p)) // ':' | ',' (':' | '**') + (_tmp_161_var = _tmp_161_rule(p)) // ':' | ',' (':' | '**') ) { D(fprintf(stderr, "%*c+ invalid_lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))")); @@ -19386,11 +19418,11 @@ invalid_with_item_rule(Parser *p) if ( (expression_var = expression_rule(p)) // expression && - (_keyword = _PyPegen_expect_token(p, 622)) // token='as' + (_keyword = _PyPegen_expect_token(p, 625)) // token='as' && (a = expression_rule(p)) // expression && - _PyPegen_lookahead(1, _tmp_161_rule, p) + _PyPegen_lookahead(1, _tmp_162_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_with_item[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression 'as' expression &(',' | ')' | ':')")); @@ -19436,7 +19468,7 @@ invalid_for_target_rule(Parser *p) if ( (_opt_var = _PyPegen_expect_token(p, ASYNC), !p->error_indicator) // ASYNC? && - (_keyword = _PyPegen_expect_token(p, 630)) // token='for' + (_keyword = _PyPegen_expect_token(p, 633)) // token='for' && (a = star_expressions_rule(p)) // star_expressions ) @@ -19606,7 +19638,7 @@ invalid_with_stmt_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' ','.(expression ['as' star_target])+ &&':'")); - asdl_seq * _gather_162_var; + asdl_seq * _gather_163_var; Token * _keyword; Token * _literal; void *_opt_var; @@ -19614,15 +19646,15 @@ invalid_with_stmt_rule(Parser *p) if ( (_opt_var = _PyPegen_expect_token(p, ASYNC), !p->error_indicator) // ASYNC? && - (_keyword = _PyPegen_expect_token(p, 606)) // token='with' + (_keyword = _PyPegen_expect_token(p, 609)) // token='with' && - (_gather_162_var = _gather_162_rule(p)) // ','.(expression ['as' star_target])+ + (_gather_163_var = _gather_163_rule(p)) // ','.(expression ['as' star_target])+ && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' ) { D(fprintf(stderr, "%*c+ invalid_with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' ','.(expression ['as' star_target])+ &&':'")); - _res = _PyPegen_dummy_name(p, _opt_var, _keyword, _gather_162_var, _literal); + _res = _PyPegen_dummy_name(p, _opt_var, _keyword, _gather_163_var, _literal); goto done; } p->mark = _mark; @@ -19635,7 +19667,7 @@ invalid_with_stmt_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' &&':'")); - asdl_seq * _gather_164_var; + asdl_seq * _gather_165_var; Token * _keyword; Token * _literal; Token * _literal_1; @@ -19647,11 +19679,11 @@ invalid_with_stmt_rule(Parser *p) if ( (_opt_var = _PyPegen_expect_token(p, ASYNC), !p->error_indicator) // ASYNC? && - (_keyword = _PyPegen_expect_token(p, 606)) // token='with' + (_keyword = _PyPegen_expect_token(p, 609)) // token='with' && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_164_var = _gather_164_rule(p)) // ','.(expressions ['as' star_target])+ + (_gather_165_var = _gather_165_rule(p)) // ','.(expressions ['as' star_target])+ && (_opt_var_1 = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -19661,7 +19693,7 @@ invalid_with_stmt_rule(Parser *p) ) { D(fprintf(stderr, "%*c+ invalid_with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' &&':'")); - _res = _PyPegen_dummy_name(p, _opt_var, _keyword, _literal, _gather_164_var, _opt_var_1, _literal_1, _literal_2); + _res = _PyPegen_dummy_name(p, _opt_var, _keyword, _literal, _gather_165_var, _opt_var_1, _literal_1, _literal_2); goto done; } p->mark = _mark; @@ -19693,7 +19725,7 @@ invalid_with_stmt_indent_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' ','.(expression ['as' star_target])+ ':' NEWLINE !INDENT")); - asdl_seq * _gather_166_var; + asdl_seq * _gather_167_var; Token * _literal; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings @@ -19702,9 +19734,9 @@ invalid_with_stmt_indent_rule(Parser *p) if ( (_opt_var = _PyPegen_expect_token(p, ASYNC), !p->error_indicator) // ASYNC? && - (a = _PyPegen_expect_token(p, 606)) // token='with' + (a = _PyPegen_expect_token(p, 609)) // token='with' && - (_gather_166_var = _gather_166_rule(p)) // ','.(expression ['as' star_target])+ + (_gather_167_var = _gather_167_rule(p)) // ','.(expression ['as' star_target])+ && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -19732,7 +19764,7 @@ invalid_with_stmt_indent_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' ':' NEWLINE !INDENT")); - asdl_seq * _gather_168_var; + asdl_seq * _gather_169_var; Token * _literal; Token * _literal_1; Token * _literal_2; @@ -19745,11 +19777,11 @@ invalid_with_stmt_indent_rule(Parser *p) if ( (_opt_var = _PyPegen_expect_token(p, ASYNC), !p->error_indicator) // ASYNC? && - (a = _PyPegen_expect_token(p, 606)) // token='with' + (a = _PyPegen_expect_token(p, 609)) // token='with' && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_168_var = _gather_168_rule(p)) // ','.(expressions ['as' star_target])+ + (_gather_169_var = _gather_169_rule(p)) // ','.(expressions ['as' star_target])+ && (_opt_var_1 = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -19802,7 +19834,7 @@ invalid_try_stmt_rule(Parser *p) Token * a; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 609)) // token='try' + (a = _PyPegen_expect_token(p, 612)) // token='try' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -19834,13 +19866,13 @@ invalid_try_stmt_rule(Parser *p) Token * _literal; asdl_stmt_seq* block_var; if ( - (_keyword = _PyPegen_expect_token(p, 609)) // token='try' + (_keyword = _PyPegen_expect_token(p, 612)) // token='try' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && (block_var = block_rule(p)) // block && - _PyPegen_lookahead(0, _tmp_170_rule, p) + _PyPegen_lookahead(0, _tmp_171_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' ':' block !('except' | 'finally')")); @@ -19890,7 +19922,7 @@ invalid_except_stmt_rule(Parser *p) expr_ty a; expr_ty expressions_var; if ( - (_keyword = _PyPegen_expect_token(p, 620)) // token='except' + (_keyword = _PyPegen_expect_token(p, 623)) // token='except' && (a = expression_rule(p)) // expression && @@ -19898,7 +19930,7 @@ invalid_except_stmt_rule(Parser *p) && (expressions_var = expressions_rule(p)) // expressions && - (_opt_var = _tmp_171_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_172_rule(p), !p->error_indicator) // ['as' NAME] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' ) @@ -19928,11 +19960,11 @@ invalid_except_stmt_rule(Parser *p) expr_ty expression_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 620)) // token='except' + (a = _PyPegen_expect_token(p, 623)) // token='except' && (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_172_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_173_rule(p), !p->error_indicator) // ['as' NAME] && (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) @@ -19959,7 +19991,7 @@ invalid_except_stmt_rule(Parser *p) Token * a; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 620)) // token='except' + (a = _PyPegen_expect_token(p, 623)) // token='except' && (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) @@ -20004,7 +20036,7 @@ invalid_finally_stmt_rule(Parser *p) Token * a; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 617)) // token='finally' + (a = _PyPegen_expect_token(p, 620)) // token='finally' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -20058,11 +20090,11 @@ invalid_except_stmt_indent_rule(Parser *p) expr_ty expression_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 620)) // token='except' + (a = _PyPegen_expect_token(p, 623)) // token='except' && (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_173_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_174_rule(p), !p->error_indicator) // ['as' NAME] && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -20094,7 +20126,7 @@ invalid_except_stmt_indent_rule(Parser *p) Token * a; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 620)) // token='except' + (a = _PyPegen_expect_token(p, 623)) // token='except' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -20319,7 +20351,7 @@ invalid_as_pattern_rule(Parser *p) if ( (or_pattern_var = or_pattern_rule(p)) // or_pattern && - (_keyword = _PyPegen_expect_token(p, 622)) // token='as' + (_keyword = _PyPegen_expect_token(p, 625)) // token='as' && (a = _PyPegen_expect_soft_keyword(p, "_")) // soft_keyword='"_"' ) @@ -20349,7 +20381,7 @@ invalid_as_pattern_rule(Parser *p) if ( (or_pattern_var = or_pattern_rule(p)) // or_pattern && - (_keyword = _PyPegen_expect_token(p, 622)) // token='as' + (_keyword = _PyPegen_expect_token(p, 625)) // token='as' && _PyPegen_lookahead_with_name(0, _PyPegen_name_token, p) && @@ -20446,7 +20478,7 @@ invalid_class_argument_pattern_rule(Parser *p) asdl_pattern_seq* a; asdl_seq* keyword_patterns_var; if ( - (_opt_var = _tmp_174_rule(p), !p->error_indicator) // [positional_patterns ','] + (_opt_var = _tmp_175_rule(p), !p->error_indicator) // [positional_patterns ','] && (keyword_patterns_var = keyword_patterns_rule(p)) // keyword_patterns && @@ -20497,7 +20529,7 @@ invalid_if_stmt_rule(Parser *p) expr_ty named_expression_var; Token * newline_var; if ( - (_keyword = _PyPegen_expect_token(p, 624)) // token='if' + (_keyword = _PyPegen_expect_token(p, 627)) // token='if' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -20528,7 +20560,7 @@ invalid_if_stmt_rule(Parser *p) expr_ty a_1; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 624)) // token='if' + (a = _PyPegen_expect_token(p, 627)) // token='if' && (a_1 = named_expression_rule(p)) // named_expression && @@ -20581,7 +20613,7 @@ invalid_elif_stmt_rule(Parser *p) expr_ty named_expression_var; Token * newline_var; if ( - (_keyword = _PyPegen_expect_token(p, 626)) // token='elif' + (_keyword = _PyPegen_expect_token(p, 629)) // token='elif' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -20612,7 +20644,7 @@ invalid_elif_stmt_rule(Parser *p) expr_ty named_expression_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 626)) // token='elif' + (a = _PyPegen_expect_token(p, 629)) // token='elif' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -20663,7 +20695,7 @@ invalid_else_stmt_rule(Parser *p) Token * a; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 627)) // token='else' + (a = _PyPegen_expect_token(p, 630)) // token='else' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -20714,7 +20746,7 @@ invalid_while_stmt_rule(Parser *p) expr_ty named_expression_var; Token * newline_var; if ( - (_keyword = _PyPegen_expect_token(p, 629)) // token='while' + (_keyword = _PyPegen_expect_token(p, 632)) // token='while' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -20745,7 +20777,7 @@ invalid_while_stmt_rule(Parser *p) expr_ty named_expression_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 629)) // token='while' + (a = _PyPegen_expect_token(p, 632)) // token='while' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -20803,11 +20835,11 @@ invalid_for_stmt_rule(Parser *p) if ( (_opt_var = _PyPegen_expect_token(p, ASYNC), !p->error_indicator) // ASYNC? && - (a = _PyPegen_expect_token(p, 630)) // token='for' + (a = _PyPegen_expect_token(p, 633)) // token='for' && (star_targets_var = star_targets_rule(p)) // star_targets && - (_keyword = _PyPegen_expect_token(p, 631)) // token='in' + (_keyword = _PyPegen_expect_token(p, 634)) // token='in' && (star_expressions_var = star_expressions_rule(p)) // star_expressions && @@ -20870,7 +20902,7 @@ invalid_def_raw_rule(Parser *p) if ( (_opt_var = _PyPegen_expect_token(p, ASYNC), !p->error_indicator) // ASYNC? && - (a = _PyPegen_expect_token(p, 632)) // token='def' + (a = _PyPegen_expect_token(p, 635)) // token='def' && (name_var = _PyPegen_name_token(p)) // NAME && @@ -20880,7 +20912,7 @@ invalid_def_raw_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' && - (_opt_var_2 = _tmp_175_rule(p), !p->error_indicator) // ['->' expression] + (_opt_var_2 = _tmp_176_rule(p), !p->error_indicator) // ['->' expression] && (_literal_2 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -20932,11 +20964,11 @@ invalid_class_def_raw_rule(Parser *p) expr_ty name_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 633)) // token='class' + (a = _PyPegen_expect_token(p, 636)) // token='class' && (name_var = _PyPegen_name_token(p)) // NAME && - (_opt_var = _tmp_176_rule(p), !p->error_indicator) // ['(' arguments? ')'] + (_opt_var = _tmp_177_rule(p), !p->error_indicator) // ['(' arguments? ')'] && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -20984,11 +21016,11 @@ invalid_double_starred_kvpairs_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_double_starred_kvpairs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ',' invalid_kvpair")); - asdl_seq * _gather_177_var; + asdl_seq * _gather_178_var; Token * _literal; void *invalid_kvpair_var; if ( - (_gather_177_var = _gather_177_rule(p)) // ','.double_starred_kvpair+ + (_gather_178_var = _gather_178_rule(p)) // ','.double_starred_kvpair+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && @@ -20996,7 +21028,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) ) { D(fprintf(stderr, "%*c+ invalid_double_starred_kvpairs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ',' invalid_kvpair")); - _res = _PyPegen_dummy_name(p, _gather_177_var, _literal, invalid_kvpair_var); + _res = _PyPegen_dummy_name(p, _gather_178_var, _literal, invalid_kvpair_var); goto done; } p->mark = _mark; @@ -21049,7 +21081,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) && (a = _PyPegen_expect_token(p, 11)) // token=':' && - _PyPegen_lookahead(1, _tmp_179_rule, p) + _PyPegen_lookahead(1, _tmp_180_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_double_starred_kvpairs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' &('}' | ',')")); @@ -21565,7 +21597,7 @@ _tmp_7_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_7[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'def'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 632)) // token='def' + (_keyword = _PyPegen_expect_token(p, 635)) // token='def' ) { D(fprintf(stderr, "%*c+ _tmp_7[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'def'")); @@ -21639,7 +21671,7 @@ _tmp_8_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_8[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 633)) // token='class' + (_keyword = _PyPegen_expect_token(p, 636)) // token='class' ) { D(fprintf(stderr, "%*c+ _tmp_8[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'class'")); @@ -21694,7 +21726,7 @@ _tmp_9_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_9[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'with'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 606)) // token='with' + (_keyword = _PyPegen_expect_token(p, 609)) // token='with' ) { D(fprintf(stderr, "%*c+ _tmp_9[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'with'")); @@ -21749,7 +21781,7 @@ _tmp_10_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_10[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'for'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 630)) // token='for' + (_keyword = _PyPegen_expect_token(p, 633)) // token='for' ) { D(fprintf(stderr, "%*c+ _tmp_10[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'for'")); @@ -21966,12 +21998,12 @@ _loop1_14_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_14[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_180_var; + void *_tmp_181_var; while ( - (_tmp_180_var = _tmp_180_rule(p)) // star_targets '=' + (_tmp_181_var = _tmp_181_rule(p)) // star_targets '=' ) { - _res = _tmp_180_var; + _res = _tmp_181_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -22518,12 +22550,12 @@ _loop0_24_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_24[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); - void *_tmp_181_var; + void *_tmp_182_var; while ( - (_tmp_181_var = _tmp_181_rule(p)) // '.' | '...' + (_tmp_182_var = _tmp_182_rule(p)) // '.' | '...' ) { - _res = _tmp_181_var; + _res = _tmp_182_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -22584,12 +22616,12 @@ _loop1_25_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_25[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); - void *_tmp_182_var; + void *_tmp_183_var; while ( - (_tmp_182_var = _tmp_182_rule(p)) // '.' | '...' + (_tmp_183_var = _tmp_183_rule(p)) // '.' | '...' ) { - _res = _tmp_182_var; + _res = _tmp_183_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -22762,7 +22794,7 @@ _tmp_28_rule(Parser *p) Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 622)) // token='as' + (_keyword = _PyPegen_expect_token(p, 625)) // token='as' && (z = _PyPegen_name_token(p)) // NAME ) @@ -22920,7 +22952,7 @@ _tmp_31_rule(Parser *p) Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 622)) // token='as' + (_keyword = _PyPegen_expect_token(p, 625)) // token='as' && (z = _PyPegen_name_token(p)) // NAME ) @@ -22971,12 +23003,12 @@ _loop1_32_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_32[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('@' named_expression NEWLINE)")); - void *_tmp_183_var; + void *_tmp_184_var; while ( - (_tmp_183_var = _tmp_183_rule(p)) // '@' named_expression NEWLINE + (_tmp_184_var = _tmp_184_rule(p)) // '@' named_expression NEWLINE ) { - _res = _tmp_183_var; + _res = _tmp_184_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -24730,7 +24762,7 @@ _tmp_60_rule(Parser *p) Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 622)) // token='as' + (_keyword = _PyPegen_expect_token(p, 625)) // token='as' && (z = _PyPegen_name_token(p)) // NAME ) @@ -25735,12 +25767,12 @@ _loop1_77_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_77[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' expression)")); - void *_tmp_184_var; + void *_tmp_185_var; while ( - (_tmp_184_var = _tmp_184_rule(p)) // ',' expression + (_tmp_185_var = _tmp_185_rule(p)) // ',' expression ) { - _res = _tmp_184_var; + _res = _tmp_185_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -25806,12 +25838,12 @@ _loop1_78_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_78[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_expression)")); - void *_tmp_185_var; + void *_tmp_186_var; while ( - (_tmp_185_var = _tmp_185_rule(p)) // ',' star_expression + (_tmp_186_var = _tmp_186_rule(p)) // ',' star_expression ) { - _res = _tmp_185_var; + _res = _tmp_186_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -25991,12 +26023,12 @@ _loop1_81_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_81[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('or' conjunction)")); - void *_tmp_186_var; + void *_tmp_187_var; while ( - (_tmp_186_var = _tmp_186_rule(p)) // 'or' conjunction + (_tmp_187_var = _tmp_187_rule(p)) // 'or' conjunction ) { - _res = _tmp_186_var; + _res = _tmp_187_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -26062,12 +26094,12 @@ _loop1_82_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_82[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('and' inversion)")); - void *_tmp_187_var; + void *_tmp_188_var; while ( - (_tmp_187_var = _tmp_187_rule(p)) // 'and' inversion + (_tmp_188_var = _tmp_188_rule(p)) // 'and' inversion ) { - _res = _tmp_187_var; + _res = _tmp_188_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -27942,12 +27974,12 @@ _loop0_111_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_111[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); - void *_tmp_188_var; + void *_tmp_189_var; while ( - (_tmp_188_var = _tmp_188_rule(p)) // 'if' disjunction + (_tmp_189_var = _tmp_189_rule(p)) // 'if' disjunction ) { - _res = _tmp_188_var; + _res = _tmp_189_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -28008,12 +28040,12 @@ _loop0_112_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); - void *_tmp_189_var; + void *_tmp_190_var; while ( - (_tmp_189_var = _tmp_189_rule(p)) // 'if' disjunction + (_tmp_190_var = _tmp_190_rule(p)) // 'if' disjunction ) { - _res = _tmp_189_var; + _res = _tmp_190_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -28136,7 +28168,7 @@ _loop0_115_rule(Parser *p) while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_190_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' + (elem = _tmp_191_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' ) { _res = elem; @@ -28200,7 +28232,7 @@ _gather_114_rule(Parser *p) void *elem; asdl_seq * seq; if ( - (elem = _tmp_190_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' + (elem = _tmp_191_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' && (seq = _loop0_115_rule(p)) // _loop0_115 ) @@ -28746,12 +28778,12 @@ _loop0_125_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); - void *_tmp_191_var; + void *_tmp_192_var; while ( - (_tmp_191_var = _tmp_191_rule(p)) // ',' star_target + (_tmp_192_var = _tmp_192_rule(p)) // ',' star_target ) { - _res = _tmp_191_var; + _res = _tmp_192_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -28926,12 +28958,12 @@ _loop1_128_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); - void *_tmp_192_var; + void *_tmp_193_var; while ( - (_tmp_192_var = _tmp_192_rule(p)) // ',' star_target + (_tmp_193_var = _tmp_193_rule(p)) // ',' star_target ) { - _res = _tmp_192_var; + _res = _tmp_193_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -29675,9 +29707,83 @@ _tmp_141_rule(Parser *p) return _res; } -// _tmp_142: NAME '=' +// _tmp_142: 'True' | 'False' | 'None' static void * _tmp_142_rule(Parser *p) +{ + D(p->level++); + if (p->error_indicator) { + D(p->level--); + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // 'True' + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); + Token * _keyword; + if ( + (_keyword = _PyPegen_expect_token(p, 597)) // token='True' + ) + { + D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); + _res = _keyword; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'True'")); + } + { // 'False' + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); + Token * _keyword; + if ( + (_keyword = _PyPegen_expect_token(p, 599)) // token='False' + ) + { + D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); + _res = _keyword; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'False'")); + } + { // 'None' + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); + Token * _keyword; + if ( + (_keyword = _PyPegen_expect_token(p, 598)) // token='None' + ) + { + D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); + _res = _keyword; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'None'")); + } + _res = NULL; + done: + D(p->level--); + return _res; +} + +// _tmp_143: NAME '=' +static void * +_tmp_143_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29691,7 +29797,7 @@ _tmp_142_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '='")); + D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '='")); Token * _literal; expr_ty name_var; if ( @@ -29700,12 +29806,12 @@ _tmp_142_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '='")); + D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '='")); _res = _PyPegen_dummy_name(p, name_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_143[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME '='")); } _res = NULL; @@ -29714,9 +29820,9 @@ _tmp_142_rule(Parser *p) return _res; } -// _tmp_143: NAME STRING | SOFT_KEYWORD +// _tmp_144: NAME STRING | SOFT_KEYWORD static void * -_tmp_143_rule(Parser *p) +_tmp_144_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29730,7 +29836,7 @@ _tmp_143_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME STRING")); + D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME STRING")); expr_ty name_var; expr_ty string_var; if ( @@ -29739,12 +29845,12 @@ _tmp_143_rule(Parser *p) (string_var = _PyPegen_string_token(p)) // STRING ) { - D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME STRING")); + D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME STRING")); _res = _PyPegen_dummy_name(p, name_var, string_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_143[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME STRING")); } { // SOFT_KEYWORD @@ -29752,18 +29858,18 @@ _tmp_143_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); + D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); expr_ty soft_keyword_var; if ( (soft_keyword_var = _PyPegen_soft_keyword_token(p)) // SOFT_KEYWORD ) { - D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); + D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); _res = soft_keyword_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_143[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "SOFT_KEYWORD")); } _res = NULL; @@ -29772,9 +29878,9 @@ _tmp_143_rule(Parser *p) return _res; } -// _tmp_144: 'else' | ':' +// _tmp_145: 'else' | ':' static void * -_tmp_144_rule(Parser *p) +_tmp_145_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29788,18 +29894,18 @@ _tmp_144_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else'")); + D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 627)) // token='else' + (_keyword = _PyPegen_expect_token(p, 630)) // token='else' ) { - D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else'")); + D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'else'")); } { // ':' @@ -29807,18 +29913,18 @@ _tmp_144_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } _res = NULL; @@ -29827,9 +29933,9 @@ _tmp_144_rule(Parser *p) return _res; } -// _tmp_145: '=' | ':=' +// _tmp_146: '=' | ':=' static void * -_tmp_145_rule(Parser *p) +_tmp_146_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29843,18 +29949,18 @@ _tmp_145_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); } { // ':=' @@ -29862,18 +29968,18 @@ _tmp_145_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 53)) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':='")); } _res = NULL; @@ -29882,9 +29988,9 @@ _tmp_145_rule(Parser *p) return _res; } -// _tmp_146: list | tuple | genexp | 'True' | 'None' | 'False' +// _tmp_147: list | tuple | genexp | 'True' | 'None' | 'False' static void * -_tmp_146_rule(Parser *p) +_tmp_147_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29898,18 +30004,18 @@ _tmp_146_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); + D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); expr_ty list_var; if ( (list_var = list_rule(p)) // list ) { - D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "list")); + D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "list")); _res = list_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "list")); } { // tuple @@ -29917,18 +30023,18 @@ _tmp_146_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); + D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); expr_ty tuple_var; if ( (tuple_var = tuple_rule(p)) // tuple ) { - D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tuple")); + D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tuple")); _res = tuple_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "tuple")); } { // genexp @@ -29936,18 +30042,18 @@ _tmp_146_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); + D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); expr_ty genexp_var; if ( (genexp_var = genexp_rule(p)) // genexp ) { - D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "genexp")); + D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "genexp")); _res = genexp_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "genexp")); } { // 'True' @@ -29955,18 +30061,18 @@ _tmp_146_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); + D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 594)) // token='True' + (_keyword = _PyPegen_expect_token(p, 597)) // token='True' ) { - D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); + D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'True'")); } { // 'None' @@ -29974,18 +30080,18 @@ _tmp_146_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); + D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 595)) // token='None' + (_keyword = _PyPegen_expect_token(p, 598)) // token='None' ) { - D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); + D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'None'")); } { // 'False' @@ -29993,18 +30099,18 @@ _tmp_146_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); + D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 596)) // token='False' + (_keyword = _PyPegen_expect_token(p, 599)) // token='False' ) { - D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); + D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'False'")); } _res = NULL; @@ -30013,9 +30119,9 @@ _tmp_146_rule(Parser *p) return _res; } -// _tmp_147: '=' | ':=' +// _tmp_148: '=' | ':=' static void * -_tmp_147_rule(Parser *p) +_tmp_148_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30029,18 +30135,18 @@ _tmp_147_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); } { // ':=' @@ -30048,18 +30154,18 @@ _tmp_147_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 53)) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':='")); } _res = NULL; @@ -30068,9 +30174,9 @@ _tmp_147_rule(Parser *p) return _res; } -// _loop0_148: star_named_expressions +// _loop0_149: star_named_expressions static asdl_seq * -_loop0_148_rule(Parser *p) +_loop0_149_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30094,7 +30200,7 @@ _loop0_148_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expressions")); + D(fprintf(stderr, "%*c> _loop0_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expressions")); asdl_expr_seq* star_named_expressions_var; while ( (star_named_expressions_var = star_named_expressions_rule(p)) // star_named_expressions @@ -30116,7 +30222,7 @@ _loop0_148_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_148[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_149[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expressions")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30129,14 +30235,14 @@ _loop0_148_rule(Parser *p) } 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_148_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_149_type, _seq); D(p->level--); return _seq; } -// _loop0_149: (star_targets '=') +// _loop0_150: (star_targets '=') static asdl_seq * -_loop0_149_rule(Parser *p) +_loop0_150_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30160,13 +30266,13 @@ _loop0_149_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_193_var; + D(fprintf(stderr, "%*c> _loop0_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); + void *_tmp_194_var; while ( - (_tmp_193_var = _tmp_193_rule(p)) // star_targets '=' + (_tmp_194_var = _tmp_194_rule(p)) // star_targets '=' ) { - _res = _tmp_193_var; + _res = _tmp_194_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30182,7 +30288,7 @@ _loop0_149_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_149[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_150[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(star_targets '=')")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30195,14 +30301,14 @@ _loop0_149_rule(Parser *p) } 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); + _PyPegen_insert_memo(p, _start_mark, _loop0_150_type, _seq); D(p->level--); return _seq; } -// _loop0_150: (star_targets '=') +// _loop0_151: (star_targets '=') static asdl_seq * -_loop0_150_rule(Parser *p) +_loop0_151_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30226,13 +30332,13 @@ _loop0_150_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_194_var; + D(fprintf(stderr, "%*c> _loop0_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); + void *_tmp_195_var; while ( - (_tmp_194_var = _tmp_194_rule(p)) // star_targets '=' + (_tmp_195_var = _tmp_195_rule(p)) // star_targets '=' ) { - _res = _tmp_194_var; + _res = _tmp_195_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30248,7 +30354,7 @@ _loop0_150_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_150[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_151[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(star_targets '=')")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30261,14 +30367,14 @@ _loop0_150_rule(Parser *p) } 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); + _PyPegen_insert_memo(p, _start_mark, _loop0_151_type, _seq); D(p->level--); return _seq; } -// _tmp_151: yield_expr | star_expressions +// _tmp_152: yield_expr | star_expressions static void * -_tmp_151_rule(Parser *p) +_tmp_152_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30282,18 +30388,18 @@ _tmp_151_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_151[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // star_expressions @@ -30301,18 +30407,18 @@ _tmp_151_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); expr_ty star_expressions_var; if ( (star_expressions_var = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); _res = star_expressions_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_151[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); } _res = NULL; @@ -30321,9 +30427,9 @@ _tmp_151_rule(Parser *p) return _res; } -// _tmp_152: '[' | '(' | '{' +// _tmp_153: '[' | '(' | '{' static void * -_tmp_152_rule(Parser *p) +_tmp_153_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30337,18 +30443,18 @@ _tmp_152_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' ) { - D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); } { // '(' @@ -30356,18 +30462,18 @@ _tmp_152_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' ) { - D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'('")); } { // '{' @@ -30375,18 +30481,18 @@ _tmp_152_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' ) { - D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); } _res = NULL; @@ -30395,9 +30501,9 @@ _tmp_152_rule(Parser *p) return _res; } -// _tmp_153: '[' | '{' +// _tmp_154: '[' | '{' static void * -_tmp_153_rule(Parser *p) +_tmp_154_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30411,18 +30517,18 @@ _tmp_153_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' ) { - D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); } { // '{' @@ -30430,18 +30536,18 @@ _tmp_153_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' ) { - D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); } _res = NULL; @@ -30450,9 +30556,9 @@ _tmp_153_rule(Parser *p) return _res; } -// _tmp_154: '[' | '{' +// _tmp_155: '[' | '{' static void * -_tmp_154_rule(Parser *p) +_tmp_155_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30466,18 +30572,18 @@ _tmp_154_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' ) { - D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); } { // '{' @@ -30485,18 +30591,18 @@ _tmp_154_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' ) { - D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); } _res = NULL; @@ -30505,9 +30611,9 @@ _tmp_154_rule(Parser *p) return _res; } -// _loop0_155: param_no_default +// _loop0_156: param_no_default static asdl_seq * -_loop0_155_rule(Parser *p) +_loop0_156_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30531,7 +30637,7 @@ _loop0_155_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _loop0_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; while ( (param_no_default_var = param_no_default_rule(p)) // param_no_default @@ -30553,7 +30659,7 @@ _loop0_155_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_155[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_156[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30566,14 +30672,14 @@ _loop0_155_rule(Parser *p) } 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_155_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_156_type, _seq); D(p->level--); return _seq; } -// _loop1_156: param_with_default +// _loop1_157: param_with_default static asdl_seq * -_loop1_156_rule(Parser *p) +_loop1_157_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30597,7 +30703,7 @@ _loop1_156_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); + D(fprintf(stderr, "%*c> _loop1_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); NameDefaultPair* param_with_default_var; while ( (param_with_default_var = param_with_default_rule(p)) // param_with_default @@ -30619,7 +30725,7 @@ _loop1_156_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_156[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_157[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -30637,14 +30743,14 @@ _loop1_156_rule(Parser *p) } 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_156_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_157_type, _seq); D(p->level--); return _seq; } -// _loop0_157: lambda_param_no_default +// _loop0_158: lambda_param_no_default static asdl_seq * -_loop0_157_rule(Parser *p) +_loop0_158_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30668,7 +30774,7 @@ _loop0_157_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop0_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -30690,7 +30796,7 @@ _loop0_157_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_157[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_158[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30703,14 +30809,14 @@ _loop0_157_rule(Parser *p) } 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_157_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_158_type, _seq); D(p->level--); return _seq; } -// _loop1_158: lambda_param_with_default +// _loop1_159: lambda_param_with_default static asdl_seq * -_loop1_158_rule(Parser *p) +_loop1_159_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30734,7 +30840,7 @@ _loop1_158_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop1_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -30756,7 +30862,7 @@ _loop1_158_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_158[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_159[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -30774,14 +30880,14 @@ _loop1_158_rule(Parser *p) } 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_158_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_159_type, _seq); D(p->level--); return _seq; } -// _tmp_159: ')' | ',' (')' | '**') +// _tmp_160: ')' | ',' (')' | '**') static void * -_tmp_159_rule(Parser *p) +_tmp_160_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30795,18 +30901,18 @@ _tmp_159_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_159[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // ',' (')' | '**') @@ -30814,21 +30920,21 @@ _tmp_159_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); + D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); Token * _literal; - void *_tmp_195_var; + void *_tmp_196_var; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_tmp_195_var = _tmp_195_rule(p)) // ')' | '**' + (_tmp_196_var = _tmp_196_rule(p)) // ')' | '**' ) { - D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); - _res = _PyPegen_dummy_name(p, _literal, _tmp_195_var); + D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); + _res = _PyPegen_dummy_name(p, _literal, _tmp_196_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_159[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (')' | '**')")); } _res = NULL; @@ -30837,9 +30943,9 @@ _tmp_159_rule(Parser *p) return _res; } -// _tmp_160: ':' | ',' (':' | '**') +// _tmp_161: ':' | ',' (':' | '**') static void * -_tmp_160_rule(Parser *p) +_tmp_161_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30853,18 +30959,18 @@ _tmp_160_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // ',' (':' | '**') @@ -30872,21 +30978,21 @@ _tmp_160_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); + D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); Token * _literal; - void *_tmp_196_var; + void *_tmp_197_var; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_tmp_196_var = _tmp_196_rule(p)) // ':' | '**' + (_tmp_197_var = _tmp_197_rule(p)) // ':' | '**' ) { - D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); - _res = _PyPegen_dummy_name(p, _literal, _tmp_196_var); + D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); + _res = _PyPegen_dummy_name(p, _literal, _tmp_197_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (':' | '**')")); } _res = NULL; @@ -30895,9 +31001,9 @@ _tmp_160_rule(Parser *p) return _res; } -// _tmp_161: ',' | ')' | ':' +// _tmp_162: ',' | ')' | ':' static void * -_tmp_161_rule(Parser *p) +_tmp_162_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30911,18 +31017,18 @@ _tmp_161_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_162[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } { // ')' @@ -30930,18 +31036,18 @@ _tmp_161_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_162[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // ':' @@ -30949,18 +31055,18 @@ _tmp_161_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_162[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } _res = NULL; @@ -30969,9 +31075,9 @@ _tmp_161_rule(Parser *p) return _res; } -// _loop0_163: ',' (expression ['as' star_target]) +// _loop0_164: ',' (expression ['as' star_target]) static asdl_seq * -_loop0_163_rule(Parser *p) +_loop0_164_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30995,13 +31101,13 @@ _loop0_163_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_163[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_164[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_197_rule(p)) // expression ['as' star_target] + (elem = _tmp_198_rule(p)) // expression ['as' star_target] ) { _res = elem; @@ -31026,7 +31132,7 @@ _loop0_163_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_163[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_164[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expression ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31039,14 +31145,14 @@ _loop0_163_rule(Parser *p) } 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_163_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_164_type, _seq); D(p->level--); return _seq; } -// _gather_162: (expression ['as' star_target]) _loop0_163 +// _gather_163: (expression ['as' star_target]) _loop0_164 static asdl_seq * -_gather_162_rule(Parser *p) +_gather_163_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31055,27 +31161,27 @@ _gather_162_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expression ['as' star_target]) _loop0_163 + { // (expression ['as' star_target]) _loop0_164 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_163")); + D(fprintf(stderr, "%*c> _gather_163[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_164")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_197_rule(p)) // expression ['as' star_target] + (elem = _tmp_198_rule(p)) // expression ['as' star_target] && - (seq = _loop0_163_rule(p)) // _loop0_163 + (seq = _loop0_164_rule(p)) // _loop0_164 ) { - D(fprintf(stderr, "%*c+ _gather_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_163")); + D(fprintf(stderr, "%*c+ _gather_163[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_164")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_162[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_163")); + D(fprintf(stderr, "%*c%s _gather_163[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_164")); } _res = NULL; done: @@ -31083,9 +31189,9 @@ _gather_162_rule(Parser *p) return _res; } -// _loop0_165: ',' (expressions ['as' star_target]) +// _loop0_166: ',' (expressions ['as' star_target]) static asdl_seq * -_loop0_165_rule(Parser *p) +_loop0_166_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31109,13 +31215,13 @@ _loop0_165_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_198_rule(p)) // expressions ['as' star_target] + (elem = _tmp_199_rule(p)) // expressions ['as' star_target] ) { _res = elem; @@ -31140,7 +31246,7 @@ _loop0_165_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_165[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_166[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expressions ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31153,14 +31259,14 @@ _loop0_165_rule(Parser *p) } 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_165_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_166_type, _seq); D(p->level--); return _seq; } -// _gather_164: (expressions ['as' star_target]) _loop0_165 +// _gather_165: (expressions ['as' star_target]) _loop0_166 static asdl_seq * -_gather_164_rule(Parser *p) +_gather_165_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31169,27 +31275,27 @@ _gather_164_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expressions ['as' star_target]) _loop0_165 + { // (expressions ['as' star_target]) _loop0_166 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_164[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_165")); + D(fprintf(stderr, "%*c> _gather_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_166")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_198_rule(p)) // expressions ['as' star_target] + (elem = _tmp_199_rule(p)) // expressions ['as' star_target] && - (seq = _loop0_165_rule(p)) // _loop0_165 + (seq = _loop0_166_rule(p)) // _loop0_166 ) { - D(fprintf(stderr, "%*c+ _gather_164[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_165")); + D(fprintf(stderr, "%*c+ _gather_165[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_166")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_164[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_165")); + D(fprintf(stderr, "%*c%s _gather_165[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_166")); } _res = NULL; done: @@ -31197,9 +31303,9 @@ _gather_164_rule(Parser *p) return _res; } -// _loop0_167: ',' (expression ['as' star_target]) +// _loop0_168: ',' (expression ['as' star_target]) static asdl_seq * -_loop0_167_rule(Parser *p) +_loop0_168_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31223,13 +31329,13 @@ _loop0_167_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_199_rule(p)) // expression ['as' star_target] + (elem = _tmp_200_rule(p)) // expression ['as' star_target] ) { _res = elem; @@ -31254,7 +31360,7 @@ _loop0_167_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_167[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_168[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expression ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31267,14 +31373,14 @@ _loop0_167_rule(Parser *p) } 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_167_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_168_type, _seq); D(p->level--); return _seq; } -// _gather_166: (expression ['as' star_target]) _loop0_167 +// _gather_167: (expression ['as' star_target]) _loop0_168 static asdl_seq * -_gather_166_rule(Parser *p) +_gather_167_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31283,27 +31389,27 @@ _gather_166_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expression ['as' star_target]) _loop0_167 + { // (expression ['as' star_target]) _loop0_168 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_167")); + D(fprintf(stderr, "%*c> _gather_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_168")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_199_rule(p)) // expression ['as' star_target] + (elem = _tmp_200_rule(p)) // expression ['as' star_target] && - (seq = _loop0_167_rule(p)) // _loop0_167 + (seq = _loop0_168_rule(p)) // _loop0_168 ) { - D(fprintf(stderr, "%*c+ _gather_166[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_167")); + D(fprintf(stderr, "%*c+ _gather_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_168")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_166[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_167")); + D(fprintf(stderr, "%*c%s _gather_167[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_168")); } _res = NULL; done: @@ -31311,9 +31417,9 @@ _gather_166_rule(Parser *p) return _res; } -// _loop0_169: ',' (expressions ['as' star_target]) +// _loop0_170: ',' (expressions ['as' star_target]) static asdl_seq * -_loop0_169_rule(Parser *p) +_loop0_170_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31337,13 +31443,13 @@ _loop0_169_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_170[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_200_rule(p)) // expressions ['as' star_target] + (elem = _tmp_201_rule(p)) // expressions ['as' star_target] ) { _res = elem; @@ -31368,7 +31474,7 @@ _loop0_169_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_169[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_170[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expressions ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31381,14 +31487,14 @@ _loop0_169_rule(Parser *p) } 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_169_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_170_type, _seq); D(p->level--); return _seq; } -// _gather_168: (expressions ['as' star_target]) _loop0_169 +// _gather_169: (expressions ['as' star_target]) _loop0_170 static asdl_seq * -_gather_168_rule(Parser *p) +_gather_169_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31397,27 +31503,27 @@ _gather_168_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expressions ['as' star_target]) _loop0_169 + { // (expressions ['as' star_target]) _loop0_170 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_169")); + D(fprintf(stderr, "%*c> _gather_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_170")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_200_rule(p)) // expressions ['as' star_target] + (elem = _tmp_201_rule(p)) // expressions ['as' star_target] && - (seq = _loop0_169_rule(p)) // _loop0_169 + (seq = _loop0_170_rule(p)) // _loop0_170 ) { - D(fprintf(stderr, "%*c+ _gather_168[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_169")); + D(fprintf(stderr, "%*c+ _gather_169[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_170")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_168[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_169")); + D(fprintf(stderr, "%*c%s _gather_169[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_170")); } _res = NULL; done: @@ -31425,9 +31531,9 @@ _gather_168_rule(Parser *p) return _res; } -// _tmp_170: 'except' | 'finally' +// _tmp_171: 'except' | 'finally' static void * -_tmp_170_rule(Parser *p) +_tmp_171_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31441,18 +31547,18 @@ _tmp_170_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_170[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'")); + D(fprintf(stderr, "%*c> _tmp_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 620)) // token='except' + (_keyword = _PyPegen_expect_token(p, 623)) // token='except' ) { - D(fprintf(stderr, "%*c+ _tmp_170[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except'")); + D(fprintf(stderr, "%*c+ _tmp_171[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_170[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_171[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except'")); } { // 'finally' @@ -31460,18 +31566,18 @@ _tmp_170_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_170[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'")); + D(fprintf(stderr, "%*c> _tmp_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 617)) // token='finally' + (_keyword = _PyPegen_expect_token(p, 620)) // token='finally' ) { - D(fprintf(stderr, "%*c+ _tmp_170[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally'")); + D(fprintf(stderr, "%*c+ _tmp_171[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_170[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_171[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'finally'")); } _res = NULL; @@ -31480,9 +31586,9 @@ _tmp_170_rule(Parser *p) return _res; } -// _tmp_171: 'as' NAME +// _tmp_172: 'as' NAME static void * -_tmp_171_rule(Parser *p) +_tmp_172_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31496,21 +31602,21 @@ _tmp_171_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_172[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( - (_keyword = _PyPegen_expect_token(p, 622)) // token='as' + (_keyword = _PyPegen_expect_token(p, 625)) // token='as' && (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_171[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_172[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_171[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_172[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -31519,9 +31625,9 @@ _tmp_171_rule(Parser *p) return _res; } -// _tmp_172: 'as' NAME +// _tmp_173: 'as' NAME static void * -_tmp_172_rule(Parser *p) +_tmp_173_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31535,21 +31641,21 @@ _tmp_172_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_172[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_173[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( - (_keyword = _PyPegen_expect_token(p, 622)) // token='as' + (_keyword = _PyPegen_expect_token(p, 625)) // token='as' && (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_172[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_173[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_172[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_173[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -31558,9 +31664,9 @@ _tmp_172_rule(Parser *p) return _res; } -// _tmp_173: 'as' NAME +// _tmp_174: 'as' NAME static void * -_tmp_173_rule(Parser *p) +_tmp_174_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31574,21 +31680,21 @@ _tmp_173_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_173[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_174[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( - (_keyword = _PyPegen_expect_token(p, 622)) // token='as' + (_keyword = _PyPegen_expect_token(p, 625)) // token='as' && (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_173[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_174[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_173[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_174[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -31597,9 +31703,9 @@ _tmp_173_rule(Parser *p) return _res; } -// _tmp_174: positional_patterns ',' +// _tmp_175: positional_patterns ',' static void * -_tmp_174_rule(Parser *p) +_tmp_175_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31613,7 +31719,7 @@ _tmp_174_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_174[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); + D(fprintf(stderr, "%*c> _tmp_175[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); Token * _literal; asdl_pattern_seq* positional_patterns_var; if ( @@ -31622,12 +31728,12 @@ _tmp_174_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_174[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); + D(fprintf(stderr, "%*c+ _tmp_175[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); _res = _PyPegen_dummy_name(p, positional_patterns_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_174[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_175[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "positional_patterns ','")); } _res = NULL; @@ -31636,9 +31742,9 @@ _tmp_174_rule(Parser *p) return _res; } -// _tmp_175: '->' expression +// _tmp_176: '->' expression static void * -_tmp_175_rule(Parser *p) +_tmp_176_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31652,7 +31758,7 @@ _tmp_175_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_175[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); + D(fprintf(stderr, "%*c> _tmp_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); Token * _literal; expr_ty expression_var; if ( @@ -31661,12 +31767,12 @@ _tmp_175_rule(Parser *p) (expression_var = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ _tmp_175[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); + D(fprintf(stderr, "%*c+ _tmp_176[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); _res = _PyPegen_dummy_name(p, _literal, expression_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_175[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_176[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'->' expression")); } _res = NULL; @@ -31675,9 +31781,9 @@ _tmp_175_rule(Parser *p) return _res; } -// _tmp_176: '(' arguments? ')' +// _tmp_177: '(' arguments? ')' static void * -_tmp_176_rule(Parser *p) +_tmp_177_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31691,7 +31797,7 @@ _tmp_176_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c> _tmp_177[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); Token * _literal; Token * _literal_1; void *_opt_var; @@ -31704,12 +31810,12 @@ _tmp_176_rule(Parser *p) (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_176[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c+ _tmp_177[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); _res = _PyPegen_dummy_name(p, _literal, _opt_var, _literal_1); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_176[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_177[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' arguments? ')'")); } _res = NULL; @@ -31718,9 +31824,9 @@ _tmp_176_rule(Parser *p) return _res; } -// _loop0_178: ',' double_starred_kvpair +// _loop0_179: ',' double_starred_kvpair static asdl_seq * -_loop0_178_rule(Parser *p) +_loop0_179_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31744,7 +31850,7 @@ _loop0_178_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); + D(fprintf(stderr, "%*c> _loop0_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); Token * _literal; KeyValuePair* elem; while ( @@ -31775,7 +31881,7 @@ _loop0_178_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_178[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_179[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' double_starred_kvpair")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31788,14 +31894,14 @@ _loop0_178_rule(Parser *p) } 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_178_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_179_type, _seq); D(p->level--); return _seq; } -// _gather_177: double_starred_kvpair _loop0_178 +// _gather_178: double_starred_kvpair _loop0_179 static asdl_seq * -_gather_177_rule(Parser *p) +_gather_178_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31804,27 +31910,27 @@ _gather_177_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // double_starred_kvpair _loop0_178 + { // double_starred_kvpair _loop0_179 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_177[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_178")); + D(fprintf(stderr, "%*c> _gather_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_179")); KeyValuePair* elem; asdl_seq * seq; if ( (elem = double_starred_kvpair_rule(p)) // double_starred_kvpair && - (seq = _loop0_178_rule(p)) // _loop0_178 + (seq = _loop0_179_rule(p)) // _loop0_179 ) { - D(fprintf(stderr, "%*c+ _gather_177[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_178")); + D(fprintf(stderr, "%*c+ _gather_178[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_179")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_177[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_178")); + D(fprintf(stderr, "%*c%s _gather_178[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_179")); } _res = NULL; done: @@ -31832,9 +31938,9 @@ _gather_177_rule(Parser *p) return _res; } -// _tmp_179: '}' | ',' +// _tmp_180: '}' | ',' static void * -_tmp_179_rule(Parser *p) +_tmp_180_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31848,18 +31954,18 @@ _tmp_179_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_179[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_179[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } { // ',' @@ -31867,18 +31973,18 @@ _tmp_179_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_179[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_179[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -31887,9 +31993,9 @@ _tmp_179_rule(Parser *p) return _res; } -// _tmp_180: star_targets '=' +// _tmp_181: star_targets '=' static void * -_tmp_180_rule(Parser *p) +_tmp_181_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31903,7 +32009,7 @@ _tmp_180_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty z; if ( @@ -31912,7 +32018,7 @@ _tmp_180_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_181[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -31922,7 +32028,7 @@ _tmp_180_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_181[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; @@ -31931,9 +32037,9 @@ _tmp_180_rule(Parser *p) return _res; } -// _tmp_181: '.' | '...' +// _tmp_182: '.' | '...' static void * -_tmp_181_rule(Parser *p) +_tmp_182_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31947,18 +32053,18 @@ _tmp_181_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 23)) // token='.' ) { - D(fprintf(stderr, "%*c+ _tmp_181[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c+ _tmp_182[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_181[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_182[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); } { // '...' @@ -31966,18 +32072,18 @@ _tmp_181_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 52)) // token='...' ) { - D(fprintf(stderr, "%*c+ _tmp_181[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c+ _tmp_182[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_181[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_182[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'")); } _res = NULL; @@ -31986,9 +32092,9 @@ _tmp_181_rule(Parser *p) return _res; } -// _tmp_182: '.' | '...' +// _tmp_183: '.' | '...' static void * -_tmp_182_rule(Parser *p) +_tmp_183_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32002,18 +32108,18 @@ _tmp_182_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 23)) // token='.' ) { - D(fprintf(stderr, "%*c+ _tmp_182[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_182[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); } { // '...' @@ -32021,18 +32127,18 @@ _tmp_182_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 52)) // token='...' ) { - D(fprintf(stderr, "%*c+ _tmp_182[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_182[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'")); } _res = NULL; @@ -32041,9 +32147,9 @@ _tmp_182_rule(Parser *p) return _res; } -// _tmp_183: '@' named_expression NEWLINE +// _tmp_184: '@' named_expression NEWLINE static void * -_tmp_183_rule(Parser *p) +_tmp_184_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32057,7 +32163,7 @@ _tmp_183_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); + D(fprintf(stderr, "%*c> _tmp_184[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); Token * _literal; expr_ty f; Token * newline_var; @@ -32069,7 +32175,7 @@ _tmp_183_rule(Parser *p) (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) { - D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); + D(fprintf(stderr, "%*c+ _tmp_184[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); _res = f; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32079,7 +32185,7 @@ _tmp_183_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_184[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'@' named_expression NEWLINE")); } _res = NULL; @@ -32088,9 +32194,9 @@ _tmp_183_rule(Parser *p) return _res; } -// _tmp_184: ',' expression +// _tmp_185: ',' expression static void * -_tmp_184_rule(Parser *p) +_tmp_185_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32104,7 +32210,7 @@ _tmp_184_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_184[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _tmp_185[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty c; if ( @@ -32113,7 +32219,7 @@ _tmp_184_rule(Parser *p) (c = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ _tmp_184[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c+ _tmp_185[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32123,7 +32229,7 @@ _tmp_184_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_184[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_185[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } _res = NULL; @@ -32132,9 +32238,9 @@ _tmp_184_rule(Parser *p) return _res; } -// _tmp_185: ',' star_expression +// _tmp_186: ',' star_expression static void * -_tmp_185_rule(Parser *p) +_tmp_186_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32148,7 +32254,7 @@ _tmp_185_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_185[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression")); + D(fprintf(stderr, "%*c> _tmp_186[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression")); Token * _literal; expr_ty c; if ( @@ -32157,7 +32263,7 @@ _tmp_185_rule(Parser *p) (c = star_expression_rule(p)) // star_expression ) { - D(fprintf(stderr, "%*c+ _tmp_185[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression")); + D(fprintf(stderr, "%*c+ _tmp_186[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32167,7 +32273,7 @@ _tmp_185_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_185[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_186[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_expression")); } _res = NULL; @@ -32176,9 +32282,9 @@ _tmp_185_rule(Parser *p) return _res; } -// _tmp_186: 'or' conjunction +// _tmp_187: 'or' conjunction static void * -_tmp_186_rule(Parser *p) +_tmp_187_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32192,7 +32298,7 @@ _tmp_186_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_186[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); + D(fprintf(stderr, "%*c> _tmp_187[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); Token * _keyword; expr_ty c; if ( @@ -32201,7 +32307,7 @@ _tmp_186_rule(Parser *p) (c = conjunction_rule(p)) // conjunction ) { - D(fprintf(stderr, "%*c+ _tmp_186[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); + D(fprintf(stderr, "%*c+ _tmp_187[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32211,7 +32317,7 @@ _tmp_186_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_186[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_187[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'or' conjunction")); } _res = NULL; @@ -32220,9 +32326,9 @@ _tmp_186_rule(Parser *p) return _res; } -// _tmp_187: 'and' inversion +// _tmp_188: 'and' inversion static void * -_tmp_187_rule(Parser *p) +_tmp_188_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32236,7 +32342,7 @@ _tmp_187_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_187[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion")); + D(fprintf(stderr, "%*c> _tmp_188[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion")); Token * _keyword; expr_ty c; if ( @@ -32245,7 +32351,7 @@ _tmp_187_rule(Parser *p) (c = inversion_rule(p)) // inversion ) { - D(fprintf(stderr, "%*c+ _tmp_187[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion")); + D(fprintf(stderr, "%*c+ _tmp_188[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32255,7 +32361,7 @@ _tmp_187_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_187[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_188[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'and' inversion")); } _res = NULL; @@ -32264,9 +32370,9 @@ _tmp_187_rule(Parser *p) return _res; } -// _tmp_188: 'if' disjunction +// _tmp_189: 'if' disjunction static void * -_tmp_188_rule(Parser *p) +_tmp_189_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32280,16 +32386,16 @@ _tmp_188_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_188[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c> _tmp_189[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 624)) // token='if' + (_keyword = _PyPegen_expect_token(p, 627)) // token='if' && (z = disjunction_rule(p)) // disjunction ) { - D(fprintf(stderr, "%*c+ _tmp_188[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c+ _tmp_189[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32299,7 +32405,7 @@ _tmp_188_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_188[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_189[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction")); } _res = NULL; @@ -32308,9 +32414,9 @@ _tmp_188_rule(Parser *p) return _res; } -// _tmp_189: 'if' disjunction +// _tmp_190: 'if' disjunction static void * -_tmp_189_rule(Parser *p) +_tmp_190_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32324,16 +32430,16 @@ _tmp_189_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_189[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c> _tmp_190[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 624)) // token='if' + (_keyword = _PyPegen_expect_token(p, 627)) // token='if' && (z = disjunction_rule(p)) // disjunction ) { - D(fprintf(stderr, "%*c+ _tmp_189[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c+ _tmp_190[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32343,7 +32449,7 @@ _tmp_189_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_189[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_190[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction")); } _res = NULL; @@ -32352,9 +32458,9 @@ _tmp_189_rule(Parser *p) return _res; } -// _tmp_190: starred_expression | (assignment_expression | expression !':=') !'=' +// _tmp_191: starred_expression | (assignment_expression | expression !':=') !'=' static void * -_tmp_190_rule(Parser *p) +_tmp_191_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32368,18 +32474,18 @@ _tmp_190_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_190[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c> _tmp_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); expr_ty starred_expression_var; if ( (starred_expression_var = starred_expression_rule(p)) // starred_expression ) { - D(fprintf(stderr, "%*c+ _tmp_190[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c+ _tmp_191[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); _res = starred_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_190[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_191[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression")); } { // (assignment_expression | expression !':=') !'=' @@ -32387,20 +32493,20 @@ _tmp_190_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_190[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); - void *_tmp_201_var; + D(fprintf(stderr, "%*c> _tmp_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); + void *_tmp_202_var; if ( - (_tmp_201_var = _tmp_201_rule(p)) // assignment_expression | expression !':=' + (_tmp_202_var = _tmp_202_rule(p)) // assignment_expression | expression !':=' && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_190[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); - _res = _tmp_201_var; + D(fprintf(stderr, "%*c+ _tmp_191[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); + _res = _tmp_202_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_190[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_191[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(assignment_expression | expression !':=') !'='")); } _res = NULL; @@ -32409,9 +32515,9 @@ _tmp_190_rule(Parser *p) return _res; } -// _tmp_191: ',' star_target +// _tmp_192: ',' star_target static void * -_tmp_191_rule(Parser *p) +_tmp_192_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32425,7 +32531,7 @@ _tmp_191_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _tmp_192[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); Token * _literal; expr_ty c; if ( @@ -32434,7 +32540,7 @@ _tmp_191_rule(Parser *p) (c = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_191[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c+ _tmp_192[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32444,7 +32550,7 @@ _tmp_191_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_191[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_192[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } _res = NULL; @@ -32453,9 +32559,9 @@ _tmp_191_rule(Parser *p) return _res; } -// _tmp_192: ',' star_target +// _tmp_193: ',' star_target static void * -_tmp_192_rule(Parser *p) +_tmp_193_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32469,7 +32575,7 @@ _tmp_192_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_192[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _tmp_193[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); Token * _literal; expr_ty c; if ( @@ -32478,7 +32584,7 @@ _tmp_192_rule(Parser *p) (c = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_192[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c+ _tmp_193[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32488,7 +32594,7 @@ _tmp_192_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_192[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_193[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } _res = NULL; @@ -32497,9 +32603,9 @@ _tmp_192_rule(Parser *p) return _res; } -// _tmp_193: star_targets '=' +// _tmp_194: star_targets '=' static void * -_tmp_193_rule(Parser *p) +_tmp_194_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32513,7 +32619,7 @@ _tmp_193_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_193[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_194[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty star_targets_var; if ( @@ -32522,12 +32628,12 @@ _tmp_193_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_193[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_194[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = _PyPegen_dummy_name(p, star_targets_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_193[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_194[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; @@ -32536,9 +32642,9 @@ _tmp_193_rule(Parser *p) return _res; } -// _tmp_194: star_targets '=' +// _tmp_195: star_targets '=' static void * -_tmp_194_rule(Parser *p) +_tmp_195_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32552,7 +32658,7 @@ _tmp_194_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_194[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_195[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty star_targets_var; if ( @@ -32561,12 +32667,12 @@ _tmp_194_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_194[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_195[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = _PyPegen_dummy_name(p, star_targets_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_194[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_195[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; @@ -32575,9 +32681,9 @@ _tmp_194_rule(Parser *p) return _res; } -// _tmp_195: ')' | '**' +// _tmp_196: ')' | '**' static void * -_tmp_195_rule(Parser *p) +_tmp_196_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32591,18 +32697,18 @@ _tmp_195_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_195[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_195[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_196[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_195[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_196[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // '**' @@ -32610,18 +32716,18 @@ _tmp_195_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_195[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_195[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_196[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_195[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_196[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } _res = NULL; @@ -32630,9 +32736,9 @@ _tmp_195_rule(Parser *p) return _res; } -// _tmp_196: ':' | '**' +// _tmp_197: ':' | '**' static void * -_tmp_196_rule(Parser *p) +_tmp_197_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32646,18 +32752,18 @@ _tmp_196_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_196[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_197[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_196[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_197[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // '**' @@ -32665,18 +32771,18 @@ _tmp_196_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_196[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_197[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_196[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_197[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } _res = NULL; @@ -32685,9 +32791,9 @@ _tmp_196_rule(Parser *p) return _res; } -// _tmp_197: expression ['as' star_target] +// _tmp_198: expression ['as' star_target] static void * -_tmp_197_rule(Parser *p) +_tmp_198_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32701,22 +32807,22 @@ _tmp_197_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_198[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_202_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_203_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_197[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_198[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); _res = _PyPegen_dummy_name(p, expression_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_197[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_198[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' star_target]")); } _res = NULL; @@ -32725,9 +32831,9 @@ _tmp_197_rule(Parser *p) return _res; } -// _tmp_198: expressions ['as' star_target] +// _tmp_199: expressions ['as' star_target] static void * -_tmp_198_rule(Parser *p) +_tmp_199_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32741,22 +32847,22 @@ _tmp_198_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_198[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_199[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expressions_var; if ( (expressions_var = expressions_rule(p)) // expressions && - (_opt_var = _tmp_203_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_204_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_198[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_199[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); _res = _PyPegen_dummy_name(p, expressions_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_198[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_199[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expressions ['as' star_target]")); } _res = NULL; @@ -32765,9 +32871,9 @@ _tmp_198_rule(Parser *p) return _res; } -// _tmp_199: expression ['as' star_target] +// _tmp_200: expression ['as' star_target] static void * -_tmp_199_rule(Parser *p) +_tmp_200_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32781,22 +32887,22 @@ _tmp_199_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_199[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_200[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_204_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_205_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_199[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_200[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); _res = _PyPegen_dummy_name(p, expression_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_199[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_200[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' star_target]")); } _res = NULL; @@ -32805,9 +32911,9 @@ _tmp_199_rule(Parser *p) return _res; } -// _tmp_200: expressions ['as' star_target] +// _tmp_201: expressions ['as' star_target] static void * -_tmp_200_rule(Parser *p) +_tmp_201_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32821,22 +32927,22 @@ _tmp_200_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_200[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expressions_var; if ( (expressions_var = expressions_rule(p)) // expressions && - (_opt_var = _tmp_205_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_206_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_200[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); _res = _PyPegen_dummy_name(p, expressions_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_200[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expressions ['as' star_target]")); } _res = NULL; @@ -32845,9 +32951,9 @@ _tmp_200_rule(Parser *p) return _res; } -// _tmp_201: assignment_expression | expression !':=' +// _tmp_202: assignment_expression | expression !':=' static void * -_tmp_201_rule(Parser *p) +_tmp_202_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32861,18 +32967,18 @@ _tmp_201_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); expr_ty assignment_expression_var; if ( (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression ) { - D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); _res = assignment_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); } { // expression !':=' @@ -32880,7 +32986,7 @@ _tmp_201_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression @@ -32888,12 +32994,12 @@ _tmp_201_rule(Parser *p) _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 53) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); _res = expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression !':='")); } _res = NULL; @@ -32902,9 +33008,9 @@ _tmp_201_rule(Parser *p) return _res; } -// _tmp_202: 'as' star_target +// _tmp_203: 'as' star_target static void * -_tmp_202_rule(Parser *p) +_tmp_203_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32918,21 +33024,21 @@ _tmp_202_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( - (_keyword = _PyPegen_expect_token(p, 622)) // token='as' + (_keyword = _PyPegen_expect_token(p, 625)) // token='as' && (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_203[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_203[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; @@ -32941,9 +33047,9 @@ _tmp_202_rule(Parser *p) return _res; } -// _tmp_203: 'as' star_target +// _tmp_204: 'as' star_target static void * -_tmp_203_rule(Parser *p) +_tmp_204_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32957,21 +33063,21 @@ _tmp_203_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_204[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( - (_keyword = _PyPegen_expect_token(p, 622)) // token='as' + (_keyword = _PyPegen_expect_token(p, 625)) // token='as' && (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_203[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_204[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_203[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_204[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; @@ -32980,9 +33086,9 @@ _tmp_203_rule(Parser *p) return _res; } -// _tmp_204: 'as' star_target +// _tmp_205: 'as' star_target static void * -_tmp_204_rule(Parser *p) +_tmp_205_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32996,21 +33102,21 @@ _tmp_204_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_204[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_205[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( - (_keyword = _PyPegen_expect_token(p, 622)) // token='as' + (_keyword = _PyPegen_expect_token(p, 625)) // token='as' && (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_204[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_205[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_204[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_205[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; @@ -33019,9 +33125,9 @@ _tmp_204_rule(Parser *p) return _res; } -// _tmp_205: 'as' star_target +// _tmp_206: 'as' star_target static void * -_tmp_205_rule(Parser *p) +_tmp_206_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -33035,21 +33141,21 @@ _tmp_205_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_205[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_206[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( - (_keyword = _PyPegen_expect_token(p, 622)) // token='as' + (_keyword = _PyPegen_expect_token(p, 625)) // token='as' && (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_205[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_206[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_205[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_206[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; From webhook-mailer at python.org Fri Nov 5 11:27:31 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 05 Nov 2021 15:27:31 -0000 Subject: [Python-checkins] bpo-45678: Add more ``singledispatchmethod`` tests (GH-29412) (GH-29424) Message-ID: https://github.com/python/cpython/commit/bcb236c19e4ddf5ccf0fc45ab541eabf1f757a64 commit: bcb236c19e4ddf5ccf0fc45ab541eabf1f757a64 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-05T16:27:22+01:00 summary: bpo-45678: Add more ``singledispatchmethod`` tests (GH-29412) (GH-29424) In order to fix a bug in the 3.9 branch in GH-29394, more tests were added to ``test_functools.py`` to ensure that ``singledispatchmethod`` still correctly wrapped a target method, even if the target method had already been wrapped by multiple other decorators. This PR brings the new tests into the 3.11 and 3.10 branches as well. (cherry picked from commit 32f55d1a5de66f9a86964fc0655d7a006a9d90b9) Co-authored-by: Alex Waygood files: A Misc/NEWS.d/next/Tests/2021-11-04-20-03-32.bpo-45678.1xNMjN.rst M Lib/test/test_functools.py diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 1a3c921509d5e..7bc355ff7213e 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -2519,6 +2519,105 @@ def static_func(arg: int) -> str: self.assertEqual(A.static_func.__name__, 'static_func') self.assertEqual(A().static_func.__name__, 'static_func') + def test_double_wrapped_methods(self): + def classmethod_friendly_decorator(func): + wrapped = func.__func__ + @classmethod + @functools.wraps(wrapped) + def wrapper(*args, **kwargs): + return wrapped(*args, **kwargs) + return wrapper + + class WithoutSingleDispatch: + @classmethod + @contextlib.contextmanager + def cls_context_manager(cls, arg: int) -> str: + try: + yield str(arg) + finally: + return 'Done' + + @classmethod_friendly_decorator + @classmethod + def decorated_classmethod(cls, arg: int) -> str: + return str(arg) + + class WithSingleDispatch: + @functools.singledispatchmethod + @classmethod + @contextlib.contextmanager + def cls_context_manager(cls, arg: int) -> str: + """My function docstring""" + try: + yield str(arg) + finally: + return 'Done' + + @functools.singledispatchmethod + @classmethod_friendly_decorator + @classmethod + def decorated_classmethod(cls, arg: int) -> str: + """My function docstring""" + return str(arg) + + # These are sanity checks + # to test the test itself is working as expected + with WithoutSingleDispatch.cls_context_manager(5) as foo: + without_single_dispatch_foo = foo + + with WithSingleDispatch.cls_context_manager(5) as foo: + single_dispatch_foo = foo + + self.assertEqual(without_single_dispatch_foo, single_dispatch_foo) + self.assertEqual(single_dispatch_foo, '5') + + self.assertEqual( + WithoutSingleDispatch.decorated_classmethod(5), + WithSingleDispatch.decorated_classmethod(5) + ) + + self.assertEqual(WithSingleDispatch.decorated_classmethod(5), '5') + + # Behavioural checks now follow + for method_name in ('cls_context_manager', 'decorated_classmethod'): + with self.subTest(method=method_name): + self.assertEqual( + getattr(WithSingleDispatch, method_name).__name__, + getattr(WithoutSingleDispatch, method_name).__name__ + ) + + self.assertEqual( + getattr(WithSingleDispatch(), method_name).__name__, + getattr(WithoutSingleDispatch(), method_name).__name__ + ) + + for meth in ( + WithSingleDispatch.cls_context_manager, + WithSingleDispatch().cls_context_manager, + WithSingleDispatch.decorated_classmethod, + WithSingleDispatch().decorated_classmethod + ): + with self.subTest(meth=meth): + self.assertEqual(meth.__doc__, 'My function docstring') + self.assertEqual(meth.__annotations__['arg'], int) + + self.assertEqual( + WithSingleDispatch.cls_context_manager.__name__, + 'cls_context_manager' + ) + self.assertEqual( + WithSingleDispatch().cls_context_manager.__name__, + 'cls_context_manager' + ) + self.assertEqual( + WithSingleDispatch.decorated_classmethod.__name__, + 'decorated_classmethod' + ) + self.assertEqual( + WithSingleDispatch().decorated_classmethod.__name__, + 'decorated_classmethod' + ) + def test_invalid_registrations(self): msg_prefix = "Invalid first argument to `register()`: " msg_suffix = ( diff --git a/Misc/NEWS.d/next/Tests/2021-11-04-20-03-32.bpo-45678.1xNMjN.rst b/Misc/NEWS.d/next/Tests/2021-11-04-20-03-32.bpo-45678.1xNMjN.rst new file mode 100644 index 0000000000000..736d5f65f961b --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-11-04-20-03-32.bpo-45678.1xNMjN.rst @@ -0,0 +1,3 @@ +Add tests for scenarios in which :class:`functools.singledispatchmethod` is +stacked on top of a method that has already been wrapped by two other +decorators. Patch by Alex Waygood. From webhook-mailer at python.org Fri Nov 5 12:25:17 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 05 Nov 2021 16:25:17 -0000 Subject: [Python-checkins] bpo-45762: Improve docs for ``@singledispatch``/``@singledispatchmethod`` (GH-29426) Message-ID: https://github.com/python/cpython/commit/71e8a3e76a32f5eabe20e7fa984f384ca9af6ec6 commit: 71e8a3e76a32f5eabe20e7fa984f384ca9af6ec6 branch: main author: Alex Waygood committer: ambv date: 2021-11-05T17:25:08+01:00 summary: bpo-45762: Improve docs for ``@singledispatch``/``@singledispatchmethod`` (GH-29426) files: A Misc/NEWS.d/next/Documentation/2021-11-05-12-15-24.bpo-45726.GwRr7e.rst M Doc/library/functools.rst diff --git a/Doc/library/functools.rst b/Doc/library/functools.rst index e40fe7bb85fc6..a01b17287878c 100644 --- a/Doc/library/functools.rst +++ b/Doc/library/functools.rst @@ -402,8 +402,8 @@ The :mod:`functools` module defines the following functions: dispatch>` :term:`generic function`. To define a generic function, decorate it with the ``@singledispatch`` - decorator. Note that the dispatch happens on the type of the first argument, - create your function accordingly:: + decorator. When defining a function using ``@singledispatch``, note that the + dispatch happens on the type of the first argument:: >>> from functools import singledispatch >>> @singledispatch @@ -413,9 +413,9 @@ The :mod:`functools` module defines the following functions: ... print(arg) To add overloaded implementations to the function, use the :func:`register` - attribute of the generic function. It is a decorator. For functions - annotated with types, the decorator will infer the type of the first - argument automatically:: + attribute of the generic function, which can be used as a decorator. For + functions annotated with types, the decorator will infer the type of the + first argument automatically:: >>> @fun.register ... def _(arg: int, verbose=False): @@ -441,17 +441,17 @@ The :mod:`functools` module defines the following functions: ... - To enable registering lambdas and pre-existing functions, the - :func:`register` attribute can be used in a functional form:: + To enable registering :term:`lambdas` and pre-existing functions, + the :func:`register` attribute can also be used in a functional form:: >>> def nothing(arg, verbose=False): ... print("Nothing.") ... >>> fun.register(type(None), nothing) - The :func:`register` attribute returns the undecorated function which - enables decorator stacking, pickling, as well as creating unit tests for - each variant independently:: + The :func:`register` attribute returns the undecorated function. This + enables decorator stacking, :mod:`pickling`, and the creation + of unit tests for each variant independently:: >>> @fun.register(float) ... @fun.register(Decimal) @@ -486,11 +486,12 @@ The :mod:`functools` module defines the following functions: Where there is no registered implementation for a specific type, its method resolution order is used to find a more generic implementation. The original function decorated with ``@singledispatch`` is registered - for the base ``object`` type, which means it is used if no better + for the base :class:`object` type, which means it is used if no better implementation is found. - If an implementation registered to :term:`abstract base class`, virtual - subclasses will be dispatched to that implementation:: + If an implementation is registered to an :term:`abstract base class`, + virtual subclasses of the base class will be dispatched to that + implementation:: >>> from collections.abc import Mapping >>> @fun.register @@ -503,7 +504,7 @@ The :mod:`functools` module defines the following functions: >>> fun({"a": "b"}) a => b - To check which implementation will the generic function choose for + To check which implementation the generic function will choose for a given type, use the ``dispatch()`` attribute:: >>> fun.dispatch(float) @@ -526,7 +527,7 @@ The :mod:`functools` module defines the following functions: .. versionadded:: 3.4 .. versionchanged:: 3.7 - The :func:`register` attribute supports using type annotations. + The :func:`register` attribute now supports using type annotations. .. class:: singledispatchmethod(func) @@ -535,8 +536,9 @@ The :mod:`functools` module defines the following functions: dispatch>` :term:`generic function`. To define a generic method, decorate it with the ``@singledispatchmethod`` - decorator. Note that the dispatch happens on the type of the first non-self - or non-cls argument, create your function accordingly:: + decorator. When defining a function using ``@singledispatchmethod``, note + that the dispatch happens on the type of the first non-*self* or non-*cls* + argument:: class Negator: @singledispatchmethod @@ -552,9 +554,10 @@ The :mod:`functools` module defines the following functions: return not arg ``@singledispatchmethod`` supports nesting with other decorators such as - ``@classmethod``. Note that to allow for ``dispatcher.register``, - ``singledispatchmethod`` must be the *outer most* decorator. Here is the - ``Negator`` class with the ``neg`` methods being class bound:: + :func:`@classmethod`. Note that to allow for + ``dispatcher.register``, ``singledispatchmethod`` must be the *outer most* + decorator. Here is the ``Negator`` class with the ``neg`` methods bound to + the class, rather than an instance of the class:: class Negator: @singledispatchmethod @@ -572,8 +575,9 @@ The :mod:`functools` module defines the following functions: def _(cls, arg: bool): return not arg - The same pattern can be used for other similar decorators: ``staticmethod``, - ``abstractmethod``, and others. + The same pattern can be used for other similar decorators: + :func:`@staticmethod`, + :func:`@abstractmethod`, and others. .. versionadded:: 3.8 diff --git a/Misc/NEWS.d/next/Documentation/2021-11-05-12-15-24.bpo-45726.GwRr7e.rst b/Misc/NEWS.d/next/Documentation/2021-11-05-12-15-24.bpo-45726.GwRr7e.rst new file mode 100644 index 0000000000000..7ff6283a2a34d --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-05-12-15-24.bpo-45726.GwRr7e.rst @@ -0,0 +1,2 @@ +Improve documentation for :func:`functools.singledispatch` and +:class:`functools.singledispatchmethod`. From webhook-mailer at python.org Fri Nov 5 12:49:50 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 05 Nov 2021 16:49:50 -0000 Subject: [Python-checkins] bpo-45762: Improve docs for ``@singledispatch``/``@singledispatchmethod`` (GH-29426) (GH-29431) Message-ID: https://github.com/python/cpython/commit/279a7a0c9429f87c9e1f1042f580faf460b176e1 commit: 279a7a0c9429f87c9e1f1042f580faf460b176e1 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-05T17:49:40+01:00 summary: bpo-45762: Improve docs for ``@singledispatch``/``@singledispatchmethod`` (GH-29426) (GH-29431) (cherry picked from commit 71e8a3e76a32f5eabe20e7fa984f384ca9af6ec6) Co-authored-by: Alex Waygood files: A Misc/NEWS.d/next/Documentation/2021-11-05-12-15-24.bpo-45726.GwRr7e.rst M Doc/library/functools.rst diff --git a/Doc/library/functools.rst b/Doc/library/functools.rst index e40fe7bb85fc6..a01b17287878c 100644 --- a/Doc/library/functools.rst +++ b/Doc/library/functools.rst @@ -402,8 +402,8 @@ The :mod:`functools` module defines the following functions: dispatch>` :term:`generic function`. To define a generic function, decorate it with the ``@singledispatch`` - decorator. Note that the dispatch happens on the type of the first argument, - create your function accordingly:: + decorator. When defining a function using ``@singledispatch``, note that the + dispatch happens on the type of the first argument:: >>> from functools import singledispatch >>> @singledispatch @@ -413,9 +413,9 @@ The :mod:`functools` module defines the following functions: ... print(arg) To add overloaded implementations to the function, use the :func:`register` - attribute of the generic function. It is a decorator. For functions - annotated with types, the decorator will infer the type of the first - argument automatically:: + attribute of the generic function, which can be used as a decorator. For + functions annotated with types, the decorator will infer the type of the + first argument automatically:: >>> @fun.register ... def _(arg: int, verbose=False): @@ -441,17 +441,17 @@ The :mod:`functools` module defines the following functions: ... - To enable registering lambdas and pre-existing functions, the - :func:`register` attribute can be used in a functional form:: + To enable registering :term:`lambdas` and pre-existing functions, + the :func:`register` attribute can also be used in a functional form:: >>> def nothing(arg, verbose=False): ... print("Nothing.") ... >>> fun.register(type(None), nothing) - The :func:`register` attribute returns the undecorated function which - enables decorator stacking, pickling, as well as creating unit tests for - each variant independently:: + The :func:`register` attribute returns the undecorated function. This + enables decorator stacking, :mod:`pickling`, and the creation + of unit tests for each variant independently:: >>> @fun.register(float) ... @fun.register(Decimal) @@ -486,11 +486,12 @@ The :mod:`functools` module defines the following functions: Where there is no registered implementation for a specific type, its method resolution order is used to find a more generic implementation. The original function decorated with ``@singledispatch`` is registered - for the base ``object`` type, which means it is used if no better + for the base :class:`object` type, which means it is used if no better implementation is found. - If an implementation registered to :term:`abstract base class`, virtual - subclasses will be dispatched to that implementation:: + If an implementation is registered to an :term:`abstract base class`, + virtual subclasses of the base class will be dispatched to that + implementation:: >>> from collections.abc import Mapping >>> @fun.register @@ -503,7 +504,7 @@ The :mod:`functools` module defines the following functions: >>> fun({"a": "b"}) a => b - To check which implementation will the generic function choose for + To check which implementation the generic function will choose for a given type, use the ``dispatch()`` attribute:: >>> fun.dispatch(float) @@ -526,7 +527,7 @@ The :mod:`functools` module defines the following functions: .. versionadded:: 3.4 .. versionchanged:: 3.7 - The :func:`register` attribute supports using type annotations. + The :func:`register` attribute now supports using type annotations. .. class:: singledispatchmethod(func) @@ -535,8 +536,9 @@ The :mod:`functools` module defines the following functions: dispatch>` :term:`generic function`. To define a generic method, decorate it with the ``@singledispatchmethod`` - decorator. Note that the dispatch happens on the type of the first non-self - or non-cls argument, create your function accordingly:: + decorator. When defining a function using ``@singledispatchmethod``, note + that the dispatch happens on the type of the first non-*self* or non-*cls* + argument:: class Negator: @singledispatchmethod @@ -552,9 +554,10 @@ The :mod:`functools` module defines the following functions: return not arg ``@singledispatchmethod`` supports nesting with other decorators such as - ``@classmethod``. Note that to allow for ``dispatcher.register``, - ``singledispatchmethod`` must be the *outer most* decorator. Here is the - ``Negator`` class with the ``neg`` methods being class bound:: + :func:`@classmethod`. Note that to allow for + ``dispatcher.register``, ``singledispatchmethod`` must be the *outer most* + decorator. Here is the ``Negator`` class with the ``neg`` methods bound to + the class, rather than an instance of the class:: class Negator: @singledispatchmethod @@ -572,8 +575,9 @@ The :mod:`functools` module defines the following functions: def _(cls, arg: bool): return not arg - The same pattern can be used for other similar decorators: ``staticmethod``, - ``abstractmethod``, and others. + The same pattern can be used for other similar decorators: + :func:`@staticmethod`, + :func:`@abstractmethod`, and others. .. versionadded:: 3.8 diff --git a/Misc/NEWS.d/next/Documentation/2021-11-05-12-15-24.bpo-45726.GwRr7e.rst b/Misc/NEWS.d/next/Documentation/2021-11-05-12-15-24.bpo-45726.GwRr7e.rst new file mode 100644 index 0000000000000..7ff6283a2a34d --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-05-12-15-24.bpo-45726.GwRr7e.rst @@ -0,0 +1,2 @@ +Improve documentation for :func:`functools.singledispatch` and +:class:`functools.singledispatchmethod`. From webhook-mailer at python.org Fri Nov 5 12:52:25 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 05 Nov 2021 16:52:25 -0000 Subject: [Python-checkins] bpo-45762: Improve docs for ``@singledispatch``/``@singledispatchmethod`` (GH-29426) (GH-29430) Message-ID: https://github.com/python/cpython/commit/a8ae7a5613dc5d8fc2e93ddffa93b251ba3218b0 commit: a8ae7a5613dc5d8fc2e93ddffa93b251ba3218b0 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-05T17:52:14+01:00 summary: bpo-45762: Improve docs for ``@singledispatch``/``@singledispatchmethod`` (GH-29426) (GH-29430) (cherry picked from commit 71e8a3e76a32f5eabe20e7fa984f384ca9af6ec6) Co-authored-by: Alex Waygood files: A Misc/NEWS.d/next/Documentation/2021-11-05-12-15-24.bpo-45726.GwRr7e.rst M Doc/library/functools.rst diff --git a/Doc/library/functools.rst b/Doc/library/functools.rst index b2901e43bef96..1e408482c7b0e 100644 --- a/Doc/library/functools.rst +++ b/Doc/library/functools.rst @@ -392,8 +392,8 @@ The :mod:`functools` module defines the following functions: dispatch>` :term:`generic function`. To define a generic function, decorate it with the ``@singledispatch`` - decorator. Note that the dispatch happens on the type of the first argument, - create your function accordingly:: + decorator. When defining a function using ``@singledispatch``, note that the + dispatch happens on the type of the first argument:: >>> from functools import singledispatch >>> @singledispatch @@ -403,9 +403,9 @@ The :mod:`functools` module defines the following functions: ... print(arg) To add overloaded implementations to the function, use the :func:`register` - attribute of the generic function. It is a decorator. For functions - annotated with types, the decorator will infer the type of the first - argument automatically:: + attribute of the generic function, which can be used as a decorator. For + functions annotated with types, the decorator will infer the type of the + first argument automatically:: >>> @fun.register ... def _(arg: int, verbose=False): @@ -431,17 +431,17 @@ The :mod:`functools` module defines the following functions: ... - To enable registering lambdas and pre-existing functions, the - :func:`register` attribute can be used in a functional form:: + To enable registering :term:`lambdas` and pre-existing functions, + the :func:`register` attribute can also be used in a functional form:: >>> def nothing(arg, verbose=False): ... print("Nothing.") ... >>> fun.register(type(None), nothing) - The :func:`register` attribute returns the undecorated function which - enables decorator stacking, pickling, as well as creating unit tests for - each variant independently:: + The :func:`register` attribute returns the undecorated function. This + enables decorator stacking, :mod:`pickling`, and the creation + of unit tests for each variant independently:: >>> @fun.register(float) ... @fun.register(Decimal) @@ -476,11 +476,12 @@ The :mod:`functools` module defines the following functions: Where there is no registered implementation for a specific type, its method resolution order is used to find a more generic implementation. The original function decorated with ``@singledispatch`` is registered - for the base ``object`` type, which means it is used if no better + for the base :class:`object` type, which means it is used if no better implementation is found. - If an implementation registered to :term:`abstract base class`, virtual - subclasses will be dispatched to that implementation:: + If an implementation is registered to an :term:`abstract base class`, + virtual subclasses of the base class will be dispatched to that + implementation:: >>> from collections.abc import Mapping >>> @fun.register @@ -493,7 +494,7 @@ The :mod:`functools` module defines the following functions: >>> fun({"a": "b"}) a => b - To check which implementation will the generic function choose for + To check which implementation the generic function will choose for a given type, use the ``dispatch()`` attribute:: >>> fun.dispatch(float) @@ -516,7 +517,7 @@ The :mod:`functools` module defines the following functions: .. versionadded:: 3.4 .. versionchanged:: 3.7 - The :func:`register` attribute supports using type annotations. + The :func:`register` attribute now supports using type annotations. .. class:: singledispatchmethod(func) @@ -525,8 +526,9 @@ The :mod:`functools` module defines the following functions: dispatch>` :term:`generic function`. To define a generic method, decorate it with the ``@singledispatchmethod`` - decorator. Note that the dispatch happens on the type of the first non-self - or non-cls argument, create your function accordingly:: + decorator. When defining a function using ``@singledispatchmethod``, note + that the dispatch happens on the type of the first non-*self* or non-*cls* + argument:: class Negator: @singledispatchmethod @@ -542,9 +544,10 @@ The :mod:`functools` module defines the following functions: return not arg ``@singledispatchmethod`` supports nesting with other decorators such as - ``@classmethod``. Note that to allow for ``dispatcher.register``, - ``singledispatchmethod`` must be the *outer most* decorator. Here is the - ``Negator`` class with the ``neg`` methods being class bound:: + :func:`@classmethod`. Note that to allow for + ``dispatcher.register``, ``singledispatchmethod`` must be the *outer most* + decorator. Here is the ``Negator`` class with the ``neg`` methods bound to + the class, rather than an instance of the class:: class Negator: @singledispatchmethod @@ -562,8 +565,9 @@ The :mod:`functools` module defines the following functions: def _(cls, arg: bool): return not arg - The same pattern can be used for other similar decorators: ``staticmethod``, - ``abstractmethod``, and others. + The same pattern can be used for other similar decorators: + :func:`@staticmethod`, + :func:`@abstractmethod`, and others. .. versionadded:: 3.8 diff --git a/Misc/NEWS.d/next/Documentation/2021-11-05-12-15-24.bpo-45726.GwRr7e.rst b/Misc/NEWS.d/next/Documentation/2021-11-05-12-15-24.bpo-45726.GwRr7e.rst new file mode 100644 index 0000000000000..7ff6283a2a34d --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-05-12-15-24.bpo-45726.GwRr7e.rst @@ -0,0 +1,2 @@ +Improve documentation for :func:`functools.singledispatch` and +:class:`functools.singledispatchmethod`. From webhook-mailer at python.org Fri Nov 5 13:19:51 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Fri, 05 Nov 2021 17:19:51 -0000 Subject: [Python-checkins] bpo-45243: Use connection limits to simplify `sqlite3` tests (GH-29356) Message-ID: https://github.com/python/cpython/commit/3d42cd9461e60c7427f3793f640cd975fbd99289 commit: 3d42cd9461e60c7427f3793f640cd975fbd99289 branch: main author: Erlend Egeberg Aasland committer: serhiy-storchaka date: 2021-11-05T19:19:43+02:00 summary: bpo-45243: Use connection limits to simplify `sqlite3` tests (GH-29356) files: M Lib/test/test_sqlite3/test_dbapi.py M Lib/test/test_sqlite3/test_regression.py M Lib/test/test_sqlite3/test_userfunctions.py diff --git a/Lib/test/test_sqlite3/test_dbapi.py b/Lib/test/test_sqlite3/test_dbapi.py index ba3652a04a2d8..6628eee975d35 100644 --- a/Lib/test/test_sqlite3/test_dbapi.py +++ b/Lib/test/test_sqlite3/test_dbapi.py @@ -29,7 +29,6 @@ from test.support import ( SHORT_TIMEOUT, - bigmemtest, check_disallow_instantiation, threading_helper, ) @@ -48,6 +47,22 @@ def managed_connect(*args, in_mem=False, **kwargs): unlink(TESTFN) +# Helper for temporary memory databases +def memory_database(): + cx = sqlite.connect(":memory:") + return contextlib.closing(cx) + + +# Temporarily limit a database connection parameter + at contextlib.contextmanager +def cx_limit(cx, category=sqlite.SQLITE_LIMIT_LENGTH, limit=128): + try: + _prev = cx.setlimit(category, limit) + yield limit + finally: + cx.setlimit(category, _prev) + + class ModuleTests(unittest.TestCase): def test_api_level(self): self.assertEqual(sqlite.apilevel, "2.0", @@ -650,6 +665,15 @@ def __getitem__(slf, x): with self.assertRaises(ZeroDivisionError): self.cu.execute("select name from test where name=?", L()) + def test_execute_too_many_params(self): + category = sqlite.SQLITE_LIMIT_VARIABLE_NUMBER + msg = "too many SQL variables" + with cx_limit(self.cx, category=category, limit=1): + self.cu.execute("select * from test where id=?", (1,)) + with self.assertRaisesRegex(sqlite.OperationalError, msg): + self.cu.execute("select * from test where id!=? and id!=?", + (1, 2)) + def test_execute_dict_mapping(self): self.cu.execute("insert into test(name) values ('foo')") self.cu.execute("select name from test where name=:name", {"name": "foo"}) @@ -1036,14 +1060,12 @@ def test_cursor_executescript_with_surrogates(self): insert into a(s) values ('\ud8ff'); """) - @unittest.skipUnless(sys.maxsize > 2**32, 'requires 64bit platform') - @bigmemtest(size=2**31, memuse=3, dry_run=False) - def test_cursor_executescript_too_large_script(self, maxsize): - con = sqlite.connect(":memory:") - cur = con.cursor() - for size in 2**31-1, 2**31: - with self.assertRaises(sqlite.DataError): - cur.executescript("create table a(s);".ljust(size)) + def test_cursor_executescript_too_large_script(self): + msg = "query string is too large" + with memory_database() as cx, cx_limit(cx) as lim: + cx.executescript("select 'almost too large'".ljust(lim-1)) + with self.assertRaisesRegex(sqlite.DataError, msg): + cx.executescript("select 'too large'".ljust(lim)) def test_cursor_executescript_tx_control(self): con = sqlite.connect(":memory:") diff --git a/Lib/test/test_sqlite3/test_regression.py b/Lib/test/test_sqlite3/test_regression.py index 3d71809d9c11c..158f4cf86f55c 100644 --- a/Lib/test/test_sqlite3/test_regression.py +++ b/Lib/test/test_sqlite3/test_regression.py @@ -28,7 +28,8 @@ import functools from test import support -from .test_dbapi import managed_connect +from .test_dbapi import memory_database, managed_connect, cx_limit + class RegressionTests(unittest.TestCase): def setUp(self): @@ -356,17 +357,18 @@ def test_surrogates(self): self.assertRaises(UnicodeEncodeError, cur.execute, "select '\ud8ff'") self.assertRaises(UnicodeEncodeError, cur.execute, "select '\udcff'") - @unittest.skipUnless(sys.maxsize > 2**32, 'requires 64bit platform') - @support.bigmemtest(size=2**31, memuse=4, dry_run=False) - def test_large_sql(self, maxsize): - # Test two cases: size+1 > INT_MAX and size+1 <= INT_MAX. - for size in (2**31, 2**31-2): - con = sqlite.connect(":memory:") - sql = "select 1".ljust(size) - self.assertRaises(sqlite.DataError, con, sql) - cur = con.cursor() - self.assertRaises(sqlite.DataError, cur.execute, sql) - del sql + def test_large_sql(self): + msg = "query string is too large" + with memory_database() as cx, cx_limit(cx) as lim: + cu = cx.cursor() + + cx("select 1".ljust(lim-1)) + # use a different SQL statement; don't reuse from the LRU cache + cu.execute("select 2".ljust(lim-1)) + + sql = "select 3".ljust(lim) + self.assertRaisesRegex(sqlite.DataError, msg, cx, sql) + self.assertRaisesRegex(sqlite.DataError, msg, cu.execute, sql) def test_commit_cursor_reset(self): """ diff --git a/Lib/test/test_sqlite3/test_userfunctions.py b/Lib/test/test_sqlite3/test_userfunctions.py index ad408475b73af..62a11a5431b7b 100644 --- a/Lib/test/test_sqlite3/test_userfunctions.py +++ b/Lib/test/test_sqlite3/test_userfunctions.py @@ -31,6 +31,7 @@ import sqlite3 as sqlite from test.support import bigmemtest +from .test_dbapi import cx_limit def with_tracebacks(strings, traceback=True): @@ -223,6 +224,14 @@ def test_func_error_on_create(self): with self.assertRaises(sqlite.OperationalError): self.con.create_function("bla", -100, lambda x: 2*x) + def test_func_too_many_args(self): + category = sqlite.SQLITE_LIMIT_FUNCTION_ARG + msg = "too many arguments on function" + with cx_limit(self.con, category=category, limit=1): + self.con.execute("select abs(-1)"); + with self.assertRaisesRegex(sqlite.OperationalError, msg): + self.con.execute("select max(1, 2)"); + def test_func_ref_count(self): def getfunc(): def f(): From webhook-mailer at python.org Fri Nov 5 15:52:55 2021 From: webhook-mailer at python.org (rhettinger) Date: Fri, 05 Nov 2021 19:52:55 -0000 Subject: [Python-checkins] bpo-45679: add `tuple` tests with `lru_cache` to `test_functools` (GH-29339) Message-ID: https://github.com/python/cpython/commit/60b5333fa936a7e7f078a82e0fa3752cc9b6c5fb commit: 60b5333fa936a7e7f078a82e0fa3752cc9b6c5fb branch: main author: Nikita Sobolev committer: rhettinger date: 2021-11-05T14:52:46-05:00 summary: bpo-45679: add `tuple` tests with `lru_cache` to `test_functools` (GH-29339) files: A Misc/NEWS.d/next/Tests/2021-10-31-10-58-45.bpo-45701.r0LAUL.rst M Lib/test/test_functools.py diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 7bc355ff7213e..08cf457cc17db 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -1495,6 +1495,33 @@ def square(x): self.assertEqual(square.cache_info().hits, 4) self.assertEqual(square.cache_info().misses, 4) + def test_lru_cache_typed_is_not_recursive(self): + cached = self.module.lru_cache(typed=True)(repr) + + self.assertEqual(cached(1), '1') + self.assertEqual(cached(True), 'True') + self.assertEqual(cached(1.0), '1.0') + self.assertEqual(cached(0), '0') + self.assertEqual(cached(False), 'False') + self.assertEqual(cached(0.0), '0.0') + + self.assertEqual(cached((1,)), '(1,)') + self.assertEqual(cached((True,)), '(1,)') + self.assertEqual(cached((1.0,)), '(1,)') + self.assertEqual(cached((0,)), '(0,)') + self.assertEqual(cached((False,)), '(0,)') + self.assertEqual(cached((0.0,)), '(0,)') + + class T(tuple): + pass + + self.assertEqual(cached(T((1,))), '(1,)') + self.assertEqual(cached(T((True,))), '(1,)') + self.assertEqual(cached(T((1.0,))), '(1,)') + self.assertEqual(cached(T((0,))), '(0,)') + self.assertEqual(cached(T((False,))), '(0,)') + self.assertEqual(cached(T((0.0,))), '(0,)') + def test_lru_with_keyword_args(self): @self.module.lru_cache() def fib(n): diff --git a/Misc/NEWS.d/next/Tests/2021-10-31-10-58-45.bpo-45701.r0LAUL.rst b/Misc/NEWS.d/next/Tests/2021-10-31-10-58-45.bpo-45701.r0LAUL.rst new file mode 100644 index 0000000000000..89106cf0660f0 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-10-31-10-58-45.bpo-45701.r0LAUL.rst @@ -0,0 +1,2 @@ +Add tests with ``tuple`` type with :func:`functools.lru_cache` to +``test_functools``. From webhook-mailer at python.org Fri Nov 5 16:51:35 2021 From: webhook-mailer at python.org (tiran) Date: Fri, 05 Nov 2021 20:51:35 -0000 Subject: [Python-checkins] bpo-43158: Regenerate configure again (GH-29433) Message-ID: https://github.com/python/cpython/commit/9b0f45c069863517a24239da301a1bf1697ac2e7 commit: 9b0f45c069863517a24239da301a1bf1697ac2e7 branch: main author: Christian Heimes committer: tiran date: 2021-11-05T21:51:26+01:00 summary: bpo-43158: Regenerate configure again (GH-29433) files: M configure M pyconfig.h.in diff --git a/configure b/configure index f0046ffab5eb0..00bea712b0633 100755 --- a/configure +++ b/configure @@ -10159,13 +10159,15 @@ $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# check for libuuid from util-linux save_LIBS=$LIBS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing uuid_generate_time_safe" >&5 -$as_echo_n "checking for library containing uuid_generate_time_safe... " >&6; } -if ${ac_cv_search_uuid_generate_time_safe+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time in -luuid" >&5 +$as_echo_n "checking for uuid_generate_time in -luuid... " >&6; } +if ${ac_cv_lib_uuid_uuid_generate_time+:} false; then : $as_echo_n "(cached) " >&6 else - ac_func_search_save_LIBS=$LIBS + ac_check_lib_save_LIBS=$LIBS +LIBS="-luuid $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -10175,61 +10177,39 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext #ifdef __cplusplus extern "C" #endif -char uuid_generate_time_safe (); +char uuid_generate_time (); int main () { -return uuid_generate_time_safe (); +return uuid_generate_time (); ; return 0; } _ACEOF -for ac_lib in '' uuid; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_uuid_generate_time_safe=$ac_res -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_uuid_generate_time_safe+:} false; then : - break -fi -done -if ${ac_cv_search_uuid_generate_time_safe+:} false; then : - +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_uuid_uuid_generate_time=yes else - ac_cv_search_uuid_generate_time_safe=no + ac_cv_lib_uuid_uuid_generate_time=no fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_uuid_generate_time_safe" >&5 -$as_echo "$ac_cv_search_uuid_generate_time_safe" >&6; } -ac_res=$ac_cv_search_uuid_generate_time_safe -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - - -$as_echo "#define HAVE_LIBUUID 1" >>confdefs.h -, - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_uuid_uuid_generate_time" >&5 +$as_echo "$ac_cv_lib_uuid_uuid_generate_time" >&6; } +if test "x$ac_cv_lib_uuid_uuid_generate_time" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBUUID 1 +_ACEOF -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + LIBS="-luuid $LIBS" fi LIBS=$save_LIBS # AIX provides support for RFC4122 (uuid) in libc.a starting with AIX 6.1 (anno 2007) -# FreeBSD and OpenBSD provides support as well +# FreeBSD and OpenBSD provides support in libc as well. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_create" >&5 $as_echo_n "checking for uuid_create... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext diff --git a/pyconfig.h.in b/pyconfig.h.in index 108a13d8d2ca9..b89377dc1b44d 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -604,7 +604,7 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LIBUTIL_H -/* Define you have libuuid. */ +/* Define to 1 if you have the `uuid' library (-luuid). */ #undef HAVE_LIBUUID /* Define if you have the 'link' function. */ From webhook-mailer at python.org Fri Nov 5 17:21:51 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 05 Nov 2021 21:21:51 -0000 Subject: [Python-checkins] Python 3.9.8 Message-ID: https://github.com/python/cpython/commit/bb3fdcfe95b9aeed13b7201ffbc634752ad8ecc9 commit: bb3fdcfe95b9aeed13b7201ffbc634752ad8ecc9 branch: 3.9 author: ?ukasz Langa committer: ambv date: 2021-11-05T20:21:41+01:00 summary: Python 3.9.8 files: A Misc/NEWS.d/3.9.8.rst D Misc/NEWS.d/next/Build/2021-09-16-18-00-43.bpo-45220.TgbkvW.rst D Misc/NEWS.d/next/Build/2021-10-11-16-27-38.bpo-45405.iSfdW5.rst D Misc/NEWS.d/next/Build/2021-10-20-16-07-39.bpo-45532.kyhvis.rst D Misc/NEWS.d/next/Build/2021-10-22-15-28-29.bpo-45571.yY8NsJ.rst D Misc/NEWS.d/next/Build/2021-11-01-12-51-46.bpo-43158.fghS6w.rst D Misc/NEWS.d/next/C API/2021-07-27-17-29-12.bpo-44751.4qmbDG.rst D Misc/NEWS.d/next/C API/2021-09-19-17-18-25.bpo-44687.3fqDRC.rst D Misc/NEWS.d/next/Core and Builtins/2021-09-01-23-55-49.bpo-45083.cLi9G3.rst D Misc/NEWS.d/next/Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst D Misc/NEWS.d/next/Core and Builtins/2021-09-08-00-30-09.bpo-44050.mFI15u.rst D Misc/NEWS.d/next/Core and Builtins/2021-09-08-08-29-41.bpo-44959.OSwwPf.rst D Misc/NEWS.d/next/Core and Builtins/2021-09-09-10-32-33.bpo-44219.WiYyjz.rst D Misc/NEWS.d/next/Core and Builtins/2021-09-14-09-23-59.bpo-45167.CPSSoV.rst D Misc/NEWS.d/next/Core and Builtins/2021-10-06-21-20-11.bpo-45385.CTUT8s.rst D Misc/NEWS.d/next/Core and Builtins/2021-10-16-17-27-48.bpo-45494.vMt1g4.rst D Misc/NEWS.d/next/Core and Builtins/2021-10-19-01-04-08.bpo-30570._G30Ms.rst D Misc/NEWS.d/next/Documentation/2021-09-18-13-45-19.bpo-45216.o56nyt.rst D Misc/NEWS.d/next/Documentation/2021-10-13-00-42-54.bpo-20692.K5rGtP.rst D Misc/NEWS.d/next/Documentation/2021-10-18-20-12-18.bpo-45516.EJh4K8.rst D Misc/NEWS.d/next/Documentation/2021-10-19-01-41-40.bpo-45449.fjHZJc.rst D Misc/NEWS.d/next/Documentation/2021-10-20-16-26-53.bpo-45464.mOISBs.rst D Misc/NEWS.d/next/Documentation/2021-10-26-10-00-45.bpo-45604.Dm-YhV.rst D Misc/NEWS.d/next/Documentation/2021-10-28-21-28-07.bpo-45655.aPYGaS.rst D Misc/NEWS.d/next/Documentation/2021-11-03-14-51-03.bpo-45680.9_NTFU.rst D Misc/NEWS.d/next/Documentation/2021-11-05-12-15-24.bpo-45726.GwRr7e.rst D Misc/NEWS.d/next/IDLE/2021-09-27-01-21-59.bpo-45296.9H8rdY.rst D Misc/NEWS.d/next/Library/2021-07-12-10-32-48.bpo-44594.eEa5zi.rst D Misc/NEWS.d/next/Library/2021-08-18-10-36-14.bpo-39039.A63LYh.rst D Misc/NEWS.d/next/Library/2021-08-27-19-01-23.bpo-45030.tAmBbY.rst D Misc/NEWS.d/next/Library/2021-08-28-13-00-12.bpo-45021.rReeaj.rst D Misc/NEWS.d/next/Library/2021-08-30-00-19-23.bpo-24444.Ki4bgz.rst D Misc/NEWS.d/next/Library/2021-09-02-12-42-25.bpo-45081.tOjJ1k.rst D Misc/NEWS.d/next/Library/2021-09-04-13-10-25.bpo-45097.5J4IC-.rst D Misc/NEWS.d/next/Library/2021-09-10-21-35-53.bpo-45166.UHipXF.rst D Misc/NEWS.d/next/Library/2021-09-11-10-45-12.bpo-35474.tEY3SD.rst D Misc/NEWS.d/next/Library/2021-09-11-14-47-05.bpo-45160.VzMXbW.rst D Misc/NEWS.d/next/Library/2021-09-14-15-52-47.bpo-45192.DjA-BI.rst D Misc/NEWS.d/next/Library/2021-09-17-09-59-33.bpo-45228.WV1dcT.rst D Misc/NEWS.d/next/Library/2021-09-17-11-20-55.bpo-45234.qUcTVt.rst D Misc/NEWS.d/next/Library/2021-09-17-16-55-37.bpo-45235.sXnmPA.rst D Misc/NEWS.d/next/Library/2021-09-18-13-14-57.bpo-36674.a2k5Zb.rst D Misc/NEWS.d/next/Library/2021-09-18-16-56-33.bpo-45238.Hng_9V.rst D Misc/NEWS.d/next/Library/2021-09-23-22-17-26.bpo-45274.gPpa4E.rst D Misc/NEWS.d/next/Library/2021-09-24-17-20-23.bpo-1596321.3nhPUk.rst D Misc/NEWS.d/next/Library/2021-09-30-08-22-44.bpo-45328.8Z-Q0B.rst D Misc/NEWS.d/next/Library/2021-09-30-23-00-18.bpo-41710.svuloZ.rst D Misc/NEWS.d/next/Library/2021-10-01-23-07-02.bpo-45343.ixmctD.rst D Misc/NEWS.d/next/Library/2021-10-03-21-14-37.bpo-20028.zBA4RK.rst D Misc/NEWS.d/next/Library/2021-10-05-11-03-48.bpo-45371.NOwcDJ.rst D Misc/NEWS.d/next/Library/2021-10-07-00-05-05.bpo-45386.q9ORpA.rst D Misc/NEWS.d/next/Library/2021-10-07-14-04-10.bpo-45262.HqF71Z.rst D Misc/NEWS.d/next/Library/2021-10-08-19-24-48.bpo-45406.Qh_Mz4.rst D Misc/NEWS.d/next/Library/2021-10-09-18-42-27.bpo-44904.RlW5h8.rst D Misc/NEWS.d/next/Library/2021-10-13-17-52-48.bpo-45239.7li1_0.rst D Misc/NEWS.d/next/Library/2021-10-14-00-19-02.bpo-45461.4LB_tJ.rst D Misc/NEWS.d/next/Library/2021-10-14-13-31-19.bpo-45467.Q7Ma6A.rst D Misc/NEWS.d/next/Library/2021-10-18-14-52-48.bpo-45515.aXdvm_.rst D Misc/NEWS.d/next/Library/2021-10-20-10-07-44.bpo-39679.nVYJJ3.rst D Misc/NEWS.d/next/Library/2021-10-22-21-57-02.bpo-45581.rlH6ay.rst D Misc/NEWS.d/next/Library/2021-10-27-10-05-39.bpo-45438.Xz5lGU.rst D Misc/NEWS.d/next/Library/2021-10-30-21-11-37.bpo-45679.Dq8Cpu.rst D Misc/NEWS.d/next/Library/2021-11-03-17-28-43.bpo-45678.Zj_O8j.rst D Misc/NEWS.d/next/Tests/2021-08-30-11-54-14.bpo-45042.QMz3X8.rst D Misc/NEWS.d/next/Tests/2021-09-13-00-28-17.bpo-45156.8oomV3.rst D Misc/NEWS.d/next/Tests/2021-09-14-13-16-18.bpo-45195.EyQR1G.rst D Misc/NEWS.d/next/Tests/2021-09-15-23-32-39.bpo-45209.55ntL5.rst D Misc/NEWS.d/next/Tests/2021-09-24-10-41-49.bpo-45269.8jKEr8.rst D Misc/NEWS.d/next/Tests/2021-09-25-11-05-31.bpo-45280.3MA6lC.rst D Misc/NEWS.d/next/Tests/2021-09-30-16-54-39.bpo-40173.J_slCw.rst D Misc/NEWS.d/next/Tests/2021-10-21-17-22-26.bpo-43592.kHRsra.rst D Misc/NEWS.d/next/Tests/2021-10-22-19-44-13.bpo-45577.dSaNvK.rst D Misc/NEWS.d/next/Tests/2021-10-30-19-00-25.bpo-45578.bvu6X2.rst D Misc/NEWS.d/next/Windows/2021-09-30-23-17-27.bpo-45337.qg7U_h.rst D Misc/NEWS.d/next/macOS/2021-10-25-02-02-21.bpo-44828.XBdXlJ.rst M Include/patchlevel.h M Lib/pydoc_data/topics.py M README.rst diff --git a/Include/patchlevel.h b/Include/patchlevel.h index 716aea5bb9694..8057ab920cb45 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -18,12 +18,12 @@ /*--start constants--*/ #define PY_MAJOR_VERSION 3 #define PY_MINOR_VERSION 9 -#define PY_MICRO_VERSION 7 +#define PY_MICRO_VERSION 8 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL #define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "3.9.7+" +#define PY_VERSION "3.9.8" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py index 1ad62250a52fb..8567e304a09ed 100644 --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Wed Sep 22 01:22:10 2021 +# Autogenerated by Sphinx on Fri Nov 5 20:19:23 2021 topics = {'assert': 'The "assert" statement\n' '**********************\n' '\n' @@ -4715,9 +4715,9 @@ 'operations.\n' '\n' 'If the "global" statement occurs within a block, all uses of ' - 'the name\n' - 'specified in the statement refer to the binding of that name in ' - 'the\n' + 'the names\n' + 'specified in the statement refer to the bindings of those names ' + 'in the\n' 'top-level namespace. Names are resolved in the top-level ' 'namespace by\n' 'searching the global namespace, i.e. the namespace of the ' @@ -4726,9 +4726,10 @@ 'namespace\n' 'of the module "builtins". The global namespace is searched ' 'first. If\n' - 'the name is not found there, the builtins namespace is ' - 'searched. The\n' - '"global" statement must precede all uses of the name.\n' + 'the names are not found there, the builtins namespace is ' + 'searched.\n' + 'The "global" statement must precede all uses of the listed ' + 'names.\n' '\n' 'The "global" statement has the same scope as a name binding ' 'operation\n' @@ -6786,8 +6787,8 @@ 'operations.\n' '\n' 'If the "global" statement occurs within a block, all uses of the ' - 'name\n' - 'specified in the statement refer to the binding of that name in ' + 'names\n' + 'specified in the statement refer to the bindings of those names in ' 'the\n' 'top-level namespace. Names are resolved in the top-level ' 'namespace by\n' @@ -6796,9 +6797,9 @@ 'namespace\n' 'of the module "builtins". The global namespace is searched ' 'first. If\n' - 'the name is not found there, the builtins namespace is searched. ' - 'The\n' - '"global" statement must precede all uses of the name.\n' + 'the names are not found there, the builtins namespace is ' + 'searched.\n' + 'The "global" statement must precede all uses of the listed names.\n' '\n' 'The "global" statement has the same scope as a name binding ' 'operation\n' @@ -7143,9 +7144,9 @@ ' of the object truncated to an "Integral" (typically an ' '"int").\n' '\n' - ' If "__int__()" is not defined then the built-in function ' - '"int()"\n' - ' falls back to "__trunc__()".\n', + ' The built-in function "int()" falls back to ' + '"__trunc__()" if\n' + ' neither "__int__()" nor "__index__()" is defined.\n', 'objects': 'Objects, values and types\n' '*************************\n' '\n' @@ -9888,9 +9889,9 @@ ' of the object truncated to an "Integral" (typically an ' '"int").\n' '\n' - ' If "__int__()" is not defined then the built-in function ' - '"int()"\n' - ' falls back to "__trunc__()".\n' + ' The built-in function "int()" falls back to "__trunc__()" ' + 'if\n' + ' neither "__int__()" nor "__index__()" is defined.\n' '\n' '\n' 'With Statement Context Managers\n' diff --git a/Misc/NEWS.d/3.9.8.rst b/Misc/NEWS.d/3.9.8.rst new file mode 100644 index 0000000000000..72cdd7a3e56f9 --- /dev/null +++ b/Misc/NEWS.d/3.9.8.rst @@ -0,0 +1,761 @@ +.. bpo: 30570 +.. date: 2021-10-19-01-04-08 +.. nonce: _G30Ms +.. release date: 2021-11-05 +.. section: Core and Builtins + +Fixed a crash in ``issubclass()`` from infinite recursion when searching +pathological ``__bases__`` tuples. + +.. + +.. bpo: 45494 +.. date: 2021-10-16-17-27-48 +.. nonce: vMt1g4 +.. section: Core and Builtins + +Fix parser crash when reporting errors involving invalid continuation +characters. Patch by Pablo Galindo. + +.. + +.. bpo: 45385 +.. date: 2021-10-06-21-20-11 +.. nonce: CTUT8s +.. section: Core and Builtins + +Fix reference leak from descr_check. Patch by Dong-hee Na. + +.. + +.. bpo: 45167 +.. date: 2021-09-14-09-23-59 +.. nonce: CPSSoV +.. section: Core and Builtins + +Fix deepcopying of :class:`types.GenericAlias` objects. + +.. + +.. bpo: 44219 +.. date: 2021-09-09-10-32-33 +.. nonce: WiYyjz +.. section: Core and Builtins + +Release the GIL while performing ``isatty`` system calls on arbitrary file +descriptors. In particular, this affects :func:`os.isatty`, +:func:`os.device_encoding` and :class:`io.TextIOWrapper`. By extension, +:func:`io.open` in text mode is also affected. This change solves a deadlock +in :func:`os.isatty`. Patch by Vincent Michel in :issue:`44219`. + +.. + +.. bpo: 44959 +.. date: 2021-09-08-08-29-41 +.. nonce: OSwwPf +.. section: Core and Builtins + +Added fallback to extension modules with '.sl' suffix on HP-UX + +.. + +.. bpo: 44050 +.. date: 2021-09-08-00-30-09 +.. nonce: mFI15u +.. section: Core and Builtins + +Extensions that indicate they use global state (by setting ``m_size`` to -1) +can again be used in multiple interpreters. This reverts to behavior of +Python 3.8. + +.. + +.. bpo: 45121 +.. date: 2021-09-07-17-10-16 +.. nonce: iG-Hsf +.. section: Core and Builtins + +Fix issue where ``Protocol.__init__`` raises ``RecursionError`` when it's +called directly or via ``super()``. Patch provided by Yurii Karabas. + +.. + +.. bpo: 45083 +.. date: 2021-09-01-23-55-49 +.. nonce: cLi9G3 +.. section: Core and Builtins + +When the interpreter renders an exception, its name now has a complete +qualname. Previously only the class name was concatenated to the module +name, which sometimes resulted in an incorrect full name being displayed. + +(This issue impacted only the C code exception rendering, the +:mod:`traceback` module was using qualname already). + +.. + +.. bpo: 45678 +.. date: 2021-11-03-17-28-43 +.. nonce: Zj_O8j +.. section: Library + +Fix bug in Python 3.9 that meant ``functools.singledispatchmethod`` failed +to properly wrap the attributes of the target method. Patch by Alex Waygood. + +.. + +.. bpo: 45679 +.. date: 2021-10-30-21-11-37 +.. nonce: Dq8Cpu +.. section: Library + +Fix caching of multi-value :data:`typing.Literal`. ``Literal[True, 2]`` is +no longer equal to ``Literal[1, 2]``. + +.. + +.. bpo: 45438 +.. date: 2021-10-27-10-05-39 +.. nonce: Xz5lGU +.. section: Library + +Fix typing.Signature string representation for generic builtin types. + +.. + +.. bpo: 45581 +.. date: 2021-10-22-21-57-02 +.. nonce: rlH6ay +.. section: Library + +:meth:`sqlite3.connect` now correctly raises :exc:`MemoryError` if the +underlying SQLite API signals memory error. Patch by Erlend E. Aasland. + +.. + +.. bpo: 39679 +.. date: 2021-10-20-10-07-44 +.. nonce: nVYJJ3 +.. section: Library + +Fix bug in :class:`functools.singledispatchmethod` that caused it to fail +when attempting to register a :func:`classmethod` or :func:`staticmethod` +using type annotations. Patch contributed by Alex Waygood. + +.. + +.. bpo: 45515 +.. date: 2021-10-18-14-52-48 +.. nonce: aXdvm_ +.. section: Library + +Add references to :mod:`zoneinfo` in the :mod:`datetime` documentation, +mostly replacing outdated references to ``dateutil.tz``. Change by Paul +Ganssle. + +.. + +.. bpo: 45467 +.. date: 2021-10-14-13-31-19 +.. nonce: Q7Ma6A +.. section: Library + +Fix incremental decoder and stream reader in the "raw-unicode-escape" codec. +Previously they failed if the escape sequence was split. + +.. + +.. bpo: 45461 +.. date: 2021-10-14-00-19-02 +.. nonce: 4LB_tJ +.. section: Library + +Fix incremental decoder and stream reader in the "unicode-escape" codec. +Previously they failed if the escape sequence was split. + +.. + +.. bpo: 45239 +.. date: 2021-10-13-17-52-48 +.. nonce: 7li1_0 +.. section: Library + +Fixed :func:`email.utils.parsedate_tz` crashing with +:exc:`UnboundLocalError` on certain invalid input instead of returning +``None``. Patch by Ben Hoyt. + +.. + +.. bpo: 44904 +.. date: 2021-10-09-18-42-27 +.. nonce: RlW5h8 +.. section: Library + +Fix bug in the :mod:`doctest` module that caused it to fail if a docstring +included an example with a ``classmethod`` ``property``. Patch by Alex +Waygood. + +.. + +.. bpo: 45406 +.. date: 2021-10-08-19-24-48 +.. nonce: Qh_Mz4 +.. section: Library + +Make :func:`inspect.getmodule` catch ``FileNotFoundError`` raised by +:'func:`inspect.getabsfile`, and return ``None`` to indicate that the module +could not be determined. + +.. + +.. bpo: 45262 +.. date: 2021-10-07-14-04-10 +.. nonce: HqF71Z +.. section: Library + +Prevent use-after-free in asyncio. Make sure the cached running loop holder +gets cleared on dealloc to prevent use-after-free in get_running_loop + +.. + +.. bpo: 45386 +.. date: 2021-10-07-00-05-05 +.. nonce: q9ORpA +.. section: Library + +Make :mod:`xmlrpc.client` more robust to C runtimes where the underlying C +``strftime`` function results in a ``ValueError`` when testing for year +formatting options. + +.. + +.. bpo: 45371 +.. date: 2021-10-05-11-03-48 +.. nonce: NOwcDJ +.. section: Library + +Fix clang rpath issue in :mod:`distutils`. The UnixCCompiler now uses +correct clang option to add a runtime library directory (rpath) to a shared +library. + +.. + +.. bpo: 20028 +.. date: 2021-10-03-21-14-37 +.. nonce: zBA4RK +.. section: Library + +Improve error message of :class:`csv.Dialect` when initializing. Patch by +Vajrasky Kok and Dong-hee Na. + +.. + +.. bpo: 45343 +.. date: 2021-10-01-23-07-02 +.. nonce: ixmctD +.. section: Library + +Update bundled pip to 21.2.4 and setuptools to 58.1.0 + +.. + +.. bpo: 41710 +.. date: 2021-09-30-23-00-18 +.. nonce: svuloZ +.. section: Library + +On Unix, if the ``sem_clockwait()`` function is available in the C library +(glibc 2.30 and newer), the :meth:`threading.Lock.acquire` method now uses +the monotonic clock (:data:`time.CLOCK_MONOTONIC`) for the timeout, rather +than using the system clock (:data:`time.CLOCK_REALTIME`), to not be +affected by system clock changes. Patch by Victor Stinner. + +.. + +.. bpo: 45328 +.. date: 2021-09-30-08-22-44 +.. nonce: 8Z-Q0B +.. section: Library + +Fixed :class:`http.client.HTTPConnection` to work properly in OSs that don't +support the ``TCP_NODELAY`` socket option. + +.. + +.. bpo: 1596321 +.. date: 2021-09-24-17-20-23 +.. nonce: 3nhPUk +.. section: Library + +Fix the :func:`threading._shutdown` function when the :mod:`threading` +module was imported first from a thread different than the main thread: no +longer log an error at Python exit. + +.. + +.. bpo: 45274 +.. date: 2021-09-23-22-17-26 +.. nonce: gPpa4E +.. section: Library + +Fix a race condition in the :meth:`Thread.join() ` +method of the :mod:`threading` module. If the function is interrupted by a +signal and the signal handler raises an exception, make sure that the thread +remains in a consistent state to prevent a deadlock. Patch by Victor +Stinner. + +.. + +.. bpo: 45238 +.. date: 2021-09-18-16-56-33 +.. nonce: Hng_9V +.. section: Library + +Fix :meth:`unittest.IsolatedAsyncioTestCase.debug`: it runs now asynchronous +methods and callbacks. + +.. + +.. bpo: 36674 +.. date: 2021-09-18-13-14-57 +.. nonce: a2k5Zb +.. section: Library + +:meth:`unittest.TestCase.debug` raises now a :class:`unittest.SkipTest` if +the class or the test method are decorated with the skipping decorator. + +.. + +.. bpo: 45235 +.. date: 2021-09-17-16-55-37 +.. nonce: sXnmPA +.. section: Library + +Fix an issue where argparse would not preserve values in a provided +namespace when using a subparser with defaults. + +.. + +.. bpo: 45234 +.. date: 2021-09-17-11-20-55 +.. nonce: qUcTVt +.. section: Library + +Fixed a regression in :func:`~shutil.copyfile`, :func:`~shutil.copy`, +:func:`~shutil.copy2` raising :exc:`FileNotFoundError` when source is a +directory, which should raise :exc:`IsADirectoryError` + +.. + +.. bpo: 45228 +.. date: 2021-09-17-09-59-33 +.. nonce: WV1dcT +.. section: Library + +Fix stack buffer overflow in parsing J1939 network address. + +.. + +.. bpo: 45192 +.. date: 2021-09-14-15-52-47 +.. nonce: DjA-BI +.. section: Library + +Fix the ``tempfile._infer_return_type`` function so that the ``dir`` +argument of the :mod:`tempfile` functions accepts an object implementing the +``os.PathLike`` protocol. + +Patch by Kyungmin Lee. + +.. + +.. bpo: 45160 +.. date: 2021-09-11-14-47-05 +.. nonce: VzMXbW +.. section: Library + +When tracing a tkinter variable used by a ttk OptionMenu, callbacks are no +longer made twice. + +.. + +.. bpo: 35474 +.. date: 2021-09-11-10-45-12 +.. nonce: tEY3SD +.. section: Library + +Calling :func:`mimetypes.guess_all_extensions` with ``strict=False`` no +longer affects the result of the following call with ``strict=True``. Also, +mutating the returned list no longer affects the global state. + +.. + +.. bpo: 45166 +.. date: 2021-09-10-21-35-53 +.. nonce: UHipXF +.. section: Library + +:func:`typing.get_type_hints` now works with :data:`~typing.Final` wrapped +in :class:`~typing.ForwardRef`. + +.. + +.. bpo: 45097 +.. date: 2021-09-04-13-10-25 +.. nonce: 5J4IC- +.. section: Library + +Remove deprecation warnings about the loop argument in :mod:`asyncio` +incorrectly emitted in cases when the user does not pass the loop argument. + +.. + +.. bpo: 45081 +.. date: 2021-09-02-12-42-25 +.. nonce: tOjJ1k +.. section: Library + +Fix issue when dataclasses that inherit from ``typing.Protocol`` subclasses +have wrong ``__init__``. Patch provided by Yurii Karabas. + +.. + +.. bpo: 24444 +.. date: 2021-08-30-00-19-23 +.. nonce: Ki4bgz +.. section: Library + +Fixed an error raised in :mod:`argparse` help display when help for an +option is set to 1+ blank spaces or when *choices* arg is an empty +container. + +.. + +.. bpo: 45021 +.. date: 2021-08-28-13-00-12 +.. nonce: rReeaj +.. section: Library + +Fix a potential deadlock at shutdown of forked children when using +:mod:`concurrent.futures` module + +.. + +.. bpo: 45030 +.. date: 2021-08-27-19-01-23 +.. nonce: tAmBbY +.. section: Library + +Fix integer overflow in pickling and copying the range iterator. + +.. + +.. bpo: 39039 +.. date: 2021-08-18-10-36-14 +.. nonce: A63LYh +.. section: Library + +tarfile.open raises :exc:`~tarfile.ReadError` when a zlib error occurs +during file extraction. + +.. + +.. bpo: 44594 +.. date: 2021-07-12-10-32-48 +.. nonce: eEa5zi +.. section: Library + +Fix an edge case of :class:`ExitStack` and :class:`AsyncExitStack` exception +chaining. They will now match ``with`` block behavior when ``__context__`` +is explicitly set to ``None`` when the exception is in flight. + +.. + +.. bpo: 45726 +.. date: 2021-11-05-12-15-24 +.. nonce: GwRr7e +.. section: Documentation + +Improve documentation for :func:`functools.singledispatch` and +:class:`functools.singledispatchmethod`. + +.. + +.. bpo: 45680 +.. date: 2021-11-03-14-51-03 +.. nonce: 9_NTFU +.. section: Documentation + +Amend the docs on ``GenericAlias`` objects to clarify that non-container +classes can also implement ``__class_getitem__``. Patch contributed by Alex +Waygood. + +.. + +.. bpo: 45655 +.. date: 2021-10-28-21-28-07 +.. nonce: aPYGaS +.. section: Documentation + +Add a new "relevant PEPs" section to the top of the documentation for the +``typing`` module. Patch by Alex Waygood. + +.. + +.. bpo: 45604 +.. date: 2021-10-26-10-00-45 +.. nonce: Dm-YhV +.. section: Documentation + +Add ``level`` argument to ``multiprocessing.log_to_stderr`` function docs. + +.. + +.. bpo: 45464 +.. date: 2021-10-20-16-26-53 +.. nonce: mOISBs +.. section: Documentation + +Mention in the documentation of :ref:`Built-in Exceptions +` that inheriting from multiple exception types in a +single subclass is not recommended due to possible memory layout +incompatibility. + +.. + +.. bpo: 45449 +.. date: 2021-10-19-01-41-40 +.. nonce: fjHZJc +.. section: Documentation + +Add note about :pep:`585` in :mod:`collections.abc`. + +.. + +.. bpo: 45516 +.. date: 2021-10-18-20-12-18 +.. nonce: EJh4K8 +.. section: Documentation + +Add protocol description to the :class:`importlib.abc.Traversable` +documentation. + +.. + +.. bpo: 20692 +.. date: 2021-10-13-00-42-54 +.. nonce: K5rGtP +.. section: Documentation + +Add Programming FAQ entry explaining that int literal attribute access +requires either a space after or parentheses around the literal. + +.. + +.. bpo: 45216 +.. date: 2021-09-18-13-45-19 +.. nonce: o56nyt +.. section: Documentation + +Remove extra documentation listing methods in ``difflib``. It was rendering +twice in pydoc and was outdated in some places. + +.. + +.. bpo: 45578 +.. date: 2021-10-30-19-00-25 +.. nonce: bvu6X2 +.. section: Tests + +Add tests for :func:`dis.distb` + +.. + +.. bpo: 45577 +.. date: 2021-10-22-19-44-13 +.. nonce: dSaNvK +.. section: Tests + +Add subtests for all ``pickle`` protocols in ``test_zoneinfo``. + +.. + +.. bpo: 43592 +.. date: 2021-10-21-17-22-26 +.. nonce: kHRsra +.. section: Tests + +:mod:`test.libregrtest` now raises the soft resource limit for the maximum +number of file descriptors when the default is too low for our test suite as +was often the case on macOS. + +.. + +.. bpo: 40173 +.. date: 2021-09-30-16-54-39 +.. nonce: J_slCw +.. section: Tests + +Fix :func:`test.support.import_helper.import_fresh_module`. + +.. + +.. bpo: 45280 +.. date: 2021-09-25-11-05-31 +.. nonce: 3MA6lC +.. section: Tests + +Add a test case for empty :class:`typing.NamedTuple`. + +.. + +.. bpo: 45269 +.. date: 2021-09-24-10-41-49 +.. nonce: 8jKEr8 +.. section: Tests + +Cover case when invalid ``markers`` type is supplied to ``c_make_encoder``. + +.. + +.. bpo: 45209 +.. date: 2021-09-15-23-32-39 +.. nonce: 55ntL5 +.. section: Tests + +Fix ``UserWarning: resource_tracker`` warning in +``_test_multiprocessing._TestSharedMemory.test_shared_memory_cleaned_after_process_termination`` + +.. + +.. bpo: 45195 +.. date: 2021-09-14-13-16-18 +.. nonce: EyQR1G +.. section: Tests + +Fix test_readline.test_nonascii(): sometimes, the newline character is not +written at the end, so don't expect it in the output. Patch by Victor +Stinner. + +.. + +.. bpo: 45156 +.. date: 2021-09-13-00-28-17 +.. nonce: 8oomV3 +.. section: Tests + +Fixes infinite loop on :func:`unittest.mock.seal` of mocks created by +:func:`~unittest.create_autospec`. + +.. + +.. bpo: 45042 +.. date: 2021-08-30-11-54-14 +.. nonce: QMz3X8 +.. section: Tests + +Fixes that test classes decorated with +``@hashlib_helper.requires_hashdigest`` were skipped all the time. + +.. + +.. bpo: 43158 +.. date: 2021-11-01-12-51-46 +.. nonce: fghS6w +.. section: Build + +``setup.py`` now uses values from configure script to build the ``_uuid`` +extension module. Configure now detects util-linux's ``libuuid``, too. + +.. + +.. bpo: 45571 +.. date: 2021-10-22-15-28-29 +.. nonce: yY8NsJ +.. section: Build + +``Modules/Setup`` now use ``PY_CFLAGS_NODIST`` instead of ``PY_CFLAGS`` to +compile shared modules. + +.. + +.. bpo: 45532 +.. date: 2021-10-20-16-07-39 +.. nonce: kyhvis +.. section: Build + +Update :data:`sys.version` to use ``main`` as fallback information. Patch by +Jeong YunWon. + +.. + +.. bpo: 45405 +.. date: 2021-10-11-16-27-38 +.. nonce: iSfdW5 +.. section: Build + +Prevent ``internal configure error`` when running ``configure`` with recent +versions of non-Apple clang. Patch by David Bohman. + +.. + +.. bpo: 45220 +.. date: 2021-09-16-18-00-43 +.. nonce: TgbkvW +.. section: Build + +Avoid building with the Windows 11 SDK previews automatically. This may be +overridden by setting the ``DefaultWindowsSDKVersion`` environment variable +before building. + +.. + +.. bpo: 45337 +.. date: 2021-09-30-23-17-27 +.. nonce: qg7U_h +.. section: Windows + +venv now warns when the created environment may need to be accessed at a +different path, due to redirections, links or junctions. It also now +correctly installs or upgrades components when the alternate path is +required. + +.. + +.. bpo: 44828 +.. date: 2021-10-25-02-02-21 +.. nonce: XBdXlJ +.. section: macOS + +Avoid tkinter file dialog failure on macOS 12 Monterey when using the Tk +8.6.11 provided by python.org macOS installers. Patch by Marc Culler of the +Tk project. + +.. + +.. bpo: 45296 +.. date: 2021-09-27-01-21-59 +.. nonce: 9H8rdY +.. section: IDLE + +On Windows, change exit/quit message to suggest Ctrl-D, which works, instead +of , which does not work in IDLE. + +.. + +.. bpo: 44687 +.. date: 2021-09-19-17-18-25 +.. nonce: 3fqDRC +.. section: C API + +:meth:`BufferedReader.peek` no longer raises :exc:`ValueError` when the +entire file has already been buffered. + +.. + +.. bpo: 44751 +.. date: 2021-07-27-17-29-12 +.. nonce: 4qmbDG +.. section: C API + +Remove ``crypt.h`` include from the public ``Python.h`` header. diff --git a/Misc/NEWS.d/next/Build/2021-09-16-18-00-43.bpo-45220.TgbkvW.rst b/Misc/NEWS.d/next/Build/2021-09-16-18-00-43.bpo-45220.TgbkvW.rst deleted file mode 100644 index 8bbd634fa61a3..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-09-16-18-00-43.bpo-45220.TgbkvW.rst +++ /dev/null @@ -1,3 +0,0 @@ -Avoid building with the Windows 11 SDK previews automatically. This may be -overridden by setting the ``DefaultWindowsSDKVersion`` environment variable -before building. diff --git a/Misc/NEWS.d/next/Build/2021-10-11-16-27-38.bpo-45405.iSfdW5.rst b/Misc/NEWS.d/next/Build/2021-10-11-16-27-38.bpo-45405.iSfdW5.rst deleted file mode 100644 index a2dc5bcc32217..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-10-11-16-27-38.bpo-45405.iSfdW5.rst +++ /dev/null @@ -1,2 +0,0 @@ -Prevent ``internal configure error`` when running ``configure`` -with recent versions of non-Apple clang. Patch by David Bohman. diff --git a/Misc/NEWS.d/next/Build/2021-10-20-16-07-39.bpo-45532.kyhvis.rst b/Misc/NEWS.d/next/Build/2021-10-20-16-07-39.bpo-45532.kyhvis.rst deleted file mode 100644 index 575e2fb9ae93b..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-10-20-16-07-39.bpo-45532.kyhvis.rst +++ /dev/null @@ -1,2 +0,0 @@ -Update :data:`sys.version` to use ``main`` as fallback information. -Patch by Jeong YunWon. diff --git a/Misc/NEWS.d/next/Build/2021-10-22-15-28-29.bpo-45571.yY8NsJ.rst b/Misc/NEWS.d/next/Build/2021-10-22-15-28-29.bpo-45571.yY8NsJ.rst deleted file mode 100644 index f2042d11e24b7..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-10-22-15-28-29.bpo-45571.yY8NsJ.rst +++ /dev/null @@ -1,2 +0,0 @@ -``Modules/Setup`` now use ``PY_CFLAGS_NODIST`` instead of ``PY_CFLAGS`` to -compile shared modules. diff --git a/Misc/NEWS.d/next/Build/2021-11-01-12-51-46.bpo-43158.fghS6w.rst b/Misc/NEWS.d/next/Build/2021-11-01-12-51-46.bpo-43158.fghS6w.rst deleted file mode 100644 index 3b1de478e7fd4..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-11-01-12-51-46.bpo-43158.fghS6w.rst +++ /dev/null @@ -1,2 +0,0 @@ -``setup.py`` now uses values from configure script to build the ``_uuid`` -extension module. Configure now detects util-linux's ``libuuid``, too. diff --git a/Misc/NEWS.d/next/C API/2021-07-27-17-29-12.bpo-44751.4qmbDG.rst b/Misc/NEWS.d/next/C API/2021-07-27-17-29-12.bpo-44751.4qmbDG.rst deleted file mode 100644 index d7b9f09819669..0000000000000 --- a/Misc/NEWS.d/next/C API/2021-07-27-17-29-12.bpo-44751.4qmbDG.rst +++ /dev/null @@ -1 +0,0 @@ -Remove ``crypt.h`` include from the public ``Python.h`` header. diff --git a/Misc/NEWS.d/next/C API/2021-09-19-17-18-25.bpo-44687.3fqDRC.rst b/Misc/NEWS.d/next/C API/2021-09-19-17-18-25.bpo-44687.3fqDRC.rst deleted file mode 100644 index d38fa6057f6f9..0000000000000 --- a/Misc/NEWS.d/next/C API/2021-09-19-17-18-25.bpo-44687.3fqDRC.rst +++ /dev/null @@ -1 +0,0 @@ -:meth:`BufferedReader.peek` no longer raises :exc:`ValueError` when the entire file has already been buffered. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-01-23-55-49.bpo-45083.cLi9G3.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-01-23-55-49.bpo-45083.cLi9G3.rst deleted file mode 100644 index 7bfd87b942059..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-09-01-23-55-49.bpo-45083.cLi9G3.rst +++ /dev/null @@ -1,3 +0,0 @@ -When the interpreter renders an exception, its name now has a complete qualname. Previously only the class name was concatenated to the module name, which sometimes resulted in an incorrect full name being displayed. - -(This issue impacted only the C code exception rendering, the :mod:`traceback` module was using qualname already). \ No newline at end of file diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst deleted file mode 100644 index 19eb331412516..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-09-07-17-10-16.bpo-45121.iG-Hsf.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix issue where ``Protocol.__init__`` raises ``RecursionError`` when it's -called directly or via ``super()``. Patch provided by Yurii Karabas. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-08-00-30-09.bpo-44050.mFI15u.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-08-00-30-09.bpo-44050.mFI15u.rst deleted file mode 100644 index d6eed9f1bcfe9..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-09-08-00-30-09.bpo-44050.mFI15u.rst +++ /dev/null @@ -1,3 +0,0 @@ -Extensions that indicate they use global state (by setting ``m_size`` to -1) -can again be used in multiple interpreters. This reverts to behavior of -Python 3.8. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-08-08-29-41.bpo-44959.OSwwPf.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-08-08-29-41.bpo-44959.OSwwPf.rst deleted file mode 100644 index 02e11ae94e430..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-09-08-08-29-41.bpo-44959.OSwwPf.rst +++ /dev/null @@ -1 +0,0 @@ -Added fallback to extension modules with '.sl' suffix on HP-UX \ No newline at end of file diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-09-10-32-33.bpo-44219.WiYyjz.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-09-10-32-33.bpo-44219.WiYyjz.rst deleted file mode 100644 index 2abd81673663b..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-09-09-10-32-33.bpo-44219.WiYyjz.rst +++ /dev/null @@ -1,5 +0,0 @@ -Release the GIL while performing ``isatty`` system calls on arbitrary file -descriptors. In particular, this affects :func:`os.isatty`, -:func:`os.device_encoding` and :class:`io.TextIOWrapper`. By extension, -:func:`io.open` in text mode is also affected. This change solves -a deadlock in :func:`os.isatty`. Patch by Vincent Michel in :issue:`44219`. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-14-09-23-59.bpo-45167.CPSSoV.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-14-09-23-59.bpo-45167.CPSSoV.rst deleted file mode 100644 index 47755ae59be2b..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-09-14-09-23-59.bpo-45167.CPSSoV.rst +++ /dev/null @@ -1 +0,0 @@ -Fix deepcopying of :class:`types.GenericAlias` objects. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-06-21-20-11.bpo-45385.CTUT8s.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-06-21-20-11.bpo-45385.CTUT8s.rst deleted file mode 100644 index 8047c102634f0..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-10-06-21-20-11.bpo-45385.CTUT8s.rst +++ /dev/null @@ -1 +0,0 @@ -Fix reference leak from descr_check. Patch by Dong-hee Na. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-16-17-27-48.bpo-45494.vMt1g4.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-16-17-27-48.bpo-45494.vMt1g4.rst deleted file mode 100644 index 97e29813ab266..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-10-16-17-27-48.bpo-45494.vMt1g4.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix parser crash when reporting errors involving invalid continuation -characters. Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-19-01-04-08.bpo-30570._G30Ms.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-19-01-04-08.bpo-30570._G30Ms.rst deleted file mode 100644 index d9ab60cd08f56..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-10-19-01-04-08.bpo-30570._G30Ms.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a crash in ``issubclass()`` from infinite recursion when searching pathological ``__bases__`` tuples. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Documentation/2021-09-18-13-45-19.bpo-45216.o56nyt.rst b/Misc/NEWS.d/next/Documentation/2021-09-18-13-45-19.bpo-45216.o56nyt.rst deleted file mode 100644 index d10b18ecdb8fd..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-09-18-13-45-19.bpo-45216.o56nyt.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove extra documentation listing methods in ``difflib``. It was rendering -twice in pydoc and was outdated in some places. diff --git a/Misc/NEWS.d/next/Documentation/2021-10-13-00-42-54.bpo-20692.K5rGtP.rst b/Misc/NEWS.d/next/Documentation/2021-10-13-00-42-54.bpo-20692.K5rGtP.rst deleted file mode 100644 index 44ae468d1bccf..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-10-13-00-42-54.bpo-20692.K5rGtP.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add Programming FAQ entry explaining that int literal attribute access -requires either a space after or parentheses around the literal. diff --git a/Misc/NEWS.d/next/Documentation/2021-10-18-20-12-18.bpo-45516.EJh4K8.rst b/Misc/NEWS.d/next/Documentation/2021-10-18-20-12-18.bpo-45516.EJh4K8.rst deleted file mode 100644 index 98f5d3432db05..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-10-18-20-12-18.bpo-45516.EJh4K8.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add protocol description to the :class:`importlib.abc.Traversable` -documentation. diff --git a/Misc/NEWS.d/next/Documentation/2021-10-19-01-41-40.bpo-45449.fjHZJc.rst b/Misc/NEWS.d/next/Documentation/2021-10-19-01-41-40.bpo-45449.fjHZJc.rst deleted file mode 100644 index fb817757a1487..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-10-19-01-41-40.bpo-45449.fjHZJc.rst +++ /dev/null @@ -1 +0,0 @@ -Add note about :pep:`585` in :mod:`collections.abc`. diff --git a/Misc/NEWS.d/next/Documentation/2021-10-20-16-26-53.bpo-45464.mOISBs.rst b/Misc/NEWS.d/next/Documentation/2021-10-20-16-26-53.bpo-45464.mOISBs.rst deleted file mode 100644 index 1721aa2c2dfc4..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-10-20-16-26-53.bpo-45464.mOISBs.rst +++ /dev/null @@ -1,4 +0,0 @@ -Mention in the documentation of :ref:`Built-in Exceptions -` that inheriting from multiple exception types in a -single subclass is not recommended due to possible memory layout -incompatibility. diff --git a/Misc/NEWS.d/next/Documentation/2021-10-26-10-00-45.bpo-45604.Dm-YhV.rst b/Misc/NEWS.d/next/Documentation/2021-10-26-10-00-45.bpo-45604.Dm-YhV.rst deleted file mode 100644 index 9da9cca7bf1ea..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-10-26-10-00-45.bpo-45604.Dm-YhV.rst +++ /dev/null @@ -1 +0,0 @@ -Add ``level`` argument to ``multiprocessing.log_to_stderr`` function docs. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Documentation/2021-10-28-21-28-07.bpo-45655.aPYGaS.rst b/Misc/NEWS.d/next/Documentation/2021-10-28-21-28-07.bpo-45655.aPYGaS.rst deleted file mode 100644 index fc5b3d0788817..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-10-28-21-28-07.bpo-45655.aPYGaS.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add a new "relevant PEPs" section to the top of the documentation for the -``typing`` module. Patch by Alex Waygood. diff --git a/Misc/NEWS.d/next/Documentation/2021-11-03-14-51-03.bpo-45680.9_NTFU.rst b/Misc/NEWS.d/next/Documentation/2021-11-03-14-51-03.bpo-45680.9_NTFU.rst deleted file mode 100644 index 79ea6e308e54a..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-11-03-14-51-03.bpo-45680.9_NTFU.rst +++ /dev/null @@ -1,3 +0,0 @@ -Amend the docs on ``GenericAlias`` objects to clarify that non-container -classes can also implement ``__class_getitem__``. Patch contributed by Alex -Waygood. diff --git a/Misc/NEWS.d/next/Documentation/2021-11-05-12-15-24.bpo-45726.GwRr7e.rst b/Misc/NEWS.d/next/Documentation/2021-11-05-12-15-24.bpo-45726.GwRr7e.rst deleted file mode 100644 index 7ff6283a2a34d..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-11-05-12-15-24.bpo-45726.GwRr7e.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve documentation for :func:`functools.singledispatch` and -:class:`functools.singledispatchmethod`. diff --git a/Misc/NEWS.d/next/IDLE/2021-09-27-01-21-59.bpo-45296.9H8rdY.rst b/Misc/NEWS.d/next/IDLE/2021-09-27-01-21-59.bpo-45296.9H8rdY.rst deleted file mode 100644 index 52bade1e5327b..0000000000000 --- a/Misc/NEWS.d/next/IDLE/2021-09-27-01-21-59.bpo-45296.9H8rdY.rst +++ /dev/null @@ -1,2 +0,0 @@ -On Windows, change exit/quit message to suggest Ctrl-D, which works, instead -of , which does not work in IDLE. diff --git a/Misc/NEWS.d/next/Library/2021-07-12-10-32-48.bpo-44594.eEa5zi.rst b/Misc/NEWS.d/next/Library/2021-07-12-10-32-48.bpo-44594.eEa5zi.rst deleted file mode 100644 index a2bfd8ff5b51b..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-07-12-10-32-48.bpo-44594.eEa5zi.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix an edge case of :class:`ExitStack` and :class:`AsyncExitStack` exception -chaining. They will now match ``with`` block behavior when ``__context__`` is -explicitly set to ``None`` when the exception is in flight. diff --git a/Misc/NEWS.d/next/Library/2021-08-18-10-36-14.bpo-39039.A63LYh.rst b/Misc/NEWS.d/next/Library/2021-08-18-10-36-14.bpo-39039.A63LYh.rst deleted file mode 100644 index 7250055c2a4a9..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-08-18-10-36-14.bpo-39039.A63LYh.rst +++ /dev/null @@ -1,2 +0,0 @@ -tarfile.open raises :exc:`~tarfile.ReadError` when a zlib error occurs -during file extraction. diff --git a/Misc/NEWS.d/next/Library/2021-08-27-19-01-23.bpo-45030.tAmBbY.rst b/Misc/NEWS.d/next/Library/2021-08-27-19-01-23.bpo-45030.tAmBbY.rst deleted file mode 100644 index dec8c88b15588..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-08-27-19-01-23.bpo-45030.tAmBbY.rst +++ /dev/null @@ -1 +0,0 @@ -Fix integer overflow in pickling and copying the range iterator. diff --git a/Misc/NEWS.d/next/Library/2021-08-28-13-00-12.bpo-45021.rReeaj.rst b/Misc/NEWS.d/next/Library/2021-08-28-13-00-12.bpo-45021.rReeaj.rst deleted file mode 100644 index 54fd9109a9ae5..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-08-28-13-00-12.bpo-45021.rReeaj.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a potential deadlock at shutdown of forked children when using :mod:`concurrent.futures` module \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2021-08-30-00-19-23.bpo-24444.Ki4bgz.rst b/Misc/NEWS.d/next/Library/2021-08-30-00-19-23.bpo-24444.Ki4bgz.rst deleted file mode 100644 index efcacb8f0eb59..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-08-30-00-19-23.bpo-24444.Ki4bgz.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed an error raised in :mod:`argparse` help display when help for an -option is set to 1+ blank spaces or when *choices* arg is an empty container. diff --git a/Misc/NEWS.d/next/Library/2021-09-02-12-42-25.bpo-45081.tOjJ1k.rst b/Misc/NEWS.d/next/Library/2021-09-02-12-42-25.bpo-45081.tOjJ1k.rst deleted file mode 100644 index 86d7182003bb9..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-02-12-42-25.bpo-45081.tOjJ1k.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix issue when dataclasses that inherit from ``typing.Protocol`` subclasses -have wrong ``__init__``. Patch provided by Yurii Karabas. diff --git a/Misc/NEWS.d/next/Library/2021-09-04-13-10-25.bpo-45097.5J4IC-.rst b/Misc/NEWS.d/next/Library/2021-09-04-13-10-25.bpo-45097.5J4IC-.rst deleted file mode 100644 index 1788300d7fa14..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-04-13-10-25.bpo-45097.5J4IC-.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove deprecation warnings about the loop argument in :mod:`asyncio` -incorrectly emitted in cases when the user does not pass the loop argument. diff --git a/Misc/NEWS.d/next/Library/2021-09-10-21-35-53.bpo-45166.UHipXF.rst b/Misc/NEWS.d/next/Library/2021-09-10-21-35-53.bpo-45166.UHipXF.rst deleted file mode 100644 index b7242d45ea9be..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-10-21-35-53.bpo-45166.UHipXF.rst +++ /dev/null @@ -1,2 +0,0 @@ -:func:`typing.get_type_hints` now works with :data:`~typing.Final` wrapped in -:class:`~typing.ForwardRef`. diff --git a/Misc/NEWS.d/next/Library/2021-09-11-10-45-12.bpo-35474.tEY3SD.rst b/Misc/NEWS.d/next/Library/2021-09-11-10-45-12.bpo-35474.tEY3SD.rst deleted file mode 100644 index f4dd3b947a493..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-11-10-45-12.bpo-35474.tEY3SD.rst +++ /dev/null @@ -1,3 +0,0 @@ -Calling :func:`mimetypes.guess_all_extensions` with ``strict=False`` no -longer affects the result of the following call with ``strict=True``. -Also, mutating the returned list no longer affects the global state. diff --git a/Misc/NEWS.d/next/Library/2021-09-11-14-47-05.bpo-45160.VzMXbW.rst b/Misc/NEWS.d/next/Library/2021-09-11-14-47-05.bpo-45160.VzMXbW.rst deleted file mode 100644 index 9d11ed0e55d24..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-11-14-47-05.bpo-45160.VzMXbW.rst +++ /dev/null @@ -1 +0,0 @@ -When tracing a tkinter variable used by a ttk OptionMenu, callbacks are no longer made twice. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2021-09-14-15-52-47.bpo-45192.DjA-BI.rst b/Misc/NEWS.d/next/Library/2021-09-14-15-52-47.bpo-45192.DjA-BI.rst deleted file mode 100644 index 7dd9795aaa170..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-14-15-52-47.bpo-45192.DjA-BI.rst +++ /dev/null @@ -1,5 +0,0 @@ -Fix the ``tempfile._infer_return_type`` function so that the ``dir`` -argument of the :mod:`tempfile` functions accepts an object implementing the -``os.PathLike`` protocol. - -Patch by Kyungmin Lee. diff --git a/Misc/NEWS.d/next/Library/2021-09-17-09-59-33.bpo-45228.WV1dcT.rst b/Misc/NEWS.d/next/Library/2021-09-17-09-59-33.bpo-45228.WV1dcT.rst deleted file mode 100644 index 9336c0aed92bc..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-17-09-59-33.bpo-45228.WV1dcT.rst +++ /dev/null @@ -1 +0,0 @@ -Fix stack buffer overflow in parsing J1939 network address. diff --git a/Misc/NEWS.d/next/Library/2021-09-17-11-20-55.bpo-45234.qUcTVt.rst b/Misc/NEWS.d/next/Library/2021-09-17-11-20-55.bpo-45234.qUcTVt.rst deleted file mode 100644 index 3817b5de6449d..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-17-11-20-55.bpo-45234.qUcTVt.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixed a regression in :func:`~shutil.copyfile`, :func:`~shutil.copy`, -:func:`~shutil.copy2` raising :exc:`FileNotFoundError` when source is a -directory, which should raise :exc:`IsADirectoryError` diff --git a/Misc/NEWS.d/next/Library/2021-09-17-16-55-37.bpo-45235.sXnmPA.rst b/Misc/NEWS.d/next/Library/2021-09-17-16-55-37.bpo-45235.sXnmPA.rst deleted file mode 100644 index 871ec5281d334..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-17-16-55-37.bpo-45235.sXnmPA.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix an issue where argparse would not preserve values in a provided namespace -when using a subparser with defaults. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2021-09-18-13-14-57.bpo-36674.a2k5Zb.rst b/Misc/NEWS.d/next/Library/2021-09-18-13-14-57.bpo-36674.a2k5Zb.rst deleted file mode 100644 index bc8c9247b080d..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-18-13-14-57.bpo-36674.a2k5Zb.rst +++ /dev/null @@ -1,2 +0,0 @@ -:meth:`unittest.TestCase.debug` raises now a :class:`unittest.SkipTest` if -the class or the test method are decorated with the skipping decorator. diff --git a/Misc/NEWS.d/next/Library/2021-09-18-16-56-33.bpo-45238.Hng_9V.rst b/Misc/NEWS.d/next/Library/2021-09-18-16-56-33.bpo-45238.Hng_9V.rst deleted file mode 100644 index 857f315c520bb..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-18-16-56-33.bpo-45238.Hng_9V.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix :meth:`unittest.IsolatedAsyncioTestCase.debug`: it runs now asynchronous -methods and callbacks. diff --git a/Misc/NEWS.d/next/Library/2021-09-23-22-17-26.bpo-45274.gPpa4E.rst b/Misc/NEWS.d/next/Library/2021-09-23-22-17-26.bpo-45274.gPpa4E.rst deleted file mode 100644 index 94d06cef89b7b..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-23-22-17-26.bpo-45274.gPpa4E.rst +++ /dev/null @@ -1,5 +0,0 @@ -Fix a race condition in the :meth:`Thread.join() ` -method of the :mod:`threading` module. If the function is interrupted by a -signal and the signal handler raises an exception, make sure that the thread -remains in a consistent state to prevent a deadlock. Patch by Victor -Stinner. diff --git a/Misc/NEWS.d/next/Library/2021-09-24-17-20-23.bpo-1596321.3nhPUk.rst b/Misc/NEWS.d/next/Library/2021-09-24-17-20-23.bpo-1596321.3nhPUk.rst deleted file mode 100644 index 61a3e5abf395e..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-24-17-20-23.bpo-1596321.3nhPUk.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix the :func:`threading._shutdown` function when the :mod:`threading` module -was imported first from a thread different than the main thread: no longer log -an error at Python exit. diff --git a/Misc/NEWS.d/next/Library/2021-09-30-08-22-44.bpo-45328.8Z-Q0B.rst b/Misc/NEWS.d/next/Library/2021-09-30-08-22-44.bpo-45328.8Z-Q0B.rst deleted file mode 100644 index eeb49310e8f66..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-30-08-22-44.bpo-45328.8Z-Q0B.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed :class:`http.client.HTTPConnection` to work properly in OSs that don't support the ``TCP_NODELAY`` socket option. diff --git a/Misc/NEWS.d/next/Library/2021-09-30-23-00-18.bpo-41710.svuloZ.rst b/Misc/NEWS.d/next/Library/2021-09-30-23-00-18.bpo-41710.svuloZ.rst deleted file mode 100644 index d8a4f9507c189..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-30-23-00-18.bpo-41710.svuloZ.rst +++ /dev/null @@ -1,5 +0,0 @@ -On Unix, if the ``sem_clockwait()`` function is available in the C library -(glibc 2.30 and newer), the :meth:`threading.Lock.acquire` method now uses the -monotonic clock (:data:`time.CLOCK_MONOTONIC`) for the timeout, rather than -using the system clock (:data:`time.CLOCK_REALTIME`), to not be affected by -system clock changes. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2021-10-01-23-07-02.bpo-45343.ixmctD.rst b/Misc/NEWS.d/next/Library/2021-10-01-23-07-02.bpo-45343.ixmctD.rst deleted file mode 100644 index 8dac4e6a25271..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-01-23-07-02.bpo-45343.ixmctD.rst +++ /dev/null @@ -1 +0,0 @@ -Update bundled pip to 21.2.4 and setuptools to 58.1.0 diff --git a/Misc/NEWS.d/next/Library/2021-10-03-21-14-37.bpo-20028.zBA4RK.rst b/Misc/NEWS.d/next/Library/2021-10-03-21-14-37.bpo-20028.zBA4RK.rst deleted file mode 100644 index e75612116e942..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-03-21-14-37.bpo-20028.zBA4RK.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve error message of :class:`csv.Dialect` when initializing. -Patch by Vajrasky Kok and Dong-hee Na. diff --git a/Misc/NEWS.d/next/Library/2021-10-05-11-03-48.bpo-45371.NOwcDJ.rst b/Misc/NEWS.d/next/Library/2021-10-05-11-03-48.bpo-45371.NOwcDJ.rst deleted file mode 100644 index 045489be81a19..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-05-11-03-48.bpo-45371.NOwcDJ.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix clang rpath issue in :mod:`distutils`. The UnixCCompiler now uses -correct clang option to add a runtime library directory (rpath) to a shared -library. diff --git a/Misc/NEWS.d/next/Library/2021-10-07-00-05-05.bpo-45386.q9ORpA.rst b/Misc/NEWS.d/next/Library/2021-10-07-00-05-05.bpo-45386.q9ORpA.rst deleted file mode 100644 index eec77ceccf933..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-07-00-05-05.bpo-45386.q9ORpA.rst +++ /dev/null @@ -1,3 +0,0 @@ -Make :mod:`xmlrpc.client` more robust to C runtimes where the underlying C -``strftime`` function results in a ``ValueError`` when testing for year -formatting options. diff --git a/Misc/NEWS.d/next/Library/2021-10-07-14-04-10.bpo-45262.HqF71Z.rst b/Misc/NEWS.d/next/Library/2021-10-07-14-04-10.bpo-45262.HqF71Z.rst deleted file mode 100644 index 4cd949fe1ed5d..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-07-14-04-10.bpo-45262.HqF71Z.rst +++ /dev/null @@ -1 +0,0 @@ -Prevent use-after-free in asyncio. Make sure the cached running loop holder gets cleared on dealloc to prevent use-after-free in get_running_loop \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2021-10-08-19-24-48.bpo-45406.Qh_Mz4.rst b/Misc/NEWS.d/next/Library/2021-10-08-19-24-48.bpo-45406.Qh_Mz4.rst deleted file mode 100644 index 2c3a8165aeb49..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-08-19-24-48.bpo-45406.Qh_Mz4.rst +++ /dev/null @@ -1 +0,0 @@ -Make :func:`inspect.getmodule` catch ``FileNotFoundError`` raised by :'func:`inspect.getabsfile`, and return ``None`` to indicate that the module could not be determined. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2021-10-09-18-42-27.bpo-44904.RlW5h8.rst b/Misc/NEWS.d/next/Library/2021-10-09-18-42-27.bpo-44904.RlW5h8.rst deleted file mode 100644 index b02d499d23500..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-09-18-42-27.bpo-44904.RlW5h8.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix bug in the :mod:`doctest` module that caused it to fail if a docstring -included an example with a ``classmethod`` ``property``. Patch by Alex -Waygood. diff --git a/Misc/NEWS.d/next/Library/2021-10-13-17-52-48.bpo-45239.7li1_0.rst b/Misc/NEWS.d/next/Library/2021-10-13-17-52-48.bpo-45239.7li1_0.rst deleted file mode 100644 index 9e5ec561c362a..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-13-17-52-48.bpo-45239.7li1_0.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixed :func:`email.utils.parsedate_tz` crashing with -:exc:`UnboundLocalError` on certain invalid input instead of returning -``None``. Patch by Ben Hoyt. diff --git a/Misc/NEWS.d/next/Library/2021-10-14-00-19-02.bpo-45461.4LB_tJ.rst b/Misc/NEWS.d/next/Library/2021-10-14-00-19-02.bpo-45461.4LB_tJ.rst deleted file mode 100644 index c1c4ed1ace248..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-14-00-19-02.bpo-45461.4LB_tJ.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix incremental decoder and stream reader in the "unicode-escape" codec. -Previously they failed if the escape sequence was split. diff --git a/Misc/NEWS.d/next/Library/2021-10-14-13-31-19.bpo-45467.Q7Ma6A.rst b/Misc/NEWS.d/next/Library/2021-10-14-13-31-19.bpo-45467.Q7Ma6A.rst deleted file mode 100644 index f2c0ae4ae51fb..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-14-13-31-19.bpo-45467.Q7Ma6A.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix incremental decoder and stream reader in the "raw-unicode-escape" codec. -Previously they failed if the escape sequence was split. diff --git a/Misc/NEWS.d/next/Library/2021-10-18-14-52-48.bpo-45515.aXdvm_.rst b/Misc/NEWS.d/next/Library/2021-10-18-14-52-48.bpo-45515.aXdvm_.rst deleted file mode 100644 index 382733ff91883..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-18-14-52-48.bpo-45515.aXdvm_.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add references to :mod:`zoneinfo` in the :mod:`datetime` documentation, -mostly replacing outdated references to ``dateutil.tz``. Change by Paul -Ganssle. diff --git a/Misc/NEWS.d/next/Library/2021-10-20-10-07-44.bpo-39679.nVYJJ3.rst b/Misc/NEWS.d/next/Library/2021-10-20-10-07-44.bpo-39679.nVYJJ3.rst deleted file mode 100644 index b0656aac51677..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-20-10-07-44.bpo-39679.nVYJJ3.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix bug in :class:`functools.singledispatchmethod` that caused it to fail -when attempting to register a :func:`classmethod` or :func:`staticmethod` -using type annotations. Patch contributed by Alex Waygood. diff --git a/Misc/NEWS.d/next/Library/2021-10-22-21-57-02.bpo-45581.rlH6ay.rst b/Misc/NEWS.d/next/Library/2021-10-22-21-57-02.bpo-45581.rlH6ay.rst deleted file mode 100644 index 13a3b237434eb..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-22-21-57-02.bpo-45581.rlH6ay.rst +++ /dev/null @@ -1,2 +0,0 @@ -:meth:`sqlite3.connect` now correctly raises :exc:`MemoryError` if the -underlying SQLite API signals memory error. Patch by Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/Library/2021-10-27-10-05-39.bpo-45438.Xz5lGU.rst b/Misc/NEWS.d/next/Library/2021-10-27-10-05-39.bpo-45438.Xz5lGU.rst deleted file mode 100644 index cd6cfc1fcd407..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-27-10-05-39.bpo-45438.Xz5lGU.rst +++ /dev/null @@ -1 +0,0 @@ -Fix typing.Signature string representation for generic builtin types. diff --git a/Misc/NEWS.d/next/Library/2021-10-30-21-11-37.bpo-45679.Dq8Cpu.rst b/Misc/NEWS.d/next/Library/2021-10-30-21-11-37.bpo-45679.Dq8Cpu.rst deleted file mode 100644 index a644492a12d17..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-30-21-11-37.bpo-45679.Dq8Cpu.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix caching of multi-value :data:`typing.Literal`. ``Literal[True, 2]`` is no -longer equal to ``Literal[1, 2]``. diff --git a/Misc/NEWS.d/next/Library/2021-11-03-17-28-43.bpo-45678.Zj_O8j.rst b/Misc/NEWS.d/next/Library/2021-11-03-17-28-43.bpo-45678.Zj_O8j.rst deleted file mode 100644 index f00707ca0099e..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-11-03-17-28-43.bpo-45678.Zj_O8j.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix bug in Python 3.9 that meant ``functools.singledispatchmethod`` failed -to properly wrap the attributes of the target method. Patch by Alex Waygood. diff --git a/Misc/NEWS.d/next/Tests/2021-08-30-11-54-14.bpo-45042.QMz3X8.rst b/Misc/NEWS.d/next/Tests/2021-08-30-11-54-14.bpo-45042.QMz3X8.rst deleted file mode 100644 index e2c0dffced96e..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-08-30-11-54-14.bpo-45042.QMz3X8.rst +++ /dev/null @@ -1 +0,0 @@ -Fixes that test classes decorated with ``@hashlib_helper.requires_hashdigest`` were skipped all the time. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Tests/2021-09-13-00-28-17.bpo-45156.8oomV3.rst b/Misc/NEWS.d/next/Tests/2021-09-13-00-28-17.bpo-45156.8oomV3.rst deleted file mode 100644 index b2094b5765331..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-09-13-00-28-17.bpo-45156.8oomV3.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixes infinite loop on :func:`unittest.mock.seal` of mocks created by -:func:`~unittest.create_autospec`. diff --git a/Misc/NEWS.d/next/Tests/2021-09-14-13-16-18.bpo-45195.EyQR1G.rst b/Misc/NEWS.d/next/Tests/2021-09-14-13-16-18.bpo-45195.EyQR1G.rst deleted file mode 100644 index 16a1f4440483c..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-09-14-13-16-18.bpo-45195.EyQR1G.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix test_readline.test_nonascii(): sometimes, the newline character is not -written at the end, so don't expect it in the output. Patch by Victor -Stinner. diff --git a/Misc/NEWS.d/next/Tests/2021-09-15-23-32-39.bpo-45209.55ntL5.rst b/Misc/NEWS.d/next/Tests/2021-09-15-23-32-39.bpo-45209.55ntL5.rst deleted file mode 100644 index 4c3bed0983b89..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-09-15-23-32-39.bpo-45209.55ntL5.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix ``UserWarning: resource_tracker`` warning in -``_test_multiprocessing._TestSharedMemory.test_shared_memory_cleaned_after_process_termination`` diff --git a/Misc/NEWS.d/next/Tests/2021-09-24-10-41-49.bpo-45269.8jKEr8.rst b/Misc/NEWS.d/next/Tests/2021-09-24-10-41-49.bpo-45269.8jKEr8.rst deleted file mode 100644 index 72dd9471134ff..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-09-24-10-41-49.bpo-45269.8jKEr8.rst +++ /dev/null @@ -1 +0,0 @@ -Cover case when invalid ``markers`` type is supplied to ``c_make_encoder``. diff --git a/Misc/NEWS.d/next/Tests/2021-09-25-11-05-31.bpo-45280.3MA6lC.rst b/Misc/NEWS.d/next/Tests/2021-09-25-11-05-31.bpo-45280.3MA6lC.rst deleted file mode 100644 index 71691f5ba2b89..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-09-25-11-05-31.bpo-45280.3MA6lC.rst +++ /dev/null @@ -1 +0,0 @@ -Add a test case for empty :class:`typing.NamedTuple`. diff --git a/Misc/NEWS.d/next/Tests/2021-09-30-16-54-39.bpo-40173.J_slCw.rst b/Misc/NEWS.d/next/Tests/2021-09-30-16-54-39.bpo-40173.J_slCw.rst deleted file mode 100644 index 21671473c16cc..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-09-30-16-54-39.bpo-40173.J_slCw.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix :func:`test.support.import_helper.import_fresh_module`. - diff --git a/Misc/NEWS.d/next/Tests/2021-10-21-17-22-26.bpo-43592.kHRsra.rst b/Misc/NEWS.d/next/Tests/2021-10-21-17-22-26.bpo-43592.kHRsra.rst deleted file mode 100644 index 2528857caf9c0..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-10-21-17-22-26.bpo-43592.kHRsra.rst +++ /dev/null @@ -1,3 +0,0 @@ -:mod:`test.libregrtest` now raises the soft resource limit for the maximum -number of file descriptors when the default is too low for our test suite as -was often the case on macOS. diff --git a/Misc/NEWS.d/next/Tests/2021-10-22-19-44-13.bpo-45577.dSaNvK.rst b/Misc/NEWS.d/next/Tests/2021-10-22-19-44-13.bpo-45577.dSaNvK.rst deleted file mode 100644 index fc9783eb9ddaa..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-10-22-19-44-13.bpo-45577.dSaNvK.rst +++ /dev/null @@ -1 +0,0 @@ -Add subtests for all ``pickle`` protocols in ``test_zoneinfo``. diff --git a/Misc/NEWS.d/next/Tests/2021-10-30-19-00-25.bpo-45578.bvu6X2.rst b/Misc/NEWS.d/next/Tests/2021-10-30-19-00-25.bpo-45578.bvu6X2.rst deleted file mode 100644 index 3d0e0ca3f04a1..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-10-30-19-00-25.bpo-45578.bvu6X2.rst +++ /dev/null @@ -1 +0,0 @@ -Add tests for :func:`dis.distb` diff --git a/Misc/NEWS.d/next/Windows/2021-09-30-23-17-27.bpo-45337.qg7U_h.rst b/Misc/NEWS.d/next/Windows/2021-09-30-23-17-27.bpo-45337.qg7U_h.rst deleted file mode 100644 index 007ee87195d6e..0000000000000 --- a/Misc/NEWS.d/next/Windows/2021-09-30-23-17-27.bpo-45337.qg7U_h.rst +++ /dev/null @@ -1,4 +0,0 @@ -venv now warns when the created environment may need to be accessed at a -different path, due to redirections, links or junctions. It also now -correctly installs or upgrades components when the alternate path is -required. diff --git a/Misc/NEWS.d/next/macOS/2021-10-25-02-02-21.bpo-44828.XBdXlJ.rst b/Misc/NEWS.d/next/macOS/2021-10-25-02-02-21.bpo-44828.XBdXlJ.rst deleted file mode 100644 index 021d7e4d73782..0000000000000 --- a/Misc/NEWS.d/next/macOS/2021-10-25-02-02-21.bpo-44828.XBdXlJ.rst +++ /dev/null @@ -1,3 +0,0 @@ -Avoid tkinter file dialog failure on macOS 12 Monterey when using the Tk -8.6.11 provided by python.org macOS installers. Patch by Marc Culler of the -Tk project. diff --git a/README.rst b/README.rst index a419856dfb4e3..ef78796301dc0 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -This is Python version 3.9.7 +This is Python version 3.9.8 ============================ .. image:: https://travis-ci.org/python/cpython.svg?branch=3.9 From webhook-mailer at python.org Fri Nov 5 17:30:38 2021 From: webhook-mailer at python.org (pablogsal) Date: Fri, 05 Nov 2021 21:30:38 -0000 Subject: [Python-checkins] Python 3.11.0a2 Message-ID: https://github.com/python/cpython/commit/e2b4e4bab90b69fbd3614fc9ce5755edfe184297 commit: e2b4e4bab90b69fbd3614fc9ce5755edfe184297 branch: main author: Pablo Galindo committer: pablogsal date: 2021-11-05T19:04:04Z summary: Python 3.11.0a2 files: A Misc/NEWS.d/3.11.0a2.rst D Misc/NEWS.d/next/Build/2021-10-11-16-08-37.bpo-45433.pVDkMV.rst D Misc/NEWS.d/next/Build/2021-10-11-16-27-38.bpo-45405.iSfdW5.rst D Misc/NEWS.d/next/Build/2021-10-12-02-13-08.bpo-45440.-zYgDb.rst D Misc/NEWS.d/next/Build/2021-10-18-10-25-56.bpo-45221.rnulhf.rst D Misc/NEWS.d/next/Build/2021-10-20-12-42-39.bpo-45536.oQNYHB.rst D Misc/NEWS.d/next/Build/2021-10-20-16-07-39.bpo-45532.kyhvis.rst D Misc/NEWS.d/next/Build/2021-10-20-17-02-56.bpo-45548.BoggEf.rst D Misc/NEWS.d/next/Build/2021-10-22-14-00-44.bpo-43974.HHZtbx.rst D Misc/NEWS.d/next/Build/2021-10-22-14-45-40.bpo-45570.61gM2A.rst D Misc/NEWS.d/next/Build/2021-10-22-15-28-29.bpo-45571.yY8NsJ.rst D Misc/NEWS.d/next/Build/2021-10-24-11-02-43.bpo-45595.WI_5YU.rst D Misc/NEWS.d/next/Build/2021-10-24-21-49-49.bpo-45548.UWx0UC.rst D Misc/NEWS.d/next/Build/2021-10-28-14-47-22.bpo-45548.mdCBxB.rst D Misc/NEWS.d/next/Build/2021-10-29-12-54-53.bpo-45666.w2G63u.rst D Misc/NEWS.d/next/Build/2021-11-01-12-51-46.bpo-43158.fghS6w.rst D Misc/NEWS.d/next/C API/2021-05-24-22-12-40.bpo-44220.H9CUGl.rst D Misc/NEWS.d/next/C API/2021-09-24-11-12-21.bpo-43760.Bfxd1-.rst D Misc/NEWS.d/next/C API/2021-10-06-15-54-40.bpo-45395.yVhdAl.rst D Misc/NEWS.d/next/C API/2021-10-08-15-54-07.bpo-45412.KHyJCT.rst D Misc/NEWS.d/next/C API/2021-10-11-22-58-33.bpo-41123.myrlIp.rst D Misc/NEWS.d/next/C API/2021-10-11-23-03-49.bpo-45434.tsS8I_.rst D Misc/NEWS.d/next/C API/2021-10-12-02-13-41.bpo-45440.Gf94rE.rst D Misc/NEWS.d/next/C API/2021-10-13-14-42-46.bpo-45434.INNEEt.rst D Misc/NEWS.d/next/C API/2021-10-14-22-16-56.bpo-45474.1OkJQh.rst D Misc/NEWS.d/next/C API/2021-10-15-00-11-51.bpo-35134.eX4zqy.rst D Misc/NEWS.d/next/C API/2021-10-15-09-29-59.bpo-35081.2teFD3.rst D Misc/NEWS.d/next/C API/2021-10-19-00-20-40.bpo-35134.Z0Zk_m.rst D Misc/NEWS.d/next/C API/2021-10-19-13-07-46.bpo-45522.kGAwmZ.rst D Misc/NEWS.d/next/C API/2021-10-20-18-41-17.bpo-29103.CMRLyq.rst D Misc/NEWS.d/next/Core and Builtins/2021-04-03-02-44-15.bpo-43706.jjsXlT.rst D Misc/NEWS.d/next/Core and Builtins/2021-06-26-16-55-08.bpo-44511.k8sMvV.rst D Misc/NEWS.d/next/Core and Builtins/2021-06-28-22-23-59.bpo-44525.sSvUKG.rst D Misc/NEWS.d/next/Core and Builtins/2021-09-08-00-30-09.bpo-44050.mFI15u.rst D Misc/NEWS.d/next/Core and Builtins/2021-09-23-14-00-05.bpo-40116.KaoeFs.rst D Misc/NEWS.d/next/Core and Builtins/2021-09-26-18-18-50.bpo-45292.aX5HVr.rst D Misc/NEWS.d/next/Core and Builtins/2021-09-29-12-02-39.bpo-45324.BTQElX.rst D Misc/NEWS.d/next/Core and Builtins/2021-10-01-09-06-54.bpo-45020.Cj5VQN.rst D Misc/NEWS.d/next/Core and Builtins/2021-10-01-09-21-02.bpo-21736.RI47BU.rst D Misc/NEWS.d/next/Core and Builtins/2021-10-05-03-49-07.bpo-45367._astoU.rst D Misc/NEWS.d/next/Core and Builtins/2021-10-06-21-20-11.bpo-45385.CTUT8s.rst D Misc/NEWS.d/next/Core and Builtins/2021-10-07-19-09-12.bpo-29410.bg5SYp.rst D Misc/NEWS.d/next/Core and Builtins/2021-10-07-21-26-44.bpo-45408.qUqzcd.rst D Misc/NEWS.d/next/Core and Builtins/2021-10-08-09-47-38.bpo-45340.ukHgDb.rst D Misc/NEWS.d/next/Core and Builtins/2021-10-12-14-41-39.bpo-45445._F5cMf.rst D Misc/NEWS.d/next/Core and Builtins/2021-10-16-17-27-48.bpo-45494.vMt1g4.rst D Misc/NEWS.d/next/Core and Builtins/2021-10-18-22-40-33.bpo-45521.GdMiuW.rst D Misc/NEWS.d/next/Core and Builtins/2021-10-19-01-04-08.bpo-30570._G30Ms.rst D Misc/NEWS.d/next/Core and Builtins/2021-10-19-10-29-47.bpo-45526.WQnvW9.rst D Misc/NEWS.d/next/Core and Builtins/2021-10-20-01-28-26.bpo-45530.5r7n4m.rst D Misc/NEWS.d/next/Core and Builtins/2021-10-20-11-57-31.bpo-44525.veL4lJ.rst D Misc/NEWS.d/next/Core and Builtins/2021-10-23-13-49-00.bpo-45379.ZF7G3n.rst D Misc/NEWS.d/next/Core and Builtins/2021-11-02-09-27-46.bpo-45688.v5Der1.rst D Misc/NEWS.d/next/Core and Builtins/2021-11-04-20-19-07.bpo-45716.5C0pA1.rst D Misc/NEWS.d/next/Documentation/2021-10-13-00-42-54.bpo-20692.K5rGtP.rst D Misc/NEWS.d/next/Documentation/2021-10-18-20-12-18.bpo-45516.EJh4K8.rst D Misc/NEWS.d/next/Documentation/2021-10-19-01-41-40.bpo-45449.fjHZJc.rst D Misc/NEWS.d/next/Documentation/2021-10-20-16-26-53.bpo-45464.mOISBs.rst D Misc/NEWS.d/next/Documentation/2021-10-22-21-57-42.bpo-45516.7_RMEX.rst D Misc/NEWS.d/next/Documentation/2021-10-26-10-00-45.bpo-45604.Dm-YhV.rst D Misc/NEWS.d/next/Documentation/2021-10-28-19-22-55.bpo-45655.aPYGaS.rst D Misc/NEWS.d/next/Documentation/2021-10-31-20-35-06.bpo-45618.RTcNXF.rst D Misc/NEWS.d/next/Documentation/2021-11-03-14-51-03.bpo-45680.9_NTFU.rst D Misc/NEWS.d/next/Documentation/2021-11-05-12-15-24.bpo-45726.GwRr7e.rst D Misc/NEWS.d/next/IDLE/2021-10-16-17-20-32.bpo-45495.ST8RFt.rst D Misc/NEWS.d/next/Library/2019-02-11-19-06-10.bpo-35970.ZRvh51.rst D Misc/NEWS.d/next/Library/2020-07-27-19-21-05.bpo-41374.cd-kFL.rst D Misc/NEWS.d/next/Library/2021-01-07-01-25-38.bpo-10572.gEEZ9z.rst D Misc/NEWS.d/next/Library/2021-07-22-21-25-56.bpo-40321.gBlFmw.rst D Misc/NEWS.d/next/Library/2021-08-20-10-52-40.bpo-44547.eu0iJq.rst D Misc/NEWS.d/next/Library/2021-08-30-00-19-23.bpo-24444.Ki4bgz.rst D Misc/NEWS.d/next/Library/2021-08-30-23-10-48.bpo-24139.e38czf.rst D Misc/NEWS.d/next/Library/2021-09-10-12-53-28.bpo-25625.SzcBCw.rst D Misc/NEWS.d/next/Library/2021-09-11-14-47-05.bpo-45160.VzMXbW.rst D Misc/NEWS.d/next/Library/2021-09-14-15-52-47.bpo-45192.DjA-BI.rst D Misc/NEWS.d/next/Library/2021-09-15-10-21-10.bpo-45320.4qaf5x.rst D Misc/NEWS.d/next/Library/2021-09-20-01-25-09.bpo-45243.0pJf0U.rst D Misc/NEWS.d/next/Library/2021-09-30-08-22-44.bpo-45328.8Z-Q0B.rst D Misc/NEWS.d/next/Library/2021-10-01-23-07-02.bpo-45343.ixmctD.rst D Misc/NEWS.d/next/Library/2021-10-03-21-14-37.bpo-20028.zBA4RK.rst D Misc/NEWS.d/next/Library/2021-10-07-00-05-05.bpo-45386.q9ORpA.rst D Misc/NEWS.d/next/Library/2021-10-07-14-04-10.bpo-45262.HqF71Z.rst D Misc/NEWS.d/next/Library/2021-10-07-21-11-48.bpo-27580.tGcBTH.rst D Misc/NEWS.d/next/Library/2021-10-08-04-11-55.bpo-10716.QSRVK2.rst D Misc/NEWS.d/next/Library/2021-10-08-11-29-29.bpo-45411.4jR--U.rst D Misc/NEWS.d/next/Library/2021-10-08-19-24-48.bpo-45406.Qh_Mz4.rst D Misc/NEWS.d/next/Library/2021-10-09-18-42-27.bpo-44904.RlW5h8.rst D Misc/NEWS.d/next/Library/2021-10-10-00-25-36.bpo-20028.bPx4Z8.rst D Misc/NEWS.d/next/Library/2021-10-10-09-42-34.bpo-45416.n35O0_.rst D Misc/NEWS.d/next/Library/2021-10-10-16-14-33.bpo-45249.xqLliz.rst D Misc/NEWS.d/next/Library/2021-10-12-20-35-06.bpo-45417.gQM-O7.rst D Misc/NEWS.d/next/Library/2021-10-13-17-52-48.bpo-45239.7li1_0.rst D Misc/NEWS.d/next/Library/2021-10-14-00-19-02.bpo-45461.4LB_tJ.rst D Misc/NEWS.d/next/Library/2021-10-14-13-31-19.bpo-45467.Q7Ma6A.rst D Misc/NEWS.d/next/Library/2021-10-14-18-04-17.bpo-45428.mM2War.rst D Misc/NEWS.d/next/Library/2021-10-15-11-30-11.bpo-42222.hdHyac.rst D Misc/NEWS.d/next/Library/2021-10-16-23-46-39.bpo-45489.QB0rhG.rst D Misc/NEWS.d/next/Library/2021-10-18-10-46-47.bpo-45475.sb9KDF.rst D Misc/NEWS.d/next/Library/2021-10-18-14-52-48.bpo-45515.aXdvm_.rst D Misc/NEWS.d/next/Library/2021-10-18-18-12-47.bpo-35673.KOkHWe.rst D Misc/NEWS.d/next/Library/2021-10-19-01-30-57.bpo-42174.O2w9bi.rst D Misc/NEWS.d/next/Library/2021-10-21-10-14-22.bpo-44019.Xk4Ncr.rst D Misc/NEWS.d/next/Library/2021-10-21-16-18-51.bpo-45557.4MQt4r.rst D Misc/NEWS.d/next/Library/2021-10-22-21-57-02.bpo-45581.rlH6ay.rst D Misc/NEWS.d/next/Library/2021-10-22-23-06-33.bpo-45574.svqA84.rst D Misc/NEWS.d/next/Library/2021-10-26-14-29-54.bpo-45613.55Ie3c.rst D Misc/NEWS.d/next/Library/2021-10-27-10-05-39.bpo-45438.Xz5lGU.rst D Misc/NEWS.d/next/Library/2021-10-27-13-28-52.bpo-42064.UK4jgV.rst D Misc/NEWS.d/next/Library/2021-10-30-21-11-37.bpo-45679.Dq8Cpu.rst D Misc/NEWS.d/next/Tests/2021-10-07-13-11-45.bpo-45400.h3iT7V.rst D Misc/NEWS.d/next/Tests/2021-10-07-13-27-12.bpo-45403.7QiDvw.rst D Misc/NEWS.d/next/Tests/2021-10-07-13-43-01.bpo-45402.jlQvep.rst D Misc/NEWS.d/next/Tests/2021-10-08-14-03-20.bpo-45410.Ex9xe2.rst D Misc/NEWS.d/next/Tests/2021-10-18-16-18-41.bpo-39679.F18qcE.rst D Misc/NEWS.d/next/Tests/2021-10-21-17-22-26.bpo-43592.kHRsra.rst D Misc/NEWS.d/next/Tests/2021-10-22-12-05-21.bpo-45566.2gQ3ZB.rst D Misc/NEWS.d/next/Tests/2021-10-22-19-44-13.bpo-45577.dSaNvK.rst D Misc/NEWS.d/next/Tests/2021-10-29-17-18-56.bpo-45668.MfAw4i.rst D Misc/NEWS.d/next/Tests/2021-10-30-13-12-20.bpo-45678.bKrYeS.rst D Misc/NEWS.d/next/Tests/2021-10-30-19-00-25.bpo-45578.bvu6X2.rst D Misc/NEWS.d/next/Tests/2021-11-04-20-03-32.bpo-45678.1xNMjN.rst D Misc/NEWS.d/next/Windows/2021-04-15-01-23-10.bpo-43851.qgU0gy.rst D Misc/NEWS.d/next/Windows/2021-09-30-23-17-27.bpo-45337.qg7U_h.rst D Misc/NEWS.d/next/Windows/2021-11-04-00-41-50.bpo-43652.RnqV7I.rst D Misc/NEWS.d/next/macOS/2021-10-25-02-02-21.bpo-44828.XBdXlJ.rst M Include/patchlevel.h M Lib/pydoc_data/topics.py M README.rst M configure M pyconfig.h.in diff --git a/Include/patchlevel.h b/Include/patchlevel.h index 591b41736f338..4f961da884b17 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -20,10 +20,10 @@ #define PY_MINOR_VERSION 11 #define PY_MICRO_VERSION 0 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_ALPHA -#define PY_RELEASE_SERIAL 1 +#define PY_RELEASE_SERIAL 2 /* Version as a string */ -#define PY_VERSION "3.11.0a1+" +#define PY_VERSION "3.11.0a2" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py index eb523370c58d7..78555cddca77c 100644 --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Tue Oct 5 13:43:52 2021 +# Autogenerated by Sphinx on Fri Nov 5 19:03:45 2021 topics = {'assert': 'The "assert" statement\n' '**********************\n' '\n' @@ -3339,9 +3339,9 @@ '\n' 'The same keyword should not be repeated in class patterns.\n' '\n' - 'The following is the logical flow for matching a mapping ' - 'pattern\n' - 'against a subject value:\n' + 'The following is the logical flow for matching a class pattern ' + 'against\n' + 'a subject value:\n' '\n' '1. If "name_or_attr" is not an instance of the builtin "type" , ' 'raise\n' @@ -5579,9 +5579,9 @@ 'operations.\n' '\n' 'If the "global" statement occurs within a block, all uses of ' - 'the name\n' - 'specified in the statement refer to the binding of that name in ' - 'the\n' + 'the names\n' + 'specified in the statement refer to the bindings of those names ' + 'in the\n' 'top-level namespace. Names are resolved in the top-level ' 'namespace by\n' 'searching the global namespace, i.e. the namespace of the ' @@ -5590,9 +5590,10 @@ 'namespace\n' 'of the module "builtins". The global namespace is searched ' 'first. If\n' - 'the name is not found there, the builtins namespace is ' - 'searched. The\n' - '"global" statement must precede all uses of the name.\n' + 'the names are not found there, the builtins namespace is ' + 'searched.\n' + 'The "global" statement must precede all uses of the listed ' + 'names.\n' '\n' 'The "global" statement has the same scope as a name binding ' 'operation\n' @@ -6948,22 +6949,31 @@ 'trailing underscore characters:\n' '\n' '"_*"\n' - ' Not imported by "from module import *". The special ' - 'identifier "_"\n' - ' is used in the interactive interpreter to store the result ' - 'of the\n' - ' last evaluation; it is stored in the "builtins" module. ' - 'When not\n' - ' in interactive mode, "_" has no special meaning and is not ' - 'defined.\n' - ' See section The import statement.\n' + ' Not imported by "from module import *".\n' + '\n' + '"_"\n' + ' In a "case" pattern within a "match" statement, "_" is a ' + 'soft\n' + ' keyword that denotes a wildcard.\n' + '\n' + ' Separately, the interactive interpreter makes the result of ' + 'the\n' + ' last evaluation available in the variable "_". (It is ' + 'stored in the\n' + ' "builtins" module, alongside built-in functions like ' + '"print".)\n' + '\n' + ' Elsewhere, "_" is a regular identifier. It is often used to ' + 'name\n' + ' ?special? items, but it is not special to Python itself.\n' '\n' ' Note:\n' '\n' ' The name "_" is often used in conjunction with\n' ' internationalization; refer to the documentation for the\n' ' "gettext" module for more information on this ' - 'convention.\n' + 'convention.It is\n' + ' also commonly used for unused variables.\n' '\n' '"__*__"\n' ' System-defined names, informally known as ?dunder? names. ' @@ -7118,15 +7128,23 @@ 'trailing underscore characters:\n' '\n' '"_*"\n' - ' Not imported by "from module import *". The special ' - 'identifier "_"\n' - ' is used in the interactive interpreter to store the result ' + ' Not imported by "from module import *".\n' + '\n' + '"_"\n' + ' In a "case" pattern within a "match" statement, "_" is a ' + 'soft\n' + ' keyword that denotes a wildcard.\n' + '\n' + ' Separately, the interactive interpreter makes the result ' 'of the\n' - ' last evaluation; it is stored in the "builtins" module. ' - 'When not\n' - ' in interactive mode, "_" has no special meaning and is not ' - 'defined.\n' - ' See section The import statement.\n' + ' last evaluation available in the variable "_". (It is ' + 'stored in the\n' + ' "builtins" module, alongside built-in functions like ' + '"print".)\n' + '\n' + ' Elsewhere, "_" is a regular identifier. It is often used ' + 'to name\n' + ' ?special? items, but it is not special to Python itself.\n' '\n' ' Note:\n' '\n' @@ -7134,7 +7152,8 @@ ' internationalization; refer to the documentation for ' 'the\n' ' "gettext" module for more information on this ' - 'convention.\n' + 'convention.It is\n' + ' also commonly used for unused variables.\n' '\n' '"__*__"\n' ' System-defined names, informally known as ?dunder? names. ' @@ -7678,8 +7697,8 @@ 'operations.\n' '\n' 'If the "global" statement occurs within a block, all uses of the ' - 'name\n' - 'specified in the statement refer to the binding of that name in ' + 'names\n' + 'specified in the statement refer to the bindings of those names in ' 'the\n' 'top-level namespace. Names are resolved in the top-level ' 'namespace by\n' @@ -7688,9 +7707,9 @@ 'namespace\n' 'of the module "builtins". The global namespace is searched ' 'first. If\n' - 'the name is not found there, the builtins namespace is searched. ' - 'The\n' - '"global" statement must precede all uses of the name.\n' + 'the names are not found there, the builtins namespace is ' + 'searched.\n' + 'The "global" statement must precede all uses of the listed names.\n' '\n' 'The "global" statement has the same scope as a name binding ' 'operation\n' @@ -8025,9 +8044,9 @@ ' of the object truncated to an "Integral" (typically an ' '"int").\n' '\n' - ' If "__int__()" is not defined then the built-in function ' - '"int()"\n' - ' falls back to "__trunc__()".\n', + ' The built-in function "int()" falls back to ' + '"__trunc__()" if\n' + ' neither "__int__()" nor "__index__()" is defined.\n', 'objects': 'Objects, values and types\n' '*************************\n' '\n' @@ -10765,9 +10784,9 @@ ' of the object truncated to an "Integral" (typically an ' '"int").\n' '\n' - ' If "__int__()" is not defined then the built-in function ' - '"int()"\n' - ' falls back to "__trunc__()".\n' + ' The built-in function "int()" falls back to "__trunc__()" ' + 'if\n' + ' neither "__int__()" nor "__index__()" is defined.\n' '\n' '\n' 'With Statement Context Managers\n' diff --git a/Misc/NEWS.d/3.11.0a2.rst b/Misc/NEWS.d/3.11.0a2.rst new file mode 100644 index 0000000000000..1f742a29ebcc9 --- /dev/null +++ b/Misc/NEWS.d/3.11.0a2.rst @@ -0,0 +1,1334 @@ +.. bpo: 45716 +.. date: 2021-11-04-20-19-07 +.. nonce: 5C0pA1 +.. release date: 2021-11-05 +.. section: Core and Builtins + +Improve the :exc:`SyntaxError` message when using ``True``, ``None`` or +``False`` as keywords in a function call. Patch by Pablo Galindo. + +.. + +.. bpo: 45688 +.. date: 2021-11-02-09-27-46 +.. nonce: v5Der1 +.. section: Core and Builtins + +:data:`sys.stdlib_module_names` now contains the macOS-specific module +:mod:`_scproxy`. + +.. + +.. bpo: 45379 +.. date: 2021-10-23-13-49-00 +.. nonce: ZF7G3n +.. section: Core and Builtins + +Clarify :exc:`ImportError` message when we try to explicitly import a frozen +module but frozen modules are disabled. + +.. + +.. bpo: 44525 +.. date: 2021-10-20-11-57-31 +.. nonce: veL4lJ +.. section: Core and Builtins + +Specialize simple calls to Python functions (no starargs, keyowrd dict, or +closure) + +.. + +.. bpo: 45530 +.. date: 2021-10-20-01-28-26 +.. nonce: 5r7n4m +.. section: Core and Builtins + +Cases of sorting using tuples as keys may now be significantly faster in +some cases. Patch by Tim Peters. + +The order of the result may differ from earlier releases if the tuple +elements don't define a total ordering (see +:ref:`expressions-value-comparisons` for information on total ordering). +It's generally true that the result of sorting simply isn't well-defined in +the absence of a total ordering on list elements. + +.. + +.. bpo: 45526 +.. date: 2021-10-19-10-29-47 +.. nonce: WQnvW9 +.. section: Core and Builtins + +In obmalloc, set ADDRESS_BITS to not ignore any bits (ignored 16 before). +That is safer in the case that the kernel gives user-space virtual addresses +that span a range greater than 48 bits. + +.. + +.. bpo: 30570 +.. date: 2021-10-19-01-04-08 +.. nonce: _G30Ms +.. section: Core and Builtins + +Fixed a crash in ``issubclass()`` from infinite recursion when searching +pathological ``__bases__`` tuples. + +.. + +.. bpo: 45521 +.. date: 2021-10-18-22-40-33 +.. nonce: GdMiuW +.. section: Core and Builtins + +Fix a bug in the obmalloc radix tree code. On 64-bit machines, the bug +causes the tree to hold 46-bits of virtual addresses, rather than the +intended 48-bits. + +.. + +.. bpo: 45494 +.. date: 2021-10-16-17-27-48 +.. nonce: vMt1g4 +.. section: Core and Builtins + +Fix parser crash when reporting errors involving invalid continuation +characters. Patch by Pablo Galindo. + +.. + +.. bpo: 45445 +.. date: 2021-10-12-14-41-39 +.. nonce: _F5cMf +.. section: Core and Builtins + +Python now fails to initialize if it finds an invalid :option:`-X` option in +the command line. Patch by Pablo Galindo. + +.. + +.. bpo: 45340 +.. date: 2021-10-08-09-47-38 +.. nonce: ukHgDb +.. section: Core and Builtins + +Object attributes are held in an array instead of a dictionary. An object's +dictionary are created lazily, only when needed. Reduces the memory +consumption of a typical Python object by about 30%. Patch by Mark Shannon. + +.. + +.. bpo: 45408 +.. date: 2021-10-07-21-26-44 +.. nonce: qUqzcd +.. section: Core and Builtins + +Fix a crash in the parser when reporting tokenizer errors that occur at the +same time unclosed parentheses are detected. Patch by Pablo Galindo. + +.. + +.. bpo: 29410 +.. date: 2021-10-07-19-09-12 +.. nonce: bg5SYp +.. section: Core and Builtins + +Add SipHash13 for string hash algorithm and use it by default. + +.. + +.. bpo: 45385 +.. date: 2021-10-06-21-20-11 +.. nonce: CTUT8s +.. section: Core and Builtins + +Fix reference leak from descr_check. Patch by Dong-hee Na. + +.. + +.. bpo: 45367 +.. date: 2021-10-05-03-49-07 +.. nonce: _astoU +.. section: Core and Builtins + +Specialized the ``BINARY_MULTIPLY`` opcode to ``BINARY_MULTIPLY_INT`` and +``BINARY_MULTIPLY_FLOAT`` using the PEP 659 machinery. + +.. + +.. bpo: 21736 +.. date: 2021-10-01-09-21-02 +.. nonce: RI47BU +.. section: Core and Builtins + +Frozen stdlib modules now have ``__file__`` to the .py file they would +otherwise be loaded from, if possible. For packages, ``__path__`` now has +the correct entry instead of being an empty list, which allows unfrozen +submodules to be imported. These are set only if the stdlib directory is +known when the runtime is initialized. Note that the file at ``__file__`` +is not guaranteed to exist. None of this affects non-stdlib frozen modules +nor, for now, frozen modules imported using +``PyImport_ImportFrozenModule()``. Also, at the moment ``co_filename`` is +not updated for the module. + +.. + +.. bpo: 45020 +.. date: 2021-10-01-09-06-54 +.. nonce: Cj5VQN +.. section: Core and Builtins + +For frozen stdlib modules, record the original module name as +``module.__spec__.loader_state.origname``. If the value is different than +``module.__spec__.name`` then the module was defined as an alias in +Tools/scripts/freeze_modules.py. If it is ``None`` then the module comes +from a source file outside the stdlib. + +.. + +.. bpo: 45324 +.. date: 2021-09-29-12-02-39 +.. nonce: BTQElX +.. section: Core and Builtins + +In FrozenImporter.find_spec(), we now preserve the information needed in +exec_module() to load the module. This change mostly impacts internal +details, rather than changing the importer's behavior. + +.. + +.. bpo: 45292 +.. date: 2021-09-26-18-18-50 +.. nonce: aX5HVr +.. section: Core and Builtins + +Implement :pep:`654`. Add :class:`ExceptionGroup` and +:class:`BaseExceptionGroup`. Update traceback display code. + +.. + +.. bpo: 40116 +.. date: 2021-09-23-14-00-05 +.. nonce: KaoeFs +.. section: Core and Builtins + +Change to the implementation of split dictionaries. Classes where the +instances differ either in the exact set of attributes, or in the order in +which those attributes are set, can still share keys. This should have no +observable effect on users of Python or the C-API. Patch by Mark Shannon. + +.. + +.. bpo: 44050 +.. date: 2021-09-08-00-30-09 +.. nonce: mFI15u +.. section: Core and Builtins + +Extensions that indicate they use global state (by setting ``m_size`` to -1) +can again be used in multiple interpreters. This reverts to behavior of +Python 3.8. + +.. + +.. bpo: 44525 +.. date: 2021-06-28-22-23-59 +.. nonce: sSvUKG +.. section: Core and Builtins + +Setup initial specialization infrastructure for the ``CALL_FUNCTION`` +opcode. Implemented initial specializations for C function calls: + +* ``CALL_FUNCTION_BUILTIN_O`` for ``METH_O`` flag. + +* ``CALL_FUNCTION_BUILTIN_FAST`` for ``METH_FASTCALL`` flag without keywords. + +* ``CALL_FUNCTION_LEN`` for ``len(o)``. + +* ``CALL_FUNCTION_ISINSTANCE`` for ``isinstance(o, t)``. + +.. + +.. bpo: 44511 +.. date: 2021-06-26-16-55-08 +.. nonce: k8sMvV +.. section: Core and Builtins + +Improve the generated bytecode for class and mapping patterns. + +.. + +.. bpo: 43706 +.. date: 2021-04-03-02-44-15 +.. nonce: jjsXlT +.. section: Core and Builtins + +Speed up calls to ``enumerate()`` by using the :pep:`590` ``vectorcall`` +calling convention. Patch by Dong-hee Na. + +.. + +.. bpo: 45679 +.. date: 2021-10-30-21-11-37 +.. nonce: Dq8Cpu +.. section: Library + +Fix caching of multi-value :data:`typing.Literal`. ``Literal[True, 2]`` is +no longer equal to ``Literal[1, 2]``. + +.. + +.. bpo: 42064 +.. date: 2021-10-27-13-28-52 +.. nonce: UK4jgV +.. section: Library + +Convert :mod:`sqlite3` to multi-phase initialisation (PEP 489). Patches by +Erlend E. Aasland. + +.. + +.. bpo: 45438 +.. date: 2021-10-27-10-05-39 +.. nonce: Xz5lGU +.. section: Library + +Fix typing.Signature string representation for generic builtin types. + +.. + +.. bpo: 45613 +.. date: 2021-10-26-14-29-54 +.. nonce: 55Ie3c +.. section: Library + +:mod:`sqlite3` now sets :attr:`sqlite3.threadsafety` based on the default +threading mode the underlying SQLite library has been compiled with. Patch +by Erlend E. Aasland. + +.. + +.. bpo: 45574 +.. date: 2021-10-22-23-06-33 +.. nonce: svqA84 +.. section: Library + +Fix warning about ``print_escape`` being unused. + +.. + +.. bpo: 45581 +.. date: 2021-10-22-21-57-02 +.. nonce: rlH6ay +.. section: Library + +:meth:`sqlite3.connect` now correctly raises :exc:`MemoryError` if the +underlying SQLite API signals memory error. Patch by Erlend E. Aasland. + +.. + +.. bpo: 45557 +.. date: 2021-10-21-16-18-51 +.. nonce: 4MQt4r +.. section: Library + +pprint.pprint() now handles underscore_numbers correctly. Previously it was +always setting it to False. + +.. + +.. bpo: 44019 +.. date: 2021-10-21-10-14-22 +.. nonce: Xk4Ncr +.. section: Library + +Add :func:`operator.call` to ``operator.__all__``. Patch by Kreusada. + +.. + +.. bpo: 42174 +.. date: 2021-10-19-01-30-57 +.. nonce: O2w9bi +.. section: Library + +:meth:`shutil.get_terminal_size` now falls back to sane values if the column +or line count are 0. + +.. + +.. bpo: 35673 +.. date: 2021-10-18-18-12-47 +.. nonce: KOkHWe +.. section: Library + +Improve the introspectability of the ``__loader__`` attribute for namespace +packages. :class:`importlib.machinery.NamespaceLoader` is now public, and +implements the :class:`importlib.abc.InspectLoader` interface. +``_NamespaceLoader`` is kept for backward compatibility. + +.. + +.. bpo: 45515 +.. date: 2021-10-18-14-52-48 +.. nonce: aXdvm_ +.. section: Library + +Add references to :mod:`zoneinfo` in the :mod:`datetime` documentation, +mostly replacing outdated references to ``dateutil.tz``. Change by Paul +Ganssle. + +.. + +.. bpo: 45475 +.. date: 2021-10-18-10-46-47 +.. nonce: sb9KDF +.. section: Library + +Reverted optimization of iterating :class:`gzip.GzipFile`, +:class:`bz2.BZ2File`, and :class:`lzma.LZMAFile` (see bpo-43787) because it +caused regression when user iterate them without having reference of them. +Patch by Inada Naoki. + +.. + +.. bpo: 45489 +.. date: 2021-10-16-23-46-39 +.. nonce: QB0rhG +.. section: Library + +Update :class:`~typing.ForwardRef` to support ``|`` operator. Patch by +Dong-hee Na. + +.. + +.. bpo: 42222 +.. date: 2021-10-15-11-30-11 +.. nonce: hdHyac +.. section: Library + +Removed deprecated support for float arguments in *randrange()*. + +.. + +.. bpo: 45428 +.. date: 2021-10-14-18-04-17 +.. nonce: mM2War +.. section: Library + +Fix a regression in py_compile when reading filenames from standard input. + +.. + +.. bpo: 45467 +.. date: 2021-10-14-13-31-19 +.. nonce: Q7Ma6A +.. section: Library + +Fix incremental decoder and stream reader in the "raw-unicode-escape" codec. +Previously they failed if the escape sequence was split. + +.. + +.. bpo: 45461 +.. date: 2021-10-14-00-19-02 +.. nonce: 4LB_tJ +.. section: Library + +Fix incremental decoder and stream reader in the "unicode-escape" codec. +Previously they failed if the escape sequence was split. + +.. + +.. bpo: 45239 +.. date: 2021-10-13-17-52-48 +.. nonce: 7li1_0 +.. section: Library + +Fixed :func:`email.utils.parsedate_tz` crashing with +:exc:`UnboundLocalError` on certain invalid input instead of returning +``None``. Patch by Ben Hoyt. + +.. + +.. bpo: 45417 +.. date: 2021-10-12-20-35-06 +.. nonce: gQM-O7 +.. section: Library + +Fix quadratic behaviour in the enum module: Creation of enum classes with a +lot of entries was quadratic. + +.. + +.. bpo: 45249 +.. date: 2021-10-10-16-14-33 +.. nonce: xqLliz +.. section: Library + +Fix the behaviour of :func:`traceback.print_exc` when displaying the caret +when the ``end_offset`` in the exception is set to 0. Patch by Pablo Galindo + +.. + +.. bpo: 45416 +.. date: 2021-10-10-09-42-34 +.. nonce: n35O0_ +.. section: Library + +Fix use of :class:`asyncio.Condition` with explicit :class:`asyncio.Lock` +objects, which was a regression due to removal of explicit loop arguments. +Patch by Joongi Kim. + +.. + +.. bpo: 20028 +.. date: 2021-10-10-00-25-36 +.. nonce: bPx4Z8 +.. section: Library + +Empty escapechar/quotechar is not allowed when initializing +:class:`csv.Dialect`. Patch by Vajrasky Kok and Dong-hee Na. + +.. + +.. bpo: 44904 +.. date: 2021-10-09-18-42-27 +.. nonce: RlW5h8 +.. section: Library + +Fix bug in the :mod:`doctest` module that caused it to fail if a docstring +included an example with a ``classmethod`` ``property``. Patch by Alex +Waygood. + +.. + +.. bpo: 45406 +.. date: 2021-10-08-19-24-48 +.. nonce: Qh_Mz4 +.. section: Library + +Make :func:`inspect.getmodule` catch ``FileNotFoundError`` raised by +:'func:`inspect.getabsfile`, and return ``None`` to indicate that the module +could not be determined. + +.. + +.. bpo: 45411 +.. date: 2021-10-08-11-29-29 +.. nonce: 4jR--U +.. section: Library + +Add extensions for files containing subtitles - .srt & .vtt - to the +mimetypes.py module. + +.. + +.. bpo: 10716 +.. date: 2021-10-08-04-11-55 +.. nonce: QSRVK2 +.. section: Library + +Migrated pydoc to HTML5 (without changing the look of it). Side effect is to +update xmlrpc's ``ServerHTMLDoc`` which now uses the CSS too. cgitb now +relies less on pydoc (as it can't use the CSS file). + +.. + +.. bpo: 27580 +.. date: 2021-10-07-21-11-48 +.. nonce: tGcBTH +.. section: Library + +Add support of null characters in :mod:`csv`. + +.. + +.. bpo: 45262 +.. date: 2021-10-07-14-04-10 +.. nonce: HqF71Z +.. section: Library + +Prevent use-after-free in asyncio. Make sure the cached running loop holder +gets cleared on dealloc to prevent use-after-free in get_running_loop + +.. + +.. bpo: 45386 +.. date: 2021-10-07-00-05-05 +.. nonce: q9ORpA +.. section: Library + +Make :mod:`xmlrpc.client` more robust to C runtimes where the underlying C +``strftime`` function results in a ``ValueError`` when testing for year +formatting options. + +.. + +.. bpo: 20028 +.. date: 2021-10-03-21-14-37 +.. nonce: zBA4RK +.. section: Library + +Improve error message of :class:`csv.Dialect` when initializing. Patch by +Vajrasky Kok and Dong-hee Na. + +.. + +.. bpo: 45343 +.. date: 2021-10-01-23-07-02 +.. nonce: ixmctD +.. section: Library + +Update bundled pip to 21.2.4 and setuptools to 58.1.0 + +.. + +.. bpo: 45328 +.. date: 2021-09-30-08-22-44 +.. nonce: 8Z-Q0B +.. section: Library + +Fixed :class:`http.client.HTTPConnection` to work properly in OSs that don't +support the ``TCP_NODELAY`` socket option. + +.. + +.. bpo: 45243 +.. date: 2021-09-20-01-25-09 +.. nonce: 0pJf0U +.. section: Library + +Add :meth:`~sqlite3.Connection.setlimit` and +:meth:`~sqlite3.Connection.getlimit` to :class:`sqlite3.Connection` for +setting and getting SQLite limits by connection basis. Patch by Erlend E. +Aasland. + +.. + +.. bpo: 45320 +.. date: 2021-09-15-10-21-10 +.. nonce: 4qaf5x +.. section: Library + +Removed from the :mod:`inspect` module: + +* the ``getargspec`` function, deprecated since Python 3.0; + use :func:`inspect.signature` or :func:`inspect.getfullargspec` instead. + +* the ``formatargspec`` function, deprecated since Python 3.5; + use the :func:`inspect.signature` function and :class:`Signature` object + directly. + +* the undocumented ``Signature.from_callable`` and ``Signature.from_function`` + functions, deprecated since Python 3.5; use the + :meth:`Signature.from_callable() ` method + instead. + +Patch by Hugo van Kemenade. + +.. + +.. bpo: 45192 +.. date: 2021-09-14-15-52-47 +.. nonce: DjA-BI +.. section: Library + +Fix the ``tempfile._infer_return_type`` function so that the ``dir`` +argument of the :mod:`tempfile` functions accepts an object implementing the +``os.PathLike`` protocol. + +Patch by Kyungmin Lee. + +.. + +.. bpo: 45160 +.. date: 2021-09-11-14-47-05 +.. nonce: VzMXbW +.. section: Library + +When tracing a tkinter variable used by a ttk OptionMenu, callbacks are no +longer made twice. + +.. + +.. bpo: 25625 +.. date: 2021-09-10-12-53-28 +.. nonce: SzcBCw +.. section: Library + +Added non parallel-safe :func:`~contextlib.chdir` context manager to change +the current working directory and then restore it on exit. Simple wrapper +around :func:`~os.chdir`. + +.. + +.. bpo: 24139 +.. date: 2021-08-30-23-10-48 +.. nonce: e38czf +.. section: Library + +Add support for SQLite extended result codes in :exc:`sqlite3.Error`. Patch +by Erlend E. Aasland. + +.. + +.. bpo: 24444 +.. date: 2021-08-30-00-19-23 +.. nonce: Ki4bgz +.. section: Library + +Fixed an error raised in :mod:`argparse` help display when help for an +option is set to 1+ blank spaces or when *choices* arg is an empty +container. + +.. + +.. bpo: 44547 +.. date: 2021-08-20-10-52-40 +.. nonce: eu0iJq +.. section: Library + +Implement ``Fraction.__int__``, so that a :class:`fractions.Fraction` +instance ``f`` passes an ``isinstance(f, typing.SupportsInt)`` check. + +.. + +.. bpo: 40321 +.. date: 2021-07-22-21-25-56 +.. nonce: gBlFmw +.. section: Library + +Adds support for HTTP 308 redirects to :mod:`urllib`. See :rfc:`7538` for +details. Patch by Jochem Schulenklopper. + +.. + +.. bpo: 10572 +.. date: 2021-01-07-01-25-38 +.. nonce: gEEZ9z +.. section: Library + +Move :mod:`sqlite3` tests to ``/Lib/test/test_sqlite3``. Patch by Erlend E. +Aasland. + +.. + +.. bpo: 41374 +.. date: 2020-07-27-19-21-05 +.. nonce: cd-kFL +.. section: Library + +Ensure that ``socket.TCP_*`` constants are exposed on Cygwin 3.1.6 and +greater. + +.. + +.. bpo: 35970 +.. date: 2019-02-11-19-06-10 +.. nonce: ZRvh51 +.. section: Library + +Add help flag to the base64 module's command line interface. Patch +contributed by Robert Kuska. + +.. + +.. bpo: 45726 +.. date: 2021-11-05-12-15-24 +.. nonce: GwRr7e +.. section: Documentation + +Improve documentation for :func:`functools.singledispatch` and +:class:`functools.singledispatchmethod`. + +.. + +.. bpo: 45680 +.. date: 2021-11-03-14-51-03 +.. nonce: 9_NTFU +.. section: Documentation + +Amend the docs on ``GenericAlias`` objects to clarify that non-container +classes can also implement ``__class_getitem__``. Patch contributed by Alex +Waygood. + +.. + +.. bpo: 45618 +.. date: 2021-10-31-20-35-06 +.. nonce: RTcNXF +.. section: Documentation + +Update Sphinx version used to build the documentation to 4.2.0. Patch by +Maciej Olko. + +.. + +.. bpo: 45655 +.. date: 2021-10-28-19-22-55 +.. nonce: aPYGaS +.. section: Documentation + +Add a new "relevant PEPs" section to the top of the documentation for the +``typing`` module. Patch by Alex Waygood. + +.. + +.. bpo: 45604 +.. date: 2021-10-26-10-00-45 +.. nonce: Dm-YhV +.. section: Documentation + +Add ``level`` argument to ``multiprocessing.log_to_stderr`` function docs. + +.. + +.. bpo: 45516 +.. date: 2021-10-22-21-57-42 +.. nonce: 7_RMEX +.. section: Documentation + +Add protocol description to the :class:`importlib.abc.TraversableResources` +documentation. + +.. + +.. bpo: 45464 +.. date: 2021-10-20-16-26-53 +.. nonce: mOISBs +.. section: Documentation + +Mention in the documentation of :ref:`Built-in Exceptions +` that inheriting from multiple exception types in a +single subclass is not recommended due to possible memory layout +incompatibility. + +.. + +.. bpo: 45449 +.. date: 2021-10-19-01-41-40 +.. nonce: fjHZJc +.. section: Documentation + +Add note about :pep:`585` in :mod:`collections.abc`. + +.. + +.. bpo: 45516 +.. date: 2021-10-18-20-12-18 +.. nonce: EJh4K8 +.. section: Documentation + +Add protocol description to the :class:`importlib.abc.Traversable` +documentation. + +.. + +.. bpo: 20692 +.. date: 2021-10-13-00-42-54 +.. nonce: K5rGtP +.. section: Documentation + +Add Programming FAQ entry explaining that int literal attribute access +requires either a space after or parentheses around the literal. + +.. + +.. bpo: 45678 +.. date: 2021-11-04-20-03-32 +.. nonce: 1xNMjN +.. section: Tests + +Add tests for scenarios in which :class:`functools.singledispatchmethod` is +stacked on top of a method that has already been wrapped by two other +decorators. Patch by Alex Waygood. + +.. + +.. bpo: 45578 +.. date: 2021-10-30-19-00-25 +.. nonce: bvu6X2 +.. section: Tests + +Add tests for :func:`dis.distb` + +.. + +.. bpo: 45678 +.. date: 2021-10-30-13-12-20 +.. nonce: bKrYeS +.. section: Tests + +Add tests to ensure that ``functools.singledispatchmethod`` correctly wraps +the attributes of the target function. + +.. + +.. bpo: 45668 +.. date: 2021-10-29-17-18-56 +.. nonce: MfAw4i +.. section: Tests + +PGO tests now pass when Python is built without test extension modules. + +.. + +.. bpo: 45577 +.. date: 2021-10-22-19-44-13 +.. nonce: dSaNvK +.. section: Tests + +Add subtests for all ``pickle`` protocols in ``test_zoneinfo``. + +.. + +.. bpo: 45566 +.. date: 2021-10-22-12-05-21 +.. nonce: 2gQ3ZB +.. section: Tests + +Fix ``test_frozen_pickle`` in ``test_dataclasses`` to check all ``pickle`` +versions. + +.. + +.. bpo: 43592 +.. date: 2021-10-21-17-22-26 +.. nonce: kHRsra +.. section: Tests + +:mod:`test.libregrtest` now raises the soft resource limit for the maximum +number of file descriptors when the default is too low for our test suite as +was often the case on macOS. + +.. + +.. bpo: 39679 +.. date: 2021-10-18-16-18-41 +.. nonce: F18qcE +.. section: Tests + +Add more test cases for `@functools.singledispatchmethod` when combined with +`@classmethod` or `@staticmethod`. + +.. + +.. bpo: 45410 +.. date: 2021-10-08-14-03-20 +.. nonce: Ex9xe2 +.. section: Tests + +When libregrtest spawns a worker process, stderr is now written into stdout +to keep messages order. Use a single pipe for stdout and stderr, rather than +two pipes. Previously, messages were out of order which made analysis of +buildbot logs harder Patch by Victor Stinner. + +.. + +.. bpo: 45402 +.. date: 2021-10-07-13-43-01 +.. nonce: jlQvep +.. section: Tests + +Fix test_tools.test_sundry() when Python is built out of tree: fix how the +freeze_modules.py tool locates the _freeze_module program. Patch by Victor +Stinner. + +.. + +.. bpo: 45403 +.. date: 2021-10-07-13-27-12 +.. nonce: 7QiDvw +.. section: Tests + +Fix test_sys.test_stdlib_dir() when Python is built outside the source tree: +compare normalized paths. Patch by Victor Stinner. + +.. + +.. bpo: 45400 +.. date: 2021-10-07-13-11-45 +.. nonce: h3iT7V +.. section: Tests + +Fix test_name_error_suggestions_do_not_trigger_for_too_many_locals() of +test_exceptions if a directory name contains "a1" (like "Python-3.11.0a1"): +use a stricter regular expression. Patch by Victor Stinner. + +.. + +.. bpo: 43158 +.. date: 2021-11-01-12-51-46 +.. nonce: fghS6w +.. section: Build + +``setup.py`` now uses values from configure script to build the ``_uuid`` +extension module. Configure now detects util-linux's ``libuuid``, too. + +.. + +.. bpo: 45666 +.. date: 2021-10-29-12-54-53 +.. nonce: w2G63u +.. section: Build + +Fix warning of ``swprintf`` and ``%s`` usage in ``_testembed.c`` + +.. + +.. bpo: 45548 +.. date: 2021-10-28-14-47-22 +.. nonce: mdCBxB +.. section: Build + +``Modules/Setup`` and ``Modules/makesetup`` have been improved. The +``Setup`` file now contains working rules for all extensions. Outdated +comments have been removed. Rules defined by ``makesetup`` track +dependencies correctly. + +.. + +.. bpo: 45548 +.. date: 2021-10-24-21-49-49 +.. nonce: UWx0UC +.. section: Build + +The :mod:`math` and :mod:`cmath` implementation now require a C99 compatible +``libm`` and no longer ship with workarounds for missing acosh, asinh, +atanh, expm1, and log1p functions. + +.. + +.. bpo: 45595 +.. date: 2021-10-24-11-02-43 +.. nonce: WI_5YU +.. section: Build + +``setup.py`` and ``makesetup`` now track build dependencies on all Python +header files and module specific header files. + +.. + +.. bpo: 45571 +.. date: 2021-10-22-15-28-29 +.. nonce: yY8NsJ +.. section: Build + +``Modules/Setup`` now use ``PY_CFLAGS_NODIST`` instead of ``PY_CFLAGS`` to +compile shared modules. + +.. + +.. bpo: 45570 +.. date: 2021-10-22-14-45-40 +.. nonce: 61gM2A +.. section: Build + +:mod:`pyexpat` and :mod:`_elementtree` no longer define obsolete macros +``HAVE_EXPAT_CONFIG_H`` and ``USE_PYEXPAT_CAPI``. ``XML_POOR_ENTROPY`` is +now defined in ``expat_config.h``. + +.. + +.. bpo: 43974 +.. date: 2021-10-22-14-00-44 +.. nonce: HHZtbx +.. section: Build + +``setup.py`` no longer defines ``Py_BUILD_CORE_MODULE``. Instead every +module, that uses the internal API, defines the macro. + +.. + +.. bpo: 45548 +.. date: 2021-10-20-17-02-56 +.. nonce: BoggEf +.. section: Build + +Fill in missing entries in Modules/Setup. + +.. + +.. bpo: 45532 +.. date: 2021-10-20-16-07-39 +.. nonce: kyhvis +.. section: Build + +Update :data:`sys.version` to use ``main`` as fallback information. Patch by +Jeong YunWon. + +.. + +.. bpo: 45536 +.. date: 2021-10-20-12-42-39 +.. nonce: oQNYHB +.. section: Build + +The ``configure`` script now checks whether OpenSSL headers and libraries +provide required APIs. Most common APIs are verified. The check detects +outdated or missing OpenSSL. Failures do not stop configure. + +.. + +.. bpo: 45221 +.. date: 2021-10-18-10-25-56 +.. nonce: rnulhf +.. section: Build + +Fixed regression in handling of ``LDFLAGS`` and ``CPPFLAGS`` options where +:meth:`argparse.parse_known_args` could interpret an option as one of the +built-in command line argument, for example ``-h`` for help. + +.. + +.. bpo: 45440 +.. date: 2021-10-12-02-13-08 +.. nonce: -zYgDb +.. section: Build + +Building Python now requires a C99 ```` header file providing the +following functions: ``copysign()``, ``hypot()``, ``isfinite()``, +``isinf()``, ``isnan()``, ``round()``. Patch by Victor Stinner. + +.. + +.. bpo: 45405 +.. date: 2021-10-11-16-27-38 +.. nonce: iSfdW5 +.. section: Build + +Prevent ``internal configure error`` when running ``configure`` with recent +versions of non-Apple clang. Patch by David Bohman. + +.. + +.. bpo: 45433 +.. date: 2021-10-11-16-08-37 +.. nonce: pVDkMV +.. section: Build + +Avoid linking libpython with libcrypt. + +.. + +.. bpo: 43652 +.. date: 2021-11-04-00-41-50 +.. nonce: RnqV7I +.. section: Windows + +Update Tcl/Tk to 8.6.11, actually this time. The previous update incorrectly +included 8.6.10. + +.. + +.. bpo: 45337 +.. date: 2021-09-30-23-17-27 +.. nonce: qg7U_h +.. section: Windows + +venv now warns when the created environment may need to be accessed at a +different path, due to redirections, links or junctions. It also now +correctly installs or upgrades components when the alternate path is +required. + +.. + +.. bpo: 43851 +.. date: 2021-04-15-01-23-10 +.. nonce: qgU0gy +.. section: Windows + +Build SQLite ``SQLITE_OMIT_AUTOINIT`` on Windows. Patch by Erlend E. +Aasland. + +.. + +.. bpo: 44828 +.. date: 2021-10-25-02-02-21 +.. nonce: XBdXlJ +.. section: macOS + +Avoid tkinter file dialog failure on macOS 12 Monterey when using the Tk +8.6.11 provided by python.org macOS installers. Patch by Marc Culler of the +Tk project. + +.. + +.. bpo: 45495 +.. date: 2021-10-16-17-20-32 +.. nonce: ST8RFt +.. section: IDLE + +Add context keywords 'case' and 'match' to completions list. + +.. + +.. bpo: 29103 +.. date: 2021-10-20-18-41-17 +.. nonce: CMRLyq +.. section: C API + +:c:func:`PyType_FromSpec* ` now copies the class +name from the spec to a buffer owned by the class, so the original can be +safely deallocated. Patch by Petr Viktorin. + +.. + +.. bpo: 45522 +.. date: 2021-10-19-13-07-46 +.. nonce: kGAwmZ +.. section: C API + +The internal freelists for frame, float, list, dict, async generators, and +context objects can now be disabled. + +.. + +.. bpo: 35134 +.. date: 2021-10-19-00-20-40 +.. nonce: Z0Zk_m +.. section: C API + +Exclude :c:func:`PyWeakref_GET_OBJECT` from the limited C API. It never +worked since the :c:type:`PyWeakReference` structure is opaque in the +limited C API. + +.. + +.. bpo: 35081 +.. date: 2021-10-15-09-29-59 +.. nonce: 2teFD3 +.. section: C API + +Move the ``interpreteridobject.h`` header file from ``Include/`` to +``Include/internal/``. It only provides private functions. Patch by Victor +Stinner. + +.. + +.. bpo: 35134 +.. date: 2021-10-15-00-11-51 +.. nonce: eX4zqy +.. section: C API + +The non-limited API files ``cellobject.h``, ``classobject.h``, +``context.h``, ``funcobject.h``, ``genobject.h`` and ``longintrepr.h`` have +been moved to the ``Include/cpython`` directory. Moreover, the ``eval.h`` +header file was removed. These files must not be included directly, as they +are already included in ``Python.h``: :ref:`Include Files `. +If they have been included directly, consider including ``Python.h`` +instead. Patch by Victor Stinner. + +.. + +.. bpo: 45474 +.. date: 2021-10-14-22-16-56 +.. nonce: 1OkJQh +.. section: C API + +The following items are no longer available when ``Py_LIMITED_API`` is +defined: + +* :c:func:`PyMarshal_WriteLongToFile` +* :c:func:`PyMarshal_WriteObjectToFile` +* :c:func:`PyMarshal_ReadObjectFromString` +* :c:func:`PyMarshal_WriteObjectToString` +* the ``Py_MARSHAL_VERSION`` macro + +These are not part of the :ref:`limited API `. + +Patch by Victor Stinner. + +.. + +.. bpo: 45434 +.. date: 2021-10-13-14-42-46 +.. nonce: INNEEt +.. section: C API + +Remove the ``pystrhex.h`` header file. It only contains private functions. C +extensions should only include the main ```` header file. Patch by +Victor Stinner. + +.. + +.. bpo: 45440 +.. date: 2021-10-12-02-13-41 +.. nonce: Gf94rE +.. section: C API + +Remove the ``Py_FORCE_DOUBLE()`` macro. It was used by the +``Py_IS_INFINITY()`` macro. Patch by Victor Stinner. + +.. + +.. bpo: 45434 +.. date: 2021-10-11-23-03-49 +.. nonce: tsS8I_ +.. section: C API + +```` no longer includes the header files ````, +````, ```` and ```` when the ``Py_LIMITED_API`` +macro is set to ``0x030b0000`` (Python 3.11) or higher. C extensions should +explicitly include the header files after ``#include ``. Patch by +Victor Stinner. + +.. + +.. bpo: 41123 +.. date: 2021-10-11-22-58-33 +.. nonce: myrlIp +.. section: C API + +Remove ``Py_UNICODE_COPY()`` and ``Py_UNICODE_FILL()`` macros, deprecated +since Python 3.3. Use ``PyUnicode_CopyCharacters()`` or ``memcpy()`` +(``wchar_t*`` string), and ``PyUnicode_Fill()`` functions instead. Patch by +Victor Stinner. + +.. + +.. bpo: 45412 +.. date: 2021-10-08-15-54-07 +.. nonce: KHyJCT +.. section: C API + +Remove the following math macros using the ``errno`` variable: + +* ``Py_ADJUST_ERANGE1()`` +* ``Py_ADJUST_ERANGE2()`` +* ``Py_OVERFLOWED()`` +* ``Py_SET_ERANGE_IF_OVERFLOW()`` +* ``Py_SET_ERRNO_ON_MATH_ERROR()`` + +Patch by Victor Stinner. + +.. + +.. bpo: 45395 +.. date: 2021-10-06-15-54-40 +.. nonce: yVhdAl +.. section: C API + +Custom frozen modules (the array set to ``PyImport_FrozenModules``) are now +treated as additions, rather than replacing all the default frozen modules. +Frozen stdlib modules can still be disabled by setting the "code" field of +the custom array entry to NULL. + +.. + +.. bpo: 43760 +.. date: 2021-09-24-11-12-21 +.. nonce: Bfxd1- +.. section: C API + +Add new :c:func:`PyThreadState_EnterTracing`, and +:c:func:`PyThreadState_LeaveTracing` functions to the limited C API to +suspend and resume tracing and profiling. Patch by Victor Stinner. + +.. + +.. bpo: 44220 +.. date: 2021-05-24-22-12-40 +.. nonce: H9CUGl +.. section: C API + +:c:var:`PyStructSequence_UnnamedField` is added to the Stable ABI. diff --git a/Misc/NEWS.d/next/Build/2021-10-11-16-08-37.bpo-45433.pVDkMV.rst b/Misc/NEWS.d/next/Build/2021-10-11-16-08-37.bpo-45433.pVDkMV.rst deleted file mode 100644 index 27869f08fbb9b..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-10-11-16-08-37.bpo-45433.pVDkMV.rst +++ /dev/null @@ -1 +0,0 @@ -Avoid linking libpython with libcrypt. diff --git a/Misc/NEWS.d/next/Build/2021-10-11-16-27-38.bpo-45405.iSfdW5.rst b/Misc/NEWS.d/next/Build/2021-10-11-16-27-38.bpo-45405.iSfdW5.rst deleted file mode 100644 index a2dc5bcc32217..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-10-11-16-27-38.bpo-45405.iSfdW5.rst +++ /dev/null @@ -1,2 +0,0 @@ -Prevent ``internal configure error`` when running ``configure`` -with recent versions of non-Apple clang. Patch by David Bohman. diff --git a/Misc/NEWS.d/next/Build/2021-10-12-02-13-08.bpo-45440.-zYgDb.rst b/Misc/NEWS.d/next/Build/2021-10-12-02-13-08.bpo-45440.-zYgDb.rst deleted file mode 100644 index 93f7f3139065f..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-10-12-02-13-08.bpo-45440.-zYgDb.rst +++ /dev/null @@ -1,4 +0,0 @@ -Building Python now requires a C99 ```` header file providing -the following functions: ``copysign()``, ``hypot()``, ``isfinite()``, -``isinf()``, ``isnan()``, ``round()``. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Build/2021-10-18-10-25-56.bpo-45221.rnulhf.rst b/Misc/NEWS.d/next/Build/2021-10-18-10-25-56.bpo-45221.rnulhf.rst deleted file mode 100644 index cb981d96f3047..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-10-18-10-25-56.bpo-45221.rnulhf.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixed regression in handling of ``LDFLAGS`` and ``CPPFLAGS`` options -where :meth:`argparse.parse_known_args` could interpret an option as -one of the built-in command line argument, for example ``-h`` for help. diff --git a/Misc/NEWS.d/next/Build/2021-10-20-12-42-39.bpo-45536.oQNYHB.rst b/Misc/NEWS.d/next/Build/2021-10-20-12-42-39.bpo-45536.oQNYHB.rst deleted file mode 100644 index e560b71ede2d2..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-10-20-12-42-39.bpo-45536.oQNYHB.rst +++ /dev/null @@ -1,3 +0,0 @@ -The ``configure`` script now checks whether OpenSSL headers and libraries -provide required APIs. Most common APIs are verified. The check detects -outdated or missing OpenSSL. Failures do not stop configure. diff --git a/Misc/NEWS.d/next/Build/2021-10-20-16-07-39.bpo-45532.kyhvis.rst b/Misc/NEWS.d/next/Build/2021-10-20-16-07-39.bpo-45532.kyhvis.rst deleted file mode 100644 index 575e2fb9ae93b..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-10-20-16-07-39.bpo-45532.kyhvis.rst +++ /dev/null @@ -1,2 +0,0 @@ -Update :data:`sys.version` to use ``main`` as fallback information. -Patch by Jeong YunWon. diff --git a/Misc/NEWS.d/next/Build/2021-10-20-17-02-56.bpo-45548.BoggEf.rst b/Misc/NEWS.d/next/Build/2021-10-20-17-02-56.bpo-45548.BoggEf.rst deleted file mode 100644 index a52afa21698f9..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-10-20-17-02-56.bpo-45548.BoggEf.rst +++ /dev/null @@ -1 +0,0 @@ -Fill in missing entries in Modules/Setup. diff --git a/Misc/NEWS.d/next/Build/2021-10-22-14-00-44.bpo-43974.HHZtbx.rst b/Misc/NEWS.d/next/Build/2021-10-22-14-00-44.bpo-43974.HHZtbx.rst deleted file mode 100644 index 728a095dc03af..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-10-22-14-00-44.bpo-43974.HHZtbx.rst +++ /dev/null @@ -1,2 +0,0 @@ -``setup.py`` no longer defines ``Py_BUILD_CORE_MODULE``. Instead every -module, that uses the internal API, defines the macro. diff --git a/Misc/NEWS.d/next/Build/2021-10-22-14-45-40.bpo-45570.61gM2A.rst b/Misc/NEWS.d/next/Build/2021-10-22-14-45-40.bpo-45570.61gM2A.rst deleted file mode 100644 index 7de50f911bf0d..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-10-22-14-45-40.bpo-45570.61gM2A.rst +++ /dev/null @@ -1 +0,0 @@ -:mod:`pyexpat` and :mod:`_elementtree` no longer define obsolete macros ``HAVE_EXPAT_CONFIG_H`` and ``USE_PYEXPAT_CAPI``. ``XML_POOR_ENTROPY`` is now defined in ``expat_config.h``. diff --git a/Misc/NEWS.d/next/Build/2021-10-22-15-28-29.bpo-45571.yY8NsJ.rst b/Misc/NEWS.d/next/Build/2021-10-22-15-28-29.bpo-45571.yY8NsJ.rst deleted file mode 100644 index f2042d11e24b7..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-10-22-15-28-29.bpo-45571.yY8NsJ.rst +++ /dev/null @@ -1,2 +0,0 @@ -``Modules/Setup`` now use ``PY_CFLAGS_NODIST`` instead of ``PY_CFLAGS`` to -compile shared modules. diff --git a/Misc/NEWS.d/next/Build/2021-10-24-11-02-43.bpo-45595.WI_5YU.rst b/Misc/NEWS.d/next/Build/2021-10-24-11-02-43.bpo-45595.WI_5YU.rst deleted file mode 100644 index bb09d6ead08d4..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-10-24-11-02-43.bpo-45595.WI_5YU.rst +++ /dev/null @@ -1,2 +0,0 @@ -``setup.py`` and ``makesetup`` now track build dependencies on all Python -header files and module specific header files. diff --git a/Misc/NEWS.d/next/Build/2021-10-24-21-49-49.bpo-45548.UWx0UC.rst b/Misc/NEWS.d/next/Build/2021-10-24-21-49-49.bpo-45548.UWx0UC.rst deleted file mode 100644 index 15fd56615ffa9..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-10-24-21-49-49.bpo-45548.UWx0UC.rst +++ /dev/null @@ -1,3 +0,0 @@ -The :mod:`math` and :mod:`cmath` implementation now require a C99 compatible -``libm`` and no longer ship with workarounds for missing acosh, asinh, atanh, -expm1, and log1p functions. diff --git a/Misc/NEWS.d/next/Build/2021-10-28-14-47-22.bpo-45548.mdCBxB.rst b/Misc/NEWS.d/next/Build/2021-10-28-14-47-22.bpo-45548.mdCBxB.rst deleted file mode 100644 index e6ccd52274de5..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-10-28-14-47-22.bpo-45548.mdCBxB.rst +++ /dev/null @@ -1,4 +0,0 @@ -``Modules/Setup`` and ``Modules/makesetup`` have been improved. The -``Setup`` file now contains working rules for all extensions. Outdated -comments have been removed. Rules defined by ``makesetup`` track -dependencies correctly. diff --git a/Misc/NEWS.d/next/Build/2021-10-29-12-54-53.bpo-45666.w2G63u.rst b/Misc/NEWS.d/next/Build/2021-10-29-12-54-53.bpo-45666.w2G63u.rst deleted file mode 100644 index 8a3e6feded856..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-10-29-12-54-53.bpo-45666.w2G63u.rst +++ /dev/null @@ -1 +0,0 @@ -Fix warning of ``swprintf`` and ``%s`` usage in ``_testembed.c`` diff --git a/Misc/NEWS.d/next/Build/2021-11-01-12-51-46.bpo-43158.fghS6w.rst b/Misc/NEWS.d/next/Build/2021-11-01-12-51-46.bpo-43158.fghS6w.rst deleted file mode 100644 index 3b1de478e7fd4..0000000000000 --- a/Misc/NEWS.d/next/Build/2021-11-01-12-51-46.bpo-43158.fghS6w.rst +++ /dev/null @@ -1,2 +0,0 @@ -``setup.py`` now uses values from configure script to build the ``_uuid`` -extension module. Configure now detects util-linux's ``libuuid``, too. diff --git a/Misc/NEWS.d/next/C API/2021-05-24-22-12-40.bpo-44220.H9CUGl.rst b/Misc/NEWS.d/next/C API/2021-05-24-22-12-40.bpo-44220.H9CUGl.rst deleted file mode 100644 index 79ba8aa07cde6..0000000000000 --- a/Misc/NEWS.d/next/C API/2021-05-24-22-12-40.bpo-44220.H9CUGl.rst +++ /dev/null @@ -1 +0,0 @@ -:c:var:`PyStructSequence_UnnamedField` is added to the Stable ABI. diff --git a/Misc/NEWS.d/next/C API/2021-09-24-11-12-21.bpo-43760.Bfxd1-.rst b/Misc/NEWS.d/next/C API/2021-09-24-11-12-21.bpo-43760.Bfxd1-.rst deleted file mode 100644 index 16bea5ff8f57c..0000000000000 --- a/Misc/NEWS.d/next/C API/2021-09-24-11-12-21.bpo-43760.Bfxd1-.rst +++ /dev/null @@ -1,4 +0,0 @@ -Add new :c:func:`PyThreadState_EnterTracing`, and -:c:func:`PyThreadState_LeaveTracing` functions to the limited C API to suspend -and resume tracing and profiling. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2021-10-06-15-54-40.bpo-45395.yVhdAl.rst b/Misc/NEWS.d/next/C API/2021-10-06-15-54-40.bpo-45395.yVhdAl.rst deleted file mode 100644 index 8996513dc9fb0..0000000000000 --- a/Misc/NEWS.d/next/C API/2021-10-06-15-54-40.bpo-45395.yVhdAl.rst +++ /dev/null @@ -1,4 +0,0 @@ -Custom frozen modules (the array set to ``PyImport_FrozenModules``) are now -treated as additions, rather than replacing all the default frozen modules. -Frozen stdlib modules can still be disabled by setting the "code" field of -the custom array entry to NULL. diff --git a/Misc/NEWS.d/next/C API/2021-10-08-15-54-07.bpo-45412.KHyJCT.rst b/Misc/NEWS.d/next/C API/2021-10-08-15-54-07.bpo-45412.KHyJCT.rst deleted file mode 100644 index 49746810ee5b9..0000000000000 --- a/Misc/NEWS.d/next/C API/2021-10-08-15-54-07.bpo-45412.KHyJCT.rst +++ /dev/null @@ -1,9 +0,0 @@ -Remove the following math macros using the ``errno`` variable: - -* ``Py_ADJUST_ERANGE1()`` -* ``Py_ADJUST_ERANGE2()`` -* ``Py_OVERFLOWED()`` -* ``Py_SET_ERANGE_IF_OVERFLOW()`` -* ``Py_SET_ERRNO_ON_MATH_ERROR()`` - -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2021-10-11-22-58-33.bpo-41123.myrlIp.rst b/Misc/NEWS.d/next/C API/2021-10-11-22-58-33.bpo-41123.myrlIp.rst deleted file mode 100644 index 3ae302bcea245..0000000000000 --- a/Misc/NEWS.d/next/C API/2021-10-11-22-58-33.bpo-41123.myrlIp.rst +++ /dev/null @@ -1,4 +0,0 @@ -Remove ``Py_UNICODE_COPY()`` and ``Py_UNICODE_FILL()`` macros, deprecated -since Python 3.3. Use ``PyUnicode_CopyCharacters()`` or ``memcpy()`` -(``wchar_t*`` string), and ``PyUnicode_Fill()`` functions instead. Patch by -Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2021-10-11-23-03-49.bpo-45434.tsS8I_.rst b/Misc/NEWS.d/next/C API/2021-10-11-23-03-49.bpo-45434.tsS8I_.rst deleted file mode 100644 index 627f687272f5a..0000000000000 --- a/Misc/NEWS.d/next/C API/2021-10-11-23-03-49.bpo-45434.tsS8I_.rst +++ /dev/null @@ -1,5 +0,0 @@ -```` no longer includes the header files ````, -````, ```` and ```` when the ``Py_LIMITED_API`` -macro is set to ``0x030b0000`` (Python 3.11) or higher. C extensions should -explicitly include the header files after ``#include ``. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2021-10-12-02-13-41.bpo-45440.Gf94rE.rst b/Misc/NEWS.d/next/C API/2021-10-12-02-13-41.bpo-45440.Gf94rE.rst deleted file mode 100644 index d9d695fd2ace4..0000000000000 --- a/Misc/NEWS.d/next/C API/2021-10-12-02-13-41.bpo-45440.Gf94rE.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove the ``Py_FORCE_DOUBLE()`` macro. It was used by the ``Py_IS_INFINITY()`` -macro. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2021-10-13-14-42-46.bpo-45434.INNEEt.rst b/Misc/NEWS.d/next/C API/2021-10-13-14-42-46.bpo-45434.INNEEt.rst deleted file mode 100644 index 933f80670f1ae..0000000000000 --- a/Misc/NEWS.d/next/C API/2021-10-13-14-42-46.bpo-45434.INNEEt.rst +++ /dev/null @@ -1,3 +0,0 @@ -Remove the ``pystrhex.h`` header file. It only contains private functions. C -extensions should only include the main ```` header file. Patch by -Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2021-10-14-22-16-56.bpo-45474.1OkJQh.rst b/Misc/NEWS.d/next/C API/2021-10-14-22-16-56.bpo-45474.1OkJQh.rst deleted file mode 100644 index d41f1b72b8966..0000000000000 --- a/Misc/NEWS.d/next/C API/2021-10-14-22-16-56.bpo-45474.1OkJQh.rst +++ /dev/null @@ -1,11 +0,0 @@ -The following items are no longer available when ``Py_LIMITED_API`` is defined: - -* :c:func:`PyMarshal_WriteLongToFile` -* :c:func:`PyMarshal_WriteObjectToFile` -* :c:func:`PyMarshal_ReadObjectFromString` -* :c:func:`PyMarshal_WriteObjectToString` -* the ``Py_MARSHAL_VERSION`` macro - -These are not part of the :ref:`limited API `. - -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2021-10-15-00-11-51.bpo-35134.eX4zqy.rst b/Misc/NEWS.d/next/C API/2021-10-15-00-11-51.bpo-35134.eX4zqy.rst deleted file mode 100644 index d0d3ce6b34f6f..0000000000000 --- a/Misc/NEWS.d/next/C API/2021-10-15-00-11-51.bpo-35134.eX4zqy.rst +++ /dev/null @@ -1,7 +0,0 @@ -The non-limited API files ``cellobject.h``, ``classobject.h``, ``context.h``, -``funcobject.h``, ``genobject.h`` and ``longintrepr.h`` have been moved to -the ``Include/cpython`` directory. Moreover, the ``eval.h`` header file was -removed. These files must not be included directly, as they are already -included in ``Python.h``: :ref:`Include Files `. If they have -been included directly, consider including ``Python.h`` instead. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2021-10-15-09-29-59.bpo-35081.2teFD3.rst b/Misc/NEWS.d/next/C API/2021-10-15-09-29-59.bpo-35081.2teFD3.rst deleted file mode 100644 index 79d4a9b9180d9..0000000000000 --- a/Misc/NEWS.d/next/C API/2021-10-15-09-29-59.bpo-35081.2teFD3.rst +++ /dev/null @@ -1,3 +0,0 @@ -Move the ``interpreteridobject.h`` header file from ``Include/`` to -``Include/internal/``. It only provides private functions. Patch by Victor -Stinner. diff --git a/Misc/NEWS.d/next/C API/2021-10-19-00-20-40.bpo-35134.Z0Zk_m.rst b/Misc/NEWS.d/next/C API/2021-10-19-00-20-40.bpo-35134.Z0Zk_m.rst deleted file mode 100644 index 57c4fa53bee66..0000000000000 --- a/Misc/NEWS.d/next/C API/2021-10-19-00-20-40.bpo-35134.Z0Zk_m.rst +++ /dev/null @@ -1,3 +0,0 @@ -Exclude :c:func:`PyWeakref_GET_OBJECT` from the limited C API. It never -worked since the :c:type:`PyWeakReference` structure is opaque in the -limited C API. diff --git a/Misc/NEWS.d/next/C API/2021-10-19-13-07-46.bpo-45522.kGAwmZ.rst b/Misc/NEWS.d/next/C API/2021-10-19-13-07-46.bpo-45522.kGAwmZ.rst deleted file mode 100644 index 658261f8ce693..0000000000000 --- a/Misc/NEWS.d/next/C API/2021-10-19-13-07-46.bpo-45522.kGAwmZ.rst +++ /dev/null @@ -1,2 +0,0 @@ -The internal freelists for frame, float, list, dict, async generators, and -context objects can now be disabled. diff --git a/Misc/NEWS.d/next/C API/2021-10-20-18-41-17.bpo-29103.CMRLyq.rst b/Misc/NEWS.d/next/C API/2021-10-20-18-41-17.bpo-29103.CMRLyq.rst deleted file mode 100644 index e923bfd3ae293..0000000000000 --- a/Misc/NEWS.d/next/C API/2021-10-20-18-41-17.bpo-29103.CMRLyq.rst +++ /dev/null @@ -1,3 +0,0 @@ -:c:func:`PyType_FromSpec* ` now copies the class name -from the spec to a buffer owned by the class, so the original can be safely -deallocated. Patch by Petr Viktorin. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-03-02-44-15.bpo-43706.jjsXlT.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-03-02-44-15.bpo-43706.jjsXlT.rst deleted file mode 100644 index ee859e37911cd..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-03-02-44-15.bpo-43706.jjsXlT.rst +++ /dev/null @@ -1,2 +0,0 @@ -Speed up calls to ``enumerate()`` by using the :pep:`590` ``vectorcall`` -calling convention. Patch by Dong-hee Na. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-06-26-16-55-08.bpo-44511.k8sMvV.rst b/Misc/NEWS.d/next/Core and Builtins/2021-06-26-16-55-08.bpo-44511.k8sMvV.rst deleted file mode 100644 index 352e046126c99..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-06-26-16-55-08.bpo-44511.k8sMvV.rst +++ /dev/null @@ -1 +0,0 @@ -Improve the generated bytecode for class and mapping patterns. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-06-28-22-23-59.bpo-44525.sSvUKG.rst b/Misc/NEWS.d/next/Core and Builtins/2021-06-28-22-23-59.bpo-44525.sSvUKG.rst deleted file mode 100644 index 8963d028cf8a9..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-06-28-22-23-59.bpo-44525.sSvUKG.rst +++ /dev/null @@ -1,10 +0,0 @@ -Setup initial specialization infrastructure for the ``CALL_FUNCTION`` opcode. -Implemented initial specializations for C function calls: - -* ``CALL_FUNCTION_BUILTIN_O`` for ``METH_O`` flag. - -* ``CALL_FUNCTION_BUILTIN_FAST`` for ``METH_FASTCALL`` flag without keywords. - -* ``CALL_FUNCTION_LEN`` for ``len(o)``. - -* ``CALL_FUNCTION_ISINSTANCE`` for ``isinstance(o, t)``. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-08-00-30-09.bpo-44050.mFI15u.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-08-00-30-09.bpo-44050.mFI15u.rst deleted file mode 100644 index d6eed9f1bcfe9..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-09-08-00-30-09.bpo-44050.mFI15u.rst +++ /dev/null @@ -1,3 +0,0 @@ -Extensions that indicate they use global state (by setting ``m_size`` to -1) -can again be used in multiple interpreters. This reverts to behavior of -Python 3.8. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-23-14-00-05.bpo-40116.KaoeFs.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-23-14-00-05.bpo-40116.KaoeFs.rst deleted file mode 100644 index 24ce96376d87e..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-09-23-14-00-05.bpo-40116.KaoeFs.rst +++ /dev/null @@ -1,4 +0,0 @@ -Change to the implementation of split dictionaries. Classes where the -instances differ either in the exact set of attributes, or in the order in -which those attributes are set, can still share keys. This should have no -observable effect on users of Python or the C-API. Patch by Mark Shannon. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-26-18-18-50.bpo-45292.aX5HVr.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-26-18-18-50.bpo-45292.aX5HVr.rst deleted file mode 100644 index 55ca14f2259f0..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-09-26-18-18-50.bpo-45292.aX5HVr.rst +++ /dev/null @@ -1 +0,0 @@ -Implement :pep:`654`. Add :class:`ExceptionGroup` and :class:`BaseExceptionGroup`. Update traceback display code. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-29-12-02-39.bpo-45324.BTQElX.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-29-12-02-39.bpo-45324.BTQElX.rst deleted file mode 100644 index 7b16847bb7339..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-09-29-12-02-39.bpo-45324.BTQElX.rst +++ /dev/null @@ -1,3 +0,0 @@ -In FrozenImporter.find_spec(), we now preserve the information needed in -exec_module() to load the module. This change mostly impacts internal -details, rather than changing the importer's behavior. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-01-09-06-54.bpo-45020.Cj5VQN.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-01-09-06-54.bpo-45020.Cj5VQN.rst deleted file mode 100644 index 839604357d121..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-10-01-09-06-54.bpo-45020.Cj5VQN.rst +++ /dev/null @@ -1,5 +0,0 @@ -For frozen stdlib modules, record the original module name as -``module.__spec__.loader_state.origname``. If the value is different than -``module.__spec__.name`` then the module was defined as an alias in -Tools/scripts/freeze_modules.py. If it is ``None`` then the module comes -from a source file outside the stdlib. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-01-09-21-02.bpo-21736.RI47BU.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-01-09-21-02.bpo-21736.RI47BU.rst deleted file mode 100644 index 8396a49c3cf73..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-10-01-09-21-02.bpo-21736.RI47BU.rst +++ /dev/null @@ -1,9 +0,0 @@ -Frozen stdlib modules now have ``__file__`` to the .py file they would -otherwise be loaded from, if possible. For packages, ``__path__`` now has -the correct entry instead of being an empty list, which allows unfrozen -submodules to be imported. These are set only if the stdlib directory is -known when the runtime is initialized. Note that the file at ``__file__`` -is not guaranteed to exist. None of this affects non-stdlib frozen modules -nor, for now, frozen modules imported using -``PyImport_ImportFrozenModule()``. Also, at the moment ``co_filename`` is -not updated for the module. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-05-03-49-07.bpo-45367._astoU.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-05-03-49-07.bpo-45367._astoU.rst deleted file mode 100644 index aae518da1e86f..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-10-05-03-49-07.bpo-45367._astoU.rst +++ /dev/null @@ -1 +0,0 @@ -Specialized the ``BINARY_MULTIPLY`` opcode to ``BINARY_MULTIPLY_INT`` and ``BINARY_MULTIPLY_FLOAT`` using the PEP 659 machinery. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-06-21-20-11.bpo-45385.CTUT8s.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-06-21-20-11.bpo-45385.CTUT8s.rst deleted file mode 100644 index 8047c102634f0..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-10-06-21-20-11.bpo-45385.CTUT8s.rst +++ /dev/null @@ -1 +0,0 @@ -Fix reference leak from descr_check. Patch by Dong-hee Na. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-07-19-09-12.bpo-29410.bg5SYp.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-07-19-09-12.bpo-29410.bg5SYp.rst deleted file mode 100644 index b08999e78d84a..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-10-07-19-09-12.bpo-29410.bg5SYp.rst +++ /dev/null @@ -1 +0,0 @@ -Add SipHash13 for string hash algorithm and use it by default. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-07-21-26-44.bpo-45408.qUqzcd.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-07-21-26-44.bpo-45408.qUqzcd.rst deleted file mode 100644 index e4d4db9cb9536..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-10-07-21-26-44.bpo-45408.qUqzcd.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a crash in the parser when reporting tokenizer errors that occur at the -same time unclosed parentheses are detected. Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-08-09-47-38.bpo-45340.ukHgDb.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-08-09-47-38.bpo-45340.ukHgDb.rst deleted file mode 100644 index 7760773d4fb20..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-10-08-09-47-38.bpo-45340.ukHgDb.rst +++ /dev/null @@ -1,3 +0,0 @@ -Object attributes are held in an array instead of a dictionary. An object's -dictionary are created lazily, only when needed. Reduces the memory -consumption of a typical Python object by about 30%. Patch by Mark Shannon. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-12-14-41-39.bpo-45445._F5cMf.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-12-14-41-39.bpo-45445._F5cMf.rst deleted file mode 100644 index d497ae26bd577..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-10-12-14-41-39.bpo-45445._F5cMf.rst +++ /dev/null @@ -1,2 +0,0 @@ -Python now fails to initialize if it finds an invalid :option:`-X` option in the -command line. Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-16-17-27-48.bpo-45494.vMt1g4.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-16-17-27-48.bpo-45494.vMt1g4.rst deleted file mode 100644 index 97e29813ab266..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-10-16-17-27-48.bpo-45494.vMt1g4.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix parser crash when reporting errors involving invalid continuation -characters. Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-18-22-40-33.bpo-45521.GdMiuW.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-18-22-40-33.bpo-45521.GdMiuW.rst deleted file mode 100644 index 3a082a4ffdbcb..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-10-18-22-40-33.bpo-45521.GdMiuW.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix a bug in the obmalloc radix tree code. On 64-bit machines, the bug -causes the tree to hold 46-bits of virtual addresses, rather than the -intended 48-bits. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-19-01-04-08.bpo-30570._G30Ms.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-19-01-04-08.bpo-30570._G30Ms.rst deleted file mode 100644 index d9ab60cd08f56..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-10-19-01-04-08.bpo-30570._G30Ms.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a crash in ``issubclass()`` from infinite recursion when searching pathological ``__bases__`` tuples. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-19-10-29-47.bpo-45526.WQnvW9.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-19-10-29-47.bpo-45526.WQnvW9.rst deleted file mode 100644 index c35e5f58a4113..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-10-19-10-29-47.bpo-45526.WQnvW9.rst +++ /dev/null @@ -1,3 +0,0 @@ -In obmalloc, set ADDRESS_BITS to not ignore any bits (ignored 16 before). That is -safer in the case that the kernel gives user-space virtual addresses that span -a range greater than 48 bits. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-20-01-28-26.bpo-45530.5r7n4m.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-20-01-28-26.bpo-45530.5r7n4m.rst deleted file mode 100644 index a8b155e7ccfcd..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-10-20-01-28-26.bpo-45530.5r7n4m.rst +++ /dev/null @@ -1,8 +0,0 @@ -Cases of sorting using tuples as keys may now be significantly faster -in some cases. Patch by Tim Peters. - -The order of the result may differ from earlier releases if the tuple -elements don't define a total ordering (see -:ref:`expressions-value-comparisons` for information on -total ordering). It's generally true that the result of sorting simply -isn't well-defined in the absence of a total ordering on list elements. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-20-11-57-31.bpo-44525.veL4lJ.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-20-11-57-31.bpo-44525.veL4lJ.rst deleted file mode 100644 index 6ab1d05603db8..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-10-20-11-57-31.bpo-44525.veL4lJ.rst +++ /dev/null @@ -1 +0,0 @@ -Specialize simple calls to Python functions (no starargs, keyowrd dict, or closure) diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-23-13-49-00.bpo-45379.ZF7G3n.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-23-13-49-00.bpo-45379.ZF7G3n.rst deleted file mode 100644 index f8e2e50dfc3e2..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-10-23-13-49-00.bpo-45379.ZF7G3n.rst +++ /dev/null @@ -1,2 +0,0 @@ -Clarify :exc:`ImportError` message when we try to explicitly import a -frozen module but frozen modules are disabled. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-02-09-27-46.bpo-45688.v5Der1.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-02-09-27-46.bpo-45688.v5Der1.rst deleted file mode 100644 index afd73a1266279..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-11-02-09-27-46.bpo-45688.v5Der1.rst +++ /dev/null @@ -1,2 +0,0 @@ -:data:`sys.stdlib_module_names` now contains the macOS-specific module -:mod:`_scproxy`. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-04-20-19-07.bpo-45716.5C0pA1.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-04-20-19-07.bpo-45716.5C0pA1.rst deleted file mode 100644 index 682900c295416..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-11-04-20-19-07.bpo-45716.5C0pA1.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve the :exc:`SyntaxError` message when using ``True``, ``None`` or -``False`` as keywords in a function call. Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Documentation/2021-10-13-00-42-54.bpo-20692.K5rGtP.rst b/Misc/NEWS.d/next/Documentation/2021-10-13-00-42-54.bpo-20692.K5rGtP.rst deleted file mode 100644 index 44ae468d1bccf..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-10-13-00-42-54.bpo-20692.K5rGtP.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add Programming FAQ entry explaining that int literal attribute access -requires either a space after or parentheses around the literal. diff --git a/Misc/NEWS.d/next/Documentation/2021-10-18-20-12-18.bpo-45516.EJh4K8.rst b/Misc/NEWS.d/next/Documentation/2021-10-18-20-12-18.bpo-45516.EJh4K8.rst deleted file mode 100644 index 98f5d3432db05..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-10-18-20-12-18.bpo-45516.EJh4K8.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add protocol description to the :class:`importlib.abc.Traversable` -documentation. diff --git a/Misc/NEWS.d/next/Documentation/2021-10-19-01-41-40.bpo-45449.fjHZJc.rst b/Misc/NEWS.d/next/Documentation/2021-10-19-01-41-40.bpo-45449.fjHZJc.rst deleted file mode 100644 index fb817757a1487..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-10-19-01-41-40.bpo-45449.fjHZJc.rst +++ /dev/null @@ -1 +0,0 @@ -Add note about :pep:`585` in :mod:`collections.abc`. diff --git a/Misc/NEWS.d/next/Documentation/2021-10-20-16-26-53.bpo-45464.mOISBs.rst b/Misc/NEWS.d/next/Documentation/2021-10-20-16-26-53.bpo-45464.mOISBs.rst deleted file mode 100644 index 1721aa2c2dfc4..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-10-20-16-26-53.bpo-45464.mOISBs.rst +++ /dev/null @@ -1,4 +0,0 @@ -Mention in the documentation of :ref:`Built-in Exceptions -` that inheriting from multiple exception types in a -single subclass is not recommended due to possible memory layout -incompatibility. diff --git a/Misc/NEWS.d/next/Documentation/2021-10-22-21-57-42.bpo-45516.7_RMEX.rst b/Misc/NEWS.d/next/Documentation/2021-10-22-21-57-42.bpo-45516.7_RMEX.rst deleted file mode 100644 index 6295dd04b626a..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-10-22-21-57-42.bpo-45516.7_RMEX.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add protocol description to the :class:`importlib.abc.TraversableResources` -documentation. diff --git a/Misc/NEWS.d/next/Documentation/2021-10-26-10-00-45.bpo-45604.Dm-YhV.rst b/Misc/NEWS.d/next/Documentation/2021-10-26-10-00-45.bpo-45604.Dm-YhV.rst deleted file mode 100644 index 9da9cca7bf1ea..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-10-26-10-00-45.bpo-45604.Dm-YhV.rst +++ /dev/null @@ -1 +0,0 @@ -Add ``level`` argument to ``multiprocessing.log_to_stderr`` function docs. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Documentation/2021-10-28-19-22-55.bpo-45655.aPYGaS.rst b/Misc/NEWS.d/next/Documentation/2021-10-28-19-22-55.bpo-45655.aPYGaS.rst deleted file mode 100644 index fc5b3d0788817..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-10-28-19-22-55.bpo-45655.aPYGaS.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add a new "relevant PEPs" section to the top of the documentation for the -``typing`` module. Patch by Alex Waygood. diff --git a/Misc/NEWS.d/next/Documentation/2021-10-31-20-35-06.bpo-45618.RTcNXF.rst b/Misc/NEWS.d/next/Documentation/2021-10-31-20-35-06.bpo-45618.RTcNXF.rst deleted file mode 100644 index 47242b9382809..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-10-31-20-35-06.bpo-45618.RTcNXF.rst +++ /dev/null @@ -1,2 +0,0 @@ -Update Sphinx version used to build the documentation to 4.2.0. -Patch by Maciej Olko. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Documentation/2021-11-03-14-51-03.bpo-45680.9_NTFU.rst b/Misc/NEWS.d/next/Documentation/2021-11-03-14-51-03.bpo-45680.9_NTFU.rst deleted file mode 100644 index 79ea6e308e54a..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-11-03-14-51-03.bpo-45680.9_NTFU.rst +++ /dev/null @@ -1,3 +0,0 @@ -Amend the docs on ``GenericAlias`` objects to clarify that non-container -classes can also implement ``__class_getitem__``. Patch contributed by Alex -Waygood. diff --git a/Misc/NEWS.d/next/Documentation/2021-11-05-12-15-24.bpo-45726.GwRr7e.rst b/Misc/NEWS.d/next/Documentation/2021-11-05-12-15-24.bpo-45726.GwRr7e.rst deleted file mode 100644 index 7ff6283a2a34d..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-11-05-12-15-24.bpo-45726.GwRr7e.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve documentation for :func:`functools.singledispatch` and -:class:`functools.singledispatchmethod`. diff --git a/Misc/NEWS.d/next/IDLE/2021-10-16-17-20-32.bpo-45495.ST8RFt.rst b/Misc/NEWS.d/next/IDLE/2021-10-16-17-20-32.bpo-45495.ST8RFt.rst deleted file mode 100644 index 3868f8d136a04..0000000000000 --- a/Misc/NEWS.d/next/IDLE/2021-10-16-17-20-32.bpo-45495.ST8RFt.rst +++ /dev/null @@ -1 +0,0 @@ -Add context keywords 'case' and 'match' to completions list. diff --git a/Misc/NEWS.d/next/Library/2019-02-11-19-06-10.bpo-35970.ZRvh51.rst b/Misc/NEWS.d/next/Library/2019-02-11-19-06-10.bpo-35970.ZRvh51.rst deleted file mode 100644 index bdae153a500f4..0000000000000 --- a/Misc/NEWS.d/next/Library/2019-02-11-19-06-10.bpo-35970.ZRvh51.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add help flag to the base64 module's command line interface. Patch contributed -by Robert Kuska. diff --git a/Misc/NEWS.d/next/Library/2020-07-27-19-21-05.bpo-41374.cd-kFL.rst b/Misc/NEWS.d/next/Library/2020-07-27-19-21-05.bpo-41374.cd-kFL.rst deleted file mode 100644 index a5b2e042a3fae..0000000000000 --- a/Misc/NEWS.d/next/Library/2020-07-27-19-21-05.bpo-41374.cd-kFL.rst +++ /dev/null @@ -1,2 +0,0 @@ -Ensure that ``socket.TCP_*`` constants are exposed on Cygwin 3.1.6 and -greater. diff --git a/Misc/NEWS.d/next/Library/2021-01-07-01-25-38.bpo-10572.gEEZ9z.rst b/Misc/NEWS.d/next/Library/2021-01-07-01-25-38.bpo-10572.gEEZ9z.rst deleted file mode 100644 index 45f44bcbb110b..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-01-07-01-25-38.bpo-10572.gEEZ9z.rst +++ /dev/null @@ -1,2 +0,0 @@ -Move :mod:`sqlite3` tests to ``/Lib/test/test_sqlite3``. Patch by Erlend E. -Aasland. diff --git a/Misc/NEWS.d/next/Library/2021-07-22-21-25-56.bpo-40321.gBlFmw.rst b/Misc/NEWS.d/next/Library/2021-07-22-21-25-56.bpo-40321.gBlFmw.rst deleted file mode 100644 index fede2a0e5e35f..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-07-22-21-25-56.bpo-40321.gBlFmw.rst +++ /dev/null @@ -1,2 +0,0 @@ -Adds support for HTTP 308 redirects to :mod:`urllib`. See :rfc:`7538` for -details. Patch by Jochem Schulenklopper. diff --git a/Misc/NEWS.d/next/Library/2021-08-20-10-52-40.bpo-44547.eu0iJq.rst b/Misc/NEWS.d/next/Library/2021-08-20-10-52-40.bpo-44547.eu0iJq.rst deleted file mode 100644 index a5f425e17cad2..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-08-20-10-52-40.bpo-44547.eu0iJq.rst +++ /dev/null @@ -1,2 +0,0 @@ -Implement ``Fraction.__int__``, so that a :class:`fractions.Fraction` -instance ``f`` passes an ``isinstance(f, typing.SupportsInt)`` check. diff --git a/Misc/NEWS.d/next/Library/2021-08-30-00-19-23.bpo-24444.Ki4bgz.rst b/Misc/NEWS.d/next/Library/2021-08-30-00-19-23.bpo-24444.Ki4bgz.rst deleted file mode 100644 index efcacb8f0eb59..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-08-30-00-19-23.bpo-24444.Ki4bgz.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed an error raised in :mod:`argparse` help display when help for an -option is set to 1+ blank spaces or when *choices* arg is an empty container. diff --git a/Misc/NEWS.d/next/Library/2021-08-30-23-10-48.bpo-24139.e38czf.rst b/Misc/NEWS.d/next/Library/2021-08-30-23-10-48.bpo-24139.e38czf.rst deleted file mode 100644 index b44d0cf6e20e3..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-08-30-23-10-48.bpo-24139.e38czf.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add support for SQLite extended result codes in :exc:`sqlite3.Error`. Patch -by Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/Library/2021-09-10-12-53-28.bpo-25625.SzcBCw.rst b/Misc/NEWS.d/next/Library/2021-09-10-12-53-28.bpo-25625.SzcBCw.rst deleted file mode 100644 index c001683b657f5..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-10-12-53-28.bpo-25625.SzcBCw.rst +++ /dev/null @@ -1,3 +0,0 @@ -Added non parallel-safe :func:`~contextlib.chdir` context manager to change -the current working directory and then restore it on exit. Simple wrapper -around :func:`~os.chdir`. diff --git a/Misc/NEWS.d/next/Library/2021-09-11-14-47-05.bpo-45160.VzMXbW.rst b/Misc/NEWS.d/next/Library/2021-09-11-14-47-05.bpo-45160.VzMXbW.rst deleted file mode 100644 index 9d11ed0e55d24..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-11-14-47-05.bpo-45160.VzMXbW.rst +++ /dev/null @@ -1 +0,0 @@ -When tracing a tkinter variable used by a ttk OptionMenu, callbacks are no longer made twice. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2021-09-14-15-52-47.bpo-45192.DjA-BI.rst b/Misc/NEWS.d/next/Library/2021-09-14-15-52-47.bpo-45192.DjA-BI.rst deleted file mode 100644 index 7dd9795aaa170..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-14-15-52-47.bpo-45192.DjA-BI.rst +++ /dev/null @@ -1,5 +0,0 @@ -Fix the ``tempfile._infer_return_type`` function so that the ``dir`` -argument of the :mod:`tempfile` functions accepts an object implementing the -``os.PathLike`` protocol. - -Patch by Kyungmin Lee. diff --git a/Misc/NEWS.d/next/Library/2021-09-15-10-21-10.bpo-45320.4qaf5x.rst b/Misc/NEWS.d/next/Library/2021-09-15-10-21-10.bpo-45320.4qaf5x.rst deleted file mode 100644 index 1f2236bd42412..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-15-10-21-10.bpo-45320.4qaf5x.rst +++ /dev/null @@ -1,15 +0,0 @@ -Removed from the :mod:`inspect` module: - -* the ``getargspec`` function, deprecated since Python 3.0; - use :func:`inspect.signature` or :func:`inspect.getfullargspec` instead. - -* the ``formatargspec`` function, deprecated since Python 3.5; - use the :func:`inspect.signature` function and :class:`Signature` object - directly. - -* the undocumented ``Signature.from_callable`` and ``Signature.from_function`` - functions, deprecated since Python 3.5; use the - :meth:`Signature.from_callable() ` method - instead. - -Patch by Hugo van Kemenade. diff --git a/Misc/NEWS.d/next/Library/2021-09-20-01-25-09.bpo-45243.0pJf0U.rst b/Misc/NEWS.d/next/Library/2021-09-20-01-25-09.bpo-45243.0pJf0U.rst deleted file mode 100644 index 8292e86245f02..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-20-01-25-09.bpo-45243.0pJf0U.rst +++ /dev/null @@ -1,4 +0,0 @@ -Add :meth:`~sqlite3.Connection.setlimit` and -:meth:`~sqlite3.Connection.getlimit` to :class:`sqlite3.Connection` for -setting and getting SQLite limits by connection basis. Patch by Erlend E. -Aasland. diff --git a/Misc/NEWS.d/next/Library/2021-09-30-08-22-44.bpo-45328.8Z-Q0B.rst b/Misc/NEWS.d/next/Library/2021-09-30-08-22-44.bpo-45328.8Z-Q0B.rst deleted file mode 100644 index eeb49310e8f66..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-30-08-22-44.bpo-45328.8Z-Q0B.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed :class:`http.client.HTTPConnection` to work properly in OSs that don't support the ``TCP_NODELAY`` socket option. diff --git a/Misc/NEWS.d/next/Library/2021-10-01-23-07-02.bpo-45343.ixmctD.rst b/Misc/NEWS.d/next/Library/2021-10-01-23-07-02.bpo-45343.ixmctD.rst deleted file mode 100644 index 8dac4e6a25271..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-01-23-07-02.bpo-45343.ixmctD.rst +++ /dev/null @@ -1 +0,0 @@ -Update bundled pip to 21.2.4 and setuptools to 58.1.0 diff --git a/Misc/NEWS.d/next/Library/2021-10-03-21-14-37.bpo-20028.zBA4RK.rst b/Misc/NEWS.d/next/Library/2021-10-03-21-14-37.bpo-20028.zBA4RK.rst deleted file mode 100644 index e75612116e942..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-03-21-14-37.bpo-20028.zBA4RK.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve error message of :class:`csv.Dialect` when initializing. -Patch by Vajrasky Kok and Dong-hee Na. diff --git a/Misc/NEWS.d/next/Library/2021-10-07-00-05-05.bpo-45386.q9ORpA.rst b/Misc/NEWS.d/next/Library/2021-10-07-00-05-05.bpo-45386.q9ORpA.rst deleted file mode 100644 index eec77ceccf933..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-07-00-05-05.bpo-45386.q9ORpA.rst +++ /dev/null @@ -1,3 +0,0 @@ -Make :mod:`xmlrpc.client` more robust to C runtimes where the underlying C -``strftime`` function results in a ``ValueError`` when testing for year -formatting options. diff --git a/Misc/NEWS.d/next/Library/2021-10-07-14-04-10.bpo-45262.HqF71Z.rst b/Misc/NEWS.d/next/Library/2021-10-07-14-04-10.bpo-45262.HqF71Z.rst deleted file mode 100644 index 4cd949fe1ed5d..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-07-14-04-10.bpo-45262.HqF71Z.rst +++ /dev/null @@ -1 +0,0 @@ -Prevent use-after-free in asyncio. Make sure the cached running loop holder gets cleared on dealloc to prevent use-after-free in get_running_loop \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2021-10-07-21-11-48.bpo-27580.tGcBTH.rst b/Misc/NEWS.d/next/Library/2021-10-07-21-11-48.bpo-27580.tGcBTH.rst deleted file mode 100644 index 15a8ff2dd6add..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-07-21-11-48.bpo-27580.tGcBTH.rst +++ /dev/null @@ -1 +0,0 @@ -Add support of null characters in :mod:`csv`. diff --git a/Misc/NEWS.d/next/Library/2021-10-08-04-11-55.bpo-10716.QSRVK2.rst b/Misc/NEWS.d/next/Library/2021-10-08-04-11-55.bpo-10716.QSRVK2.rst deleted file mode 100644 index 8ec944960211a..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-08-04-11-55.bpo-10716.QSRVK2.rst +++ /dev/null @@ -1,3 +0,0 @@ -Migrated pydoc to HTML5 (without changing the look of it). Side effect is to -update xmlrpc's ``ServerHTMLDoc`` which now uses the CSS too. cgitb now -relies less on pydoc (as it can't use the CSS file). diff --git a/Misc/NEWS.d/next/Library/2021-10-08-11-29-29.bpo-45411.4jR--U.rst b/Misc/NEWS.d/next/Library/2021-10-08-11-29-29.bpo-45411.4jR--U.rst deleted file mode 100644 index 5f774dcda9849..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-08-11-29-29.bpo-45411.4jR--U.rst +++ /dev/null @@ -1 +0,0 @@ -Add extensions for files containing subtitles - .srt & .vtt - to the mimetypes.py module. diff --git a/Misc/NEWS.d/next/Library/2021-10-08-19-24-48.bpo-45406.Qh_Mz4.rst b/Misc/NEWS.d/next/Library/2021-10-08-19-24-48.bpo-45406.Qh_Mz4.rst deleted file mode 100644 index 2c3a8165aeb49..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-08-19-24-48.bpo-45406.Qh_Mz4.rst +++ /dev/null @@ -1 +0,0 @@ -Make :func:`inspect.getmodule` catch ``FileNotFoundError`` raised by :'func:`inspect.getabsfile`, and return ``None`` to indicate that the module could not be determined. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2021-10-09-18-42-27.bpo-44904.RlW5h8.rst b/Misc/NEWS.d/next/Library/2021-10-09-18-42-27.bpo-44904.RlW5h8.rst deleted file mode 100644 index b02d499d23500..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-09-18-42-27.bpo-44904.RlW5h8.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix bug in the :mod:`doctest` module that caused it to fail if a docstring -included an example with a ``classmethod`` ``property``. Patch by Alex -Waygood. diff --git a/Misc/NEWS.d/next/Library/2021-10-10-00-25-36.bpo-20028.bPx4Z8.rst b/Misc/NEWS.d/next/Library/2021-10-10-00-25-36.bpo-20028.bPx4Z8.rst deleted file mode 100644 index 9db15bc39e7ca..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-10-00-25-36.bpo-20028.bPx4Z8.rst +++ /dev/null @@ -1,2 +0,0 @@ -Empty escapechar/quotechar is not allowed when initializing -:class:`csv.Dialect`. Patch by Vajrasky Kok and Dong-hee Na. diff --git a/Misc/NEWS.d/next/Library/2021-10-10-09-42-34.bpo-45416.n35O0_.rst b/Misc/NEWS.d/next/Library/2021-10-10-09-42-34.bpo-45416.n35O0_.rst deleted file mode 100644 index cf335d1bcd2c9..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-10-09-42-34.bpo-45416.n35O0_.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix use of :class:`asyncio.Condition` with explicit :class:`asyncio.Lock` objects, which was a regression due to removal of explicit loop arguments. -Patch by Joongi Kim. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2021-10-10-16-14-33.bpo-45249.xqLliz.rst b/Misc/NEWS.d/next/Library/2021-10-10-16-14-33.bpo-45249.xqLliz.rst deleted file mode 100644 index 1d5a857e25435..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-10-16-14-33.bpo-45249.xqLliz.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix the behaviour of :func:`traceback.print_exc` when displaying the caret -when the ``end_offset`` in the exception is set to 0. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Library/2021-10-12-20-35-06.bpo-45417.gQM-O7.rst b/Misc/NEWS.d/next/Library/2021-10-12-20-35-06.bpo-45417.gQM-O7.rst deleted file mode 100644 index a15c23917a7e6..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-12-20-35-06.bpo-45417.gQM-O7.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix quadratic behaviour in the enum module: Creation of enum classes with a -lot of entries was quadratic. diff --git a/Misc/NEWS.d/next/Library/2021-10-13-17-52-48.bpo-45239.7li1_0.rst b/Misc/NEWS.d/next/Library/2021-10-13-17-52-48.bpo-45239.7li1_0.rst deleted file mode 100644 index 9e5ec561c362a..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-13-17-52-48.bpo-45239.7li1_0.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixed :func:`email.utils.parsedate_tz` crashing with -:exc:`UnboundLocalError` on certain invalid input instead of returning -``None``. Patch by Ben Hoyt. diff --git a/Misc/NEWS.d/next/Library/2021-10-14-00-19-02.bpo-45461.4LB_tJ.rst b/Misc/NEWS.d/next/Library/2021-10-14-00-19-02.bpo-45461.4LB_tJ.rst deleted file mode 100644 index c1c4ed1ace248..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-14-00-19-02.bpo-45461.4LB_tJ.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix incremental decoder and stream reader in the "unicode-escape" codec. -Previously they failed if the escape sequence was split. diff --git a/Misc/NEWS.d/next/Library/2021-10-14-13-31-19.bpo-45467.Q7Ma6A.rst b/Misc/NEWS.d/next/Library/2021-10-14-13-31-19.bpo-45467.Q7Ma6A.rst deleted file mode 100644 index f2c0ae4ae51fb..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-14-13-31-19.bpo-45467.Q7Ma6A.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix incremental decoder and stream reader in the "raw-unicode-escape" codec. -Previously they failed if the escape sequence was split. diff --git a/Misc/NEWS.d/next/Library/2021-10-14-18-04-17.bpo-45428.mM2War.rst b/Misc/NEWS.d/next/Library/2021-10-14-18-04-17.bpo-45428.mM2War.rst deleted file mode 100644 index 556eca43ed3c7..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-14-18-04-17.bpo-45428.mM2War.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a regression in py_compile when reading filenames from standard input. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2021-10-15-11-30-11.bpo-42222.hdHyac.rst b/Misc/NEWS.d/next/Library/2021-10-15-11-30-11.bpo-42222.hdHyac.rst deleted file mode 100644 index 9b29fa44d7711..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-15-11-30-11.bpo-42222.hdHyac.rst +++ /dev/null @@ -1 +0,0 @@ -Removed deprecated support for float arguments in *randrange()*. diff --git a/Misc/NEWS.d/next/Library/2021-10-16-23-46-39.bpo-45489.QB0rhG.rst b/Misc/NEWS.d/next/Library/2021-10-16-23-46-39.bpo-45489.QB0rhG.rst deleted file mode 100644 index 3921437d97ac5..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-16-23-46-39.bpo-45489.QB0rhG.rst +++ /dev/null @@ -1,2 +0,0 @@ -Update :class:`~typing.ForwardRef` to support ``|`` operator. Patch by -Dong-hee Na. diff --git a/Misc/NEWS.d/next/Library/2021-10-18-10-46-47.bpo-45475.sb9KDF.rst b/Misc/NEWS.d/next/Library/2021-10-18-10-46-47.bpo-45475.sb9KDF.rst deleted file mode 100644 index 6fce894e6e4d4..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-18-10-46-47.bpo-45475.sb9KDF.rst +++ /dev/null @@ -1,4 +0,0 @@ -Reverted optimization of iterating :class:`gzip.GzipFile`, -:class:`bz2.BZ2File`, and :class:`lzma.LZMAFile` (see bpo-43787) because it -caused regression when user iterate them without having reference of them. -Patch by Inada Naoki. diff --git a/Misc/NEWS.d/next/Library/2021-10-18-14-52-48.bpo-45515.aXdvm_.rst b/Misc/NEWS.d/next/Library/2021-10-18-14-52-48.bpo-45515.aXdvm_.rst deleted file mode 100644 index 382733ff91883..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-18-14-52-48.bpo-45515.aXdvm_.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add references to :mod:`zoneinfo` in the :mod:`datetime` documentation, -mostly replacing outdated references to ``dateutil.tz``. Change by Paul -Ganssle. diff --git a/Misc/NEWS.d/next/Library/2021-10-18-18-12-47.bpo-35673.KOkHWe.rst b/Misc/NEWS.d/next/Library/2021-10-18-18-12-47.bpo-35673.KOkHWe.rst deleted file mode 100644 index e7d6a5fa5a910..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-18-18-12-47.bpo-35673.KOkHWe.rst +++ /dev/null @@ -1,4 +0,0 @@ -Improve the introspectability of the ``__loader__`` attribute for namespace -packages. :class:`importlib.machinery.NamespaceLoader` is now public, and -implements the :class:`importlib.abc.InspectLoader` interface. ``_NamespaceLoader`` -is kept for backward compatibility. diff --git a/Misc/NEWS.d/next/Library/2021-10-19-01-30-57.bpo-42174.O2w9bi.rst b/Misc/NEWS.d/next/Library/2021-10-19-01-30-57.bpo-42174.O2w9bi.rst deleted file mode 100644 index 412582ded3e12..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-19-01-30-57.bpo-42174.O2w9bi.rst +++ /dev/null @@ -1,2 +0,0 @@ -:meth:`shutil.get_terminal_size` now falls back to sane values if the column -or line count are 0. diff --git a/Misc/NEWS.d/next/Library/2021-10-21-10-14-22.bpo-44019.Xk4Ncr.rst b/Misc/NEWS.d/next/Library/2021-10-21-10-14-22.bpo-44019.Xk4Ncr.rst deleted file mode 100644 index 1793603637fbb..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-21-10-14-22.bpo-44019.Xk4Ncr.rst +++ /dev/null @@ -1 +0,0 @@ -Add :func:`operator.call` to ``operator.__all__``. Patch by Kreusada. diff --git a/Misc/NEWS.d/next/Library/2021-10-21-16-18-51.bpo-45557.4MQt4r.rst b/Misc/NEWS.d/next/Library/2021-10-21-16-18-51.bpo-45557.4MQt4r.rst deleted file mode 100644 index 7472b08d1b08e..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-21-16-18-51.bpo-45557.4MQt4r.rst +++ /dev/null @@ -1,2 +0,0 @@ -pprint.pprint() now handles underscore_numbers correctly. Previously it was -always setting it to False. diff --git a/Misc/NEWS.d/next/Library/2021-10-22-21-57-02.bpo-45581.rlH6ay.rst b/Misc/NEWS.d/next/Library/2021-10-22-21-57-02.bpo-45581.rlH6ay.rst deleted file mode 100644 index 13a3b237434eb..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-22-21-57-02.bpo-45581.rlH6ay.rst +++ /dev/null @@ -1,2 +0,0 @@ -:meth:`sqlite3.connect` now correctly raises :exc:`MemoryError` if the -underlying SQLite API signals memory error. Patch by Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/Library/2021-10-22-23-06-33.bpo-45574.svqA84.rst b/Misc/NEWS.d/next/Library/2021-10-22-23-06-33.bpo-45574.svqA84.rst deleted file mode 100644 index b404d24473960..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-22-23-06-33.bpo-45574.svqA84.rst +++ /dev/null @@ -1 +0,0 @@ -Fix warning about ``print_escape`` being unused. diff --git a/Misc/NEWS.d/next/Library/2021-10-26-14-29-54.bpo-45613.55Ie3c.rst b/Misc/NEWS.d/next/Library/2021-10-26-14-29-54.bpo-45613.55Ie3c.rst deleted file mode 100644 index ac0937b54aeea..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-26-14-29-54.bpo-45613.55Ie3c.rst +++ /dev/null @@ -1,3 +0,0 @@ -:mod:`sqlite3` now sets :attr:`sqlite3.threadsafety` based on the default -threading mode the underlying SQLite library has been compiled with. Patch by -Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/Library/2021-10-27-10-05-39.bpo-45438.Xz5lGU.rst b/Misc/NEWS.d/next/Library/2021-10-27-10-05-39.bpo-45438.Xz5lGU.rst deleted file mode 100644 index cd6cfc1fcd407..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-27-10-05-39.bpo-45438.Xz5lGU.rst +++ /dev/null @@ -1 +0,0 @@ -Fix typing.Signature string representation for generic builtin types. diff --git a/Misc/NEWS.d/next/Library/2021-10-27-13-28-52.bpo-42064.UK4jgV.rst b/Misc/NEWS.d/next/Library/2021-10-27-13-28-52.bpo-42064.UK4jgV.rst deleted file mode 100644 index bcb3307d37bc2..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-27-13-28-52.bpo-42064.UK4jgV.rst +++ /dev/null @@ -1,2 +0,0 @@ -Convert :mod:`sqlite3` to multi-phase initialisation (PEP 489). Patches by -Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/Library/2021-10-30-21-11-37.bpo-45679.Dq8Cpu.rst b/Misc/NEWS.d/next/Library/2021-10-30-21-11-37.bpo-45679.Dq8Cpu.rst deleted file mode 100644 index a644492a12d17..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-10-30-21-11-37.bpo-45679.Dq8Cpu.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix caching of multi-value :data:`typing.Literal`. ``Literal[True, 2]`` is no -longer equal to ``Literal[1, 2]``. diff --git a/Misc/NEWS.d/next/Tests/2021-10-07-13-11-45.bpo-45400.h3iT7V.rst b/Misc/NEWS.d/next/Tests/2021-10-07-13-11-45.bpo-45400.h3iT7V.rst deleted file mode 100644 index 61b6653320dfc..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-10-07-13-11-45.bpo-45400.h3iT7V.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix test_name_error_suggestions_do_not_trigger_for_too_many_locals() of -test_exceptions if a directory name contains "a1" (like "Python-3.11.0a1"): -use a stricter regular expression. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Tests/2021-10-07-13-27-12.bpo-45403.7QiDvw.rst b/Misc/NEWS.d/next/Tests/2021-10-07-13-27-12.bpo-45403.7QiDvw.rst deleted file mode 100644 index e4d1709960980..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-10-07-13-27-12.bpo-45403.7QiDvw.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix test_sys.test_stdlib_dir() when Python is built outside the source tree: -compare normalized paths. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Tests/2021-10-07-13-43-01.bpo-45402.jlQvep.rst b/Misc/NEWS.d/next/Tests/2021-10-07-13-43-01.bpo-45402.jlQvep.rst deleted file mode 100644 index d8c655306584c..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-10-07-13-43-01.bpo-45402.jlQvep.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix test_tools.test_sundry() when Python is built out of tree: fix how -the freeze_modules.py tool locates the _freeze_module program. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Tests/2021-10-08-14-03-20.bpo-45410.Ex9xe2.rst b/Misc/NEWS.d/next/Tests/2021-10-08-14-03-20.bpo-45410.Ex9xe2.rst deleted file mode 100644 index 5f7b8bf1d6c66..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-10-08-14-03-20.bpo-45410.Ex9xe2.rst +++ /dev/null @@ -1,4 +0,0 @@ -When libregrtest spawns a worker process, stderr is now written into stdout -to keep messages order. Use a single pipe for stdout and stderr, rather than -two pipes. Previously, messages were out of order which made analysis of -buildbot logs harder Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Tests/2021-10-18-16-18-41.bpo-39679.F18qcE.rst b/Misc/NEWS.d/next/Tests/2021-10-18-16-18-41.bpo-39679.F18qcE.rst deleted file mode 100644 index b0d1b686392ef..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-10-18-16-18-41.bpo-39679.F18qcE.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add more test cases for `@functools.singledispatchmethod` when combined with -`@classmethod` or `@staticmethod`. diff --git a/Misc/NEWS.d/next/Tests/2021-10-21-17-22-26.bpo-43592.kHRsra.rst b/Misc/NEWS.d/next/Tests/2021-10-21-17-22-26.bpo-43592.kHRsra.rst deleted file mode 100644 index 2528857caf9c0..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-10-21-17-22-26.bpo-43592.kHRsra.rst +++ /dev/null @@ -1,3 +0,0 @@ -:mod:`test.libregrtest` now raises the soft resource limit for the maximum -number of file descriptors when the default is too low for our test suite as -was often the case on macOS. diff --git a/Misc/NEWS.d/next/Tests/2021-10-22-12-05-21.bpo-45566.2gQ3ZB.rst b/Misc/NEWS.d/next/Tests/2021-10-22-12-05-21.bpo-45566.2gQ3ZB.rst deleted file mode 100644 index a2ecf721800d9..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-10-22-12-05-21.bpo-45566.2gQ3ZB.rst +++ /dev/null @@ -1 +0,0 @@ -Fix ``test_frozen_pickle`` in ``test_dataclasses`` to check all ``pickle`` versions. diff --git a/Misc/NEWS.d/next/Tests/2021-10-22-19-44-13.bpo-45577.dSaNvK.rst b/Misc/NEWS.d/next/Tests/2021-10-22-19-44-13.bpo-45577.dSaNvK.rst deleted file mode 100644 index fc9783eb9ddaa..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-10-22-19-44-13.bpo-45577.dSaNvK.rst +++ /dev/null @@ -1 +0,0 @@ -Add subtests for all ``pickle`` protocols in ``test_zoneinfo``. diff --git a/Misc/NEWS.d/next/Tests/2021-10-29-17-18-56.bpo-45668.MfAw4i.rst b/Misc/NEWS.d/next/Tests/2021-10-29-17-18-56.bpo-45668.MfAw4i.rst deleted file mode 100644 index 2ef6a02efd1b7..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-10-29-17-18-56.bpo-45668.MfAw4i.rst +++ /dev/null @@ -1 +0,0 @@ -PGO tests now pass when Python is built without test extension modules. diff --git a/Misc/NEWS.d/next/Tests/2021-10-30-13-12-20.bpo-45678.bKrYeS.rst b/Misc/NEWS.d/next/Tests/2021-10-30-13-12-20.bpo-45678.bKrYeS.rst deleted file mode 100644 index 885b2fa64ad0f..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-10-30-13-12-20.bpo-45678.bKrYeS.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add tests to ensure that ``functools.singledispatchmethod`` correctly wraps -the attributes of the target function. diff --git a/Misc/NEWS.d/next/Tests/2021-10-30-19-00-25.bpo-45578.bvu6X2.rst b/Misc/NEWS.d/next/Tests/2021-10-30-19-00-25.bpo-45578.bvu6X2.rst deleted file mode 100644 index 3d0e0ca3f04a1..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-10-30-19-00-25.bpo-45578.bvu6X2.rst +++ /dev/null @@ -1 +0,0 @@ -Add tests for :func:`dis.distb` diff --git a/Misc/NEWS.d/next/Tests/2021-11-04-20-03-32.bpo-45678.1xNMjN.rst b/Misc/NEWS.d/next/Tests/2021-11-04-20-03-32.bpo-45678.1xNMjN.rst deleted file mode 100644 index 736d5f65f961b..0000000000000 --- a/Misc/NEWS.d/next/Tests/2021-11-04-20-03-32.bpo-45678.1xNMjN.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add tests for scenarios in which :class:`functools.singledispatchmethod` is -stacked on top of a method that has already been wrapped by two other -decorators. Patch by Alex Waygood. diff --git a/Misc/NEWS.d/next/Windows/2021-04-15-01-23-10.bpo-43851.qgU0gy.rst b/Misc/NEWS.d/next/Windows/2021-04-15-01-23-10.bpo-43851.qgU0gy.rst deleted file mode 100644 index e9555d56754cc..0000000000000 --- a/Misc/NEWS.d/next/Windows/2021-04-15-01-23-10.bpo-43851.qgU0gy.rst +++ /dev/null @@ -1 +0,0 @@ -Build SQLite ``SQLITE_OMIT_AUTOINIT`` on Windows. Patch by Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/Windows/2021-09-30-23-17-27.bpo-45337.qg7U_h.rst b/Misc/NEWS.d/next/Windows/2021-09-30-23-17-27.bpo-45337.qg7U_h.rst deleted file mode 100644 index 007ee87195d6e..0000000000000 --- a/Misc/NEWS.d/next/Windows/2021-09-30-23-17-27.bpo-45337.qg7U_h.rst +++ /dev/null @@ -1,4 +0,0 @@ -venv now warns when the created environment may need to be accessed at a -different path, due to redirections, links or junctions. It also now -correctly installs or upgrades components when the alternate path is -required. diff --git a/Misc/NEWS.d/next/Windows/2021-11-04-00-41-50.bpo-43652.RnqV7I.rst b/Misc/NEWS.d/next/Windows/2021-11-04-00-41-50.bpo-43652.RnqV7I.rst deleted file mode 100644 index 7da8fc79a9dab..0000000000000 --- a/Misc/NEWS.d/next/Windows/2021-11-04-00-41-50.bpo-43652.RnqV7I.rst +++ /dev/null @@ -1,2 +0,0 @@ -Update Tcl/Tk to 8.6.11, actually this time. The previous update incorrectly -included 8.6.10. diff --git a/Misc/NEWS.d/next/macOS/2021-10-25-02-02-21.bpo-44828.XBdXlJ.rst b/Misc/NEWS.d/next/macOS/2021-10-25-02-02-21.bpo-44828.XBdXlJ.rst deleted file mode 100644 index 021d7e4d73782..0000000000000 --- a/Misc/NEWS.d/next/macOS/2021-10-25-02-02-21.bpo-44828.XBdXlJ.rst +++ /dev/null @@ -1,3 +0,0 @@ -Avoid tkinter file dialog failure on macOS 12 Monterey when using the Tk -8.6.11 provided by python.org macOS installers. Patch by Marc Culler of the -Tk project. diff --git a/README.rst b/README.rst index a789408d78d53..d43f6fabae3a5 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -This is Python version 3.11.0 alpha 1 +This is Python version 3.11.0 alpha 2 ===================================== .. image:: https://travis-ci.com/python/cpython.svg?branch=main diff --git a/configure b/configure index f0046ffab5eb0..00bea712b0633 100755 --- a/configure +++ b/configure @@ -10159,13 +10159,15 @@ $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# check for libuuid from util-linux save_LIBS=$LIBS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing uuid_generate_time_safe" >&5 -$as_echo_n "checking for library containing uuid_generate_time_safe... " >&6; } -if ${ac_cv_search_uuid_generate_time_safe+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time in -luuid" >&5 +$as_echo_n "checking for uuid_generate_time in -luuid... " >&6; } +if ${ac_cv_lib_uuid_uuid_generate_time+:} false; then : $as_echo_n "(cached) " >&6 else - ac_func_search_save_LIBS=$LIBS + ac_check_lib_save_LIBS=$LIBS +LIBS="-luuid $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -10175,61 +10177,39 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext #ifdef __cplusplus extern "C" #endif -char uuid_generate_time_safe (); +char uuid_generate_time (); int main () { -return uuid_generate_time_safe (); +return uuid_generate_time (); ; return 0; } _ACEOF -for ac_lib in '' uuid; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_uuid_generate_time_safe=$ac_res -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_uuid_generate_time_safe+:} false; then : - break -fi -done -if ${ac_cv_search_uuid_generate_time_safe+:} false; then : - +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_uuid_uuid_generate_time=yes else - ac_cv_search_uuid_generate_time_safe=no + ac_cv_lib_uuid_uuid_generate_time=no fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_uuid_generate_time_safe" >&5 -$as_echo "$ac_cv_search_uuid_generate_time_safe" >&6; } -ac_res=$ac_cv_search_uuid_generate_time_safe -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - - -$as_echo "#define HAVE_LIBUUID 1" >>confdefs.h -, - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_uuid_uuid_generate_time" >&5 +$as_echo "$ac_cv_lib_uuid_uuid_generate_time" >&6; } +if test "x$ac_cv_lib_uuid_uuid_generate_time" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBUUID 1 +_ACEOF -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + LIBS="-luuid $LIBS" fi LIBS=$save_LIBS # AIX provides support for RFC4122 (uuid) in libc.a starting with AIX 6.1 (anno 2007) -# FreeBSD and OpenBSD provides support as well +# FreeBSD and OpenBSD provides support in libc as well. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_create" >&5 $as_echo_n "checking for uuid_create... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext diff --git a/pyconfig.h.in b/pyconfig.h.in index 108a13d8d2ca9..b89377dc1b44d 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -604,7 +604,7 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LIBUTIL_H -/* Define you have libuuid. */ +/* Define to 1 if you have the `uuid' library (-luuid). */ #undef HAVE_LIBUUID /* Define if you have the 'link' function. */ From webhook-mailer at python.org Fri Nov 5 19:06:50 2021 From: webhook-mailer at python.org (zooba) Date: Fri, 05 Nov 2021 23:06:50 -0000 Subject: [Python-checkins] bpo-45720: Drop references to shlwapi.dll on Windows (GH-29417) Message-ID: https://github.com/python/cpython/commit/a4774f42e35861c4bb16928cffb011c2d8a285ac commit: a4774f42e35861c4bb16928cffb011c2d8a285ac branch: main author: Steve Dower committer: zooba date: 2021-11-05T23:06:45Z summary: bpo-45720: Drop references to shlwapi.dll on Windows (GH-29417) files: A Misc/NEWS.d/next/Windows/2021-11-05-01-05-46.bpo-45720.47Nc5I.rst M PC/getpathp.c M PCbuild/_freeze_module.vcxproj M PCbuild/pythoncore.vcxproj diff --git a/Misc/NEWS.d/next/Windows/2021-11-05-01-05-46.bpo-45720.47Nc5I.rst b/Misc/NEWS.d/next/Windows/2021-11-05-01-05-46.bpo-45720.47Nc5I.rst new file mode 100644 index 0000000000000..315759b07e147 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2021-11-05-01-05-46.bpo-45720.47Nc5I.rst @@ -0,0 +1,3 @@ +Internal reference to :file:`shlwapi.dll` was dropped to help improve +startup time. This DLL will no longer be loaded at the start of every Python +process. diff --git a/PC/getpathp.c b/PC/getpathp.c index 549353d78b116..a27348024d252 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -92,7 +92,6 @@ #include #include -#include #ifdef HAVE_SYS_TYPES_H #include @@ -265,7 +264,8 @@ canonicalize(wchar_t *buffer, const wchar_t *path) return _PyStatus_NO_MEMORY(); } - if (PathIsRelativeW(path)) { + const wchar_t *pathTail; + if (FAILED(PathCchSkipRoot(path, &pathTail)) || path == pathTail) { wchar_t buff[MAXPATHLEN + 1]; if (!GetCurrentDirectoryW(MAXPATHLEN, buff)) { return _PyStatus_ERR("unable to find current working directory"); diff --git a/PCbuild/_freeze_module.vcxproj b/PCbuild/_freeze_module.vcxproj index 12bdde2af84d9..d33e07c54b8c9 100644 --- a/PCbuild/_freeze_module.vcxproj +++ b/PCbuild/_freeze_module.vcxproj @@ -92,7 +92,7 @@ Console - version.lib;shlwapi.lib;ws2_32.lib;pathcch.lib;bcrypt.lib;%(AdditionalDependencies) + version.lib;ws2_32.lib;pathcch.lib;bcrypt.lib;%(AdditionalDependencies) diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 646bc8e4800b1..b65998186927b 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -106,7 +106,7 @@ _Py_HAVE_ZLIB;%(PreprocessorDefinitions) - version.lib;shlwapi.lib;ws2_32.lib;pathcch.lib;bcrypt.lib;%(AdditionalDependencies) + version.lib;ws2_32.lib;pathcch.lib;bcrypt.lib;%(AdditionalDependencies) From webhook-mailer at python.org Fri Nov 5 20:25:38 2021 From: webhook-mailer at python.org (zooba) Date: Sat, 06 Nov 2021 00:25:38 -0000 Subject: [Python-checkins] bpo-45720: Drop references to shlwapi.dll on Windows (GH-29417) Message-ID: https://github.com/python/cpython/commit/804ea41211b042fa20c3cd8c0457bbfa3873128a commit: 804ea41211b042fa20c3cd8c0457bbfa3873128a branch: 3.10 author: Steve Dower committer: zooba date: 2021-11-06T00:25:29Z summary: bpo-45720: Drop references to shlwapi.dll on Windows (GH-29417) files: A Misc/NEWS.d/next/Windows/2021-11-05-01-05-46.bpo-45720.47Nc5I.rst M PC/getpathp.c M PCbuild/pythoncore.vcxproj diff --git a/Misc/NEWS.d/next/Windows/2021-11-05-01-05-46.bpo-45720.47Nc5I.rst b/Misc/NEWS.d/next/Windows/2021-11-05-01-05-46.bpo-45720.47Nc5I.rst new file mode 100644 index 0000000000000..315759b07e147 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2021-11-05-01-05-46.bpo-45720.47Nc5I.rst @@ -0,0 +1,3 @@ +Internal reference to :file:`shlwapi.dll` was dropped to help improve +startup time. This DLL will no longer be loaded at the start of every Python +process. diff --git a/PC/getpathp.c b/PC/getpathp.c index dc5b201d145f3..7c0eeab5dbab4 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -91,7 +91,6 @@ #include #include -#include #ifdef HAVE_SYS_TYPES_H #include diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 0382977d6c367..c39ba3e1a9f41 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -106,7 +106,7 @@ _Py_HAVE_ZLIB;%(PreprocessorDefinitions) - version.lib;shlwapi.lib;ws2_32.lib;pathcch.lib;%(AdditionalDependencies) + version.lib;ws2_32.lib;pathcch.lib;%(AdditionalDependencies) From webhook-mailer at python.org Fri Nov 5 21:39:03 2021 From: webhook-mailer at python.org (zooba) Date: Sat, 06 Nov 2021 01:39:03 -0000 Subject: [Python-checkins] bpo-45720: Drop references to shlwapi.dll on Windows (GH-29417) Message-ID: https://github.com/python/cpython/commit/5017306c8732b3ceda878db13088f8c2cf0c5e71 commit: 5017306c8732b3ceda878db13088f8c2cf0c5e71 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: zooba date: 2021-11-06T01:38:50Z summary: bpo-45720: Drop references to shlwapi.dll on Windows (GH-29417) (cherry picked from commit 804ea41211b042fa20c3cd8c0457bbfa3873128a) Co-authored-by: Steve Dower Co-authored-by: Steve Dower files: A Misc/NEWS.d/next/Windows/2021-11-05-01-05-46.bpo-45720.47Nc5I.rst M PC/getpathp.c M PCbuild/pythoncore.vcxproj diff --git a/Misc/NEWS.d/next/Windows/2021-11-05-01-05-46.bpo-45720.47Nc5I.rst b/Misc/NEWS.d/next/Windows/2021-11-05-01-05-46.bpo-45720.47Nc5I.rst new file mode 100644 index 0000000000000..315759b07e147 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2021-11-05-01-05-46.bpo-45720.47Nc5I.rst @@ -0,0 +1,3 @@ +Internal reference to :file:`shlwapi.dll` was dropped to help improve +startup time. This DLL will no longer be loaded at the start of every Python +process. diff --git a/PC/getpathp.c b/PC/getpathp.c index dc5b201d145f3..7c0eeab5dbab4 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -91,7 +91,6 @@ #include #include -#include #ifdef HAVE_SYS_TYPES_H #include diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 2625d0293dde6..9a40905fe01f8 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -106,7 +106,7 @@ _Py_HAVE_ZLIB;%(PreprocessorDefinitions) - version.lib;shlwapi.lib;ws2_32.lib;pathcch.lib;%(AdditionalDependencies) + version.lib;ws2_32.lib;pathcch.lib;%(AdditionalDependencies) From webhook-mailer at python.org Sat Nov 6 05:30:42 2021 From: webhook-mailer at python.org (tiran) Date: Sat, 06 Nov 2021 09:30:42 -0000 Subject: [Python-checkins] bpo-45731: Handle --enable-loadable-sqlite-extensions in configure (GH-29434) Message-ID: https://github.com/python/cpython/commit/e9594f6747eaaaa848c26e2bf67d467aabfd62b3 commit: e9594f6747eaaaa848c26e2bf67d467aabfd62b3 branch: main author: Christian Heimes committer: tiran date: 2021-11-06T10:30:37+01:00 summary: bpo-45731: Handle --enable-loadable-sqlite-extensions in configure (GH-29434) files: A Misc/NEWS.d/next/Build/2021-11-05-20-56-29.bpo-45731.9SDnDf.rst M Modules/_sqlite/clinic/connection.c.h M Modules/_sqlite/connection.c M configure M configure.ac M pyconfig.h.in M setup.py diff --git a/Misc/NEWS.d/next/Build/2021-11-05-20-56-29.bpo-45731.9SDnDf.rst b/Misc/NEWS.d/next/Build/2021-11-05-20-56-29.bpo-45731.9SDnDf.rst new file mode 100644 index 0000000000000..1e490fac6ee5d --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-05-20-56-29.bpo-45731.9SDnDf.rst @@ -0,0 +1 @@ +``configure --enable-loadable-sqlite-extensions`` is now handled by new ``PY_SQLITE_ENABLE_LOAD_EXTENSION`` macro instead of logic in setup.py. diff --git a/Modules/_sqlite/clinic/connection.c.h b/Modules/_sqlite/clinic/connection.c.h index f9323eb21d6f4..4e5ee500ad18e 100644 --- a/Modules/_sqlite/clinic/connection.c.h +++ b/Modules/_sqlite/clinic/connection.c.h @@ -367,7 +367,7 @@ pysqlite_connection_set_trace_callback(pysqlite_Connection *self, PyTypeObject * return return_value; } -#if !defined(SQLITE_OMIT_LOAD_EXTENSION) +#if defined(PY_SQLITE_ENABLE_LOAD_EXTENSION) PyDoc_STRVAR(pysqlite_connection_enable_load_extension__doc__, "enable_load_extension($self, enable, /)\n" @@ -398,9 +398,9 @@ pysqlite_connection_enable_load_extension(pysqlite_Connection *self, PyObject *a return return_value; } -#endif /* !defined(SQLITE_OMIT_LOAD_EXTENSION) */ +#endif /* defined(PY_SQLITE_ENABLE_LOAD_EXTENSION) */ -#if !defined(SQLITE_OMIT_LOAD_EXTENSION) +#if defined(PY_SQLITE_ENABLE_LOAD_EXTENSION) PyDoc_STRVAR(pysqlite_connection_load_extension__doc__, "load_extension($self, name, /)\n" @@ -440,7 +440,7 @@ pysqlite_connection_load_extension(pysqlite_Connection *self, PyObject *arg) return return_value; } -#endif /* !defined(SQLITE_OMIT_LOAD_EXTENSION) */ +#endif /* defined(PY_SQLITE_ENABLE_LOAD_EXTENSION) */ PyDoc_STRVAR(pysqlite_connection_execute__doc__, "execute($self, sql, parameters=, /)\n" @@ -834,4 +834,4 @@ getlimit(pysqlite_Connection *self, PyObject *arg) #ifndef PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF #define PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF #endif /* !defined(PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF) */ -/*[clinic end generated code: output=0c3901153a3837a5 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d71bf16bef67878f input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index f913267e1560e..964673a6125f3 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -1225,7 +1225,7 @@ pysqlite_connection_set_trace_callback_impl(pysqlite_Connection *self, Py_RETURN_NONE; } -#ifndef SQLITE_OMIT_LOAD_EXTENSION +#ifdef PY_SQLITE_ENABLE_LOAD_EXTENSION /*[clinic input] _sqlite3.Connection.enable_load_extension as pysqlite_connection_enable_load_extension diff --git a/configure b/configure index 00bea712b0633..1eea2d1320578 100755 --- a/configure +++ b/configure @@ -10913,13 +10913,20 @@ $as_echo_n "checking for --enable-loadable-sqlite-extensions... " >&6; } if test "${enable_loadable_sqlite_extensions+set}" = set; then : enableval=$enable_loadable_sqlite_extensions; else - enable_loadable_sqlite_extensions="no" + enable_loadable_sqlite_extensions=no fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_loadable_sqlite_extensions" >&5 $as_echo "$enable_loadable_sqlite_extensions" >&6; } +if test "x$enable_loadable_sqlite_extensions" = xyes; then : + + +$as_echo "#define PY_SQLITE_ENABLE_LOAD_EXTENSION 1" >>confdefs.h + + +fi + # Check for --with-tcltk-includes=path and --with-tcltk-libs=path diff --git a/configure.ac b/configure.ac index ea119085ab157..8895818d19da6 100644 --- a/configure.ac +++ b/configure.ac @@ -3199,10 +3199,14 @@ AC_ARG_ENABLE(loadable-sqlite-extensions, AS_HELP_STRING([--enable-loadable-sqlite-extensions], [support loadable extensions in _sqlite module, see Doc/library/sqlite3.rst (default is no)]), [], - [enable_loadable_sqlite_extensions="no"]) - + [enable_loadable_sqlite_extensions=no]) AC_MSG_RESULT($enable_loadable_sqlite_extensions) +AS_VAR_IF([enable_loadable_sqlite_extensions], [yes], [ + AC_DEFINE(PY_SQLITE_ENABLE_LOAD_EXTENSION, 1, + [Define to 1 to build the sqlite module with loadable extensions support.]) +]) + # Check for --with-tcltk-includes=path and --with-tcltk-libs=path AC_SUBST(TCLTK_INCLUDES) AC_SUBST(TCLTK_LIBS) diff --git a/pyconfig.h.in b/pyconfig.h.in index b89377dc1b44d..0c149e24bca5f 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -1395,6 +1395,9 @@ /* Define to printf format modifier for Py_ssize_t */ #undef PY_FORMAT_SIZE_T +/* Define to 1 to build the sqlite module with loadable extensions support. */ +#undef PY_SQLITE_ENABLE_LOAD_EXTENSION + /* Default cipher suites list for ssl module. 1: Python's preferred selection, 2: leave OpenSSL defaults untouched, 0: custom string */ #undef PY_SSL_DEFAULT_CIPHERS diff --git a/setup.py b/setup.py index 22c5ccf0a073a..b6bf8e129373b 100644 --- a/setup.py +++ b/setup.py @@ -1602,9 +1602,11 @@ def detect_sqlite(self): # Enable support for loadable extensions in the sqlite3 module # if --enable-loadable-sqlite-extensions configure option is used. - if '--enable-loadable-sqlite-extensions' not in sysconfig.get_config_var("CONFIG_ARGS"): - sqlite_defines.append(("SQLITE_OMIT_LOAD_EXTENSION", "1")) - elif MACOS and sqlite_incdir == os.path.join(MACOS_SDK_ROOT, "usr/include"): + if ( + MACOS and + sqlite_incdir == os.path.join(MACOS_SDK_ROOT, "usr/include") and + sysconfig.get_config_var("PY_SQLITE_ENABLE_LOAD_EXTENSION") + ): raise DistutilsError("System version of SQLite does not support loadable extensions") if MACOS: From webhook-mailer at python.org Sat Nov 6 13:11:43 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 06 Nov 2021 17:11:43 -0000 Subject: [Python-checkins] bpo-45644: Make json.tool read infile before writing to outfile (GH-29273) Message-ID: https://github.com/python/cpython/commit/815dad42d53fc40a6dc057e067f4a8a885c3b858 commit: 815dad42d53fc40a6dc057e067f4a8a885c3b858 branch: main author: Chris Wesseling committer: ambv date: 2021-11-06T18:11:35+01:00 summary: bpo-45644: Make json.tool read infile before writing to outfile (GH-29273) so that $ python -m json.tool foo.json foo.json doesn't result in an empty foo.json. Co-authored-by: ?ukasz Langa files: A Misc/NEWS.d/next/Library/2021-11-06-17-47-46.bpo-45644.ZMqHD_.rst M Lib/json/tool.py M Lib/test/test_json/test_tool.py diff --git a/Lib/json/tool.py b/Lib/json/tool.py index 5dee0a744b2a9..0490b8c0be11d 100644 --- a/Lib/json/tool.py +++ b/Lib/json/tool.py @@ -13,6 +13,7 @@ import argparse import json import sys +from pathlib import Path def main(): @@ -25,9 +26,9 @@ def main(): help='a JSON file to be validated or pretty-printed', default=sys.stdin) parser.add_argument('outfile', nargs='?', - type=argparse.FileType('w', encoding="utf-8"), + type=Path, help='write the output of infile to outfile', - default=sys.stdout) + default=None) parser.add_argument('--sort-keys', action='store_true', default=False, help='sort the output of dictionaries alphabetically by key') parser.add_argument('--no-ensure-ascii', dest='ensure_ascii', action='store_false', @@ -58,15 +59,21 @@ def main(): dump_args['indent'] = None dump_args['separators'] = ',', ':' - with options.infile as infile, options.outfile as outfile: + with options.infile as infile: try: if options.json_lines: objs = (json.loads(line) for line in infile) else: - objs = (json.load(infile), ) - for obj in objs: - json.dump(obj, outfile, **dump_args) - outfile.write('\n') + objs = (json.load(infile),) + + if options.outfile is None: + out = sys.stdout + else: + out = options.outfile.open('w', encoding='utf-8') + with out as outfile: + for obj in objs: + json.dump(obj, outfile, **dump_args) + outfile.write('\n') except ValueError as e: raise SystemExit(e) diff --git a/Lib/test/test_json/test_tool.py b/Lib/test/test_json/test_tool.py index 0386690cad95b..1d7fca6efb1cc 100644 --- a/Lib/test/test_json/test_tool.py +++ b/Lib/test/test_json/test_tool.py @@ -131,6 +131,15 @@ def test_infile_outfile(self): self.assertEqual(out, b'') self.assertEqual(err, b'') + def test_writing_in_place(self): + infile = self._create_infile() + rc, out, err = assert_python_ok('-m', 'json.tool', infile, infile) + with open(infile, "r", encoding="utf-8") as fp: + self.assertEqual(fp.read(), self.expect) + self.assertEqual(rc, 0) + self.assertEqual(out, b'') + self.assertEqual(err, b'') + def test_jsonlines(self): args = sys.executable, '-m', 'json.tool', '--json-lines' process = subprocess.run(args, input=self.jsonlines_raw, capture_output=True, text=True, check=True) diff --git a/Misc/NEWS.d/next/Library/2021-11-06-17-47-46.bpo-45644.ZMqHD_.rst b/Misc/NEWS.d/next/Library/2021-11-06-17-47-46.bpo-45644.ZMqHD_.rst new file mode 100644 index 0000000000000..2cf4eae02c449 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-06-17-47-46.bpo-45644.ZMqHD_.rst @@ -0,0 +1,3 @@ +In-place JSON file formatting using ``python3 -m json.tool infile infile`` +now works correctly, previously it left the file empty. Patch by Chris +Wesseling. From webhook-mailer at python.org Sat Nov 6 13:16:51 2021 From: webhook-mailer at python.org (ethanfurman) Date: Sat, 06 Nov 2021 17:16:51 -0000 Subject: [Python-checkins] bpo-45740: [Enum] add versionadded markers to docs (GH-29443) Message-ID: https://github.com/python/cpython/commit/cb755dba7a988f92a7d1cad48f3c27df18c9342d commit: cb755dba7a988f92a7d1cad48f3c27df18c9342d branch: main author: Ethan Furman committer: ethanfurman date: 2021-11-06T10:16:43-07:00 summary: bpo-45740: [Enum] add versionadded markers to docs (GH-29443) [Enum] add versionadded markers to docs files: M Doc/howto/enum.rst M Doc/library/enum.rst diff --git a/Doc/howto/enum.rst b/Doc/howto/enum.rst index d9cfad972cfa9..b0b17b1669f1a 100644 --- a/Doc/howto/enum.rst +++ b/Doc/howto/enum.rst @@ -636,7 +636,7 @@ an incorrect member:: Before :class:`StrEnum`, ``Directions.NORTH`` would have been the :class:`tuple` ``('north',)``. -.. versionadded:: 3.10 +.. versionadded:: 3.11 IntFlag @@ -659,7 +659,7 @@ used. details. .. versionadded:: 3.6 -.. versionchanged:: 3.10 +.. versionchanged:: 3.11 Sample :class:`IntFlag` class:: @@ -696,7 +696,7 @@ It is also possible to name the combinations:: Named combinations are considered aliases. Aliases do not show up during iteration, but can be returned from by-value lookups. -.. versionchanged:: 3.10 +.. versionchanged:: 3.11 Another important difference between :class:`IntFlag` and :class:`Enum` is that if no flags are set (the value is 0), its boolean evaluation is :data:`False`:: @@ -728,7 +728,7 @@ be combined with them (but may lose :class:`IntFlag` membership:: >>> list(RW) [Perm.R, Perm.W] -.. versionadded:: 3.10 +.. versionadded:: 3.11 Flag @@ -789,7 +789,7 @@ value:: >>> list(purple) [Color.RED, Color.BLUE] -.. versionadded:: 3.10 +.. versionadded:: 3.11 .. note:: @@ -939,7 +939,7 @@ _Private__names :ref:`Private names ` are not converted to enum members, but remain normal attributes. -.. versionchanged:: 3.10 +.. versionchanged:: 3.11 ``Enum`` member type @@ -962,7 +962,6 @@ it will raise a :exc:`DeprecationWarning`:: .. versionchanged:: 3.5 -.. versionchanged:: 3.10 Creating members that are mixed with other data types diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst index 86bf705af77e7..850b491680c68 100644 --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -397,6 +397,7 @@ Data Types Using :class:`auto` with :class:`StrEnum` results in values of the member name, lower-cased. +.. versionadded:: 3.11 .. class:: Flag From webhook-mailer at python.org Sat Nov 6 13:26:52 2021 From: webhook-mailer at python.org (ethanfurman) Date: Sat, 06 Nov 2021 17:26:52 -0000 Subject: [Python-checkins] [doc] minor fixes to expressions.rst (GH-29444) Message-ID: https://github.com/python/cpython/commit/6ecead106ad886f423abf4f547a1a54d14e32305 commit: 6ecead106ad886f423abf4f547a1a54d14e32305 branch: main author: Ethan Furman committer: ethanfurman date: 2021-11-06T10:26:43-07:00 summary: [doc] minor fixes to expressions.rst (GH-29444) files: M Doc/reference/expressions.rst diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index d21a44431e52a..6108c46236217 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -965,8 +965,8 @@ formal parameters. If there are N positional arguments, they are placed in the first N slots. Next, for each keyword argument, the identifier is used to determine the corresponding slot (if the identifier is the same as the first formal parameter name, the first slot is used, and so on). If the slot is -already filled, a :exc:`TypeError` exception is raised. Otherwise, the value of -the argument is placed in the slot, filling it (even if the expression is +already filled, a :exc:`TypeError` exception is raised. Otherwise, the +argument is placed in the slot, filling it (even if the expression is ``None``, it fills the slot). When all arguments have been processed, the slots that are still unfilled are filled with the corresponding default value from the function definition. (Default values are calculated, once, when the function is @@ -1026,7 +1026,7 @@ keyword arguments (and any ``**expression`` arguments -- see below). So:: 1 2 It is unusual for both keyword arguments and the ``*expression`` syntax to be -used in the same call, so in practice this confusion does not arise. +used in the same call, so in practice this confusion does not often arise. .. index:: single: **; in function calls From webhook-mailer at python.org Sat Nov 6 14:00:57 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 06 Nov 2021 18:00:57 -0000 Subject: [Python-checkins] [doc] bpo-45680: Improve glossary entry for generic types (GH-29388) Message-ID: https://github.com/python/cpython/commit/77a2c77c84d2ead2d19f96df862c119308e90071 commit: 77a2c77c84d2ead2d19f96df862c119308e90071 branch: main author: Alex Waygood committer: ambv date: 2021-11-06T19:00:45+01:00 summary: [doc] bpo-45680: Improve glossary entry for generic types (GH-29388) Co-authored-by: ?ukasz Langa files: M Doc/glossary.rst diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 1f14946fa1342..ccbfc0e6c36c7 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -510,12 +510,13 @@ Glossary :func:`functools.singledispatch` decorator, and :pep:`443`. generic type - A :term:`type` that can be parameterized; typically a container like - :class:`list`. Used for :term:`type hints ` and + A :term:`type` that can be parameterized; typically a + :ref:`container class` such as :class:`list` or + :class:`dict`. Used for :term:`type hints ` and :term:`annotations `. - See :pep:`483` for more details, and :mod:`typing` or - :ref:`generic alias type ` for its uses. + For more details, see :ref:`generic alias types`, + :pep:`483`, :pep:`484`, :pep:`585`, and the :mod:`typing` module. GIL See :term:`global interpreter lock`. From webhook-mailer at python.org Sat Nov 6 14:01:27 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 06 Nov 2021 18:01:27 -0000 Subject: [Python-checkins] bpo-45644: Make json.tool read infile before writing to outfile (GH-29273) (GH-29445) Message-ID: https://github.com/python/cpython/commit/6603f6b5bdf0ed164bad4eb432619da2e95fb518 commit: 6603f6b5bdf0ed164bad4eb432619da2e95fb518 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-06T19:01:17+01:00 summary: bpo-45644: Make json.tool read infile before writing to outfile (GH-29273) (GH-29445) so that $ python -m json.tool foo.json foo.json doesn't result in an empty foo.json. Co-authored-by: ?ukasz Langa (cherry picked from commit 815dad42d53fc40a6dc057e067f4a8a885c3b858) Co-authored-by: Chris Wesseling files: A Misc/NEWS.d/next/Library/2021-11-06-17-47-46.bpo-45644.ZMqHD_.rst M Lib/json/tool.py M Lib/test/test_json/test_tool.py diff --git a/Lib/json/tool.py b/Lib/json/tool.py index 5dee0a744b2a9..0490b8c0be11d 100644 --- a/Lib/json/tool.py +++ b/Lib/json/tool.py @@ -13,6 +13,7 @@ import argparse import json import sys +from pathlib import Path def main(): @@ -25,9 +26,9 @@ def main(): help='a JSON file to be validated or pretty-printed', default=sys.stdin) parser.add_argument('outfile', nargs='?', - type=argparse.FileType('w', encoding="utf-8"), + type=Path, help='write the output of infile to outfile', - default=sys.stdout) + default=None) parser.add_argument('--sort-keys', action='store_true', default=False, help='sort the output of dictionaries alphabetically by key') parser.add_argument('--no-ensure-ascii', dest='ensure_ascii', action='store_false', @@ -58,15 +59,21 @@ def main(): dump_args['indent'] = None dump_args['separators'] = ',', ':' - with options.infile as infile, options.outfile as outfile: + with options.infile as infile: try: if options.json_lines: objs = (json.loads(line) for line in infile) else: - objs = (json.load(infile), ) - for obj in objs: - json.dump(obj, outfile, **dump_args) - outfile.write('\n') + objs = (json.load(infile),) + + if options.outfile is None: + out = sys.stdout + else: + out = options.outfile.open('w', encoding='utf-8') + with out as outfile: + for obj in objs: + json.dump(obj, outfile, **dump_args) + outfile.write('\n') except ValueError as e: raise SystemExit(e) diff --git a/Lib/test/test_json/test_tool.py b/Lib/test/test_json/test_tool.py index 0386690cad95b..1d7fca6efb1cc 100644 --- a/Lib/test/test_json/test_tool.py +++ b/Lib/test/test_json/test_tool.py @@ -131,6 +131,15 @@ def test_infile_outfile(self): self.assertEqual(out, b'') self.assertEqual(err, b'') + def test_writing_in_place(self): + infile = self._create_infile() + rc, out, err = assert_python_ok('-m', 'json.tool', infile, infile) + with open(infile, "r", encoding="utf-8") as fp: + self.assertEqual(fp.read(), self.expect) + self.assertEqual(rc, 0) + self.assertEqual(out, b'') + self.assertEqual(err, b'') + def test_jsonlines(self): args = sys.executable, '-m', 'json.tool', '--json-lines' process = subprocess.run(args, input=self.jsonlines_raw, capture_output=True, text=True, check=True) diff --git a/Misc/NEWS.d/next/Library/2021-11-06-17-47-46.bpo-45644.ZMqHD_.rst b/Misc/NEWS.d/next/Library/2021-11-06-17-47-46.bpo-45644.ZMqHD_.rst new file mode 100644 index 0000000000000..2cf4eae02c449 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-06-17-47-46.bpo-45644.ZMqHD_.rst @@ -0,0 +1,3 @@ +In-place JSON file formatting using ``python3 -m json.tool infile infile`` +now works correctly, previously it left the file empty. Patch by Chris +Wesseling. From webhook-mailer at python.org Sat Nov 6 14:01:54 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 06 Nov 2021 18:01:54 -0000 Subject: [Python-checkins] bpo-45644: Make json.tool read infile before writing to outfile (GH-29273) (GH-29446) Message-ID: https://github.com/python/cpython/commit/a932631890d148444e5f9b09f4b57305475d6386 commit: a932631890d148444e5f9b09f4b57305475d6386 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-06T19:01:44+01:00 summary: bpo-45644: Make json.tool read infile before writing to outfile (GH-29273) (GH-29446) so that $ python -m json.tool foo.json foo.json doesn't result in an empty foo.json. Co-authored-by: ?ukasz Langa (cherry picked from commit 815dad42d53fc40a6dc057e067f4a8a885c3b858) Co-authored-by: Chris Wesseling files: A Misc/NEWS.d/next/Library/2021-11-06-17-47-46.bpo-45644.ZMqHD_.rst M Lib/json/tool.py M Lib/test/test_json/test_tool.py diff --git a/Lib/json/tool.py b/Lib/json/tool.py index 5dee0a744b2a9..0490b8c0be11d 100644 --- a/Lib/json/tool.py +++ b/Lib/json/tool.py @@ -13,6 +13,7 @@ import argparse import json import sys +from pathlib import Path def main(): @@ -25,9 +26,9 @@ def main(): help='a JSON file to be validated or pretty-printed', default=sys.stdin) parser.add_argument('outfile', nargs='?', - type=argparse.FileType('w', encoding="utf-8"), + type=Path, help='write the output of infile to outfile', - default=sys.stdout) + default=None) parser.add_argument('--sort-keys', action='store_true', default=False, help='sort the output of dictionaries alphabetically by key') parser.add_argument('--no-ensure-ascii', dest='ensure_ascii', action='store_false', @@ -58,15 +59,21 @@ def main(): dump_args['indent'] = None dump_args['separators'] = ',', ':' - with options.infile as infile, options.outfile as outfile: + with options.infile as infile: try: if options.json_lines: objs = (json.loads(line) for line in infile) else: - objs = (json.load(infile), ) - for obj in objs: - json.dump(obj, outfile, **dump_args) - outfile.write('\n') + objs = (json.load(infile),) + + if options.outfile is None: + out = sys.stdout + else: + out = options.outfile.open('w', encoding='utf-8') + with out as outfile: + for obj in objs: + json.dump(obj, outfile, **dump_args) + outfile.write('\n') except ValueError as e: raise SystemExit(e) diff --git a/Lib/test/test_json/test_tool.py b/Lib/test/test_json/test_tool.py index fc2a7a4fca3c5..d441bb15a7e8f 100644 --- a/Lib/test/test_json/test_tool.py +++ b/Lib/test/test_json/test_tool.py @@ -130,6 +130,15 @@ def test_infile_outfile(self): self.assertEqual(out, b'') self.assertEqual(err, b'') + def test_writing_in_place(self): + infile = self._create_infile() + rc, out, err = assert_python_ok('-m', 'json.tool', infile, infile) + with open(infile, "r", encoding="utf-8") as fp: + self.assertEqual(fp.read(), self.expect) + self.assertEqual(rc, 0) + self.assertEqual(out, b'') + self.assertEqual(err, b'') + def test_jsonlines(self): args = sys.executable, '-m', 'json.tool', '--json-lines' process = subprocess.run(args, input=self.jsonlines_raw, capture_output=True, text=True, check=True) diff --git a/Misc/NEWS.d/next/Library/2021-11-06-17-47-46.bpo-45644.ZMqHD_.rst b/Misc/NEWS.d/next/Library/2021-11-06-17-47-46.bpo-45644.ZMqHD_.rst new file mode 100644 index 0000000000000..2cf4eae02c449 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-06-17-47-46.bpo-45644.ZMqHD_.rst @@ -0,0 +1,3 @@ +In-place JSON file formatting using ``python3 -m json.tool infile infile`` +now works correctly, previously it left the file empty. Patch by Chris +Wesseling. From webhook-mailer at python.org Sat Nov 6 14:09:27 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 06 Nov 2021 18:09:27 -0000 Subject: [Python-checkins] bpo-39452: [doc] Change "must" to "can" on relative import style in `__main__` (GH-29379) Message-ID: https://github.com/python/cpython/commit/57457a1e5caf714034a75fe4f382b8b669ce6ed8 commit: 57457a1e5caf714034a75fe4f382b8b669ce6ed8 branch: main author: Andre Delfino committer: ambv date: 2021-11-06T19:09:23+01:00 summary: bpo-39452: [doc] Change "must" to "can" on relative import style in `__main__` (GH-29379) files: M Doc/library/__main__.rst diff --git a/Doc/library/__main__.rst b/Doc/library/__main__.rst index 116a9a9d1d729..d92266e43b961 100644 --- a/Doc/library/__main__.rst +++ b/Doc/library/__main__.rst @@ -231,7 +231,7 @@ students:: print(f'Found student: {search_students(student_name)}') Note that ``from .student import search_students`` is an example of a relative -import. This import style must be used when referencing modules within a +import. This import style can be used when referencing modules within a package. For more details, see :ref:`intra-package-references` in the :ref:`tut-modules` section of the tutorial. From webhook-mailer at python.org Sat Nov 6 14:21:44 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 06 Nov 2021 18:21:44 -0000 Subject: [Python-checkins] [doc] bpo-45680: Improve glossary entry for generic types (GH-29388) (GH-29447) Message-ID: https://github.com/python/cpython/commit/494f8da741054e5bab33f23f3961400ea5778235 commit: 494f8da741054e5bab33f23f3961400ea5778235 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-06T19:21:36+01:00 summary: [doc] bpo-45680: Improve glossary entry for generic types (GH-29388) (GH-29447) Co-authored-by: ?ukasz Langa (cherry picked from commit 77a2c77c84d2ead2d19f96df862c119308e90071) Co-authored-by: Alex Waygood files: M Doc/glossary.rst diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 652f8d919607f..40b57bd41e8c6 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -520,12 +520,13 @@ Glossary :func:`functools.singledispatch` decorator, and :pep:`443`. generic type - A :term:`type` that can be parameterized; typically a container like - :class:`list`. Used for :term:`type hints ` and + A :term:`type` that can be parameterized; typically a + :ref:`container class` such as :class:`list` or + :class:`dict`. Used for :term:`type hints ` and :term:`annotations `. - See :pep:`483` for more details, and :mod:`typing` or - :ref:`generic alias type ` for its uses. + For more details, see :ref:`generic alias types`, + :pep:`483`, :pep:`484`, :pep:`585`, and the :mod:`typing` module. GIL See :term:`global interpreter lock`. From webhook-mailer at python.org Sat Nov 6 14:50:09 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 06 Nov 2021 18:50:09 -0000 Subject: [Python-checkins] bpo-39452: [doc] Change "must" to "can" on relative import style in `__main__` (GH-29379) (GH-29449) Message-ID: https://github.com/python/cpython/commit/e53cb9811f97ded5a20872fe0f3486bc7f8f1b6e commit: e53cb9811f97ded5a20872fe0f3486bc7f8f1b6e branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-06T19:50:00+01:00 summary: bpo-39452: [doc] Change "must" to "can" on relative import style in `__main__` (GH-29379) (GH-29449) (cherry picked from commit 57457a1e5caf714034a75fe4f382b8b669ce6ed8) Co-authored-by: Andre Delfino files: M Doc/library/__main__.rst diff --git a/Doc/library/__main__.rst b/Doc/library/__main__.rst index 116a9a9d1d729..d92266e43b961 100644 --- a/Doc/library/__main__.rst +++ b/Doc/library/__main__.rst @@ -231,7 +231,7 @@ students:: print(f'Found student: {search_students(student_name)}') Note that ``from .student import search_students`` is an example of a relative -import. This import style must be used when referencing modules within a +import. This import style can be used when referencing modules within a package. For more details, see :ref:`intra-package-references` in the :ref:`tut-modules` section of the tutorial. From webhook-mailer at python.org Sat Nov 6 14:50:23 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 06 Nov 2021 18:50:23 -0000 Subject: [Python-checkins] [doc] bpo-45680: Improve glossary entry for generic types (GH-29388) (GH-29448) Message-ID: https://github.com/python/cpython/commit/643f50ca5e9e12a4d8269ddc8baf2279d8608745 commit: 643f50ca5e9e12a4d8269ddc8baf2279d8608745 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-06T19:50:18+01:00 summary: [doc] bpo-45680: Improve glossary entry for generic types (GH-29388) (GH-29448) Co-authored-by: ?ukasz Langa (cherry picked from commit 77a2c77c84d2ead2d19f96df862c119308e90071) Co-authored-by: Alex Waygood files: M Doc/glossary.rst diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 96d33ac1abb83..da9dc9ceebfc4 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -485,12 +485,13 @@ Glossary :func:`functools.singledispatch` decorator, and :pep:`443`. generic type - A :term:`type` that can be parameterized; typically a container like - :class:`list`. Used for :term:`type hints ` and + A :term:`type` that can be parameterized; typically a + :ref:`container class` such as :class:`list` or + :class:`dict`. Used for :term:`type hints ` and :term:`annotations `. - See :pep:`483` for more details, and :mod:`typing` or - :ref:`generic alias type ` for its uses. + For more details, see :ref:`generic alias types`, + :pep:`483`, :pep:`484`, :pep:`585`, and the :mod:`typing` module. GIL See :term:`global interpreter lock`. From webhook-mailer at python.org Sat Nov 6 15:01:48 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 06 Nov 2021 19:01:48 -0000 Subject: [Python-checkins] bpo-27313: Use non-deprecated methods for tracing (GH-29425) Message-ID: https://github.com/python/cpython/commit/cc1cbcbb2d75cacc31ff3359d83043bc7bd5a89d commit: cc1cbcbb2d75cacc31ff3359d83043bc7bd5a89d branch: main author: Serhiy Storchaka committer: ambv date: 2021-11-06T20:01:39+01:00 summary: bpo-27313: Use non-deprecated methods for tracing (GH-29425) files: M Lib/tkinter/test/test_ttk/test_extensions.py diff --git a/Lib/tkinter/test/test_ttk/test_extensions.py b/Lib/tkinter/test/test_ttk/test_extensions.py index 7fc1ebb95c970..1220c4831c52f 100644 --- a/Lib/tkinter/test/test_ttk/test_extensions.py +++ b/Lib/tkinter/test/test_ttk/test_extensions.py @@ -307,14 +307,14 @@ def test_trace_variable(self): items = ('a', 'b', 'c') textvar = tkinter.StringVar(self.root) def cb_test(*args): - self.assertEqual(textvar.get(), items[1]) - success.append(True) + success.append(textvar.get()) optmenu = ttk.OptionMenu(self.root, textvar, "a", *items) optmenu.pack() - cb_name = textvar.trace("w", cb_test) + cb_name = textvar.trace_add("write", cb_test) optmenu['menu'].invoke(1) - self.assertEqual(success, [True]) - textvar.trace_vdelete("w", cb_name) + self.assertEqual(success, ['b']) + self.assertEqual(textvar.get(), 'b') + textvar.trace_remove("write", cb_name) optmenu.destroy() From webhook-mailer at python.org Sat Nov 6 15:08:52 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 06 Nov 2021 19:08:52 -0000 Subject: [Python-checkins] bpo-45392: Update the docstring of the 'type' built-in (GH-29439) Message-ID: https://github.com/python/cpython/commit/91275207296c39e495fe118019a757c4ddefede8 commit: 91275207296c39e495fe118019a757c4ddefede8 branch: main author: Mark Dickinson committer: ambv date: 2021-11-06T20:08:44+01:00 summary: bpo-45392: Update the docstring of the 'type' built-in (GH-29439) files: A Misc/NEWS.d/next/Documentation/2021-11-06-10-54-17.bpo-45392.JZnVOz.rst M Objects/typeobject.c diff --git a/Misc/NEWS.d/next/Documentation/2021-11-06-10-54-17.bpo-45392.JZnVOz.rst b/Misc/NEWS.d/next/Documentation/2021-11-06-10-54-17.bpo-45392.JZnVOz.rst new file mode 100644 index 0000000000000..09c16578ff478 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-06-10-54-17.bpo-45392.JZnVOz.rst @@ -0,0 +1,2 @@ +Update the docstring of the :class:`type` built-in to remove a redundant +line and to mention keyword arguments for the constructor. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 51ec93d875271..4180a9d13c45f 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -4268,10 +4268,8 @@ static PyMethodDef type_methods[] = { }; PyDoc_STRVAR(type_doc, -/* this text signature cannot be accurate yet. will fix. --larry */ -"type(object_or_name, bases, dict)\n" "type(object) -> the object's type\n" -"type(name, bases, dict) -> a new type"); +"type(name, bases, dict, **kwds) -> a new type"); static int type_traverse(PyTypeObject *type, visitproc visit, void *arg) From webhook-mailer at python.org Sat Nov 6 15:23:05 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 06 Nov 2021 19:23:05 -0000 Subject: [Python-checkins] bpo-27313: Use non-deprecated methods for tracing (GH-29425) (GH-29450) Message-ID: https://github.com/python/cpython/commit/8fdf6c64d3e0183c21f069d31d350a907ce42708 commit: 8fdf6c64d3e0183c21f069d31d350a907ce42708 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-06T20:23:00+01:00 summary: bpo-27313: Use non-deprecated methods for tracing (GH-29425) (GH-29450) (cherry picked from commit cc1cbcbb2d75cacc31ff3359d83043bc7bd5a89d) Co-authored-by: Serhiy Storchaka files: M Lib/tkinter/test/test_ttk/test_extensions.py diff --git a/Lib/tkinter/test/test_ttk/test_extensions.py b/Lib/tkinter/test/test_ttk/test_extensions.py index 7fc1ebb95c970..1220c4831c52f 100644 --- a/Lib/tkinter/test/test_ttk/test_extensions.py +++ b/Lib/tkinter/test/test_ttk/test_extensions.py @@ -307,14 +307,14 @@ def test_trace_variable(self): items = ('a', 'b', 'c') textvar = tkinter.StringVar(self.root) def cb_test(*args): - self.assertEqual(textvar.get(), items[1]) - success.append(True) + success.append(textvar.get()) optmenu = ttk.OptionMenu(self.root, textvar, "a", *items) optmenu.pack() - cb_name = textvar.trace("w", cb_test) + cb_name = textvar.trace_add("write", cb_test) optmenu['menu'].invoke(1) - self.assertEqual(success, [True]) - textvar.trace_vdelete("w", cb_name) + self.assertEqual(success, ['b']) + self.assertEqual(textvar.get(), 'b') + textvar.trace_remove("write", cb_name) optmenu.destroy() From webhook-mailer at python.org Sat Nov 6 15:23:32 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 06 Nov 2021 19:23:32 -0000 Subject: [Python-checkins] bpo-27313: Use non-deprecated methods for tracing (GH-29425) (GH-29451) Message-ID: https://github.com/python/cpython/commit/376218e1c65c029c24e45ca408a14f681cf1aeae commit: 376218e1c65c029c24e45ca408a14f681cf1aeae branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-06T20:23:28+01:00 summary: bpo-27313: Use non-deprecated methods for tracing (GH-29425) (GH-29451) (cherry picked from commit cc1cbcbb2d75cacc31ff3359d83043bc7bd5a89d) Co-authored-by: Serhiy Storchaka files: M Lib/tkinter/test/test_ttk/test_extensions.py diff --git a/Lib/tkinter/test/test_ttk/test_extensions.py b/Lib/tkinter/test/test_ttk/test_extensions.py index 7fc1ebb95c970..1220c4831c52f 100644 --- a/Lib/tkinter/test/test_ttk/test_extensions.py +++ b/Lib/tkinter/test/test_ttk/test_extensions.py @@ -307,14 +307,14 @@ def test_trace_variable(self): items = ('a', 'b', 'c') textvar = tkinter.StringVar(self.root) def cb_test(*args): - self.assertEqual(textvar.get(), items[1]) - success.append(True) + success.append(textvar.get()) optmenu = ttk.OptionMenu(self.root, textvar, "a", *items) optmenu.pack() - cb_name = textvar.trace("w", cb_test) + cb_name = textvar.trace_add("write", cb_test) optmenu['menu'].invoke(1) - self.assertEqual(success, [True]) - textvar.trace_vdelete("w", cb_name) + self.assertEqual(success, ['b']) + self.assertEqual(textvar.get(), 'b') + textvar.trace_remove("write", cb_name) optmenu.destroy() From webhook-mailer at python.org Sat Nov 6 16:18:08 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 06 Nov 2021 20:18:08 -0000 Subject: [Python-checkins] bpo-45392: Update the docstring of the 'type' built-in (GH-29439) (GH-29453) Message-ID: https://github.com/python/cpython/commit/f5287ecd59d83a662490f89188a0fc2ef3718f8b commit: f5287ecd59d83a662490f89188a0fc2ef3718f8b branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-06T21:17:59+01:00 summary: bpo-45392: Update the docstring of the 'type' built-in (GH-29439) (GH-29453) (cherry picked from commit 91275207296c39e495fe118019a757c4ddefede8) Co-authored-by: Mark Dickinson files: A Misc/NEWS.d/next/Documentation/2021-11-06-10-54-17.bpo-45392.JZnVOz.rst M Objects/typeobject.c diff --git a/Misc/NEWS.d/next/Documentation/2021-11-06-10-54-17.bpo-45392.JZnVOz.rst b/Misc/NEWS.d/next/Documentation/2021-11-06-10-54-17.bpo-45392.JZnVOz.rst new file mode 100644 index 0000000000000..09c16578ff478 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-06-10-54-17.bpo-45392.JZnVOz.rst @@ -0,0 +1,2 @@ +Update the docstring of the :class:`type` built-in to remove a redundant +line and to mention keyword arguments for the constructor. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index feae25f2eb367..1cdf80bfcf5af 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3673,10 +3673,8 @@ static PyMethodDef type_methods[] = { }; PyDoc_STRVAR(type_doc, -/* this text signature cannot be accurate yet. will fix. --larry */ -"type(object_or_name, bases, dict)\n" "type(object) -> the object's type\n" -"type(name, bases, dict) -> a new type"); +"type(name, bases, dict, **kwds) -> a new type"); static int type_traverse(PyTypeObject *type, visitproc visit, void *arg) From webhook-mailer at python.org Sat Nov 6 16:21:13 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 06 Nov 2021 20:21:13 -0000 Subject: [Python-checkins] bpo-45392: Update the docstring of the 'type' built-in (GH-29439) (GH-29452) Message-ID: https://github.com/python/cpython/commit/045f205ba4710c4c633364a4e2e098483af936e5 commit: 045f205ba4710c4c633364a4e2e098483af936e5 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-06T21:21:04+01:00 summary: bpo-45392: Update the docstring of the 'type' built-in (GH-29439) (GH-29452) (cherry picked from commit 91275207296c39e495fe118019a757c4ddefede8) Co-authored-by: Mark Dickinson files: A Misc/NEWS.d/next/Documentation/2021-11-06-10-54-17.bpo-45392.JZnVOz.rst M Objects/typeobject.c diff --git a/Misc/NEWS.d/next/Documentation/2021-11-06-10-54-17.bpo-45392.JZnVOz.rst b/Misc/NEWS.d/next/Documentation/2021-11-06-10-54-17.bpo-45392.JZnVOz.rst new file mode 100644 index 0000000000000..09c16578ff478 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-06-10-54-17.bpo-45392.JZnVOz.rst @@ -0,0 +1,2 @@ +Update the docstring of the :class:`type` built-in to remove a redundant +line and to mention keyword arguments for the constructor. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index dc06cf0a0c11b..02046e5f2ebef 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -4221,10 +4221,8 @@ static PyMethodDef type_methods[] = { }; PyDoc_STRVAR(type_doc, -/* this text signature cannot be accurate yet. will fix. --larry */ -"type(object_or_name, bases, dict)\n" "type(object) -> the object's type\n" -"type(name, bases, dict) -> a new type"); +"type(name, bases, dict, **kwds) -> a new type"); static int type_traverse(PyTypeObject *type, visitproc visit, void *arg) From webhook-mailer at python.org Sun Nov 7 05:18:50 2021 From: webhook-mailer at python.org (tiran) Date: Sun, 07 Nov 2021 10:18:50 -0000 Subject: [Python-checkins] bpo-45723: Detect missing pkg-config (GH-29442) Message-ID: https://github.com/python/cpython/commit/be3cd5c05d9fb1d1cdb55cb98ca6ef8f866774be commit: be3cd5c05d9fb1d1cdb55cb98ca6ef8f866774be branch: main author: Christian Heimes committer: tiran date: 2021-11-07T11:18:45+01:00 summary: bpo-45723: Detect missing pkg-config (GH-29442) files: A Misc/NEWS.d/next/Build/2021-11-07-10-36-12.bpo-45723.JNwKSG.rst M configure M configure.ac diff --git a/Misc/NEWS.d/next/Build/2021-11-07-10-36-12.bpo-45723.JNwKSG.rst b/Misc/NEWS.d/next/Build/2021-11-07-10-36-12.bpo-45723.JNwKSG.rst new file mode 100644 index 0000000000000..0e06560fcbab9 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-07-10-36-12.bpo-45723.JNwKSG.rst @@ -0,0 +1 @@ +``configure`` now prints a warning when pkg-config is missing. diff --git a/configure b/configure index 1eea2d1320578..7c34a60763d6b 100755 --- a/configure +++ b/configure @@ -2777,7 +2777,6 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu - if test "$srcdir" != . -a "$srcdir" != "$(pwd)"; then # If we're building out-of-tree, we need to make sure the following # resources get picked up before their $srcdir counterparts. @@ -19574,6 +19573,11 @@ $SHELL $srcdir/Modules/makesetup -c $srcdir/Modules/config.c.in \ Modules/Setup.local $srcdir/Modules/Setup mv config.c Modules +if test -z "$PKG_CONFIG"; then + echo "" >&6 + echo "pkg-config is missing. Some dependencies may not be detected correctly." >&6 +fi + if test "$Py_OPT" = 'false' -a "$Py_DEBUG" != 'true'; then echo "" >&6 echo "" >&6 diff --git a/configure.ac b/configure.ac index 8895818d19da6..d7699dc4ea90d 100644 --- a/configure.ac +++ b/configure.ac @@ -16,7 +16,12 @@ m4_ifdef( [AX_C_FLOAT_WORDS_BIGENDIAN], [], [AC_MSG_ERROR([Please install autoconf-archive package and re-run autoreconf])] -) +)dnl +m4_ifdef( + [PKG_PROG_PKG_CONFIG], + [], + [AC_MSG_ERROR([Please install pkgconf's m4 macro package and re-run autoreconf])] +)dnl AC_SUBST(BASECPPFLAGS) if test "$srcdir" != . -a "$srcdir" != "$(pwd)"; then @@ -6114,6 +6119,11 @@ $SHELL $srcdir/Modules/makesetup -c $srcdir/Modules/config.c.in \ Modules/Setup.local $srcdir/Modules/Setup mv config.c Modules +if test -z "$PKG_CONFIG"; then + echo "" >&AS_MESSAGE_FD + echo "pkg-config is missing. Some dependencies may not be detected correctly." >&AS_MESSAGE_FD +fi + if test "$Py_OPT" = 'false' -a "$Py_DEBUG" != 'true'; then echo "" >&AS_MESSAGE_FD echo "" >&AS_MESSAGE_FD From webhook-mailer at python.org Sun Nov 7 18:44:19 2021 From: webhook-mailer at python.org (zware) Date: Sun, 07 Nov 2021 23:44:19 -0000 Subject: [Python-checkins] General cleanup of test_pydoc (GH-29459) Message-ID: https://github.com/python/cpython/commit/fd41125f0f1bd73e0137580d4a5bfaeaef87c283 commit: fd41125f0f1bd73e0137580d4a5bfaeaef87c283 branch: main author: Zachary Ware committer: zware date: 2021-11-07T17:44:11-06:00 summary: General cleanup of test_pydoc (GH-29459) - Uniform usage of `test.support.requires_docstrings` instead of a local check for `-OO`. - Added `requires_docstrings` to a couple more methods that need it. - Replaced a few instances of `test.test_pydoc` with `__name__` to allow for different methods of running just this test file. - Rewrote `test_server` to run faster and better test the server. - Removed unused import. - Removed unused locals. - Minor whitespace cleanups. files: M Lib/test/test_pydoc.py diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py index 0a7d72c768424..057780d51f9ac 100644 --- a/Lib/test/test_pydoc.py +++ b/Lib/test/test_pydoc.py @@ -10,10 +10,8 @@ import pkgutil import re import stat -import string import tempfile import test.support -import time import types import typing import unittest @@ -23,6 +21,7 @@ import textwrap from io import StringIO from collections import namedtuple +from urllib.request import urlopen, urlcleanup from test.support import import_helper from test.support import os_helper from test.support.script_helper import assert_python_ok, assert_python_failure @@ -379,8 +378,6 @@ def call_url_handler(self, url, expected_title): class PydocDocTest(unittest.TestCase): maxDiff = None - @unittest.skipIf(sys.flags.optimize >= 2, - "Docstrings are omitted with -O2 and above") @unittest.skipIf(hasattr(sys, 'gettrace') and sys.gettrace(), 'trace function introduces __locals__ unexpectedly') @requires_docstrings @@ -396,9 +393,6 @@ def test_html_doc(self): self.assertIn(mod_file, result) self.assertIn(doc_loc, result) - - @unittest.skipIf(sys.flags.optimize >= 2, - "Docstrings are omitted with -O2 and above") @unittest.skipIf(hasattr(sys, 'gettrace') and sys.gettrace(), 'trace function introduces __locals__ unexpectedly') @requires_docstrings @@ -457,8 +451,7 @@ def test_not_here(self): self.assertEqual(expected, result, "documentation for missing module found") - @unittest.skipIf(sys.flags.optimize >= 2, - 'Docstrings are omitted with -OO and above') + @requires_docstrings def test_not_ascii(self): result = run_pydoc('test.test_pydoc.nonascii', PYTHONIOENCODING='ascii') encoded = nonascii.__doc__.encode('ascii', 'backslashreplace') @@ -612,15 +605,12 @@ def test_builtin_on_metaclasses(self): # Testing that the subclasses section does not appear self.assertNotIn('Built-in subclasses', text) - @unittest.skipIf(sys.flags.optimize >= 2, - 'Docstrings are omitted with -O2 and above') @unittest.skipIf(hasattr(sys, 'gettrace') and sys.gettrace(), 'trace function introduces __locals__ unexpectedly') @requires_docstrings def test_help_output_redirect(self): # issue 940286, if output is set in Helper, then all output from # Helper.help should be redirected - old_pattern = expected_text_pattern getpager_old = pydoc.getpager getpager_new = lambda: (lambda x: x) self.maxDiff = None @@ -682,8 +672,7 @@ def test_synopsis(self): synopsis = pydoc.synopsis(TESTFN, {}) self.assertEqual(synopsis, 'line 1: h\xe9') - @unittest.skipIf(sys.flags.optimize >= 2, - 'Docstrings are omitted with -OO and above') + @requires_docstrings def test_synopsis_sourceless(self): os = import_helper.import_fresh_module('os') expected = os.__doc__.splitlines()[0] @@ -745,6 +734,7 @@ def method_returning_true(self): methods = pydoc.allmethods(TestClass) self.assertDictEqual(methods, expected) + @requires_docstrings def test_method_aliases(self): class A: def tkraise(self, aboveThis=None): @@ -801,10 +791,10 @@ class B(A) ''' % __name__) doc = pydoc.render_doc(B, renderer=pydoc.HTMLDoc()) - expected_text = """ + expected_text = f""" Python Library Documentation -class B in module test.test_pydoc +class B in module {__name__} class B(A) Method resolution order: B @@ -1210,12 +1200,12 @@ def __get__(self, obj, cls): class X: attr = Descr() - self.assertEqual(self._get_summary_lines(X.attr), """\ -.Descr object>""") + self.assertEqual(self._get_summary_lines(X.attr), f"""\ +<{__name__}.TestDescriptions.test_custom_non_data_descriptor..Descr object>""") X.attr.__doc__ = 'Custom descriptor' - self.assertEqual(self._get_summary_lines(X.attr), """\ -.Descr object> + self.assertEqual(self._get_summary_lines(X.attr), f"""\ +<{__name__}.TestDescriptions.test_custom_non_data_descriptor..Descr object> Custom descriptor """) @@ -1274,6 +1264,7 @@ async def an_async_generator(): 'async an_async_generator', html) + @requires_docstrings def test_html_for_https_links(self): def a_fn_with_https_link(): """a link https://localhost/""" @@ -1285,29 +1276,43 @@ def a_fn_with_https_link(): html ) + class PydocServerTest(unittest.TestCase): """Tests for pydoc._start_server""" def test_server(self): - - # Minimal test that starts the server, then stops it. + # Minimal test that starts the server, checks that it works, then stops + # it and checks its cleanup. def my_url_handler(url, content_type): text = 'the URL sent was: (%s, %s)' % (url, content_type) return text - serverthread = pydoc._start_server(my_url_handler, hostname='0.0.0.0', port=0) - self.assertIn('0.0.0.0', serverthread.docserver.address) - - starttime = time.monotonic() - timeout = test.support.SHORT_TIMEOUT + serverthread = pydoc._start_server( + my_url_handler, + hostname='localhost', + port=0, + ) + self.assertEqual(serverthread.error, None) + self.assertTrue(serverthread.serving) + self.addCleanup( + lambda: serverthread.stop() if serverthread.serving else None + ) + self.assertIn('localhost', serverthread.url) - while serverthread.serving: - time.sleep(.01) - if serverthread.serving and time.monotonic() - starttime > timeout: - serverthread.stop() - break + self.addCleanup(urlcleanup) + self.assertEqual( + b'the URL sent was: (/test, text/html)', + urlopen(urllib.parse.urljoin(serverthread.url, '/test')).read(), + ) + self.assertEqual( + b'the URL sent was: (/test.css, text/css)', + urlopen(urllib.parse.urljoin(serverthread.url, '/test.css')).read(), + ) - self.assertEqual(serverthread.error, None) + serverthread.stop() + self.assertFalse(serverthread.serving) + self.assertIsNone(serverthread.docserver) + self.assertIsNone(serverthread.url) class PydocUrlHandlerTest(PydocBaseTest): @@ -1346,11 +1351,11 @@ def test_keywords(self): self.assertEqual(sorted(pydoc.Helper.keywords), sorted(keyword.kwlist)) + class PydocWithMetaClasses(unittest.TestCase): - @unittest.skipIf(sys.flags.optimize >= 2, - "Docstrings are omitted with -O2 and above") @unittest.skipIf(hasattr(sys, 'gettrace') and sys.gettrace(), 'trace function introduces __locals__ unexpectedly') + @requires_docstrings def test_DynamicClassAttribute(self): class Meta(type): def __getattr__(self, name): @@ -1371,10 +1376,9 @@ def ham(self): result = output.getvalue().strip() self.assertEqual(expected_text, result) - @unittest.skipIf(sys.flags.optimize >= 2, - "Docstrings are omitted with -O2 and above") @unittest.skipIf(hasattr(sys, 'gettrace') and sys.gettrace(), 'trace function introduces __locals__ unexpectedly') + @requires_docstrings def test_virtualClassAttributeWithOneMeta(self): class Meta(type): def __dir__(cls): @@ -1392,10 +1396,9 @@ class Class(metaclass=Meta): result = output.getvalue().strip() self.assertEqual(expected_text, result) - @unittest.skipIf(sys.flags.optimize >= 2, - "Docstrings are omitted with -O2 and above") @unittest.skipIf(hasattr(sys, 'gettrace') and sys.gettrace(), 'trace function introduces __locals__ unexpectedly') + @requires_docstrings def test_virtualClassAttributeWithTwoMeta(self): class Meta1(type): def __dir__(cls): @@ -1424,7 +1427,6 @@ class Class1(metaclass=Meta1): pass class Class2(Class1, metaclass=Meta3): pass - fail1 = fail2 = False output = StringIO() helper = pydoc.Helper(output=output) helper(Class1) @@ -1438,10 +1440,9 @@ class Class2(Class1, metaclass=Meta3): result2 = output.getvalue().strip() self.assertEqual(expected_text2, result2) - @unittest.skipIf(sys.flags.optimize >= 2, - "Docstrings are omitted with -O2 and above") @unittest.skipIf(hasattr(sys, 'gettrace') and sys.gettrace(), 'trace function introduces __locals__ unexpectedly') + @requires_docstrings def test_buggy_dir(self): class M(type): def __dir__(cls): @@ -1502,7 +1503,6 @@ def test_sys_path_adjustment_removes_argv0_dir(self): trailing_argv0dir = clean_path + [self.argv0dir] self.assertEqual(self._get_revised_path(trailing_argv0dir), expected_path) - def test_sys_path_adjustment_protects_pydoc_dir(self): def _get_revised_path(given_path): return self._get_revised_path(given_path, argv0=pydoc.__file__) From webhook-mailer at python.org Mon Nov 8 01:03:53 2021 From: webhook-mailer at python.org (miss-islington) Date: Mon, 08 Nov 2021 06:03:53 -0000 Subject: [Python-checkins] bpo-45741: docs: fix plural (GH-29461) Message-ID: https://github.com/python/cpython/commit/19b107e9b52dbd73f4c52adcb91e8185a53b45ae commit: 19b107e9b52dbd73f4c52adcb91e8185a53b45ae branch: main author: Rafael Fontenelle committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-07T22:03:44-08:00 summary: bpo-45741: docs: fix plural (GH-29461) "entry points provides" -> "entry points provide" Automerge-Triggered-By: GH:ericvsmith files: M Doc/whatsnew/3.10.rst diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index b1040d4888ed8..a30fd2d0c0c05 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -1182,7 +1182,7 @@ Feature parity with ``importlib_metadata`` 4.6 (`history `_). :ref:`importlib.metadata entry points ` -now provides a nicer experience +now provide a nicer experience for selecting entry points by group and name through a new :class:`importlib.metadata.EntryPoints` class. See the Compatibility Note in the docs for more info on the deprecation and usage. From webhook-mailer at python.org Mon Nov 8 01:32:35 2021 From: webhook-mailer at python.org (ericvsmith) Date: Mon, 08 Nov 2021 06:32:35 -0000 Subject: [Python-checkins] bpo-45741: docs: fix plural (GH-29461) (GH-29463) Message-ID: https://github.com/python/cpython/commit/77afb76942ea7067d74d9c07fb4da6f5f23ad2f5 commit: 77afb76942ea7067d74d9c07fb4da6f5f23ad2f5 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ericvsmith date: 2021-11-08T01:32:23-05:00 summary: bpo-45741: docs: fix plural (GH-29461) (GH-29463) "entry points provides" -> "entry points provide" Automerge-Triggered-By: GH:ericvsmith (cherry picked from commit 19b107e9b52dbd73f4c52adcb91e8185a53b45ae) Co-authored-by: Rafael Fontenelle Co-authored-by: Rafael Fontenelle files: M Doc/whatsnew/3.10.rst diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index 5ac45c50c27c3..4ee193f158fde 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -1171,7 +1171,7 @@ Feature parity with ``importlib_metadata`` 4.6 (`history `_). :ref:`importlib.metadata entry points ` -now provides a nicer experience +now provide a nicer experience for selecting entry points by group and name through a new :class:`importlib.metadata.EntryPoints` class. See the Compatibility Note in the docs for more info on the deprecation and usage. From webhook-mailer at python.org Mon Nov 8 02:06:41 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 08 Nov 2021 07:06:41 -0000 Subject: [Python-checkins] bpo-45723: Add helper macros and more caching to configure.ac (GH-29429) Message-ID: https://github.com/python/cpython/commit/57c50c9c7c701a8301c5a89b2b2d050550f62022 commit: 57c50c9c7c701a8301c5a89b2b2d050550f62022 branch: main author: Christian Heimes committer: tiran date: 2021-11-08T08:06:31+01:00 summary: bpo-45723: Add helper macros and more caching to configure.ac (GH-29429) Almost all checks are now cached by AC_CACHE_CHECK(). Common patterns are replaced by helper macros. Variable names now use naming scheme ``ac_cv_func_$funcname``, ``ac_cv_lib_$library_$funcname``, or ``ac_cv_header_$headername_h``. ``SYS_SELECT_WITH_SYS_TIME`` is no longer used. ``uuid_create`` and ``uuid_enc_be`` are provided by libc on BSD. It is safe to use ``AC_CHECK_FUNCS`` here. Caching speeds up ./configure -C from ~ 4s to 2.6s on my system. Co-authored-by: Erlend Egeberg Aasland files: A Misc/NEWS.d/next/Build/2021-11-05-15-09-49.bpo-45723.gfSxur.rst M configure M configure.ac M pyconfig.h.in diff --git a/Misc/NEWS.d/next/Build/2021-11-05-15-09-49.bpo-45723.gfSxur.rst b/Misc/NEWS.d/next/Build/2021-11-05-15-09-49.bpo-45723.gfSxur.rst new file mode 100644 index 0000000000000..bd6666aad34d6 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-05-15-09-49.bpo-45723.gfSxur.rst @@ -0,0 +1,2 @@ +configure.ac now uses custom helper macros and ``AC_CACHE_CHECK`` to +simplify and speed up configure runs. diff --git a/configure b/configure index 7c34a60763d6b..48d8bfd0899ff 100755 --- a/configure +++ b/configure @@ -8478,31 +8478,43 @@ done # checks for typedefs -was_it_defined=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_t in time.h" >&5 $as_echo_n "checking for clock_t in time.h... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ${ac_cv_clock_t_time_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "clock_t" >/dev/null 2>&1; then : - was_it_defined=yes + ac_cv_clock_t_time_h=yes else + ac_cv_clock_t_time_h=no +fi +rm -f conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_clock_t_time_h" >&5 +$as_echo "$ac_cv_clock_t_time_h" >&6; } +if test "x$ac_cv_clock_t_time_h" = xno; then : $as_echo "#define clock_t long" >>confdefs.h fi -rm -f conftest* - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $was_it_defined" >&5 -$as_echo "$was_it_defined" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for makedev" >&5 $as_echo_n "checking for makedev... " >&6; } +if ${ac_cv_func_makedev+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -8525,23 +8537,32 @@ main () _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ac_cv_has_makedev=yes + ac_cv_func_makedev=yes else - ac_cv_has_makedev=no + ac_cv_func_makedev=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_has_makedev" >&5 -$as_echo "$ac_cv_has_makedev" >&6; } -if test "$ac_cv_has_makedev" = "yes"; then + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_makedev" >&5 +$as_echo "$ac_cv_func_makedev" >&6; } + +if test "x$ac_cv_func_makedev" = xyes; then : + $as_echo "#define HAVE_MAKEDEV 1" >>confdefs.h + fi # byte swapping { $as_echo "$as_me:${as_lineno-$LINENO}: checking for le64toh" >&5 $as_echo_n "checking for le64toh... " >&6; } +if ${ac_cv_func_le64toh+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -8562,18 +8583,23 @@ main () _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ac_cv_has_le64toh=yes + ac_cv_func_le64toh=yes else - ac_cv_has_le64toh=no + ac_cv_func_le64toh=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_has_le64toh" >&5 -$as_echo "$ac_cv_has_le64toh" >&6; } -if test "$ac_cv_has_le64toh" = "yes"; then + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_le64toh" >&5 +$as_echo "$ac_cv_func_le64toh" >&6; } + +if test "x$ac_cv_func_le64toh" = xyes; then : + $as_echo "#define HAVE_HTOLE64 1" >>confdefs.h + fi use_lfs=yes @@ -9356,7 +9382,10 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_t" >&5 $as_echo_n "checking for pthread_t... " >&6; } -have_pthread_t=no +if ${ac_cv_have_pthread_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -9371,12 +9400,17 @@ pthread_t x; x = *(pthread_t*)0; _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - have_pthread_t=yes + ac_cv_have_pthread_t=yes +else + ac_cv_have_pthread_t=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_pthread_t" >&5 -$as_echo "$have_pthread_t" >&6; } -if test "$have_pthread_t" = yes ; then + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_pthread_t" >&5 +$as_echo "$ac_cv_have_pthread_t" >&6; } +if test "x$ac_cv_have_pthread_t" = xyes; then : + # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. @@ -9415,6 +9449,7 @@ cat >>confdefs.h <<_ACEOF _ACEOF + fi # Issue #25658: POSIX hasn't defined that pthread_key_t is compatible with int. @@ -9455,6 +9490,10 @@ _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthread_key_t is compatible with int" >&5 $as_echo_n "checking whether pthread_key_t is compatible with int... " >&6; } +if ${ac_cv_pthread_key_t_is_arithmetic_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$ac_cv_sizeof_pthread_key_t" -eq "$ac_cv_sizeof_int" ; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -9468,23 +9507,27 @@ pthread_key_t k; k * 1; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ac_pthread_key_t_is_arithmetic_type=yes + ac_cv_pthread_key_t_is_arithmetic_type=yes else - ac_pthread_key_t_is_arithmetic_type=no + ac_cv_pthread_key_t_is_arithmetic_type=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pthread_key_t_is_arithmetic_type" >&5 -$as_echo "$ac_pthread_key_t_is_arithmetic_type" >&6; } - if test "$ac_pthread_key_t_is_arithmetic_type" = yes ; then +else + ac_cv_pthread_key_t_is_arithmetic_type=no +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_pthread_key_t_is_arithmetic_type" >&5 +$as_echo "$ac_cv_pthread_key_t_is_arithmetic_type" >&6; } +if test "x$ac_cv_pthread_key_t_is_arithmetic_type" = xyes; then : + $as_echo "#define PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT 1" >>confdefs.h - fi -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + fi + CC="$ac_save_cc" @@ -10130,6 +10173,10 @@ done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time_safe" >&5 $as_echo_n "checking for uuid_generate_time_safe... " >&6; } +if ${ac_cv_lib_uuid_uuid_generate_time_safe+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include @@ -10146,17 +10193,22 @@ void *x = uuid_generate_time_safe } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_lib_uuid_uuid_generate_time_safe=yes +else + ac_cv_lib_uuid_uuid_generate_time_safe=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_uuid_uuid_generate_time_safe" >&5 +$as_echo "$ac_cv_lib_uuid_uuid_generate_time_safe" >&6; } +if test "x$ac_cv_lib_uuid_uuid_generate_time_safe" = xyes; then : + $as_echo "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # check for libuuid from util-linux save_LIBS=$LIBS @@ -10209,67 +10261,20 @@ LIBS=$save_LIBS # AIX provides support for RFC4122 (uuid) in libc.a starting with AIX 6.1 (anno 2007) # FreeBSD and OpenBSD provides support in libc as well. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_create" >&5 -$as_echo_n "checking for uuid_create... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ - -#ifndef uuid_create -void *x = uuid_create -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - -$as_echo "#define HAVE_UUID_CREATE 1" >>confdefs.h - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - # Little-endian FreeBSD, OpenBSD and NetBSD needs encoding into an octet # stream in big-endian byte-order -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_enc_be" >&5 -$as_echo_n "checking for uuid_enc_be... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ - -#ifndef uuid_enc_be -void *x = uuid_enc_be -#endif - - ; - return 0; -} +for ac_func in uuid_create uuid_enc_be +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - -$as_echo "#define HAVE_UUID_ENC_BE 1" >>confdefs.h - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +done + # 'Real Time' functions on Solaris # posix4 on Solaris 2.6 @@ -11680,8 +11685,13 @@ if test "$ipv6" = "yes" -a "$ipv6lib" != "none"; then fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CAN_RAW_FD_FRAMES" >&5 -$as_echo_n "checking for CAN_RAW_FD_FRAMES... " >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking CAN_RAW_FD_FRAMES" >&5 +$as_echo_n "checking CAN_RAW_FD_FRAMES... " >&6; } +if ${ac_cv_can_raw_fd_frames+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* CAN_RAW_FD_FRAMES available check */ @@ -11695,23 +11705,29 @@ int can_raw_fd_frames = CAN_RAW_FD_FRAMES; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_can_raw_fd_frames=yes +else + ac_cv_can_raw_fd_frames=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_can_raw_fd_frames" >&5 +$as_echo "$ac_cv_can_raw_fd_frames" >&6; } +if test "x$ac_cv_can_raw_fd_frames" = xyes; then : -$as_echo "#define HAVE_LINUX_CAN_RAW_FD_FRAMES 1" >>confdefs.h - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else +$as_echo "#define HAVE_LINUX_CAN_RAW_FD_FRAMES 1" >>confdefs.h - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CAN_RAW_JOIN_FILTERS" >&5 $as_echo_n "checking for CAN_RAW_JOIN_FILTERS... " >&6; } +if ${ac_cv_can_raw_join_filters+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -11725,20 +11741,22 @@ int can_raw_join_filters = CAN_RAW_JOIN_FILTERS; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_can_raw_join_filters=yes +else + ac_cv_can_raw_join_filters=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_can_raw_join_filters" >&5 +$as_echo "$ac_cv_can_raw_join_filters" >&6; } +if test "x$ac_cv_can_raw_join_filters" = xyes; then : -$as_echo "#define HAVE_LINUX_CAN_RAW_JOIN_FILTERS 1" >>confdefs.h - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else +$as_echo "#define HAVE_LINUX_CAN_RAW_JOIN_FILTERS 1" >>confdefs.h - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Check for --with-doc-strings { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-doc-strings" >&5 @@ -12085,11 +12103,18 @@ $as_echo "#define HAVE_DIRFD 1" >>confdefs.h fi + + # For some functions, having a definition is not sufficient, since # we want to take their address. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for chroot" >&5 + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for chroot" >&5 $as_echo_n "checking for chroot... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ${ac_cv_func_chroot+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int @@ -12101,20 +12126,31 @@ void *x=chroot } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_chroot=yes +else + ac_cv_func_chroot=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_CHROOT 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_chroot" >&5 +$as_echo "$ac_cv_func_chroot" >&6; } + if test "x$ac_cv_func_chroot" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_CHROOT 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for link" >&5 + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for link" >&5 $as_echo_n "checking for link... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ${ac_cv_func_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int @@ -12126,20 +12162,31 @@ void *x=link } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_link=yes +else + ac_cv_func_link=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_LINK 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_link" >&5 +$as_echo "$ac_cv_func_link" >&6; } + if test "x$ac_cv_func_link" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_LINK 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for symlink" >&5 + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for symlink" >&5 $as_echo_n "checking for symlink... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ${ac_cv_func_symlink+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int @@ -12151,20 +12198,31 @@ void *x=symlink } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_symlink=yes +else + ac_cv_func_symlink=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_SYMLINK 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_symlink" >&5 +$as_echo "$ac_cv_func_symlink" >&6; } + if test "x$ac_cv_func_symlink" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_SYMLINK 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fchdir" >&5 + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fchdir" >&5 $as_echo_n "checking for fchdir... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ${ac_cv_func_fchdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int @@ -12176,20 +12234,31 @@ void *x=fchdir } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_fchdir=yes +else + ac_cv_func_fchdir=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_FCHDIR 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fchdir" >&5 +$as_echo "$ac_cv_func_fchdir" >&6; } + if test "x$ac_cv_func_fchdir" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_FCHDIR 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fsync" >&5 + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fsync" >&5 $as_echo_n "checking for fsync... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ${ac_cv_func_fsync+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int @@ -12201,20 +12270,31 @@ void *x=fsync } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_fsync=yes +else + ac_cv_func_fsync=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_FSYNC 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fsync" >&5 +$as_echo "$ac_cv_func_fsync" >&6; } + if test "x$ac_cv_func_fsync" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_FSYNC 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fdatasync" >&5 -$as_echo_n "checking for fdatasync... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fdatasync" >&5 +$as_echo_n "checking for fdatasync... " >&6; } +if ${ac_cv_func_fdatasync+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int @@ -12226,45 +12306,67 @@ void *x=fdatasync } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_fdatasync=yes +else + ac_cv_func_fdatasync=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_FDATASYNC 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fdatasync" >&5 +$as_echo "$ac_cv_func_fdatasync" >&6; } + if test "x$ac_cv_func_fdatasync" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_FDATASYNC 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for epoll" >&5 + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for epoll" >&5 $as_echo_n "checking for epoll... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ${ac_cv_func_epoll+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { -void *x=epoll_create +void *x=epoll ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_epoll=yes +else + ac_cv_func_epoll=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_EPOLL 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_epoll" >&5 +$as_echo "$ac_cv_func_epoll" >&6; } + if test "x$ac_cv_func_epoll" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_EPOLL 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for epoll_create1" >&5 + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for epoll_create1" >&5 $as_echo_n "checking for epoll_create1... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ${ac_cv_func_epoll_create1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int @@ -12276,20 +12378,31 @@ void *x=epoll_create1 } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_epoll_create1=yes +else + ac_cv_func_epoll_create1=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_EPOLL_CREATE1 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_epoll_create1" >&5 +$as_echo "$ac_cv_func_epoll_create1" >&6; } + if test "x$ac_cv_func_epoll_create1" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_EPOLL_CREATE1 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for kqueue" >&5 + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for kqueue" >&5 $as_echo_n "checking for kqueue... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ${ac_cv_func_kqueue+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include @@ -12298,26 +12411,37 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext int main () { -int x=kqueue() +void *x=kqueue ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_kqueue=yes +else + ac_cv_func_kqueue=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_KQUEUE 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_kqueue" >&5 +$as_echo "$ac_cv_func_kqueue" >&6; } + if test "x$ac_cv_func_kqueue" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_KQUEUE 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for prlimit" >&5 + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for prlimit" >&5 $as_echo_n "checking for prlimit... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ${ac_cv_func_prlimit+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include @@ -12332,20 +12456,32 @@ void *x=prlimit } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_prlimit=yes +else + ac_cv_func_prlimit=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_PRLIMIT 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_prlimit" >&5 +$as_echo "$ac_cv_func_prlimit" >&6; } + if test "x$ac_cv_func_prlimit" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_PRLIMIT 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _dyld_shared_cache_contains_path" >&5 + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _dyld_shared_cache_contains_path" >&5 $as_echo_n "checking for _dyld_shared_cache_contains_path... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ${ac_cv_func__dyld_shared_cache_contains_path+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int @@ -12357,21 +12493,32 @@ void *x=_dyld_shared_cache_contains_path } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func__dyld_shared_cache_contains_path=yes +else + ac_cv_func__dyld_shared_cache_contains_path=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func__dyld_shared_cache_contains_path" >&5 +$as_echo "$ac_cv_func__dyld_shared_cache_contains_path" >&6; } + if test "x$ac_cv_func__dyld_shared_cache_contains_path" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for memfd_create" >&5 + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for memfd_create" >&5 $as_echo_n "checking for memfd_create... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ${ac_cv_func_memfd_create+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef HAVE_SYS_MMAN_H @@ -12390,21 +12537,32 @@ void *x=memfd_create } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_memfd_create=yes +else + ac_cv_func_memfd_create=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_MEMFD_CREATE 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_memfd_create" >&5 +$as_echo "$ac_cv_func_memfd_create" >&6; } + if test "x$ac_cv_func_memfd_create" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_MEMFD_CREATE 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for eventfd" >&5 + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for eventfd" >&5 $as_echo_n "checking for eventfd... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ${ac_cv_func_eventfd+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef HAVE_SYS_EVENTFD_H @@ -12414,23 +12572,29 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext int main () { -int x = eventfd(0, EFD_CLOEXEC) +void *x=eventfd ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_eventfd=yes +else + ac_cv_func_eventfd=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_EVENTFD 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_eventfd" >&5 +$as_echo "$ac_cv_func_eventfd" >&6; } + if test "x$ac_cv_func_eventfd" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_EVENTFD 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + + # On some systems (eg. FreeBSD 5), we would find a definition of the # functions ctermid_r, setgroups in the library, but no prototype @@ -12438,33 +12602,42 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # address to avoid compiler warnings and potential miscompilations # because of the missing prototypes. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ctermid_r" >&5 + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ctermid_r" >&5 $as_echo_n "checking for ctermid_r... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ${ac_cv_func_ctermid_r+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #include - int main () { -void* p = ctermid_r +void *x=ctermid_r ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_ctermid_r=yes +else + ac_cv_func_ctermid_r=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_CTERMID_R 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_ctermid_r" >&5 +$as_echo "$ac_cv_func_ctermid_r" >&6; } + if test "x$ac_cv_func_ctermid_r" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_CTERMID_R 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for flock declaration" >&5 $as_echo_n "checking for flock declaration... " >&6; } @@ -12555,41 +12728,51 @@ done fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getpagesize" >&5 + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getpagesize" >&5 $as_echo_n "checking for getpagesize... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ${ac_cv_func_getpagesize+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #include - int main () { -void* p = getpagesize +void *x=getpagesize ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_getpagesize=yes +else + ac_cv_func_getpagesize=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_GETPAGESIZE 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_getpagesize" >&5 +$as_echo "$ac_cv_func_getpagesize" >&6; } + if test "x$ac_cv_func_getpagesize" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_GETPAGESIZE 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for broken unsetenv" >&5 $as_echo_n "checking for broken unsetenv... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ${ac_cv_broken_unsetenv+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #include - int main () { @@ -12599,17 +12782,23 @@ int res = unsetenv("DUMMY") } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + ac_cv_broken_unsetenv=no else + ac_cv_broken_unsetenv=yes + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_broken_unsetenv" >&5 +$as_echo "$ac_cv_broken_unsetenv" >&6; } +if test "x$ac_cv_broken_unsetenv" = xyes; then : + $as_echo "#define HAVE_BROKEN_UNSETENV 1" >>confdefs.h - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext for ac_prog in true do @@ -12843,6 +13032,7 @@ $as_echo "#define HAVE_LCHFLAGS 1" >>confdefs.h fi +# Check for compression libraries case $ac_sys_system/$ac_sys_release in Darwin/*) _CUR_CFLAGS="${CFLAGS}" @@ -12902,38 +13092,51 @@ Darwin/*) ;; esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for hstrerror" >&5 + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for hstrerror" >&5 $as_echo_n "checking for hstrerror... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ${ac_cv_func_hstrerror+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #include - int main () { -void* p = hstrerror; hstrerror(0) +void *x=hstrerror ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_hstrerror=yes +else + ac_cv_func_hstrerror=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_HSTRERROR 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_hstrerror" >&5 +$as_echo "$ac_cv_func_hstrerror" >&6; } + if test "x$ac_cv_func_hstrerror" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_HSTRERROR 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_aton" >&5 + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_aton" >&5 $as_echo_n "checking for inet_aton... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ${ac_cv_func_inet_aton+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include @@ -12944,28 +13147,38 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext int main () { -void* p = inet_aton;inet_aton(0,0) +void *x=inet_aton ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_inet_aton=yes +else + ac_cv_func_inet_aton=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_INET_ATON 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_inet_aton" >&5 +$as_echo "$ac_cv_func_inet_aton" >&6; } + if test "x$ac_cv_func_inet_aton" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_INET_ATON 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_pton" >&5 + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_pton" >&5 $as_echo_n "checking for inet_pton... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ${ac_cv_func_inet_pton+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include @@ -12976,28 +13189,39 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext int main () { -void* p = inet_pton +void *x=inet_pton ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_inet_pton=yes +else + ac_cv_func_inet_pton=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_INET_PTON 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_inet_pton" >&5 +$as_echo "$ac_cv_func_inet_pton" >&6; } + if test "x$ac_cv_func_inet_pton" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_INET_PTON 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + + # On some systems, setgroups is in unistd.h, on others, in grp.h -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for setgroups" >&5 + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for setgroups" >&5 $as_echo_n "checking for setgroups... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ${ac_cv_func_setgroups+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include @@ -13008,23 +13232,29 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext int main () { -void* p = setgroups +void *x=setgroups ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_setgroups=yes +else + ac_cv_func_setgroups=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_SETGROUPS 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_setgroups" >&5 +$as_echo "$ac_cv_func_setgroups" >&6; } + if test "x$ac_cv_func_setgroups" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_SETGROUPS 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + + # check for openpty and forkpty @@ -13749,8 +13979,12 @@ fi done -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for major" >&5 -$as_echo_n "checking for major... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for major, minor, and makedev" >&5 +$as_echo_n "checking for major, minor, and makedev... " >&6; } +if ${ac_cv_device_macros+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -13773,26 +14007,36 @@ main () } _ACEOF if ac_fn_c_try_link "$LINENO"; then : + ac_cv_device_macros=yes +else + ac_cv_device_macros=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_device_macros" >&5 +$as_echo "$ac_cv_device_macros" >&6; } +if test "x$ac_cv_device_macros" = xyes; then : $as_echo "#define HAVE_DEVICE_MACROS 1" >>confdefs.h - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else +fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext +$as_echo "#define SYS_SELECT_WITH_SYS_TIME 1" >>confdefs.h + # On OSF/1 V5.1, getaddrinfo is available, but a define # for [no]getaddrinfo in netdb.h. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getaddrinfo" >&5 $as_echo_n "checking for getaddrinfo... " >&6; } +if ${ac_cv_func_getaddrinfo+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -13810,16 +14054,19 @@ getaddrinfo(NULL, NULL, NULL, NULL); } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - have_getaddrinfo=yes + ac_cv_func_getaddrinfo=yes else - have_getaddrinfo=no + ac_cv_func_getaddrinfo=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_getaddrinfo" >&5 -$as_echo "$have_getaddrinfo" >&6; } -if test $have_getaddrinfo = yes -then + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_getaddrinfo" >&5 +$as_echo "$ac_cv_func_getaddrinfo" >&6; } + +if test "x$ac_cv_func_getaddrinfo" = xyes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking getaddrinfo bug" >&5 $as_echo_n "checking getaddrinfo bug... " >&6; } if ${ac_cv_buggy_getaddrinfo+:} false; then : @@ -13937,12 +14184,14 @@ fi fi + + fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_buggy_getaddrinfo" >&5 $as_echo "$ac_cv_buggy_getaddrinfo" >&6; } -if test $have_getaddrinfo = no || test "$ac_cv_buggy_getaddrinfo" = yes +if test "$ac_cv_func_getaddrinfo" = no -o "$ac_cv_buggy_getaddrinfo" = yes then if test $ipv6 = yes then @@ -14240,36 +14489,6 @@ $as_echo "#define HAVE_ALTZONE 1" >>confdefs.h fi -was_it_defined=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether sys/select.h and sys/time.h may both be included" >&5 -$as_echo_n "checking whether sys/select.h and sys/time.h may both be included... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#include -#include -#include - -int -main () -{ -; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - - -$as_echo "#define SYS_SELECT_WITH_SYS_TIME 1" >>confdefs.h - - was_it_defined=yes - -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $was_it_defined" >&5 -$as_echo "$was_it_defined" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for addrinfo" >&5 $as_echo_n "checking for addrinfo... " >&6; } if ${ac_cv_struct_addrinfo+:} false; then : @@ -14488,9 +14707,12 @@ $as_echo "#define const /**/" >>confdefs.h fi -works=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working signed char" >&5 $as_echo_n "checking for working signed char... " >&6; } +if ${ac_cv_working_signed_char_c+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -14503,20 +14725,29 @@ signed char c; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - works=yes + ac_cv_working_signed_char_c=yes else + ac_cv_working_signed_char_c=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_signed_char_c" >&5 +$as_echo "$ac_cv_working_signed_char_c" >&6; } +if test "x$ac_cv_working_signed_char_c" = xno; then : + $as_echo "#define signed /**/" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $works" >&5 -$as_echo "$works" >&6; } -have_prototypes=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for prototypes" >&5 $as_echo_n "checking for prototypes... " >&6; } +if ${ac_cv_function_prototypes+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo(int x) { return 0; } @@ -14529,18 +14760,30 @@ return foo(10); } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_function_prototypes=yes +else + ac_cv_function_prototypes=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_function_prototypes" >&5 +$as_echo "$ac_cv_function_prototypes" >&6; } +if test "x$ac_cv_function_prototypes" = xyes; then : + $as_echo "#define HAVE_PROTOTYPES 1" >>confdefs.h - have_prototypes=yes + fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_prototypes" >&5 -$as_echo "$have_prototypes" >&6; } works=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for variable length prototypes and stdarg.h" >&5 $as_echo_n "checking for variable length prototypes and stdarg.h... " >&6; } +if ${ac_cv_stdarg_prototypes+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -14563,21 +14806,33 @@ return foo(10, "", 3.14); } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_stdarg_prototypes=yes +else + ac_cv_stdarg_prototypes=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_stdarg_prototypes" >&5 +$as_echo "$ac_cv_stdarg_prototypes" >&6; } +if test "x$ac_cv_stdarg_prototypes" = xyes; then : $as_echo "#define HAVE_STDARG_PROTOTYPES 1" >>confdefs.h - works=yes fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $works" >&5 -$as_echo "$works" >&6; } + # check for socketpair -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for socketpair" >&5 + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socketpair" >&5 $as_echo_n "checking for socketpair... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ${ac_cv_func_socketpair+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include @@ -14592,21 +14847,31 @@ void *x=socketpair } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_socketpair=yes +else + ac_cv_func_socketpair=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_SOCKETPAIR 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_socketpair" >&5 +$as_echo "$ac_cv_func_socketpair" >&6; } + if test "x$ac_cv_func_socketpair" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_SOCKETPAIR 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + + # check if sockaddr has sa_len member { $as_echo "$as_me:${as_lineno-$LINENO}: checking if sockaddr has sa_len member" >&5 $as_echo_n "checking if sockaddr has sa_len member... " >&6; } +if ${ac_cv_struct_sockaddr_sa_len+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include @@ -14621,17 +14886,22 @@ x.sa_len = 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } + ac_cv_struct_sockaddr_sa_len=yes +else + ac_cv_struct_sockaddr_sa_len=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_sockaddr_sa_len" >&5 +$as_echo "$ac_cv_struct_sockaddr_sa_len" >&6; } +if test "x$ac_cv_struct_sockaddr_sa_len" = xyes; then : + $as_echo "#define HAVE_SOCKADDR_SA_LEN 1" >>confdefs.h -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # sigh -- gethostbyname_r is a mess; it can have 3, 5 or 6 arguments :-( @@ -14898,8 +15168,13 @@ fi # * Check for gcc x64 inline assembler * # ************************************** + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for x64 gcc inline assembler" >&5 $as_echo_n "checking for x64 gcc inline assembler... " >&6; } +if ${ac_cv_gcc_asm_for_x64+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -14914,19 +15189,23 @@ main () } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - have_gcc_asm_for_x64=yes + ac_cv_gcc_asm_for_x64=yes else - have_gcc_asm_for_x64=no + ac_cv_gcc_asm_for_x64=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_gcc_asm_for_x64" >&5 -$as_echo "$have_gcc_asm_for_x64" >&6; } -if test "$have_gcc_asm_for_x64" = yes -then + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_gcc_asm_for_x64" >&5 +$as_echo "$ac_cv_gcc_asm_for_x64" >&6; } + +if test "x$ac_cv_gcc_asm_for_x64" = xyes; then : + $as_echo "#define HAVE_GCC_ASM_FOR_X64 1" >>confdefs.h + fi # ************************************************** @@ -15021,6 +15300,10 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we can use gcc inline assembler to get and set x87 control word" >&5 $as_echo_n "checking whether we can use gcc inline assembler to get and set x87 control word... " >&6; } +if ${ac_cv_gcc_asm_for_x87+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -15037,23 +15320,30 @@ main () } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - have_gcc_asm_for_x87=yes + ac_cv_gcc_asm_for_x87=yes else - have_gcc_asm_for_x87=no + ac_cv_gcc_asm_for_x87=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_gcc_asm_for_x87" >&5 -$as_echo "$have_gcc_asm_for_x87" >&6; } -if test "$have_gcc_asm_for_x87" = yes -then + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_gcc_asm_for_x87" >&5 +$as_echo "$ac_cv_gcc_asm_for_x87" >&6; } +if test "x$ac_cv_gcc_asm_for_x87" = xyes; then : + $as_echo "#define HAVE_GCC_ASM_FOR_X87 1" >>confdefs.h + fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we can use gcc inline assembler to get and set mc68881 fpcr" >&5 $as_echo_n "checking whether we can use gcc inline assembler to get and set mc68881 fpcr... " >&6; } +if ${ac_cv_gcc_asm_for_mc68881+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -15070,19 +15360,22 @@ main () } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - have_gcc_asm_for_mc68881=yes + ac_cv_gcc_asm_for_mc68881=yes else - have_gcc_asm_for_mc68881=no + ac_cv_gcc_asm_for_mc68881=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_gcc_asm_for_mc68881" >&5 -$as_echo "$have_gcc_asm_for_mc68881" >&6; } -if test "$have_gcc_asm_for_mc68881" = yes -then + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_gcc_asm_for_mc68881" >&5 +$as_echo "$ac_cv_gcc_asm_for_mc68881" >&6; } +if test "x$ac_cv_gcc_asm_for_mc68881" = xyes; then : + $as_echo "#define HAVE_GCC_ASM_FOR_MC68881 1" >>confdefs.h + fi # Detect whether system arithmetic is subject to x87-style double @@ -15092,6 +15385,10 @@ fi # 0 otherwise. See http://bugs.python.org/issue2937 for more info. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for x87-style double rounding" >&5 $as_echo_n "checking for x87-style double rounding... " >&6; } +if ${ac_cv_x87_double_rounding+:} false; then : + $as_echo_n "(cached) " >&6 +else + # $BASECFLAGS may affect the result ac_save_cc="$CC" CC="$CC $BASECFLAGS" @@ -15131,13 +15428,17 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ fi CC="$ac_save_cc" + +fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_x87_double_rounding" >&5 $as_echo "$ac_cv_x87_double_rounding" >&6; } -if test "$ac_cv_x87_double_rounding" = yes -then + +if test "x$ac_cv_x87_double_rounding" = xyes; then : + $as_echo "#define X87_DOUBLE_ROUNDING 1" >>confdefs.h + fi # ************************************ @@ -16732,324 +17033,448 @@ $as_echo "#define WINDOW_HAS_FLAGS 1" >>confdefs.h fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for is_pad" >&5 -$as_echo_n "checking for is_pad... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for curses function is_pad" >&5 +$as_echo_n "checking for curses function is_pad... " >&6; } +if ${ac_cv_lib_curses_is_pad+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { -#ifndef is_pad -void *x=is_pad -#endif + #ifndef is_pad + void *x=is_pad + #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_lib_curses_is_pad=yes +else + ac_cv_lib_curses_is_pad=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_CURSES_IS_PAD 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curses_is_pad" >&5 +$as_echo "$ac_cv_lib_curses_is_pad" >&6; } + if test "x$ac_cv_lib_curses_is_pad" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_CURSES_IS_PAD 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for is_term_resized" >&5 -$as_echo_n "checking for is_term_resized... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for curses function is_term_resized" >&5 +$as_echo_n "checking for curses function is_term_resized... " >&6; } +if ${ac_cv_lib_curses_is_term_resized+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { -void *x=is_term_resized + + #ifndef is_term_resized + void *x=is_term_resized + #endif + ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_lib_curses_is_term_resized=yes +else + ac_cv_lib_curses_is_term_resized=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_CURSES_IS_TERM_RESIZED 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curses_is_term_resized" >&5 +$as_echo "$ac_cv_lib_curses_is_term_resized" >&6; } + if test "x$ac_cv_lib_curses_is_term_resized" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_CURSES_IS_TERM_RESIZED 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for resize_term" >&5 -$as_echo_n "checking for resize_term... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for curses function resize_term" >&5 +$as_echo_n "checking for curses function resize_term... " >&6; } +if ${ac_cv_lib_curses_resize_term+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { -void *x=resize_term + + #ifndef resize_term + void *x=resize_term + #endif + ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_lib_curses_resize_term=yes +else + ac_cv_lib_curses_resize_term=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_CURSES_RESIZE_TERM 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curses_resize_term" >&5 +$as_echo "$ac_cv_lib_curses_resize_term" >&6; } + if test "x$ac_cv_lib_curses_resize_term" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_CURSES_RESIZE_TERM 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for resizeterm" >&5 -$as_echo_n "checking for resizeterm... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for curses function resizeterm" >&5 +$as_echo_n "checking for curses function resizeterm... " >&6; } +if ${ac_cv_lib_curses_resizeterm+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { -void *x=resizeterm + + #ifndef resizeterm + void *x=resizeterm + #endif + ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_lib_curses_resizeterm=yes +else + ac_cv_lib_curses_resizeterm=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_CURSES_RESIZETERM 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curses_resizeterm" >&5 +$as_echo "$ac_cv_lib_curses_resizeterm" >&6; } + if test "x$ac_cv_lib_curses_resizeterm" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_CURSES_RESIZETERM 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for immedok" >&5 -$as_echo_n "checking for immedok... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for curses function immedok" >&5 +$as_echo_n "checking for curses function immedok... " >&6; } +if ${ac_cv_lib_curses_immedok+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { -#ifndef immedok -void *x=immedok -#endif + #ifndef immedok + void *x=immedok + #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_lib_curses_immedok=yes +else + ac_cv_lib_curses_immedok=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_CURSES_IMMEDOK 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curses_immedok" >&5 +$as_echo "$ac_cv_lib_curses_immedok" >&6; } + if test "x$ac_cv_lib_curses_immedok" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_CURSES_IMMEDOK 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for syncok" >&5 -$as_echo_n "checking for syncok... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for curses function syncok" >&5 +$as_echo_n "checking for curses function syncok... " >&6; } +if ${ac_cv_lib_curses_syncok+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { -#ifndef syncok -void *x=syncok -#endif + #ifndef syncok + void *x=syncok + #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_lib_curses_syncok=yes +else + ac_cv_lib_curses_syncok=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_CURSES_SYNCOK 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curses_syncok" >&5 +$as_echo "$ac_cv_lib_curses_syncok" >&6; } + if test "x$ac_cv_lib_curses_syncok" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_CURSES_SYNCOK 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for wchgat" >&5 -$as_echo_n "checking for wchgat... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for curses function wchgat" >&5 +$as_echo_n "checking for curses function wchgat... " >&6; } +if ${ac_cv_lib_curses_wchgat+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { -#ifndef wchgat -void *x=wchgat -#endif + #ifndef wchgat + void *x=wchgat + #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_lib_curses_wchgat=yes +else + ac_cv_lib_curses_wchgat=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_CURSES_WCHGAT 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curses_wchgat" >&5 +$as_echo "$ac_cv_lib_curses_wchgat" >&6; } + if test "x$ac_cv_lib_curses_wchgat" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_CURSES_WCHGAT 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for filter" >&5 -$as_echo_n "checking for filter... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for curses function filter" >&5 +$as_echo_n "checking for curses function filter... " >&6; } +if ${ac_cv_lib_curses_filter+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { -#ifndef filter -void *x=filter -#endif + #ifndef filter + void *x=filter + #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_lib_curses_filter=yes +else + ac_cv_lib_curses_filter=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_CURSES_FILTER 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curses_filter" >&5 +$as_echo "$ac_cv_lib_curses_filter" >&6; } + if test "x$ac_cv_lib_curses_filter" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_CURSES_FILTER 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for has_key" >&5 -$as_echo_n "checking for has_key... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for curses function has_key" >&5 +$as_echo_n "checking for curses function has_key... " >&6; } +if ${ac_cv_lib_curses_has_key+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { -#ifndef has_key -void *x=has_key -#endif + #ifndef has_key + void *x=has_key + #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_lib_curses_has_key=yes +else + ac_cv_lib_curses_has_key=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_CURSES_HAS_KEY 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curses_has_key" >&5 +$as_echo "$ac_cv_lib_curses_has_key" >&6; } + if test "x$ac_cv_lib_curses_has_key" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_CURSES_HAS_KEY 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for typeahead" >&5 -$as_echo_n "checking for typeahead... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for curses function typeahead" >&5 +$as_echo_n "checking for curses function typeahead... " >&6; } +if ${ac_cv_lib_curses_typeahead+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { -#ifndef typeahead -void *x=typeahead -#endif + #ifndef typeahead + void *x=typeahead + #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_lib_curses_typeahead=yes +else + ac_cv_lib_curses_typeahead=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_CURSES_TYPEAHEAD 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curses_typeahead" >&5 +$as_echo "$ac_cv_lib_curses_typeahead" >&6; } + if test "x$ac_cv_lib_curses_typeahead" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_CURSES_TYPEAHEAD 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for use_env" >&5 -$as_echo_n "checking for use_env... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for curses function use_env" >&5 +$as_echo_n "checking for curses function use_env... " >&6; } +if ${ac_cv_lib_curses_use_env+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { -#ifndef use_env -void *x=use_env -#endif + #ifndef use_env + void *x=use_env + #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_lib_curses_use_env=yes +else + ac_cv_lib_curses_use_env=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -$as_echo "#define HAVE_CURSES_USE_ENV 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curses_use_env" >&5 +$as_echo "$ac_cv_lib_curses_use_env" >&6; } + if test "x$ac_cv_lib_curses_use_env" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } +$as_echo "#define HAVE_CURSES_USE_ENV 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -# last curses configure check + + + CPPFLAGS=$ac_save_cppflags { $as_echo "$as_me:${as_lineno-$LINENO}: checking for device files" >&5 @@ -17373,6 +17798,10 @@ $as_echo "done" >&6; } # Availability of -O2: { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -O2" >&5 $as_echo_n "checking for -O2... " >&6; } +if ${ac_cv_compile_o2+:} false; then : + $as_echo_n "(cached) " >&6 +else + saved_cflags="$CFLAGS" CFLAGS="-O2" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -17382,28 +17811,29 @@ int main () { - ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - have_O2=yes + ac_cv_compile_o2=yes else - have_O2=no + ac_cv_compile_o2=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_O2" >&5 -$as_echo "$have_O2" >&6; } CFLAGS="$saved_cflags" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_compile_o2" >&5 +$as_echo "$ac_cv_compile_o2" >&6; } + # _FORTIFY_SOURCE wrappers for memmove and bcopy are incorrect: # http://sourceware.org/ml/libc-alpha/2010-12/msg00009.html { $as_echo "$as_me:${as_lineno-$LINENO}: checking for glibc _FORTIFY_SOURCE/memmove bug" >&5 $as_echo_n "checking for glibc _FORTIFY_SOURCE/memmove bug... " >&6; } saved_cflags="$CFLAGS" CFLAGS="-O2 -D_FORTIFY_SOURCE=2" -if test "$have_O2" = no; then +if test "$ac_cv_compile_o2" = no; then CFLAGS="" fi if test "$cross_compiling" = yes; then : @@ -17446,7 +17876,7 @@ $as_echo "#define HAVE_GLIBC_MEMMOVE_BUG 1" >>confdefs.h fi -if test "$have_gcc_asm_for_x87" = yes; then +if test "$ac_cv_gcc_asm_for_x87" = yes; then # Some versions of gcc miscompile inline asm: # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46491 # http://gcc.gnu.org/ml/gcc/2010-11/msg00366.html @@ -17503,6 +17933,10 @@ fi # Check for stdatomic.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdatomic.h" >&5 $as_echo_n "checking for stdatomic.h... " >&6; } +if ${ac_cv_header_stdatomic_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -17520,25 +17954,32 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext _ACEOF if ac_fn_c_try_link "$LINENO"; then : - have_stdatomic_h=yes + ac_cv_header_stdatomic_h=yes else - have_stdatomic_h=no + ac_cv_header_stdatomic_h=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_stdatomic_h" >&5 -$as_echo "$have_stdatomic_h" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdatomic_h" >&5 +$as_echo "$ac_cv_header_stdatomic_h" >&6; } + +if test "x$ac_cv_header_stdatomic_h" = xyes; then : -if test "$have_stdatomic_h" = yes; then $as_echo "#define HAVE_STD_ATOMIC 1" >>confdefs.h + fi # Check for GCC >= 4.7 and clang __atomic builtin functions { $as_echo "$as_me:${as_lineno-$LINENO}: checking for builtin __atomic_load_n and __atomic_store_n functions" >&5 $as_echo_n "checking for builtin __atomic_load_n and __atomic_store_n functions... " >&6; } +if ${ac_cv_builtin_atomic+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -17553,20 +17994,23 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext _ACEOF if ac_fn_c_try_link "$LINENO"; then : - have_builtin_atomic=yes + ac_cv_builtin_atomic=yes else - have_builtin_atomic=no + ac_cv_builtin_atomic=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_builtin_atomic" >&5 -$as_echo "$have_builtin_atomic" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_builtin_atomic" >&5 +$as_echo "$ac_cv_builtin_atomic" >&6; } + +if test "x$ac_cv_builtin_atomic" = xyes; then : -if test "$have_builtin_atomic" = yes; then $as_echo "#define HAVE_BUILTIN_ATOMIC 1" >>confdefs.h + fi # ensurepip option @@ -17597,6 +18041,10 @@ $as_echo "$ENSUREPIP" >&6; } # check if the dirent structure of a d_type field and DT_UNKNOWN is defined { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the dirent structure of a d_type field" >&5 $as_echo_n "checking if the dirent structure of a d_type field... " >&6; } +if ${ac_cv_dirent_d_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -17611,24 +18059,32 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext _ACEOF if ac_fn_c_try_link "$LINENO"; then : - have_dirent_d_type=yes + ac_cv_dirent_d_type=yes else - have_dirent_d_type=no + ac_cv_dirent_d_type=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_dirent_d_type" >&5 -$as_echo "$have_dirent_d_type" >&6; } -if test "$have_dirent_d_type" = yes; then +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_dirent_d_type" >&5 +$as_echo "$ac_cv_dirent_d_type" >&6; } + +if test "x$ac_cv_dirent_d_type" = xyes; then : + $as_echo "#define HAVE_DIRENT_D_TYPE 1" >>confdefs.h + fi # check if the Linux getrandom() syscall is available { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the Linux getrandom() syscall" >&5 $as_echo_n "checking for the Linux getrandom() syscall... " >&6; } +if ${ac_cv_getrandom_syscall+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -17649,25 +18105,33 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext _ACEOF if ac_fn_c_try_link "$LINENO"; then : - have_getrandom_syscall=yes + ac_cv_getrandom_syscall=yes else - have_getrandom_syscall=no + ac_cv_getrandom_syscall=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_getrandom_syscall" >&5 -$as_echo "$have_getrandom_syscall" >&6; } -if test "$have_getrandom_syscall" = yes; then +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_getrandom_syscall" >&5 +$as_echo "$ac_cv_getrandom_syscall" >&6; } + +if test "x$ac_cv_getrandom_syscall" = xyes; then : + $as_echo "#define HAVE_GETRANDOM_SYSCALL 1" >>confdefs.h + fi # check if the getrandom() function is available # the test was written for the Solaris function of { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the getrandom() function" >&5 $as_echo_n "checking for the getrandom() function... " >&6; } +if ${ac_cv_func_getrandom+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -17686,19 +18150,23 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext _ACEOF if ac_fn_c_try_link "$LINENO"; then : - have_getrandom=yes + ac_cv_func_getrandom=yes else - have_getrandom=no + ac_cv_func_getrandom=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_getrandom" >&5 -$as_echo "$have_getrandom" >&6; } -if test "$have_getrandom" = yes; then +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_getrandom" >&5 +$as_echo "$ac_cv_func_getrandom" >&6; } + +if test "x$ac_cv_func_getrandom" = xyes; then : + $as_echo "#define HAVE_GETRANDOM 1" >>confdefs.h + fi # checks for POSIX shared memory, used by Modules/_multiprocessing/posixshmem.c @@ -18041,6 +18509,10 @@ $as_echo "$OPENSSL_RPATH" >&6; } # check if OpenSSL libraries work as expected { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL provides required APIs" >&5 $as_echo_n "checking whether OpenSSL provides required APIs... " >&6; } +if ${ac_cv_working_openssl+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" save_LDFLAGS="$LDFLAGS" @@ -18086,11 +18558,9 @@ EVP_PBE_scrypt(NULL, 0, NULL, 0, 2, 8, 1, 0, NULL, 0); } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } + ac_cv_working_openssl=yes else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + ac_cv_working_openssl=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext @@ -18098,6 +18568,10 @@ LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" LDFLAGS="$save_LDFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_openssl" >&5 +$as_echo "$ac_cv_working_openssl" >&6; } + # ssl module default cipher suite string diff --git a/configure.ac b/configure.ac index d7699dc4ea90d..a982a2f0c88c8 100644 --- a/configure.ac +++ b/configure.ac @@ -2320,14 +2320,15 @@ AC_CHECK_HEADERS(linux/can.h linux/can/bcm.h linux/can/j1939.h linux/can/raw.h,, ]) # checks for typedefs -was_it_defined=no -AC_MSG_CHECKING(for clock_t in time.h) -AC_EGREP_HEADER(clock_t, time.h, was_it_defined=yes, [ - AC_DEFINE(clock_t, long, [Define to 'long' if doesn't define.]) +AC_CACHE_CHECK([for clock_t in time.h], [ac_cv_clock_t_time_h], [ + AC_EGREP_HEADER([clock_t], [time.h], [ac_cv_clock_t_time_h=yes], [ac_cv_clock_t_time_h=no]) +]) +dnl checks for "no" +AS_VAR_IF([ac_cv_clock_t_time_h], [no], [ + AC_DEFINE(clock_t, long, [Define to 'long' if doesn't define.]) ]) -AC_MSG_RESULT($was_it_defined) -AC_MSG_CHECKING(for makedev) +AC_CACHE_CHECK([for makedev], [ac_cv_func_makedev], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #if defined(MAJOR_IN_MKDEV) #include @@ -2338,14 +2339,15 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #endif ]], [[ makedev(0, 0) ]]) -],[ac_cv_has_makedev=yes],[ac_cv_has_makedev=no]) -AC_MSG_RESULT($ac_cv_has_makedev) -if test "$ac_cv_has_makedev" = "yes"; then +],[ac_cv_func_makedev=yes],[ac_cv_func_makedev=no]) +]) + +AS_VAR_IF([ac_cv_func_makedev], [yes], [ AC_DEFINE(HAVE_MAKEDEV, 1, [Define this if you have the makedev macro.]) -fi +]) # byte swapping -AC_MSG_CHECKING(for le64toh) +AC_CACHE_CHECK([for le64toh], [ac_cv_func_le64toh], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #ifdef HAVE_ENDIAN_H #include @@ -2354,11 +2356,12 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #endif ]], [[ le64toh(1) ]]) -],[ac_cv_has_le64toh=yes],[ac_cv_has_le64toh=no]) -AC_MSG_RESULT($ac_cv_has_le64toh) -if test "$ac_cv_has_le64toh" = "yes"; then +],[ac_cv_func_le64toh=yes],[ac_cv_func_le64toh=no]) +]) + +AS_VAR_IF([ac_cv_func_le64toh], [yes], [ AC_DEFINE(HAVE_HTOLE64, 1, [Define this if you have le64toh()]) -fi +]) use_lfs=yes # Don't use largefile support for GNU/Hurd @@ -2460,38 +2463,38 @@ elif test "$ac_cv_pthread" = "yes" then CC="$CC -pthread" fi -AC_MSG_CHECKING(for pthread_t) -have_pthread_t=no +AC_CACHE_CHECK([for pthread_t], [ac_cv_have_pthread_t], [ AC_COMPILE_IFELSE([ AC_LANG_PROGRAM([[#include ]], [[pthread_t x; x = *(pthread_t*)0;]]) -],[have_pthread_t=yes],[]) -AC_MSG_RESULT($have_pthread_t) -if test "$have_pthread_t" = yes ; then +], [ac_cv_have_pthread_t=yes], [ac_cv_have_pthread_t=no]) +]) +AS_VAR_IF([ac_cv_have_pthread_t], [yes], [ AC_CHECK_SIZEOF(pthread_t, [], [ #ifdef HAVE_PTHREAD_H #include #endif ]) -fi +]) # Issue #25658: POSIX hasn't defined that pthread_key_t is compatible with int. # This checking will be unnecessary after removing deprecated TLS API. AC_CHECK_SIZEOF(pthread_key_t, [], [[#include ]]) -AC_MSG_CHECKING(whether pthread_key_t is compatible with int) +AC_CACHE_CHECK([whether pthread_key_t is compatible with int], [ac_cv_pthread_key_t_is_arithmetic_type], [ if test "$ac_cv_sizeof_pthread_key_t" -eq "$ac_cv_sizeof_int" ; then AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[#include ]], [[pthread_key_t k; k * 1;]])], - [ac_pthread_key_t_is_arithmetic_type=yes], - [ac_pthread_key_t_is_arithmetic_type=no] + [ac_cv_pthread_key_t_is_arithmetic_type=yes], + [ac_cv_pthread_key_t_is_arithmetic_type=no] ) - AC_MSG_RESULT($ac_pthread_key_t_is_arithmetic_type) - if test "$ac_pthread_key_t_is_arithmetic_type" = yes ; then - AC_DEFINE(PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT, 1, - [Define if pthread_key_t is compatible with int.]) - fi else - AC_MSG_RESULT(no) + ac_cv_pthread_key_t_is_arithmetic_type=no fi +]) +AS_VAR_IF([ac_cv_pthread_key_t_is_arithmetic_type], [yes], [ + AC_DEFINE(PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT, 1, + [Define if pthread_key_t is compatible with int.]) +]) + CC="$ac_save_cc" AC_SUBST(OTHER_LIBTOOL_OPT) @@ -2939,16 +2942,17 @@ AC_CHECK_LIB(dld, shl_load) # Dynamic linking for HP-UX # checks for uuid.h location AC_CHECK_HEADERS([uuid/uuid.h uuid.h]) -AC_MSG_CHECKING(for uuid_generate_time_safe) +AC_CACHE_CHECK([for uuid_generate_time_safe], [ac_cv_lib_uuid_uuid_generate_time_safe], [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ #ifndef uuid_generate_time_safe void *x = uuid_generate_time_safe #endif ]])], - [AC_DEFINE(HAVE_UUID_GENERATE_TIME_SAFE, 1, Define if uuid_generate_time_safe() exists.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no)] -) +[ac_cv_lib_uuid_uuid_generate_time_safe=yes], [ac_cv_lib_uuid_uuid_generate_time_safe=no]) +]) +AS_VAR_IF([ac_cv_lib_uuid_uuid_generate_time_safe], [yes], [ + AC_DEFINE(HAVE_UUID_GENERATE_TIME_SAFE, 1, [Define if uuid_generate_time_safe() exists.]) +]) # check for libuuid from util-linux save_LIBS=$LIBS @@ -2957,29 +2961,9 @@ LIBS=$save_LIBS # AIX provides support for RFC4122 (uuid) in libc.a starting with AIX 6.1 (anno 2007) # FreeBSD and OpenBSD provides support in libc as well. -AC_MSG_CHECKING(for uuid_create) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ -#ifndef uuid_create -void *x = uuid_create -#endif -]])], - [AC_DEFINE(HAVE_UUID_CREATE, 1, Define if uuid_create() exists.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no)] -) - # Little-endian FreeBSD, OpenBSD and NetBSD needs encoding into an octet # stream in big-endian byte-order -AC_MSG_CHECKING(for uuid_enc_be) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ -#ifndef uuid_enc_be -void *x = uuid_enc_be -#endif -]])], - [AC_DEFINE(HAVE_UUID_ENC_BE, 1, Define if uuid_enc_be() exists.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no)] -) +AC_CHECK_FUNCS([uuid_create uuid_enc_be]) # 'Real Time' functions on Solaris # posix4 on Solaris 2.6 @@ -3579,24 +3563,27 @@ if test "$ipv6" = "yes" -a "$ipv6lib" != "none"; then fi fi -AC_MSG_CHECKING(for CAN_RAW_FD_FRAMES) + +AC_CACHE_CHECK([CAN_RAW_FD_FRAMES], [ac_cv_can_raw_fd_frames], [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ /* CAN_RAW_FD_FRAMES available check */ #include ]], -[[int can_raw_fd_frames = CAN_RAW_FD_FRAMES;]])],[ - AC_DEFINE(HAVE_LINUX_CAN_RAW_FD_FRAMES, 1, [Define if compiling using Linux 3.6 or later.]) - AC_MSG_RESULT(yes) -],[ - AC_MSG_RESULT(no) +[[int can_raw_fd_frames = CAN_RAW_FD_FRAMES;]])], +[ac_cv_can_raw_fd_frames=yes], +[ac_cv_can_raw_fd_frames=no]) +]) +AS_VAR_IF([ac_cv_can_raw_fd_frames], [yes], [ + AC_DEFINE(HAVE_LINUX_CAN_RAW_FD_FRAMES, 1, [Define if compiling using Linux 3.6 or later.]) ]) -AC_MSG_CHECKING(for CAN_RAW_JOIN_FILTERS) +AC_CACHE_CHECK([for CAN_RAW_JOIN_FILTERS], [ac_cv_can_raw_join_filters], [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], -[[int can_raw_join_filters = CAN_RAW_JOIN_FILTERS;]])],[ - AC_DEFINE(HAVE_LINUX_CAN_RAW_JOIN_FILTERS, 1, [Define if compiling using Linux 4.1 or later.]) - AC_MSG_RESULT(yes) -],[ - AC_MSG_RESULT(no) +[[int can_raw_join_filters = CAN_RAW_JOIN_FILTERS;]])], +[ac_cv_can_raw_join_filters=yes], +[ac_cv_can_raw_join_filters=no]) +]) +AS_VAR_IF([ac_cv_can_raw_join_filters], [yes], [ + AC_DEFINE(HAVE_LINUX_CAN_RAW_JOIN_FILTERS, 1, [Define if compiling using Linux 4.1 or later.]) ]) # Check for --with-doc-strings @@ -3807,104 +3794,60 @@ AC_CHECK_DECL(dirfd, [#include #include ]) +dnl PY_CHECK_FUNC(FUNCTION, [INCLUDES], [AC_DEFINE-VAR]) +AC_DEFUN([PY_CHECK_FUNC], +[ AS_VAR_PUSHDEF([py_var], [ac_cv_func_$1]) + AS_VAR_PUSHDEF([py_define], m4_ifblank([$3], [[HAVE_]m4_toupper($1)], [$3])) + AC_CACHE_CHECK( + [for $1], + [py_var], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([$2], [void *x=$1])], + [AS_VAR_SET([py_var], [yes])], + [AS_VAR_SET([py_var], [no])])] + ) + AS_VAR_IF( + [py_var], + [yes], + [AC_DEFINE([py_define], [1], [Define if you have the '$1' function.])]) + AS_VAR_POPDEF([py_var]) + AS_VAR_POPDEF([py_define]) +]) + # For some functions, having a definition is not sufficient, since # we want to take their address. -AC_MSG_CHECKING(for chroot) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[void *x=chroot]])], - [AC_DEFINE(HAVE_CHROOT, 1, Define if you have the 'chroot' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no) -]) -AC_MSG_CHECKING(for link) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[void *x=link]])], - [AC_DEFINE(HAVE_LINK, 1, Define if you have the 'link' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no) -]) -AC_MSG_CHECKING(for symlink) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[void *x=symlink]])], - [AC_DEFINE(HAVE_SYMLINK, 1, Define if you have the 'symlink' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no) -]) -AC_MSG_CHECKING(for fchdir) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[void *x=fchdir]])], - [AC_DEFINE(HAVE_FCHDIR, 1, Define if you have the 'fchdir' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no) -]) -AC_MSG_CHECKING(for fsync) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[void *x=fsync]])], - [AC_DEFINE(HAVE_FSYNC, 1, Define if you have the 'fsync' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no) -]) -AC_MSG_CHECKING(for fdatasync) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[void *x=fdatasync]])], - [AC_DEFINE(HAVE_FDATASYNC, 1, Define if you have the 'fdatasync' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no) -]) -AC_MSG_CHECKING(for epoll) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[void *x=epoll_create]])], - [AC_DEFINE(HAVE_EPOLL, 1, Define if you have the 'epoll' functions.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no) -]) -AC_MSG_CHECKING(for epoll_create1) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[void *x=epoll_create1]])], - [AC_DEFINE(HAVE_EPOLL_CREATE1, 1, Define if you have the 'epoll_create1' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no) -]) -AC_MSG_CHECKING(for kqueue) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +PY_CHECK_FUNC([chroot], [#include ]) +PY_CHECK_FUNC([link], [#include ]) +PY_CHECK_FUNC([symlink], [#include ]) +PY_CHECK_FUNC([fchdir], [#include ]) +PY_CHECK_FUNC([fsync], [#include ]) +PY_CHECK_FUNC([fdatasync], [#include ]) +PY_CHECK_FUNC([epoll], [#include ]) +PY_CHECK_FUNC([epoll_create1], [#include ]) +PY_CHECK_FUNC([kqueue],[ #include #include - ]], [[int x=kqueue()]])], - [AC_DEFINE(HAVE_KQUEUE, 1, Define if you have the 'kqueue' functions.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no) ]) -AC_MSG_CHECKING(for prlimit) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +PY_CHECK_FUNC([prlimit], [ #include #include - ]], [[void *x=prlimit]])], - [AC_DEFINE(HAVE_PRLIMIT, 1, Define if you have the 'prlimit' functions.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no) -]) -AC_MSG_CHECKING(for _dyld_shared_cache_contains_path) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[void *x=_dyld_shared_cache_contains_path]])], - [AC_DEFINE(HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH, 1, Define if you have the '_dyld_shared_cache_contains_path' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no) ]) -AC_MSG_CHECKING(for memfd_create) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +PY_CHECK_FUNC([_dyld_shared_cache_contains_path], [#include ], [HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH]) + +PY_CHECK_FUNC([memfd_create], [ #ifdef HAVE_SYS_MMAN_H #include #endif #ifdef HAVE_SYS_MEMFD_H #include #endif -]], [[void *x=memfd_create]])], - [AC_DEFINE(HAVE_MEMFD_CREATE, 1, Define if you have the 'memfd_create' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no) ]) -AC_MSG_CHECKING(for eventfd) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +PY_CHECK_FUNC([eventfd], [ #ifdef HAVE_SYS_EVENTFD_H #include #endif -]], [[int x = eventfd(0, EFD_CLOEXEC)]])], - [AC_DEFINE(HAVE_EVENTFD, 1, Define if you have the 'eventfd' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no) ]) # On some systems (eg. FreeBSD 5), we would find a definition of the @@ -3913,14 +3856,7 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ # address to avoid compiler warnings and potential miscompilations # because of the missing prototypes. -AC_MSG_CHECKING(for ctermid_r) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#include -]], [[void* p = ctermid_r]])], - [AC_DEFINE(HAVE_CTERMID_R, 1, Define if you have the 'ctermid_r' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no) -]) +PY_CHECK_FUNC([ctermid_r], [#include ]) AC_CACHE_CHECK([for flock declaration], [ac_cv_flock_decl], [AC_COMPILE_IFELSE( @@ -3941,22 +3877,19 @@ if test "x${ac_cv_flock_decl}" = xyes; then ) fi -AC_MSG_CHECKING(for getpagesize) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#include -]], [[void* p = getpagesize]])], - [AC_DEFINE(HAVE_GETPAGESIZE, 1, Define if you have the 'getpagesize' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no) -]) +PY_CHECK_FUNC([getpagesize], [#include ]) -AC_MSG_CHECKING(for broken unsetenv) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#include -]], [[int res = unsetenv("DUMMY")]])], - [AC_MSG_RESULT(no)], - [AC_DEFINE(HAVE_BROKEN_UNSETENV, 1, Define if `unsetenv` does not return an int.) - AC_MSG_RESULT(yes) +AC_CACHE_CHECK([for broken unsetenv], [ac_cv_broken_unsetenv], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [#include ], + [int res = unsetenv("DUMMY")])], + [ac_cv_broken_unsetenv=no], + [ac_cv_broken_unsetenv=yes] + ) +]) +AS_VAR_IF([ac_cv_broken_unsetenv], [yes], [ + AC_DEFINE(HAVE_BROKEN_UNSETENV, 1, [Define if 'unsetenv' does not return an int.]) ]) dnl check for true @@ -4011,6 +3944,7 @@ if test "$ac_cv_have_lchflags" = yes ; then AC_DEFINE(HAVE_LCHFLAGS, 1, [Define to 1 if you have the 'lchflags' function.]) fi +# Check for compression libraries dnl Check if system zlib has *Copy() functions dnl dnl On MacOSX the linker will search for dylibs on the entire linker path @@ -4040,50 +3974,28 @@ Darwin/*) ;; esac -AC_MSG_CHECKING(for hstrerror) -AC_LINK_IFELSE([AC_LANG_PROGRAM([[ -#include -]], [[void* p = hstrerror; hstrerror(0)]])], - [AC_DEFINE(HAVE_HSTRERROR, 1, Define if you have the 'hstrerror' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no) -]) +PY_CHECK_FUNC([hstrerror], [#include ]) -AC_MSG_CHECKING(for inet_aton) -AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +PY_CHECK_FUNC([inet_aton], [ #include #include #include #include -]], [[void* p = inet_aton;inet_aton(0,0)]])], - [AC_DEFINE(HAVE_INET_ATON, 1, Define if you have the 'inet_aton' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no) ]) -AC_MSG_CHECKING(for inet_pton) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +PY_CHECK_FUNC([inet_pton], [ #include #include #include #include -]], [[void* p = inet_pton]])], - [AC_DEFINE(HAVE_INET_PTON, 1, Define if you have the 'inet_pton' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no) ]) # On some systems, setgroups is in unistd.h, on others, in grp.h -AC_MSG_CHECKING(for setgroups) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +PY_CHECK_FUNC([setgroups], [ #include #ifdef HAVE_GRP_H #include #endif -]], [[void* p = setgroups]])], - [AC_DEFINE(HAVE_SETGROUPS, 1, Define if you have the 'setgroups' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no) ]) # check for openpty and forkpty @@ -4169,7 +4081,7 @@ AC_CHECK_FUNCS(nanosleep, [], [ ]) ]) -AC_MSG_CHECKING(for major, minor, and makedev) +AC_CACHE_CHECK([for major, minor, and makedev], [ac_cv_device_macros], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #if defined(MAJOR_IN_MKDEV) #include @@ -4180,28 +4092,32 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #endif ]], [[ makedev(major(0),minor(0)); -]])],[ +]])],[ac_cv_device_macros=yes], [ac_cv_device_macros=no]) +]) +AS_VAR_IF([ac_cv_device_macros], [yes], [ AC_DEFINE(HAVE_DEVICE_MACROS, 1, [Define to 1 if you have the device macros.]) - AC_MSG_RESULT(yes) -],[ - AC_MSG_RESULT(no) ]) +dnl no longer used, now always defined for backwards compatibility +AC_DEFINE(SYS_SELECT_WITH_SYS_TIME, 1, + [Define if you can safely include both and + (which you can't on SCO ODT 3.0).]) + # On OSF/1 V5.1, getaddrinfo is available, but a define # for [no]getaddrinfo in netdb.h. -AC_MSG_CHECKING(for getaddrinfo) +AC_CACHE_CHECK([for getaddrinfo], [ac_cv_func_getaddrinfo], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #include #include #include ]], [[getaddrinfo(NULL, NULL, NULL, NULL);]])], -[have_getaddrinfo=yes], -[have_getaddrinfo=no]) -AC_MSG_RESULT($have_getaddrinfo) -if test $have_getaddrinfo = yes -then +[ac_cv_func_getaddrinfo=yes], +[ac_cv_func_getaddrinfo=no]) +]) + +AS_VAR_IF([ac_cv_func_getaddrinfo], [yes], [ AC_MSG_CHECKING(getaddrinfo bug) AC_CACHE_VAL(ac_cv_buggy_getaddrinfo, AC_RUN_IFELSE([AC_LANG_SOURCE([[[ @@ -4302,11 +4218,13 @@ if test "${enable_ipv6+set}" = set; then else ac_cv_buggy_getaddrinfo=yes fi])) -fi + +dnl if ac_cv_func_getaddrinfo +]) AC_MSG_RESULT($ac_cv_buggy_getaddrinfo) -if test $have_getaddrinfo = no || test "$ac_cv_buggy_getaddrinfo" = yes +if test "$ac_cv_func_getaddrinfo" = no -o "$ac_cv_buggy_getaddrinfo" = yes then if test $ipv6 = yes then @@ -4348,20 +4266,6 @@ if test $ac_cv_header_time_altzone = yes; then AC_DEFINE(HAVE_ALTZONE, 1, [Define this if your time.h defines altzone.]) fi -was_it_defined=no -AC_MSG_CHECKING(whether sys/select.h and sys/time.h may both be included) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#include -#include -#include -]], [[;]])],[ - AC_DEFINE(SYS_SELECT_WITH_SYS_TIME, 1, - [Define if you can safely include both and - (which you can't on SCO ODT 3.0).]) - was_it_defined=yes -],[]) -AC_MSG_RESULT($was_it_defined) - AC_MSG_CHECKING(for addrinfo) AC_CACHE_VAL(ac_cv_struct_addrinfo, AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[struct addrinfo a]])], @@ -4402,26 +4306,25 @@ fi AC_C_CHAR_UNSIGNED AC_C_CONST -works=no -AC_MSG_CHECKING(for working signed char) +AC_CACHE_CHECK([for working signed char], [ac_cv_working_signed_char_c], [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[signed char c;]])], - [works=yes], - [AC_DEFINE(signed, , [Define to empty if the keyword does not work.])] -) -AC_MSG_RESULT($works) + [ac_cv_working_signed_char_c=yes], [ac_cv_working_signed_char_c=no]) +]) +AS_VAR_IF([ac_cv_working_signed_char_c], [no], [ + AC_DEFINE(signed, , [Define to empty if the keyword does not work.]) +]) -have_prototypes=no -AC_MSG_CHECKING(for prototypes) +AC_CACHE_CHECK([for prototypes], [ac_cv_function_prototypes], [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[int foo(int x) { return 0; }]], [[return foo(10);]])], - [AC_DEFINE(HAVE_PROTOTYPES, 1, + [ac_cv_function_prototypes=yes], [ac_cv_function_prototypes=no]) +]) +AS_VAR_IF([ac_cv_function_prototypes], [yes], [ + AC_DEFINE(HAVE_PROTOTYPES, 1, [Define if your compiler supports function prototype]) - have_prototypes=yes], - [] -) -AC_MSG_RESULT($have_prototypes) +]) works=no -AC_MSG_CHECKING(for variable length prototypes and stdarg.h) +AC_CACHE_CHECK([for variable length prototypes and stdarg.h], [ac_cv_stdarg_prototypes], [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include int foo(int x, ...) { @@ -4432,34 +4335,32 @@ int foo(int x, ...) { va_arg(va, double); return 0; } -]], [[return foo(10, "", 3.14);]])],[ +]], [[return foo(10, "", 3.14);]])], + [ac_cv_stdarg_prototypes=yes], [ac_cv_stdarg_prototypes=no]) +]) +AS_VAR_IF([ac_cv_stdarg_prototypes], [yes], [ AC_DEFINE(HAVE_STDARG_PROTOTYPES, 1, [Define if your compiler supports variable length function prototypes (e.g. void fprintf(FILE *, char *, ...);) *and* ]) - works=yes -],[]) -AC_MSG_RESULT($works) +]) + # check for socketpair -AC_MSG_CHECKING(for socketpair) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +PY_CHECK_FUNC([socketpair], [ #include #include -]], [[void *x=socketpair]])], - [AC_DEFINE(HAVE_SOCKETPAIR, 1, [Define if you have the 'socketpair' function.]) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no)] -) +]) # check if sockaddr has sa_len member -AC_MSG_CHECKING(if sockaddr has sa_len member) +AC_CACHE_CHECK([if sockaddr has sa_len member], [ac_cv_struct_sockaddr_sa_len], [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[struct sockaddr x; x.sa_len = 0;]])], - [AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_SOCKADDR_SA_LEN, 1, [Define if sockaddr has sa_len member])], - [AC_MSG_RESULT(no)] -) + [ac_cv_struct_sockaddr_sa_len=yes], [ac_cv_struct_sockaddr_sa_len=no]) +]) +AS_VAR_IF([ac_cv_struct_sockaddr_sa_len], [yes], [ + AC_DEFINE(HAVE_SOCKADDR_SA_LEN, 1, [Define if sockaddr has sa_len member]) +]) # sigh -- gethostbyname_r is a mess; it can have 3, 5 or 6 arguments :-( AH_TEMPLATE(HAVE_GETHOSTBYNAME_R, @@ -4585,16 +4486,17 @@ fi], # * Check for gcc x64 inline assembler * # ************************************** -AC_MSG_CHECKING(for x64 gcc inline assembler) -AC_LINK_IFELSE( [AC_LANG_PROGRAM([[]], [[ + +AC_CACHE_CHECK([for x64 gcc inline assembler], [ac_cv_gcc_asm_for_x64], [ +AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[ __asm__ __volatile__ ("movq %rcx, %rax"); -]])],[have_gcc_asm_for_x64=yes],[have_gcc_asm_for_x64=no]) -AC_MSG_RESULT($have_gcc_asm_for_x64) -if test "$have_gcc_asm_for_x64" = yes -then +]])],[ac_cv_gcc_asm_for_x64=yes],[ac_cv_gcc_asm_for_x64=no]) +]) + +AS_VAR_IF([ac_cv_gcc_asm_for_x64], [yes], [ AC_DEFINE(HAVE_GCC_ASM_FOR_X64, 1, [Define if we can use x64 gcc inline assembler]) -fi +]) # ************************************************** # * Check for various properties of floating point * @@ -4633,38 +4535,36 @@ fi # This inline assembler syntax may also work for suncc and icc, # so we try it on all platforms. -AC_MSG_CHECKING(whether we can use gcc inline assembler to get and set x87 control word) +AC_CACHE_CHECK([whether we can use gcc inline assembler to get and set x87 control word], [ac_cv_gcc_asm_for_x87], [ AC_LINK_IFELSE( [AC_LANG_PROGRAM([[]], [[ unsigned short cw; __asm__ __volatile__ ("fnstcw %0" : "=m" (cw)); __asm__ __volatile__ ("fldcw %0" : : "m" (cw)); -]])],[have_gcc_asm_for_x87=yes],[have_gcc_asm_for_x87=no]) -AC_MSG_RESULT($have_gcc_asm_for_x87) -if test "$have_gcc_asm_for_x87" = yes -then +]])],[ac_cv_gcc_asm_for_x87=yes],[ac_cv_gcc_asm_for_x87=no]) +]) +AS_VAR_IF([ac_cv_gcc_asm_for_x87], [yes], [ AC_DEFINE(HAVE_GCC_ASM_FOR_X87, 1, [Define if we can use gcc inline assembler to get and set x87 control word]) -fi +]) -AC_MSG_CHECKING(whether we can use gcc inline assembler to get and set mc68881 fpcr) +AC_CACHE_CHECK([whether we can use gcc inline assembler to get and set mc68881 fpcr], [ac_cv_gcc_asm_for_mc68881], [ AC_LINK_IFELSE( [AC_LANG_PROGRAM([[]], [[ unsigned int fpcr; __asm__ __volatile__ ("fmove.l %%fpcr,%0" : "=g" (fpcr)); __asm__ __volatile__ ("fmove.l %0,%%fpcr" : : "g" (fpcr)); -]])],[have_gcc_asm_for_mc68881=yes],[have_gcc_asm_for_mc68881=no]) -AC_MSG_RESULT($have_gcc_asm_for_mc68881) -if test "$have_gcc_asm_for_mc68881" = yes -then +]])],[ac_cv_gcc_asm_for_mc68881=yes],[ac_cv_gcc_asm_for_mc68881=no]) +]) +AS_VAR_IF([ac_cv_gcc_asm_for_mc68881], [yes], [ AC_DEFINE(HAVE_GCC_ASM_FOR_MC68881, 1, [Define if we can use gcc inline assembler to get and set mc68881 fpcr]) -fi +]) # Detect whether system arithmetic is subject to x87-style double # rounding issues. The result of this test has little meaning on non # IEEE 754 platforms. On IEEE 754, test should return 1 if rounding # mode is round-to-nearest and double rounding issues are present, and # 0 otherwise. See http://bugs.python.org/issue2937 for more info. -AC_MSG_CHECKING(for x87-style double rounding) +AC_CACHE_CHECK([for x87-style double rounding], [ac_cv_x87_double_rounding], [ # $BASECFLAGS may affect the result ac_save_cc="$CC" CC="$CC $BASECFLAGS" @@ -4692,12 +4592,12 @@ int main() { [ac_cv_x87_double_rounding=yes], [ac_cv_x87_double_rounding=no]) CC="$ac_save_cc" -AC_MSG_RESULT($ac_cv_x87_double_rounding) -if test "$ac_cv_x87_double_rounding" = yes -then +]) + +AS_VAR_IF([ac_cv_x87_double_rounding], [yes], [ AC_DEFINE(X87_DOUBLE_ROUNDING, 1, [Define if arithmetic is subject to x87-style double rounding issue]) -fi +]) # ************************************ # * Check for mathematical functions * @@ -5365,115 +5265,42 @@ then [Define if WINDOW in curses.h offers a field _flags.]) fi -AC_MSG_CHECKING(for is_pad) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ -#ifndef is_pad -void *x=is_pad -#endif -]])], - [AC_DEFINE(HAVE_CURSES_IS_PAD, 1, Define if you have the 'is_pad' function or macro.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no)] -) - -AC_MSG_CHECKING(for is_term_resized) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[void *x=is_term_resized]])], - [AC_DEFINE(HAVE_CURSES_IS_TERM_RESIZED, 1, Define if you have the 'is_term_resized' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no)] -) - -AC_MSG_CHECKING(for resize_term) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[void *x=resize_term]])], - [AC_DEFINE(HAVE_CURSES_RESIZE_TERM, 1, Define if you have the 'resize_term' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no)] -) - -AC_MSG_CHECKING(for resizeterm) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[void *x=resizeterm]])], - [AC_DEFINE(HAVE_CURSES_RESIZETERM, 1, Define if you have the 'resizeterm' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no)] -) - -AC_MSG_CHECKING(for immedok) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ -#ifndef immedok -void *x=immedok -#endif -]])], - [AC_DEFINE(HAVE_CURSES_IMMEDOK, 1, Define if you have the 'immedok' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no)] -) - -AC_MSG_CHECKING(for syncok) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ -#ifndef syncok -void *x=syncok -#endif -]])], - [AC_DEFINE(HAVE_CURSES_SYNCOK, 1, Define if you have the 'syncok' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no)] -) - -AC_MSG_CHECKING(for wchgat) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ -#ifndef wchgat -void *x=wchgat -#endif -]])], - [AC_DEFINE(HAVE_CURSES_WCHGAT, 1, Define if you have the 'wchgat' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no)] -) - -AC_MSG_CHECKING(for filter) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ -#ifndef filter -void *x=filter -#endif -]])], - [AC_DEFINE(HAVE_CURSES_FILTER, 1, Define if you have the 'filter' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no)] -) - -AC_MSG_CHECKING(for has_key) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ -#ifndef has_key -void *x=has_key -#endif -]])], - [AC_DEFINE(HAVE_CURSES_HAS_KEY, 1, Define if you have the 'has_key' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no)] -) - -AC_MSG_CHECKING(for typeahead) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ -#ifndef typeahead -void *x=typeahead -#endif -]])], - [AC_DEFINE(HAVE_CURSES_TYPEAHEAD, 1, Define if you have the 'typeahead' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no)] -) +dnl PY_CHECK_CURSES_FUNC(FUNCTION) +AC_DEFUN([PY_CHECK_CURSES_FUNC], +[ AS_VAR_PUSHDEF([py_var], [ac_cv_lib_curses_$1]) + AS_VAR_PUSHDEF([py_define], [HAVE_CURSES_]m4_toupper($1)) + AC_CACHE_CHECK( + [for curses function $1], + [py_var], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [#include ], [ + #ifndef $1 + void *x=$1 + #endif + ])], + [AS_VAR_SET([py_var], [yes])], + [AS_VAR_SET([py_var], [no])])] + ) + AS_VAR_IF( + [py_var], + [yes], + [AC_DEFINE([py_define], [1], [Define if you have the '$1' function.])]) + AS_VAR_POPDEF([py_var]) + AS_VAR_POPDEF([py_define]) +]) -AC_MSG_CHECKING(for use_env) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ -#ifndef use_env -void *x=use_env -#endif -]])], - [AC_DEFINE(HAVE_CURSES_USE_ENV, 1, Define if you have the 'use_env' function.) - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no)] -) -# last curses configure check +PY_CHECK_CURSES_FUNC([is_pad]) +PY_CHECK_CURSES_FUNC([is_term_resized]) +PY_CHECK_CURSES_FUNC([resize_term]) +PY_CHECK_CURSES_FUNC([resizeterm]) +PY_CHECK_CURSES_FUNC([immedok]) +PY_CHECK_CURSES_FUNC([syncok]) +PY_CHECK_CURSES_FUNC([wchgat]) +PY_CHECK_CURSES_FUNC([filter]) +PY_CHECK_CURSES_FUNC([has_key]) +PY_CHECK_CURSES_FUNC([typeahead]) +PY_CHECK_CURSES_FUNC([use_env]) CPPFLAGS=$ac_save_cppflags AC_MSG_NOTICE([checking for device files]) @@ -5676,20 +5503,19 @@ done AC_MSG_RESULT(done) # Availability of -O2: -AC_MSG_CHECKING(for -O2) +AC_CACHE_CHECK([for -O2], [ac_cv_compile_o2], [ saved_cflags="$CFLAGS" CFLAGS="-O2" -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[ -]])],[have_O2=yes],[have_O2=no]) -AC_MSG_RESULT($have_O2) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])], [ac_cv_compile_o2=yes], [ac_cv_compile_o2=no]) CFLAGS="$saved_cflags" +]) # _FORTIFY_SOURCE wrappers for memmove and bcopy are incorrect: # http://sourceware.org/ml/libc-alpha/2010-12/msg00009.html AC_MSG_CHECKING(for glibc _FORTIFY_SOURCE/memmove bug) saved_cflags="$CFLAGS" CFLAGS="-O2 -D_FORTIFY_SOURCE=2" -if test "$have_O2" = no; then +if test "$ac_cv_compile_o2" = no; then CFLAGS="" fi AC_RUN_IFELSE([AC_LANG_SOURCE([[ @@ -5719,7 +5545,7 @@ if test "$have_glibc_memmove_bug" = yes; then for memmove and bcopy.]) fi -if test "$have_gcc_asm_for_x87" = yes; then +if test "$ac_cv_gcc_asm_for_x87" = yes; then # Some versions of gcc miscompile inline asm: # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46491 # http://gcc.gnu.org/ml/gcc/2010-11/msg00366.html @@ -5759,7 +5585,7 @@ if test "$have_gcc_asm_for_x87" = yes; then fi # Check for stdatomic.h -AC_MSG_CHECKING(for stdatomic.h) +AC_CACHE_CHECK([for stdatomic.h], [ac_cv_header_stdatomic_h], [ AC_LINK_IFELSE( [ AC_LANG_SOURCE([[ @@ -5773,17 +5599,16 @@ AC_LINK_IFELSE( return 0; } ]]) -],[have_stdatomic_h=yes],[have_stdatomic_h=no]) - -AC_MSG_RESULT($have_stdatomic_h) +],[ac_cv_header_stdatomic_h=yes],[ac_cv_header_stdatomic_h=no]) +]) -if test "$have_stdatomic_h" = yes; then +AS_VAR_IF([ac_cv_header_stdatomic_h], [yes], [ AC_DEFINE(HAVE_STD_ATOMIC, 1, [Has stdatomic.h with atomic_int and atomic_uintptr_t]) -fi +]) # Check for GCC >= 4.7 and clang __atomic builtin functions -AC_MSG_CHECKING(for builtin __atomic_load_n and __atomic_store_n functions) +AC_CACHE_CHECK([for builtin __atomic_load_n and __atomic_store_n functions], [ac_cv_builtin_atomic], [ AC_LINK_IFELSE( [ AC_LANG_SOURCE([[ @@ -5794,13 +5619,12 @@ AC_LINK_IFELSE( return 0; } ]]) -],[have_builtin_atomic=yes],[have_builtin_atomic=no]) - -AC_MSG_RESULT($have_builtin_atomic) +],[ac_cv_builtin_atomic=yes],[ac_cv_builtin_atomic=no]) +]) -if test "$have_builtin_atomic" = yes; then +AS_VAR_IF([ac_cv_builtin_atomic], [yes], [ AC_DEFINE(HAVE_BUILTIN_ATOMIC, 1, [Has builtin __atomic_load_n() and __atomic_store_n() functions]) -fi +]) # ensurepip option AC_MSG_CHECKING(for ensurepip) @@ -5818,7 +5642,7 @@ AC_MSG_RESULT($ENSUREPIP) AC_SUBST(ENSUREPIP) # check if the dirent structure of a d_type field and DT_UNKNOWN is defined -AC_MSG_CHECKING(if the dirent structure of a d_type field) +AC_CACHE_CHECK([if the dirent structure of a d_type field], [ac_cv_dirent_d_type], [ AC_LINK_IFELSE( [ AC_LANG_SOURCE([[ @@ -5829,16 +5653,16 @@ AC_LINK_IFELSE( return entry.d_type == DT_UNKNOWN; } ]]) -],[have_dirent_d_type=yes],[have_dirent_d_type=no]) -AC_MSG_RESULT($have_dirent_d_type) +],[ac_cv_dirent_d_type=yes],[ac_cv_dirent_d_type=no]) +]) -if test "$have_dirent_d_type" = yes; then +AS_VAR_IF([ac_cv_dirent_d_type], [yes], [ AC_DEFINE(HAVE_DIRENT_D_TYPE, 1, [Define to 1 if the dirent structure has a d_type field]) -fi +]) # check if the Linux getrandom() syscall is available -AC_MSG_CHECKING(for the Linux getrandom() syscall) +AC_CACHE_CHECK([for the Linux getrandom() syscall], [ac_cv_getrandom_syscall], [ AC_LINK_IFELSE( [ AC_LANG_SOURCE([[ @@ -5855,17 +5679,17 @@ AC_LINK_IFELSE( return 0; } ]]) -],[have_getrandom_syscall=yes],[have_getrandom_syscall=no]) -AC_MSG_RESULT($have_getrandom_syscall) +],[ac_cv_getrandom_syscall=yes],[ac_cv_getrandom_syscall=no]) +]) -if test "$have_getrandom_syscall" = yes; then +AS_VAR_IF([ac_cv_getrandom_syscall], [yes], [ AC_DEFINE(HAVE_GETRANDOM_SYSCALL, 1, [Define to 1 if the Linux getrandom() syscall is available]) -fi +]) # check if the getrandom() function is available # the test was written for the Solaris function of -AC_MSG_CHECKING(for the getrandom() function) +AC_CACHE_CHECK([for the getrandom() function], [ac_cv_func_getrandom], [ AC_LINK_IFELSE( [ AC_LANG_SOURCE([[ @@ -5880,13 +5704,13 @@ AC_LINK_IFELSE( return 0; } ]]) -],[have_getrandom=yes],[have_getrandom=no]) -AC_MSG_RESULT($have_getrandom) +],[ac_cv_func_getrandom=yes],[ac_cv_func_getrandom=no]) +]) -if test "$have_getrandom" = yes; then +AS_VAR_IF([ac_cv_func_getrandom], [yes], [ AC_DEFINE(HAVE_GETRANDOM, 1, [Define to 1 if the getrandom() function is available]) -fi +]) # checks for POSIX shared memory, used by Modules/_multiprocessing/posixshmem.c # shm_* may only be available if linking against librt @@ -5940,7 +5764,7 @@ AC_MSG_RESULT($OPENSSL_RPATH) AC_SUBST([OPENSSL_RPATH]) # check if OpenSSL libraries work as expected -AC_MSG_CHECKING(whether OpenSSL provides required APIs) +AC_CACHE_CHECK([whether OpenSSL provides required APIs], [ac_cv_working_openssl], [ save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" save_LDFLAGS="$LDFLAGS" @@ -5975,11 +5799,12 @@ OBJ_nid2sn(NID_sha3_512); OBJ_nid2sn(NID_blake2b512); EVP_PBE_scrypt(NULL, 0, NULL, 0, 2, 8, 1, 0, NULL, 0); ]])], - [AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no)]) + [ac_cv_working_openssl=yes], + [ac_cv_working_openssl=no]) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" LDFLAGS="$save_LDFLAGS" +]) # ssl module default cipher suite string AH_TEMPLATE(PY_SSL_DEFAULT_CIPHERS, diff --git a/pyconfig.h.in b/pyconfig.h.in index 0c149e24bca5f..df77b7ccdd725 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -118,7 +118,7 @@ /* define to 1 if your sem_getvalue is broken. */ #undef HAVE_BROKEN_SEM_GETVALUE -/* Define if `unsetenv` does not return an int. */ +/* Define if 'unsetenv' does not return an int. */ #undef HAVE_BROKEN_UNSETENV /* Has builtin __atomic_load_n() and __atomic_store_n() functions */ @@ -187,7 +187,7 @@ /* Define if you have the 'immedok' function. */ #undef HAVE_CURSES_IMMEDOK -/* Define if you have the 'is_pad' function or macro. */ +/* Define if you have the 'is_pad' function. */ #undef HAVE_CURSES_IS_PAD /* Define if you have the 'is_term_resized' function. */ @@ -290,7 +290,7 @@ /* Define to 1 if you have the header file. */ #undef HAVE_ENDIAN_H -/* Define if you have the 'epoll' functions. */ +/* Define if you have the 'epoll' function. */ #undef HAVE_EPOLL /* Define if you have the 'epoll_create1' function. */ @@ -559,7 +559,7 @@ /* Define to 1 if you have the `killpg' function. */ #undef HAVE_KILLPG -/* Define if you have the 'kqueue' functions. */ +/* Define if you have the 'kqueue' function. */ #undef HAVE_KQUEUE /* Define to 1 if you have the header file. */ @@ -779,7 +779,7 @@ /* Define to 1 if you have the `preadv2' function. */ #undef HAVE_PREADV2 -/* Define if you have the 'prlimit' functions. */ +/* Define if you have the 'prlimit' function. */ #undef HAVE_PRLIMIT /* Define to 1 if you have the header file. */ @@ -1287,10 +1287,10 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UTIME_H -/* Define if uuid_create() exists. */ +/* Define to 1 if you have the `uuid_create' function. */ #undef HAVE_UUID_CREATE -/* Define if uuid_enc_be() exists. */ +/* Define to 1 if you have the `uuid_enc_be' function. */ #undef HAVE_UUID_ENC_BE /* Define if uuid_generate_time_safe() exists. */ From webhook-mailer at python.org Mon Nov 8 03:20:02 2021 From: webhook-mailer at python.org (asvetlov) Date: Mon, 08 Nov 2021 08:20:02 -0000 Subject: [Python-checkins] remove the repeat 'the' (#29455) Message-ID: https://github.com/python/cpython/commit/122ca4d73faba279a579aa2011fa34661ce537a2 commit: 122ca4d73faba279a579aa2011fa34661ce537a2 branch: main author: 180909 <734461790 at qq.com> committer: asvetlov date: 2021-11-08T10:19:54+02:00 summary: remove the repeat 'the' (#29455) files: M Modules/_ctypes/libffi_osx/README diff --git a/Modules/_ctypes/libffi_osx/README b/Modules/_ctypes/libffi_osx/README index 69e46cbf8a420..54f00e3ec1ff3 100644 --- a/Modules/_ctypes/libffi_osx/README +++ b/Modules/_ctypes/libffi_osx/README @@ -165,7 +165,7 @@ for checking. It will be one of the following: Before making the call, the VALUES vector should be initialized with pointers to the appropriate argument values. -To call the the function using the initialized ffi_cif, use the +To call the function using the initialized ffi_cif, use the ffi_call function: void ffi_call(ffi_cif *cif, void *fn, void *rvalue, void **avalues); From webhook-mailer at python.org Mon Nov 8 03:45:16 2021 From: webhook-mailer at python.org (miss-islington) Date: Mon, 08 Nov 2021 08:45:16 -0000 Subject: [Python-checkins] remove the repeat 'the' (GH-29455) Message-ID: https://github.com/python/cpython/commit/6b0ea06ea83217bed5edcebbb771e45222ae591c commit: 6b0ea06ea83217bed5edcebbb771e45222ae591c branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-08T00:45:06-08:00 summary: remove the repeat 'the' (GH-29455) (cherry picked from commit 122ca4d73faba279a579aa2011fa34661ce537a2) Co-authored-by: 180909 <734461790 at qq.com> files: M Modules/_ctypes/libffi_osx/README diff --git a/Modules/_ctypes/libffi_osx/README b/Modules/_ctypes/libffi_osx/README index 69e46cbf8a420..54f00e3ec1ff3 100644 --- a/Modules/_ctypes/libffi_osx/README +++ b/Modules/_ctypes/libffi_osx/README @@ -165,7 +165,7 @@ for checking. It will be one of the following: Before making the call, the VALUES vector should be initialized with pointers to the appropriate argument values. -To call the the function using the initialized ffi_cif, use the +To call the function using the initialized ffi_cif, use the ffi_call function: void ffi_call(ffi_cif *cif, void *fn, void *rvalue, void **avalues); From webhook-mailer at python.org Mon Nov 8 06:48:49 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 08 Nov 2021 11:48:49 -0000 Subject: [Python-checkins] bpo-45743: Move __APPLE_USE_RFC_3542 into socketmodule.c (GH-29456) Message-ID: https://github.com/python/cpython/commit/24af9a40a8f85af813ea89998aa4e931fcc78cd9 commit: 24af9a40a8f85af813ea89998aa4e931fcc78cd9 branch: main author: Christian Heimes committer: tiran date: 2021-11-08T12:48:34+01:00 summary: bpo-45743: Move __APPLE_USE_RFC_3542 into socketmodule.c (GH-29456) files: M Modules/socketmodule.c M setup.py diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 50962c41cd3a6..ed1043c0c43a5 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -86,6 +86,8 @@ Local naming conventions: */ #ifdef __APPLE__ +// Issue #35569: Expose RFC 3542 socket options. +#define __APPLE_USE_RFC_3542 1 #include /* for getaddrinfo thread safety test on old versions of OS X */ #ifndef MAC_OS_X_VERSION_10_5 diff --git a/setup.py b/setup.py index b6bf8e129373b..fb641bd57d0d6 100644 --- a/setup.py +++ b/setup.py @@ -1222,13 +1222,7 @@ def detect_crypt(self): self.add(Extension('_crypt', ['_cryptmodule.c'], libraries=libs)) def detect_socket(self): - # socket(2) - kwargs = {'depends': ['socketmodule.h']} - if MACOS: - # Issue #35569: Expose RFC 3542 socket options. - kwargs['extra_compile_args'] = ['-D__APPLE_USE_RFC_3542'] - - self.add(Extension('_socket', ['socketmodule.c'], **kwargs)) + self.add(Extension('_socket', ['socketmodule.c'], depends=['socketmodule.h'])) def detect_dbm_gdbm(self): # Modules that provide persistent dictionary-like semantics. You will From webhook-mailer at python.org Mon Nov 8 11:42:09 2021 From: webhook-mailer at python.org (vstinner) Date: Mon, 08 Nov 2021 16:42:09 -0000 Subject: [Python-checkins] bpo-40170: Update What's New in Python 3.9 (GH-29470) Message-ID: https://github.com/python/cpython/commit/99c7e9853fa13af414168f179213e3d2fae03a45 commit: 99c7e9853fa13af414168f179213e3d2fae03a45 branch: main author: Victor Stinner committer: vstinner date: 2021-11-08T17:41:56+01:00 summary: bpo-40170: Update What's New in Python 3.9 (GH-29470) The PyType_HasFeature() change has been reverted: the static inline function access directly the PyTypeObject.tp_flags member. files: M Doc/whatsnew/3.9.rst diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index 941fae5fb8781..0d514084d6cc1 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -1378,10 +1378,6 @@ Porting to Python 3.9 becomes an alias to the :c:func:`PyObject_NewVar` macro. They no longer access directly the :c:member:`PyTypeObject.tp_basicsize` member. - * :c:func:`PyType_HasFeature` now always calls :c:func:`PyType_GetFlags`. - Previously, it accessed directly the :c:member:`PyTypeObject.tp_flags` - member when the limited C API was not used. - * :c:func:`PyObject_GET_WEAKREFS_LISTPTR` macro was converted to a function: the macro accessed directly the :c:member:`PyTypeObject.tp_weaklistoffset` member. From webhook-mailer at python.org Mon Nov 8 11:51:10 2021 From: webhook-mailer at python.org (zware) Date: Mon, 08 Nov 2021 16:51:10 -0000 Subject: [Python-checkins] Closes bpo-45712: Add missing word in control flow tutorial (GH-29460) Message-ID: https://github.com/python/cpython/commit/7484a5c82a2dfc106bb1e4b060cad2df00521bfd commit: 7484a5c82a2dfc106bb1e4b060cad2df00521bfd branch: main author: 180909 <734461790 at qq.com> committer: zware date: 2021-11-08T10:51:01-06:00 summary: Closes bpo-45712: Add missing word in control flow tutorial (GH-29460) files: M Doc/tutorial/controlflow.rst diff --git a/Doc/tutorial/controlflow.rst b/Doc/tutorial/controlflow.rst index fb3b140fe79ba..a819756602612 100644 --- a/Doc/tutorial/controlflow.rst +++ b/Doc/tutorial/controlflow.rst @@ -378,7 +378,7 @@ Several other key features of this statement: - Mapping patterns: ``{"bandwidth": b, "latency": l}`` captures the ``"bandwidth"`` and ``"latency"`` values from a dictionary. Unlike sequence patterns, extra keys are ignored. An unpacking like ``**rest`` is also - supported. (But ``**_`` would be redundant, so it not allowed.) + supported. (But ``**_`` would be redundant, so it is not allowed.) - Subpatterns may be captured using the ``as`` keyword:: From webhook-mailer at python.org Mon Nov 8 12:05:23 2021 From: webhook-mailer at python.org (miss-islington) Date: Mon, 08 Nov 2021 17:05:23 -0000 Subject: [Python-checkins] bpo-40170: Update What's New in Python 3.9 (GH-29470) Message-ID: https://github.com/python/cpython/commit/69b3de65adc691cc5ad66e70e5c7caf61c202c79 commit: 69b3de65adc691cc5ad66e70e5c7caf61c202c79 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-08T09:05:15-08:00 summary: bpo-40170: Update What's New in Python 3.9 (GH-29470) The PyType_HasFeature() change has been reverted: the static inline function access directly the PyTypeObject.tp_flags member. (cherry picked from commit 99c7e9853fa13af414168f179213e3d2fae03a45) Co-authored-by: Victor Stinner files: M Doc/whatsnew/3.9.rst diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index f1725e7df0220..296c64d737d3e 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -1378,10 +1378,6 @@ Porting to Python 3.9 becomes an alias to the :c:func:`PyObject_NewVar` macro. They no longer access directly the :c:member:`PyTypeObject.tp_basicsize` member. - * :c:func:`PyType_HasFeature` now always calls :c:func:`PyType_GetFlags`. - Previously, it accessed directly the :c:member:`PyTypeObject.tp_flags` - member when the limited C API was not used. - * :c:func:`PyObject_GET_WEAKREFS_LISTPTR` macro was converted to a function: the macro accessed directly the :c:member:`PyTypeObject.tp_weaklistoffset` member. From webhook-mailer at python.org Mon Nov 8 12:10:50 2021 From: webhook-mailer at python.org (vstinner) Date: Mon, 08 Nov 2021 17:10:50 -0000 Subject: [Python-checkins] bpo-40170: Update What's New in Python 3.9 (GH-29470) (GH-29472) Message-ID: https://github.com/python/cpython/commit/80580f5ab85e3c45c8c5e8999963a891598d10bf commit: 80580f5ab85e3c45c8c5e8999963a891598d10bf branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: vstinner date: 2021-11-08T18:10:41+01:00 summary: bpo-40170: Update What's New in Python 3.9 (GH-29470) (GH-29472) The PyType_HasFeature() change has been reverted: the static inline function access directly the PyTypeObject.tp_flags member. (cherry picked from commit 99c7e9853fa13af414168f179213e3d2fae03a45) Co-authored-by: Victor Stinner files: M Doc/whatsnew/3.9.rst diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index c29715d192f95..0662adba7d4af 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -1377,10 +1377,6 @@ Porting to Python 3.9 becomes an alias to the :c:func:`PyObject_NewVar` macro. They no longer access directly the :c:member:`PyTypeObject.tp_basicsize` member. - * :c:func:`PyType_HasFeature` now always calls :c:func:`PyType_GetFlags`. - Previously, it accessed directly the :c:member:`PyTypeObject.tp_flags` - member when the limited C API was not used. - * :c:func:`PyObject_GET_WEAKREFS_LISTPTR` macro was converted to a function: the macro accessed directly the :c:member:`PyTypeObject.tp_weaklistoffset` member. From webhook-mailer at python.org Mon Nov 8 12:13:09 2021 From: webhook-mailer at python.org (miss-islington) Date: Mon, 08 Nov 2021 17:13:09 -0000 Subject: [Python-checkins] Closes bpo-45712: Add missing word in control flow tutorial (GH-29460) Message-ID: https://github.com/python/cpython/commit/2c4792264f9218692a1bd87398a60591f756b171 commit: 2c4792264f9218692a1bd87398a60591f756b171 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-08T09:13:02-08:00 summary: Closes bpo-45712: Add missing word in control flow tutorial (GH-29460) (cherry picked from commit 7484a5c82a2dfc106bb1e4b060cad2df00521bfd) Co-authored-by: 180909 <734461790 at qq.com> files: M Doc/tutorial/controlflow.rst diff --git a/Doc/tutorial/controlflow.rst b/Doc/tutorial/controlflow.rst index fb3b140fe79ba..a819756602612 100644 --- a/Doc/tutorial/controlflow.rst +++ b/Doc/tutorial/controlflow.rst @@ -378,7 +378,7 @@ Several other key features of this statement: - Mapping patterns: ``{"bandwidth": b, "latency": l}`` captures the ``"bandwidth"`` and ``"latency"`` values from a dictionary. Unlike sequence patterns, extra keys are ignored. An unpacking like ``**rest`` is also - supported. (But ``**_`` would be redundant, so it not allowed.) + supported. (But ``**_`` would be redundant, so it is not allowed.) - Subpatterns may be captured using the ``as`` keyword:: From webhook-mailer at python.org Mon Nov 8 12:58:32 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 08 Nov 2021 17:58:32 -0000 Subject: [Python-checkins] bpo-45723: Add macro for disabling/enabling CC warnings (GH-29466) Message-ID: https://github.com/python/cpython/commit/9bd0cf5970997b63d296e30d51e7bb9a15dcabaf commit: 9bd0cf5970997b63d296e30d51e7bb9a15dcabaf branch: main author: Erlend Egeberg Aasland committer: tiran date: 2021-11-08T18:58:22+01:00 summary: bpo-45723: Add macro for disabling/enabling CC warnings (GH-29466) Co-authored-by: Christian Heimes files: M configure M configure.ac diff --git a/configure b/configure index 48d8bfd0899ff..207291850032b 100755 --- a/configure +++ b/configure @@ -7074,22 +7074,25 @@ fi UNIVERSAL_ARCH_FLAGS= + + # tweak BASECFLAGS based on compiler and platform case $GCC in yes) CFLAGS_NODIST="$CFLAGS_NODIST -std=c99" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -Wextra" >&5 -$as_echo_n "checking for -Wextra... " >&6; } - ac_save_cc="$CC" - CC="$CC -Wextra -Werror" - if ${ac_cv_extra_warnings+:} false; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Wextra" >&5 +$as_echo_n "checking if we can add -Wextra... " >&6; } + + py_cflags=$CFLAGS + CFLAGS="$CFLAGS -Wextra -Werror" + if ${ac_cv_enable_extra_warning+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - int main () { @@ -7097,28 +7100,24 @@ main () ; return 0; } - _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - - ac_cv_extra_warnings=yes - + ac_cv_enable_extra_warning=yes else - - ac_cv_extra_warnings=no - + ac_cv_enable_extra_warning=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi - CC="$ac_save_cc" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_extra_warnings" >&5 -$as_echo "$ac_cv_extra_warnings" >&6; } + CFLAGS=$py_cflags + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_extra_warning" >&5 +$as_echo "$ac_cv_enable_extra_warning" >&6; } - if test $ac_cv_extra_warnings = yes - then - CFLAGS_NODIST="$CFLAGS_NODIST -Wextra" - fi + + if test "x$ac_cv_enable_extra_warning" = xyes; then : + CFLAGS_NODIST="$CFLAGS_NODIST -Wextra" +fi # Python doesn't violate C99 aliasing rules, but older versions of # GCC produce warnings for legal Python code. Enable @@ -7185,30 +7184,27 @@ fi CC="$ac_save_cc" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_no_strict_aliasing" >&5 $as_echo "$ac_cv_no_strict_aliasing" >&6; } - if test $ac_cv_no_strict_aliasing = yes - then - BASECFLAGS="$BASECFLAGS -fno-strict-aliasing" - fi + if test "x$ac_cv_no_strict_aliasing" = xyes; then : + BASECFLAGS="$BASECFLAGS -fno-strict-aliasing" +fi # ICC doesn't recognize the option, but only emits a warning ## XXX does it emit an unused result warning and can it be disabled? - case "$CC" in - *icc*) + case $CC in #( + *icc*) : ac_cv_disable_unused_result_warning=no - ;; - *) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can turn off $CC unused result warning" >&5 -$as_echo_n "checking if we can turn off $CC unused result warning... " >&6; } - ac_save_cc="$CC" - CC="$CC -Wunused-result -Werror" - save_CFLAGS="$CFLAGS" - if ${ac_cv_disable_unused_result_warning+:} false; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can disable $CC unused-result warning" >&5 +$as_echo_n "checking if we can disable $CC unused-result warning... " >&6; } + + py_cflags=$CFLAGS + CFLAGS="$CFLAGS -Wunused-result -Werror" + if ${ac_cv_disable_unused_result_warning+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - int main () { @@ -7216,44 +7212,41 @@ main () ; return 0; } - _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - - ac_cv_disable_unused_result_warning=yes - + ac_cv_disable_unused_result_warning=yes else - - ac_cv_disable_unused_result_warning=no - + ac_cv_disable_unused_result_warning=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi - CFLAGS="$save_CFLAGS" - CC="$ac_save_cc" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_disable_unused_result_warning" >&5 + CFLAGS=$py_cflags + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_disable_unused_result_warning" >&5 $as_echo "$ac_cv_disable_unused_result_warning" >&6; } - ;; - esac - if test $ac_cv_disable_unused_result_warning = yes - then - BASECFLAGS="$BASECFLAGS -Wno-unused-result" - CFLAGS_NODIST="$CFLAGS_NODIST -Wno-unused-result" - fi + ;; #( + *) : + ;; +esac + if test "x$ac_cv_disable_unused_result_warning" = xyes; then : + BASECFLAGS="$BASECFLAGS -Wno-unused-result" + CFLAGS_NODIST="$CFLAGS_NODIST -Wno-unused-result" +fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can turn off $CC unused parameter warning" >&5 -$as_echo_n "checking if we can turn off $CC unused parameter warning... " >&6; } - ac_save_cc="$CC" - CC="$CC -Wunused-parameter -Werror" - if ${ac_cv_disable_unused_parameter_warning+:} false; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can disable $CC unused-parameter warning" >&5 +$as_echo_n "checking if we can disable $CC unused-parameter warning... " >&6; } + + py_cflags=$CFLAGS + CFLAGS="$CFLAGS -Wunused-parameter -Werror" + if ${ac_cv_disable_unused_parameter_warning+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - int main () { @@ -7261,40 +7254,37 @@ main () ; return 0; } - _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - - ac_cv_disable_unused_parameter_warning=yes - + ac_cv_disable_unused_parameter_warning=yes else - - ac_cv_disable_unused_parameter_warning=no - + ac_cv_disable_unused_parameter_warning=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi - CC="$ac_save_cc" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_disable_unused_parameter_warning" >&5 + CFLAGS=$py_cflags + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_disable_unused_parameter_warning" >&5 $as_echo "$ac_cv_disable_unused_parameter_warning" >&6; } - if test $ac_cv_disable_unused_parameter_warning = yes - then - CFLAGS_NODIST="$CFLAGS_NODIST -Wno-unused-parameter" - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can turn off $CC missing field initializers warning" >&5 -$as_echo_n "checking if we can turn off $CC missing field initializers warning... " >&6; } - ac_save_cc="$CC" - CC="$CC -Wmissing-field-initializers -Werror" - if ${ac_cv_disable_missing_field_initializers+:} false; then : + if test "x$ac_cv_disable_unused_parameter_warning" = xyes; then : + CFLAGS_NODIST="$CFLAGS_NODIST -Wno-unused-parameter" +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can disable $CC missing-field-initializers warning" >&5 +$as_echo_n "checking if we can disable $CC missing-field-initializers warning... " >&6; } + + py_cflags=$CFLAGS + CFLAGS="$CFLAGS -Wmissing-field-initializers -Werror" + if ${ac_cv_disable_missing_field_initializers_warning+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - int main () { @@ -7302,41 +7292,37 @@ main () ; return 0; } - _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_disable_missing_field_initializers_warning=yes +else + ac_cv_disable_missing_field_initializers_warning=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_cv_disable_missing_field_initializers=yes +fi -else + CFLAGS=$py_cflags + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_disable_missing_field_initializers_warning" >&5 +$as_echo "$ac_cv_disable_missing_field_initializers_warning" >&6; } - ac_cv_disable_missing_field_initializers=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test "x$ac_cv_disable_missing_field_initializers_warning" = xyes; then : + CFLAGS_NODIST="$CFLAGS_NODIST -Wno-missing-field-initializers" fi - CC="$ac_save_cc" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_disable_missing_field_initializers" >&5 -$as_echo "$ac_cv_disable_missing_field_initializers" >&6; } - if test $ac_cv_disable_missing_field_initializers = yes - then - CFLAGS_NODIST="$CFLAGS_NODIST -Wno-missing-field-initializers" - fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can enable $CC sign-compare warning" >&5 +$as_echo_n "checking if we can enable $CC sign-compare warning... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can turn on $CC mixed sign comparison warning" >&5 -$as_echo_n "checking if we can turn on $CC mixed sign comparison warning... " >&6; } - ac_save_cc="$CC" - CC="$CC -Wsign-compare" - save_CFLAGS="$CFLAGS" - if ${ac_cv_enable_sign_compare_warning+:} false; then : + py_cflags=$CFLAGS + CFLAGS="$CFLAGS -Wsign-compare -Werror" + if ${ac_cv_enable_sign_compare_warning+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - int main () { @@ -7344,42 +7330,37 @@ main () ; return 0; } - _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - - ac_cv_enable_sign_compare_warning=yes - + ac_cv_enable_sign_compare_warning=yes else - - ac_cv_enable_sign_compare_warning=no - + ac_cv_enable_sign_compare_warning=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi - CFLAGS="$save_CFLAGS" - CC="$ac_save_cc" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_sign_compare_warning" >&5 + CFLAGS=$py_cflags + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_sign_compare_warning" >&5 $as_echo "$ac_cv_enable_sign_compare_warning" >&6; } - if test $ac_cv_enable_sign_compare_warning = yes - then - BASECFLAGS="$BASECFLAGS -Wsign-compare" - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can turn on $CC unreachable code warning" >&5 -$as_echo_n "checking if we can turn on $CC unreachable code warning... " >&6; } - ac_save_cc="$CC" - CC="$CC -Wunreachable-code" - save_CFLAGS="$CFLAGS" - if ${ac_cv_enable_unreachable_code_warning+:} false; then : + if test "x$ac_cv_enable_sign_compare_warning" = xyes; then : + BASECFLAGS="$BASECFLAGS -Wsign-compare" +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can enable $CC unreachable-code warning" >&5 +$as_echo_n "checking if we can enable $CC unreachable-code warning... " >&6; } + + py_cflags=$CFLAGS + CFLAGS="$CFLAGS -Wunreachable-code -Werror" + if ${ac_cv_enable_unreachable_code_warning+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - int main () { @@ -7387,22 +7368,20 @@ main () ; return 0; } - _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - - ac_cv_enable_unreachable_code_warning=yes - + ac_cv_enable_unreachable_code_warning=yes else - - ac_cv_enable_unreachable_code_warning=no - + ac_cv_enable_unreachable_code_warning=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi - CFLAGS="$save_CFLAGS" - CC="$ac_save_cc" + CFLAGS=$py_cflags + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_unreachable_code_warning" >&5 +$as_echo "$ac_cv_enable_unreachable_code_warning" >&6; } + # Don't enable unreachable code warning in debug mode, since it usually # results in non-standard code paths. @@ -7419,20 +7398,19 @@ fi else ac_cv_enable_unreachable_code_warning=no fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_unreachable_code_warning" >&5 -$as_echo "$ac_cv_enable_unreachable_code_warning" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can turn on $CC strict-prototypes warning" >&5 -$as_echo_n "checking if we can turn on $CC strict-prototypes warning... " >&6; } - ac_save_cc="$CC" - CC="$CC -Werror -Wstrict-prototypes" - if ${ac_cv_enable_enable_strict_prototypes_warning+:} false; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can enable $CC strict-prototypes warning" >&5 +$as_echo_n "checking if we can enable $CC strict-prototypes warning... " >&6; } + + py_cflags=$CFLAGS + CFLAGS="$CFLAGS -Wstrict-prototypes -Werror" + if ${ac_cv_enable_strict_prototypes_warning+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - int main () { @@ -7440,28 +7418,24 @@ main () ; return 0; } - _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - - ac_cv_enable_strict_prototypes_warning=yes - + ac_cv_enable_strict_prototypes_warning=yes else - - ac_cv_enable_strict_prototypes_warning=no - + ac_cv_enable_strict_prototypes_warning=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi - CC="$ac_save_cc" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_strict_prototypes_warning" >&5 + CFLAGS=$py_cflags + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_strict_prototypes_warning" >&5 $as_echo "$ac_cv_enable_strict_prototypes_warning" >&6; } - if test $ac_cv_enable_strict_prototypes_warning = yes - then - CFLAGS_NODIST="$CFLAGS_NODIST -Wstrict-prototypes" - fi + + if test "x$ac_cv_enable_strict_prototypes_warning" = xyes; then : + CFLAGS_NODIST="$CFLAGS_NODIST -Wstrict-prototypes" +fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can make implicit function declaration an error in $CC" >&5 $as_echo_n "checking if we can make implicit function declaration an error in $CC... " >&6; } @@ -7499,10 +7473,9 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_implicit_function_declaration_error" >&5 $as_echo "$ac_cv_enable_implicit_function_declaration_error" >&6; } - if test $ac_cv_enable_implicit_function_declaration_error = yes - then - CFLAGS_NODIST="$CFLAGS_NODIST -Werror=implicit-function-declaration" - fi + if test "x$ac_cv_enable_implicit_function_declaration_error" = xyes; then : + CFLAGS_NODIST="$CFLAGS_NODIST -Werror=implicit-function-declaration" +fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can use visibility in $CC" >&5 $as_echo_n "checking if we can use visibility in $CC... " >&6; } @@ -7540,10 +7513,9 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_visibility" >&5 $as_echo "$ac_cv_enable_visibility" >&6; } - if test $ac_cv_enable_visibility = yes - then - CFLAGS_NODIST="$CFLAGS_NODIST -fvisibility=hidden" - fi + if test "x$ac_cv_enable_visibility" = xyes; then : + CFLAGS_NODIST="$CFLAGS_NODIST -fvisibility=hidden" +fi # if using gcc on alpha, use -mieee to get (near) full IEEE 754 # support. Without this, treatment of subnormals doesn't follow diff --git a/configure.ac b/configure.ac index a982a2f0c88c8..eef36a16afa3a 100644 --- a/configure.ac +++ b/configure.ac @@ -1640,30 +1640,33 @@ AC_SUBST(LDFLAGS_NODIST) UNIVERSAL_ARCH_FLAGS= AC_SUBST(UNIVERSAL_ARCH_FLAGS) +dnl PY_CHECK_CC_WARNING(ENABLE, WARNING, [MSG]) +AC_DEFUN([PY_CHECK_CC_WARNING], [ + AC_MSG_CHECKING(m4_ifblank([$3], [if we can $1 $CC $2 warning], [$3])) + AS_VAR_PUSHDEF([py_var], [ac_cv_$1_]m4_normalize($2)[_warning]) + AS_VAR_COPY([py_cflags], [CFLAGS]) + AS_VAR_SET([CFLAGS], ["$CFLAGS -W$2 -Werror"]) + AC_CACHE_VAL( + [py_var], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[]], [[]])], + [AS_VAR_SET([py_var], [yes])], + [AS_VAR_SET([py_var], [no])], + )] + ) + AS_VAR_COPY([CFLAGS], [py_cflags]) + AC_MSG_RESULT([$py_var]) + AS_VAR_POPDEF([py_var]) +]) + # tweak BASECFLAGS based on compiler and platform case $GCC in yes) CFLAGS_NODIST="$CFLAGS_NODIST -std=c99" - AC_MSG_CHECKING(for -Wextra) - ac_save_cc="$CC" - CC="$CC -Wextra -Werror" - AC_CACHE_VAL(ac_cv_extra_warnings, - AC_COMPILE_IFELSE( - [ - AC_LANG_PROGRAM([[]], [[]]) - ],[ - ac_cv_extra_warnings=yes - ],[ - ac_cv_extra_warnings=no - ])) - CC="$ac_save_cc" - AC_MSG_RESULT($ac_cv_extra_warnings) - - if test $ac_cv_extra_warnings = yes - then - CFLAGS_NODIST="$CFLAGS_NODIST -Wextra" - fi + PY_CHECK_CC_WARNING([enable], [extra], [if we can add -Wextra]) + AS_VAR_IF([ac_cv_enable_extra_warning], [yes], + [CFLAGS_NODIST="$CFLAGS_NODIST -Wextra"]) # Python doesn't violate C99 aliasing rules, but older versions of # GCC produce warnings for legal Python code. Enable @@ -1695,121 +1698,31 @@ yes) CFLAGS="$save_CFLAGS" CC="$ac_save_cc" AC_MSG_RESULT($ac_cv_no_strict_aliasing) - if test $ac_cv_no_strict_aliasing = yes - then - BASECFLAGS="$BASECFLAGS -fno-strict-aliasing" - fi + AS_VAR_IF([ac_cv_no_strict_aliasing], [yes], + [BASECFLAGS="$BASECFLAGS -fno-strict-aliasing"]) # ICC doesn't recognize the option, but only emits a warning ## XXX does it emit an unused result warning and can it be disabled? - case "$CC" in - *icc*) - ac_cv_disable_unused_result_warning=no - ;; - *) - AC_MSG_CHECKING(if we can turn off $CC unused result warning) - ac_save_cc="$CC" - CC="$CC -Wunused-result -Werror" - save_CFLAGS="$CFLAGS" - AC_CACHE_VAL(ac_cv_disable_unused_result_warning, - AC_COMPILE_IFELSE( - [ - AC_LANG_PROGRAM([[]], [[]]) - ],[ - ac_cv_disable_unused_result_warning=yes - ],[ - ac_cv_disable_unused_result_warning=no - ])) - CFLAGS="$save_CFLAGS" - CC="$ac_save_cc" - AC_MSG_RESULT($ac_cv_disable_unused_result_warning) - ;; - esac - - if test $ac_cv_disable_unused_result_warning = yes - then - BASECFLAGS="$BASECFLAGS -Wno-unused-result" - CFLAGS_NODIST="$CFLAGS_NODIST -Wno-unused-result" - fi - - AC_MSG_CHECKING(if we can turn off $CC unused parameter warning) - ac_save_cc="$CC" - CC="$CC -Wunused-parameter -Werror" - AC_CACHE_VAL(ac_cv_disable_unused_parameter_warning, - AC_COMPILE_IFELSE( - [ - AC_LANG_PROGRAM([[]], [[]]) - ],[ - ac_cv_disable_unused_parameter_warning=yes - ],[ - ac_cv_disable_unused_parameter_warning=no - ])) - CC="$ac_save_cc" - AC_MSG_RESULT($ac_cv_disable_unused_parameter_warning) - - if test $ac_cv_disable_unused_parameter_warning = yes - then - CFLAGS_NODIST="$CFLAGS_NODIST -Wno-unused-parameter" - fi - - AC_MSG_CHECKING(if we can turn off $CC missing field initializers warning) - ac_save_cc="$CC" - CC="$CC -Wmissing-field-initializers -Werror" - AC_CACHE_VAL(ac_cv_disable_missing_field_initializers, - AC_COMPILE_IFELSE( - [ - AC_LANG_PROGRAM([[]], [[]]) - ],[ - ac_cv_disable_missing_field_initializers=yes - ],[ - ac_cv_disable_missing_field_initializers=no - ])) - CC="$ac_save_cc" - AC_MSG_RESULT($ac_cv_disable_missing_field_initializers) - - if test $ac_cv_disable_missing_field_initializers = yes - then - CFLAGS_NODIST="$CFLAGS_NODIST -Wno-missing-field-initializers" - fi - - AC_MSG_CHECKING(if we can turn on $CC mixed sign comparison warning) - ac_save_cc="$CC" - CC="$CC -Wsign-compare" - save_CFLAGS="$CFLAGS" - AC_CACHE_VAL(ac_cv_enable_sign_compare_warning, - AC_COMPILE_IFELSE( - [ - AC_LANG_PROGRAM([[]], [[]]) - ],[ - ac_cv_enable_sign_compare_warning=yes - ],[ - ac_cv_enable_sign_compare_warning=no - ])) - CFLAGS="$save_CFLAGS" - CC="$ac_save_cc" - AC_MSG_RESULT($ac_cv_enable_sign_compare_warning) - - if test $ac_cv_enable_sign_compare_warning = yes - then - BASECFLAGS="$BASECFLAGS -Wsign-compare" - fi - - AC_MSG_CHECKING(if we can turn on $CC unreachable code warning) - ac_save_cc="$CC" - CC="$CC -Wunreachable-code" - save_CFLAGS="$CFLAGS" - AC_CACHE_VAL(ac_cv_enable_unreachable_code_warning, - AC_COMPILE_IFELSE( - [ - AC_LANG_PROGRAM([[]], [[]]) - ],[ - ac_cv_enable_unreachable_code_warning=yes - ],[ - ac_cv_enable_unreachable_code_warning=no - ])) - CFLAGS="$save_CFLAGS" - CC="$ac_save_cc" - + AS_CASE([$CC], + [*icc*], [ac_cv_disable_unused_result_warning=no] + [PY_CHECK_CC_WARNING([disable], [unused-result])]) + AS_VAR_IF([ac_cv_disable_unused_result_warning], [yes], + [BASECFLAGS="$BASECFLAGS -Wno-unused-result" + CFLAGS_NODIST="$CFLAGS_NODIST -Wno-unused-result"]) + + PY_CHECK_CC_WARNING([disable], [unused-parameter]) + AS_VAR_IF([ac_cv_disable_unused_parameter_warning], [yes], + [CFLAGS_NODIST="$CFLAGS_NODIST -Wno-unused-parameter"]) + + PY_CHECK_CC_WARNING([disable], [missing-field-initializers]) + AS_VAR_IF([ac_cv_disable_missing_field_initializers_warning], [yes], + [CFLAGS_NODIST="$CFLAGS_NODIST -Wno-missing-field-initializers"]) + + PY_CHECK_CC_WARNING([enable], [sign-compare]) + AS_VAR_IF([ac_cv_enable_sign_compare_warning], [yes], + [BASECFLAGS="$BASECFLAGS -Wsign-compare"]) + + PY_CHECK_CC_WARNING([enable], [unreachable-code]) # Don't enable unreachable code warning in debug mode, since it usually # results in non-standard code paths. # Issue #24324: Unfortunately, the unreachable code warning does not work @@ -1825,27 +1738,10 @@ yes) else ac_cv_enable_unreachable_code_warning=no fi - AC_MSG_RESULT($ac_cv_enable_unreachable_code_warning) - AC_MSG_CHECKING(if we can turn on $CC strict-prototypes warning) - ac_save_cc="$CC" - CC="$CC -Werror -Wstrict-prototypes" - AC_CACHE_VAL(ac_cv_enable_enable_strict_prototypes_warning, - AC_COMPILE_IFELSE( - [ - AC_LANG_PROGRAM([[]], [[]]) - ],[ - ac_cv_enable_strict_prototypes_warning=yes - ],[ - ac_cv_enable_strict_prototypes_warning=no - ])) - CC="$ac_save_cc" - AC_MSG_RESULT($ac_cv_enable_strict_prototypes_warning) - - if test $ac_cv_enable_strict_prototypes_warning = yes - then - CFLAGS_NODIST="$CFLAGS_NODIST -Wstrict-prototypes" - fi + PY_CHECK_CC_WARNING([enable], [strict-prototypes]) + AS_VAR_IF([ac_cv_enable_strict_prototypes_warning], [yes], + [CFLAGS_NODIST="$CFLAGS_NODIST -Wstrict-prototypes"]) AC_MSG_CHECKING(if we can make implicit function declaration an error in $CC) ac_save_cc="$CC" @@ -1862,10 +1758,8 @@ yes) CC="$ac_save_cc" AC_MSG_RESULT($ac_cv_enable_implicit_function_declaration_error) - if test $ac_cv_enable_implicit_function_declaration_error = yes - then - CFLAGS_NODIST="$CFLAGS_NODIST -Werror=implicit-function-declaration" - fi + AS_VAR_IF([ac_cv_enable_implicit_function_declaration_error], [yes], + [CFLAGS_NODIST="$CFLAGS_NODIST -Werror=implicit-function-declaration"]) AC_MSG_CHECKING(if we can use visibility in $CC) ac_save_cc="$CC" @@ -1882,10 +1776,8 @@ yes) CC="$ac_save_cc" AC_MSG_RESULT($ac_cv_enable_visibility) - if test $ac_cv_enable_visibility = yes - then - CFLAGS_NODIST="$CFLAGS_NODIST -fvisibility=hidden" - fi + AS_VAR_IF([ac_cv_enable_visibility], [yes], + [CFLAGS_NODIST="$CFLAGS_NODIST -fvisibility=hidden"]) # if using gcc on alpha, use -mieee to get (near) full IEEE 754 # support. Without this, treatment of subnormals doesn't follow From webhook-mailer at python.org Mon Nov 8 13:31:23 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 08 Nov 2021 18:31:23 -0000 Subject: [Python-checkins] bpo-45723: Prepare support for autoconf 2.71 (GH-29441) Message-ID: https://github.com/python/cpython/commit/cbab997efb3ba5123dc8d9f706184fa8e634b3ec commit: cbab997efb3ba5123dc8d9f706184fa8e634b3ec branch: main author: Christian Heimes committer: tiran date: 2021-11-08T19:31:14+01:00 summary: bpo-45723: Prepare support for autoconf 2.71 (GH-29441) files: A Misc/NEWS.d/next/Build/2021-11-07-10-45-40.bpo-45723.AreusF.rst M Include/pyport.h M Modules/_collectionsmodule.c M Modules/arraymodule.c M Objects/listobject.c M configure M configure.ac M pyconfig.h.in diff --git a/Include/pyport.h b/Include/pyport.h index 61ca3a97c186b..953f75c970d83 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -216,17 +216,10 @@ typedef Py_ssize_t Py_ssize_clean_t; * WRAPPER FOR and/or * ********************************************/ -#ifdef TIME_WITH_SYS_TIME -#include -#include -#else /* !TIME_WITH_SYS_TIME */ #ifdef HAVE_SYS_TIME_H #include -#else /* !HAVE_SYS_TIME_H */ +#endif #include -#endif /* !HAVE_SYS_TIME_H */ -#endif /* !TIME_WITH_SYS_TIME */ - /****************************** * WRAPPER FOR * diff --git a/Misc/NEWS.d/next/Build/2021-11-07-10-45-40.bpo-45723.AreusF.rst b/Misc/NEWS.d/next/Build/2021-11-07-10-45-40.bpo-45723.AreusF.rst new file mode 100644 index 0000000000000..066465edb600b --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-07-10-45-40.bpo-45723.AreusF.rst @@ -0,0 +1,2 @@ +``configure.ac`` is now compatible with autoconf 2.71. Deprecated checks +``STDC_HEADERS`` and ``AC_HEADER_TIME`` have been removed. diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index c6de9636032c0..4c4e1f762a4a6 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -2,12 +2,7 @@ #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_long.h" // _PyLong_GetZero() #include "structmember.h" // PyMemberDef - -#ifdef STDC_HEADERS #include -#else -#include // size_t -#endif /*[clinic input] module _collections diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index 030ede57351e9..8e430632813e6 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -13,14 +13,7 @@ #include "pycore_moduleobject.h" // _PyModule_GetState() #include "structmember.h" // PyMemberDef #include // offsetof() - -#ifdef STDC_HEADERS #include -#else /* !STDC_HEADERS */ -#ifdef HAVE_SYS_TYPES_H -#include /* For size_t */ -#endif /* HAVE_SYS_TYPES_H */ -#endif /* !STDC_HEADERS */ /*[clinic input] module array diff --git a/Objects/listobject.c b/Objects/listobject.c index 05743cde55191..be84cf9c330e3 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -5,12 +5,7 @@ #include "pycore_interp.h" // PyInterpreterState.list #include "pycore_object.h" // _PyObject_GC_TRACK() #include "pycore_tuple.h" // _PyTuple_FromArray() - -#ifdef STDC_HEADERS #include -#else -#include /* For size_t */ -#endif /*[clinic input] class list "PyListObject *" "&PyList_Type" diff --git a/configure b/configure index 207291850032b..cd25c1d68e11d 100755 --- a/configure +++ b/configure @@ -718,7 +718,6 @@ DLLLIBRARY LDLIBRARY LIBRARY BUILDEXEEXT -EGREP NO_AS_NEEDED MULTIARCH_CPPFLAGS PLATFORM_TRIPLET @@ -726,6 +725,7 @@ MULTIARCH ac_ct_CXX MAINCC CXX +EGREP SED GREP CPP @@ -1806,52 +1806,6 @@ fi } # ac_fn_c_try_cpp -# ac_fn_c_try_link LINENO -# ----------------------- -# Try to link conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_link () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext conftest$ac_exeext - if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - test -x conftest$ac_exeext - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information - # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would - # interfere with the next link command; also delete a directory that is - # left behind by Apple's compiler. We do this before executing the actions. - rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_c_try_link - # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using @@ -2016,6 +1970,52 @@ $as_echo "$ac_res" >&6; } } # ac_fn_c_check_header_compile +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache @@ -3051,12 +3051,6 @@ VERSION=3.11 SOVERSION=1.0 -# The later definition of _XOPEN_SOURCE disables certain features -# on Linux, so we need _GNU_SOURCE to re-enable them (makedev, tm_zone). - -$as_echo "#define _GNU_SOURCE 1" >>confdefs.h - - # The later definition of _XOPEN_SOURCE and _POSIX_C_SOURCE disables # certain features on NetBSD, so we need _NETBSD_SOURCE to re-enable # them. @@ -4672,143 +4666,308 @@ $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-cxx-main=" >&5 -$as_echo_n "checking for --with-cxx-main=... " >&6; } - -# Check whether --with-cxx_main was given. -if test "${with_cxx_main+set}" = set; then : - withval=$with_cxx_main; - - case $withval in - no) with_cxx_main=no - MAINCC='$(CC)';; - yes) with_cxx_main=yes - MAINCC='$(CXX)';; - *) with_cxx_main=yes - MAINCC=$withval - if test -z "$CXX" - then - CXX=$withval - fi;; - esac -else - - with_cxx_main=no - MAINCC='$(CC)' - -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_cxx_main" >&5 -$as_echo "$with_cxx_main" >&6; } - -preset_cxx="$CXX" -if test -z "$CXX" -then - case "$CC" in - gcc) if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}g++", so it can be a program name with args. -set dummy ${ac_tool_prefix}g++; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_CXX+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else - case $CXX in - [\\/]* | ?:[\\/]*) - ac_cv_path_CXX="$CXX" # Let the user override the test with a path. - ;; - *) + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in notfound +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_CXX="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break done -IFS=$as_save_IFS - - ;; + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac -fi -CXX=$ac_cv_path_CXX -if test -n "$CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 -$as_echo "$CXX" >&6; } + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + ac_cv_path_EGREP=$EGREP fi - + fi fi -if test -z "$ac_cv_path_CXX"; then - ac_pt_CXX=$CXX - # Extract the first word of "g++", so it can be a program name with args. -set dummy g++; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_ac_pt_CXX+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + + +# checks for UNIX variants that set C preprocessor variables +# may set _GNU_SOURCE, __EXTENSIONS__, _POSIX_PTHREAD_SEMANTICS, +# _POSIX_SOURCE, _POSIX_1_SOURCE, and more + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else - case $ac_pt_CXX in - [\\/]* | ?:[\\/]*) - ac_cv_path_ac_pt_CXX="$ac_pt_CXX" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in notfound -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_ac_pt_CXX="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include - ;; -esac +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no fi -ac_pt_CXX=$ac_cv_path_ac_pt_CXX -if test -n "$ac_pt_CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_CXX" >&5 -$as_echo "$ac_pt_CXX" >&6; } +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + ac_cv_header_stdc=no fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default" +if test "x$ac_cv_header_minix_config_h" = xyes; then : + MINIX=yes +else + MINIX= +fi + + + if test "$MINIX" = yes; then + +$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h + + +$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h + + +$as_echo "#define _MINIX 1" >>confdefs.h - if test "x$ac_pt_CXX" = x; then - CXX="g++" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CXX=$ac_pt_CXX fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 +$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } +if ${ac_cv_safe_to_define___extensions__+:} false; then : + $as_echo_n "(cached) " >&6 else - CXX="$ac_cv_path_CXX" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# define __EXTENSIONS__ 1 + $ac_includes_default +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_safe_to_define___extensions__=yes +else + ac_cv_safe_to_define___extensions__=no fi - ;; - cc) if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}c++", so it can be a program name with args. -set dummy ${ac_tool_prefix}c++; ac_word=$2 +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5 +$as_echo "$ac_cv_safe_to_define___extensions__" >&6; } + test $ac_cv_safe_to_define___extensions__ = yes && + $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h + + $as_echo "#define _ALL_SOURCE 1" >>confdefs.h + + $as_echo "#define _GNU_SOURCE 1" >>confdefs.h + + $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h + + $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-cxx-main=" >&5 +$as_echo_n "checking for --with-cxx-main=... " >&6; } + +# Check whether --with-cxx_main was given. +if test "${with_cxx_main+set}" = set; then : + withval=$with_cxx_main; + + case $withval in + no) with_cxx_main=no + MAINCC='$(CC)';; + yes) with_cxx_main=yes + MAINCC='$(CXX)';; + *) with_cxx_main=yes + MAINCC=$withval + if test -z "$CXX" + then + CXX=$withval + fi;; + esac +else + + with_cxx_main=no + MAINCC='$(CC)' + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_cxx_main" >&5 +$as_echo "$with_cxx_main" >&6; } + +preset_cxx="$CXX" +if test -z "$CXX" +then + case "$CC" in + gcc) if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}g++", so it can be a program name with args. +set dummy ${ac_tool_prefix}g++; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_CXX+:} false; then : @@ -4850,8 +5009,8 @@ fi fi if test -z "$ac_cv_path_CXX"; then ac_pt_CXX=$CXX - # Extract the first word of "c++", so it can be a program name with args. -set dummy c++; ac_word=$2 + # Extract the first word of "g++", so it can be a program name with args. +set dummy g++; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pt_CXX+:} false; then : @@ -4890,7 +5049,7 @@ $as_echo "no" >&6; } fi if test "x$ac_pt_CXX" = x; then - CXX="c++" + CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) @@ -4904,9 +5063,9 @@ else CXX="$ac_cv_path_CXX" fi ;; - clang|*/clang) if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}clang++", so it can be a program name with args. -set dummy ${ac_tool_prefix}clang++; ac_word=$2 + cc) if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}c++", so it can be a program name with args. +set dummy ${ac_tool_prefix}c++; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_CXX+:} false; then : @@ -4948,8 +5107,8 @@ fi fi if test -z "$ac_cv_path_CXX"; then ac_pt_CXX=$CXX - # Extract the first word of "clang++", so it can be a program name with args. -set dummy clang++; ac_word=$2 + # Extract the first word of "c++", so it can be a program name with args. +set dummy c++; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pt_CXX+:} false; then : @@ -4988,7 +5147,7 @@ $as_echo "no" >&6; } fi if test "x$ac_pt_CXX" = x; then - CXX="clang++" + CXX="c++" else case $cross_compiling:$ac_tool_warned in yes:) @@ -5002,9 +5161,107 @@ else CXX="$ac_cv_path_CXX" fi ;; - icc|*/icc) if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}icpc", so it can be a program name with args. -set dummy ${ac_tool_prefix}icpc; ac_word=$2 + clang|*/clang) if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}clang++", so it can be a program name with args. +set dummy ${ac_tool_prefix}clang++; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $CXX in + [\\/]* | ?:[\\/]*) + ac_cv_path_CXX="$CXX" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in notfound +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_CXX="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +CXX=$ac_cv_path_CXX +if test -n "$CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_CXX"; then + ac_pt_CXX=$CXX + # Extract the first word of "clang++", so it can be a program name with args. +set dummy clang++; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_CXX in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_CXX="$ac_pt_CXX" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in notfound +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_CXX="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_CXX=$ac_cv_path_ac_pt_CXX +if test -n "$ac_pt_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_CXX" >&5 +$as_echo "$ac_pt_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_CXX" = x; then + CXX="clang++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_pt_CXX + fi +else + CXX="$ac_cv_path_CXX" +fi + ;; + icc|*/icc) if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}icpc", so it can be a program name with args. +set dummy ${ac_tool_prefix}icpc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_CXX+:} false; then : @@ -5376,295 +5633,41 @@ cat >> conftest.c <conftest.out 2>/dev/null; then - PLATFORM_TRIPLET=`grep -v '^#' conftest.out | grep -v '^ *$' | tr -d ' '` - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PLATFORM_TRIPLET" >&5 -$as_echo "$PLATFORM_TRIPLET" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 -$as_echo "none" >&6; } -fi -rm -f conftest.c conftest.out - -if test x$PLATFORM_TRIPLET != xdarwin; then - MULTIARCH=$($CC --print-multiarch 2>/dev/null) -fi - - -if test x$PLATFORM_TRIPLET != x && test x$MULTIARCH != x; then - if test x$PLATFORM_TRIPLET != x$MULTIARCH; then - as_fn_error $? "internal configure error for the platform triplet, please file a bug report" "$LINENO" 5 - fi -elif test x$PLATFORM_TRIPLET != x && test x$MULTIARCH = x; then - MULTIARCH=$PLATFORM_TRIPLET -fi - -if test x$MULTIARCH != x; then - MULTIARCH_CPPFLAGS="-DMULTIARCH=\\\"$MULTIARCH\\\"" -fi - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -Wl,--no-as-needed" >&5 -$as_echo_n "checking for -Wl,--no-as-needed... " >&6; } -save_LDFLAGS="$LDFLAGS" -LDFLAGS="$LDFLAGS -Wl,--no-as-needed" - -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - NO_AS_NEEDED="-Wl,--no-as-needed" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - NO_AS_NEEDED="" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LDFLAGS="$save_LDFLAGS" - - - -# checks for UNIX variants that set C preprocessor variables - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 -$as_echo_n "checking for egrep... " >&6; } -if ${ac_cv_path_EGREP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 - then ac_cv_path_EGREP="$GREP -E" - else - if test -z "$EGREP"; then - ac_path_EGREP_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in egrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" - as_fn_executable_p "$ac_path_EGREP" || continue -# Check for GNU ac_path_EGREP and select it if it is found. - # Check for GNU $ac_path_EGREP -case `"$ac_path_EGREP" --version 2>&1` in -*GNU*) - ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; -*) - ac_count=0 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo 'EGREP' >> "conftest.nl" - "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_EGREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_EGREP="$ac_path_EGREP" - ac_path_EGREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - $ac_path_EGREP_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_EGREP"; then - as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 - fi -else - ac_cv_path_EGREP=$EGREP -fi - - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 -$as_echo "$ac_cv_path_EGREP" >&6; } - EGREP="$ac_cv_path_EGREP" - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 -$as_echo_n "checking for ANSI C header files... " >&6; } -if ${ac_cv_header_stdc+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#include -#include - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_header_stdc=yes -else - ac_cv_header_stdc=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then : - : -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif - -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - return 2; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - -else - ac_cv_header_stdc=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 -$as_echo "$ac_cv_header_stdc" >&6; } -if test $ac_cv_header_stdc = yes; then - -$as_echo "#define STDC_HEADERS 1" >>confdefs.h - -fi - -# On IRIX 5.3, sys/types and inttypes.h are conflicting. -for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ - inttypes.h stdint.h unistd.h -do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default -" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - - - - ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default" -if test "x$ac_cv_header_minix_config_h" = xyes; then : - MINIX=yes -else - MINIX= -fi - - - if test "$MINIX" = yes; then - -$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h - - -$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h +if $CPP $CPPFLAGS conftest.c >conftest.out 2>/dev/null; then + PLATFORM_TRIPLET=`grep -v '^#' conftest.out | grep -v '^ *$' | tr -d ' '` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PLATFORM_TRIPLET" >&5 +$as_echo "$PLATFORM_TRIPLET" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +rm -f conftest.c conftest.out +if test x$PLATFORM_TRIPLET != xdarwin; then + MULTIARCH=$($CC --print-multiarch 2>/dev/null) +fi -$as_echo "#define _MINIX 1" >>confdefs.h +if test x$PLATFORM_TRIPLET != x && test x$MULTIARCH != x; then + if test x$PLATFORM_TRIPLET != x$MULTIARCH; then + as_fn_error $? "internal configure error for the platform triplet, please file a bug report" "$LINENO" 5 fi +elif test x$PLATFORM_TRIPLET != x && test x$MULTIARCH = x; then + MULTIARCH=$PLATFORM_TRIPLET +fi +if test x$MULTIARCH != x; then + MULTIARCH_CPPFLAGS="-DMULTIARCH=\\\"$MULTIARCH\\\"" +fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 -$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } -if ${ac_cv_safe_to_define___extensions__+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -Wl,--no-as-needed" >&5 +$as_echo_n "checking for -Wl,--no-as-needed... " >&6; } +save_LDFLAGS="$LDFLAGS" +LDFLAGS="$LDFLAGS -Wl,--no-as-needed" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -# define __EXTENSIONS__ 1 - $ac_includes_default int main () { @@ -5673,26 +5676,18 @@ main () return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_safe_to_define___extensions__=yes +if ac_fn_c_try_link "$LINENO"; then : + NO_AS_NEEDED="-Wl,--no-as-needed" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } else - ac_cv_safe_to_define___extensions__=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + NO_AS_NEEDED="" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5 -$as_echo "$ac_cv_safe_to_define___extensions__" >&6; } - test $ac_cv_safe_to_define___extensions__ = yes && - $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h - - $as_echo "#define _ALL_SOURCE 1" >>confdefs.h - - $as_echo "#define _GNU_SOURCE 1" >>confdefs.h - - $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h - - $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h - +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LDFLAGS="$save_LDFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the Android API level" >&5 @@ -7973,119 +7968,11 @@ fi CXX="$ac_save_cxx" -# checks for header files -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 -$as_echo_n "checking for ANSI C header files... " >&6; } -if ${ac_cv_header_stdc+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#include -#include - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_header_stdc=yes -else - ac_cv_header_stdc=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then : - : -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif - -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - return 2; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - -else - ac_cv_header_stdc=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 -$as_echo "$ac_cv_header_stdc" >&6; } -if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h -fi +# checks for header files for ac_header in asm/types.h crypt.h conio.h direct.h dlfcn.h errno.h \ fcntl.h grp.h \ ieeefp.h io.h langinfo.h libintl.h process.h pthread.h \ @@ -8344,14 +8231,8 @@ CFLAGS=$SAVE_CFLAGS for ac_header in net/if.h do : ac_fn_c_check_header_compile "$LINENO" "net/if.h" "ac_cv_header_net_if_h" "#include -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif +#include +#include #ifdef HAVE_SYS_SOCKET_H # include #endif @@ -13514,9 +13395,9 @@ done # This gets us our -lcrypt in LIBS when required on the target platform. # Save/restore LIBS to avoid linking libpython with libcrypt. LIBS_SAVE=$LIBS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing crypt" >&5 -$as_echo_n "checking for library containing crypt... " >&6; } -if ${ac_cv_search_crypt+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing crypt_r" >&5 +$as_echo_n "checking for library containing crypt_r... " >&6; } +if ${ac_cv_search_crypt_r+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS @@ -13529,11 +13410,11 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext #ifdef __cplusplus extern "C" #endif -char crypt (); +char crypt_r (); int main () { -return crypt (); +return crypt_r (); ; return 0; } @@ -13546,33 +13427,34 @@ for ac_lib in '' crypt; do LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_crypt=$ac_res + ac_cv_search_crypt_r=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext - if ${ac_cv_search_crypt+:} false; then : + if ${ac_cv_search_crypt_r+:} false; then : break fi done -if ${ac_cv_search_crypt+:} false; then : +if ${ac_cv_search_crypt_r+:} false; then : else - ac_cv_search_crypt=no + ac_cv_search_crypt_r=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_crypt" >&5 -$as_echo "$ac_cv_search_crypt" >&6; } -ac_res=$ac_cv_search_crypt +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_crypt_r" >&5 +$as_echo "$ac_cv_search_crypt_r" >&6; } +ac_res=$ac_cv_search_crypt_r if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing crypt_r" >&5 -$as_echo_n "checking for library containing crypt_r... " >&6; } -if ${ac_cv_search_crypt_r+:} false; then : +LIBS="$LIBS_SAVE" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing crypt" >&5 +$as_echo_n "checking for library containing crypt... " >&6; } +if ${ac_cv_search_crypt+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS @@ -13585,11 +13467,11 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext #ifdef __cplusplus extern "C" #endif -char crypt_r (); +char crypt (); int main () { -return crypt_r (); +return crypt (); ; return 0; } @@ -13602,25 +13484,25 @@ for ac_lib in '' crypt; do LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_crypt_r=$ac_res + ac_cv_search_crypt=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext - if ${ac_cv_search_crypt_r+:} false; then : + if ${ac_cv_search_crypt+:} false; then : break fi done -if ${ac_cv_search_crypt_r+:} false; then : +if ${ac_cv_search_crypt+:} false; then : else - ac_cv_search_crypt_r=no + ac_cv_search_crypt=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_crypt_r" >&5 -$as_echo "$ac_cv_search_crypt_r" >&6; } -ac_res=$ac_cv_search_crypt_r +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_crypt" >&5 +$as_echo "$ac_cv_search_crypt" >&6; } +ac_res=$ac_cv_search_crypt if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" @@ -13632,7 +13514,6 @@ if test "x$ac_cv_func_crypt_r" = xyes; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#define _GNU_SOURCE /* Required for crypt_r()'s prototype in glibc. */ #include int @@ -14189,42 +14070,15 @@ fi done -# checks for structures -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 -$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } -if ${ac_cv_header_time+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#include +if test "x$ac_cv_header_sys_time_h" = xyes; then : -int -main () -{ -if ((struct tm *) 0) -return 0; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_header_time=yes -else - ac_cv_header_time=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 -$as_echo "$ac_cv_header_time" >&6; } -if test $ac_cv_header_time = yes; then $as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h + fi +# checks for structures { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5 $as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; } if ${ac_cv_struct_tm+:} false; then : diff --git a/configure.ac b/configure.ac index eef36a16afa3a..87cf10251b2d5 100644 --- a/configure.ac +++ b/configure.ac @@ -61,7 +61,7 @@ else fi AC_CONFIG_SRCDIR([Include/object.h]) -AC_CONFIG_HEADER(pyconfig.h) +AC_CONFIG_HEADERS([pyconfig.h]) AC_CANONICAL_HOST AC_SUBST(build) @@ -133,10 +133,6 @@ VERSION=PYTHON_VERSION AC_SUBST(SOVERSION) SOVERSION=1.0 -# The later definition of _XOPEN_SOURCE disables certain features -# on Linux, so we need _GNU_SOURCE to re-enable them (makedev, tm_zone). -AC_DEFINE(_GNU_SOURCE, 1, [Define on Linux to activate all library features]) - # The later definition of _XOPEN_SOURCE and _POSIX_C_SOURCE disables # certain features on NetBSD, so we need _NETBSD_SOURCE to re-enable # them. @@ -664,6 +660,12 @@ AC_PROG_CC AC_PROG_CPP AC_PROG_GREP AC_PROG_SED +AC_PROG_EGREP + +# checks for UNIX variants that set C preprocessor variables +# may set _GNU_SOURCE, __EXTENSIONS__, _POSIX_PTHREAD_SEMANTICS, +# _POSIX_SOURCE, _POSIX_1_SOURCE, and more +AC_USE_SYSTEM_EXTENSIONS AC_SUBST(CXX) AC_SUBST(MAINCC) @@ -906,10 +908,6 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])], LDFLAGS="$save_LDFLAGS" AC_SUBST(NO_AS_NEEDED) - -# checks for UNIX variants that set C preprocessor variables -AC_USE_SYSTEM_EXTENSIONS - AC_MSG_CHECKING([for the Android API level]) cat >> conftest.c < -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif +#include +#include #ifdef HAVE_SYS_SOCKET_H # include #endif @@ -3924,12 +3919,12 @@ AC_CHECK_FUNCS(setpgrp, # This gets us our -lcrypt in LIBS when required on the target platform. # Save/restore LIBS to avoid linking libpython with libcrypt. LIBS_SAVE=$LIBS -AC_SEARCH_LIBS(crypt, crypt) AC_SEARCH_LIBS(crypt_r, crypt) +LIBS="$LIBS_SAVE" +AC_SEARCH_LIBS(crypt, crypt) AC_CHECK_FUNC(crypt_r, AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#define _GNU_SOURCE /* Required for crypt_r()'s prototype in glibc. */ #include ]], [[ struct crypt_data d; @@ -4130,8 +4125,13 @@ fi AC_CHECK_FUNCS(getnameinfo) +dnl autoconf 2.71 deprecates AC_HEADER_TIME, keep for backwards compatibility +dnl TIME_WITH_SYS_TIME works on all supported systems that have sys/time.h +AS_VAR_IF([ac_cv_header_sys_time_h], [yes], [ + AC_DEFINE([TIME_WITH_SYS_TIME], 1, [Define to 1 if you can safely include both and .]) +]) + # checks for structures -AC_HEADER_TIME AC_STRUCT_TM AC_STRUCT_TIMEZONE AC_CHECK_MEMBERS([struct stat.st_rdev]) diff --git a/pyconfig.h.in b/pyconfig.h.in index df77b7ccdd725..45617f25db257 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -1589,9 +1589,6 @@ /* This must be set to 64 on some systems to enable large file support. */ #undef _FILE_OFFSET_BITS -/* Define on Linux to activate all library features */ -#undef _GNU_SOURCE - /* Define to include mbstate_t for mbrtowc */ #undef _INCLUDE__STDC_A1_SOURCE From webhook-mailer at python.org Mon Nov 8 17:16:58 2021 From: webhook-mailer at python.org (zooba) Date: Mon, 08 Nov 2021 22:16:58 -0000 Subject: [Python-checkins] Add third-party Windows build definitions (GH-29476) Message-ID: https://github.com/python/cpython/commit/cfc9154121e2d677b782cfadfc90b949b1259332 commit: cfc9154121e2d677b782cfadfc90b949b1259332 branch: main author: Steve Dower committer: zooba date: 2021-11-08T22:16:53Z summary: Add third-party Windows build definitions (GH-29476) These definition files are for OpenSSL, libffi and Tcl/Tk, which we build and sign ourselves. files: A .azure-pipelines/find-tools.yml A .azure-pipelines/libffi-build.yml A .azure-pipelines/openssl-build.yml A .azure-pipelines/tcltk-build.yml diff --git a/.azure-pipelines/find-tools.yml b/.azure-pipelines/find-tools.yml new file mode 100644 index 0000000000000..9ad0f5622bb31 --- /dev/null +++ b/.azure-pipelines/find-tools.yml @@ -0,0 +1,26 @@ +# Locate a set of the tools used for builds + +steps: + - template: windows-release/find-sdk.yml + parameters: + toolname: 'signtool.exe' + + - powershell: | + $vcvarsall = (& "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" ` + -prerelease ` + -latest ` + -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 ` + -find VC\Auxiliary\Build\vcvarsall.bat) + Write-Host "Found vcvarsall at $vcvarsall" + Write-Host "##vso[task.setVariable variable=vcvarsall]$vcvarsall" + displayName: 'Find vcvarsall.bat' + + - powershell: | + $msbuild = (& "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" ` + -prerelease ` + -latest ` + -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 ` + -find MSBuild\Current\Bin\msbuild.exe) + Write-Host "Found MSBuild at $msbuild" + Write-Host "##vso[task.setVariable variable=msbuild]$msbuild" + displayName: 'Find MSBuild' diff --git a/.azure-pipelines/libffi-build.yml b/.azure-pipelines/libffi-build.yml new file mode 100644 index 0000000000000..dd26ff215a807 --- /dev/null +++ b/.azure-pipelines/libffi-build.yml @@ -0,0 +1,86 @@ +name: $(SourceTag)_$(Date:yyyyMMdd)$(Rev:.rr) + +variables: + IntDir: '$(Build.BinariesDirectory)' + OutDir: '$(Build.ArtifactStagingDirectory)' + + # MUST BE SET AT QUEUE TIME + # SigningCertificate: 'Python Software Foundation' + # SourcesRepo: 'https://github.com/python/cpython-source-deps' + # SourceTag: 'libffi-3.4.2' + +jobs: +- job: Build_LibFFI + displayName: LibFFI + pool: + vmImage: windows-latest + + workspace: + clean: all + + steps: + - checkout: none + + - template: ./find-tools.yml + + - powershell: | + mkdir -Force "$(IntDir)\script" + iwr "https://github.com/python/cpython/raw/main/PCbuild/prepare_libffi.bat" ` + -outfile "$(IntDir)\script\prepare_libffi.bat" + displayName: 'Download build script' + + - powershell: | + git clone $(SourcesRepo) -b $(SourceTag) --depth 1 -c core.autocrlf=false -c core.eol=lf . + displayName: 'Check out LibFFI sources' + + - script: 'prepare_libffi.bat --install-cygwin' + workingDirectory: '$(IntDir)\script' + displayName: 'Install Cygwin and build' + env: + VCVARSALL: '$(vcvarsall)' + LIBFFI_SOURCE: '$(Build.SourcesDirectory)' + LIBFFI_OUT: '$(OutDir)' + + - powershell: | + if ((gci *\*.dll).Count -lt 4) { + Write-Error "Did not generate enough DLL files" + } + if ((gci *\Include\ffi.h).Count -lt 4) { + Write-Error "Did not generate enough include files" + } + failOnStderr: true + workingDirectory: '$(OutDir)' + displayName: 'Verify files were created' + + - publish: '$(OutDir)' + artifact: 'unsigned' + displayName: 'Publish unsigned build' + +- job: Sign_LibFFI + displayName: Sign LibFFI + dependsOn: Build_LibFFI + pool: + name: 'Windows Release' + + workspace: + clean: all + + steps: + - checkout: none + - download: current + artifact: unsigned + + - template: ./find-tools.yml + + - powershell: | + signtool sign /q /a ` + /n "Python Software Foundation" ` + /fd sha256 ` + /tr http://timestamp.digicert.com/ /td sha256 ` + /d "LibFFI for Python" ` + (gci "$(Pipeline.Workspace)\unsigned\*.dll" -r) + displayName: 'Sign files' + + - publish: '$(Pipeline.Workspace)\unsigned' + artifact: 'libffi' + displayName: 'Publish libffi' diff --git a/.azure-pipelines/openssl-build.yml b/.azure-pipelines/openssl-build.yml new file mode 100644 index 0000000000000..8aab7ea0b9419 --- /dev/null +++ b/.azure-pipelines/openssl-build.yml @@ -0,0 +1,110 @@ +name: $(SourceTag)_$(Date:yyyyMMdd)$(Rev:.rr) + +variables: + IntDir: '$(Build.BinariesDirectory)' + OutDir: '$(Build.ArtifactStagingDirectory)' + + # MUST BE SET AT QUEUE TIME + # SigningCertificate: 'Python Software Foundation' + # SourcesRepo: 'https://github.com/python/cpython-source-deps' + # SourceTag: 'openssl-1.1.1k' + +jobs: +- job: Build_SSL + displayName: OpenSSL + pool: + name: 'Windows Release' + #vmImage: windows-latest + + strategy: + matrix: + win32: + Platform: 'win32' + VCPlatform: 'amd64_x86' + OpenSSLPlatform: 'VC-WIN32 no-asm' + amd64: + Platform: 'amd64' + VCPlatform: 'amd64' + OpenSSLPlatform: 'VC-WIN64A-masm' + arm32: + Platform: 'arm32' + VCPlatform: 'amd64_arm' + OpenSSLPlatform: 'VC-WIN32-ARM' + arm64: + Platform: 'arm64' + VCPlatform: 'amd64_arm64' + OpenSSLPlatform: 'VC-WIN64-ARM' + + workspace: + clean: all + + steps: + - checkout: none + + - template: ./find-tools.yml + + - powershell: | + git clone $(SourcesRepo) -b $(SourceTag) --depth 1 . + displayName: 'Check out OpenSSL sources' + + - powershell: | + $f = gi ms\uplink.c + $c1 = gc $f + $c2 = $c1 -replace '\(\(h = GetModuleHandle\(NULL\)\) == NULL\)', '((h = GetModuleHandleA("_ssl.pyd")) == NULL) if ((h = GetModuleHandleA("_ssl_d.pyd")) == NULL) if ((h = GetModuleHandle(NULL)) == NULL /*patched*/)' + if ($c2 -ne $c1) { + $c2 | Out-File $f -Encoding ASCII + } else { + Write-Host '##warning Failed to patch uplink.c' + } + displayName: 'Apply uplink.c patch' + + - script: | + call "$(vcvarsall)" $(VCPlatform) + perl "$(Build.SourcesDirectory)\Configure" $(OpenSSLPlatform) + nmake + workingDirectory: '$(IntDir)' + displayName: 'Build OpenSSL' + + - script: | + call "$(vcvarsall)" $(VCPlatform) + signtool sign /q /a /n "$(SigningCertificate)" /fd sha256 /tr http://timestamp.digicert.com/ /td sha256 /d "OpenSSL for Python" *.dll + workingDirectory: '$(IntDir)' + displayName: 'Sign OpenSSL Build' + condition: and(succeeded(), variables['SigningCertificate']) + + - task: CopyFiles at 2 + displayName: 'Copy built libraries for upload' + inputs: + SourceFolder: '$(IntDir)' + Contents: | + lib*.dll + lib*.pdb + lib*.lib + include\openssl\*.h + TargetFolder: '$(OutDir)' + + - task: CopyFiles at 2 + displayName: 'Copy header files for upload' + inputs: + SourceFolder: '$(Build.SourcesDirectory)' + Contents: | + include\openssl\* + TargetFolder: '$(OutDir)' + + - task: CopyFiles at 2 + displayName: 'Copy applink files for upload' + inputs: + SourceFolder: '$(Build.SourcesDirectory)\ms' + Contents: applink.c + TargetFolder: '$(OutDir)\include' + + - task: CopyFiles at 2 + displayName: 'Copy LICENSE for upload' + inputs: + SourceFolder: '$(Build.SourcesDirectory)' + Contents: LICENSE + TargetFolder: '$(OutDir)' + + - publish: '$(OutDir)' + artifact: '$(Platform)' + displayName: 'Publishing $(Platform)' diff --git a/.azure-pipelines/tcltk-build.yml b/.azure-pipelines/tcltk-build.yml new file mode 100644 index 0000000000000..27968e886cc14 --- /dev/null +++ b/.azure-pipelines/tcltk-build.yml @@ -0,0 +1,65 @@ +name: tcl$(TkSourceTag)_$(Date:yyyyMMdd)$(Rev:.rr) + +variables: + IntDir: '$(Build.BinariesDirectory)\obj' + ExternalsDir: '$(Build.BinariesDirectory)\externals' + OutDir: '$(Build.ArtifactStagingDirectory)' + Configuration: 'Release' + + # MUST BE SET AT QUEUE TIME + # SigningCertificate: 'Python Software Foundation' + # SourcesRepo: 'https://github.com/python/cpython-source-deps' + # TclSourceTag: 'tcl-core-8.6.12.0' + # TkSourceTag: 'tk-8.6.12.0' + # TixSourceTag: 'tix-8.4.3.6' + +jobs: +- job: Build_TclTk + displayName: 'Tcl/Tk' + pool: + name: 'Windows Release' + #vmImage: windows-latest + + workspace: + clean: all + + steps: + - template: ./find-tools.yml + + - powershell: | + git clone $(SourcesRepo) -b $(TclSourceTag) --depth 1 "$(ExternalsDir)\$(TclSourceTag)" + displayName: 'Check out Tcl sources' + + - powershell: | + git clone $(SourcesRepo) -b $(TkSourceTag) --depth 1 "$(ExternalsDir)\$(TkSourceTag)" + displayName: 'Check out Tk sources' + + - powershell: | + git clone $(SourcesRepo) -b $(TixSourceTag) --depth 1 "$(ExternalsDir)\$(TixSourceTag)" + displayName: 'Check out Tix sources' + + # This msbuild.rsp file will be used by the build to forcibly override these variables + - powershell: | + del -Force -EA 0 msbuild.rsp + "/p:IntDir=$(IntDir)\" >> msbuild.rsp + "/p:ExternalsDir=$(ExternalsDir)\" >> msbuild.rsp + "/p:tclDir=$(ExternalsDir)\$(TclSourceTag)\" >> msbuild.rsp + "/p:tkDir=$(ExternalsDir)\$(TkSourceTag)\" >> msbuild.rsp + "/p:tixDir=$(ExternalsDir)\$(TixSourceTag)\" >> msbuild.rsp + displayName: 'Generate msbuild.rsp' + + - powershell: | + & "$(msbuild)" PCbuild\tcl.vcxproj "@msbuild.rsp" /p:Platform=Win32 /p:tcltkDir="$(OutDir)\win32" + & "$(msbuild)" PCbuild\tk.vcxproj "@msbuild.rsp" /p:Platform=Win32 /p:tcltkDir="$(OutDir)\win32" + & "$(msbuild)" PCbuild\tix.vcxproj "@msbuild.rsp" /p:Platform=Win32 /p:tcltkDir="$(OutDir)\win32" + displayName: 'Build for win32' + + - powershell: | + & "$(msbuild)" PCbuild\tcl.vcxproj "@msbuild.rsp" /p:Platform=x64 /p:tcltkDir="$(OutDir)\amd64" + & "$(msbuild)" PCbuild\tk.vcxproj "@msbuild.rsp" /p:Platform=x64 /p:tcltkDir="$(OutDir)\amd64" + & "$(msbuild)" PCbuild\tix.vcxproj "@msbuild.rsp" /p:Platform=x64 /p:tcltkDir="$(OutDir)\amd64" + displayName: 'Build for amd64' + + - publish: '$(OutDir)' + artifact: 'tcltk' + displayName: 'Publishing tcltk' From webhook-mailer at python.org Tue Nov 9 03:06:51 2021 From: webhook-mailer at python.org (tiran) Date: Tue, 09 Nov 2021 08:06:51 -0000 Subject: [Python-checkins] bpo-45743: -Wl, -search_paths_first is no longer needed (GH-29464) Message-ID: https://github.com/python/cpython/commit/8fefaad242f45b3bd97e000a00f2aac16d935315 commit: 8fefaad242f45b3bd97e000a00f2aac16d935315 branch: main author: Christian Heimes committer: tiran date: 2021-11-09T09:06:41+01:00 summary: bpo-45743: -Wl,-search_paths_first is no longer needed (GH-29464) files: A Misc/NEWS.d/next/Build/2021-11-08-08-58-06.bpo-45743.fZ8CTi.rst M configure M configure.ac M setup.py diff --git a/Misc/NEWS.d/next/Build/2021-11-08-08-58-06.bpo-45743.fZ8CTi.rst b/Misc/NEWS.d/next/Build/2021-11-08-08-58-06.bpo-45743.fZ8CTi.rst new file mode 100644 index 0000000000000..7241bd9637172 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-08-08-58-06.bpo-45743.fZ8CTi.rst @@ -0,0 +1,2 @@ +On macOS, the build system no longer passes ``search_paths_first`` to the +linker. The flag has been the default since Xcode 4 / macOS 10.6. diff --git a/configure b/configure index cd25c1d68e11d..76d9c49936134 100755 --- a/configure +++ b/configure @@ -12886,15 +12886,6 @@ $as_echo "#define HAVE_LCHFLAGS 1" >>confdefs.h fi # Check for compression libraries -case $ac_sys_system/$ac_sys_release in -Darwin/*) - _CUR_CFLAGS="${CFLAGS}" - _CUR_LDFLAGS="${LDFLAGS}" - CFLAGS="${CFLAGS} -Wl,-search_paths_first" - LDFLAGS="${LDFLAGS} -Wl,-search_paths_first -L/usr/local/lib" - ;; -esac - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflateCopy in -lz" >&5 $as_echo_n "checking for inflateCopy in -lz... " >&6; } if ${ac_cv_lib_z_inflateCopy+:} false; then : @@ -12938,13 +12929,6 @@ $as_echo "#define HAVE_ZLIB_COPY 1" >>confdefs.h fi -case $ac_sys_system/$ac_sys_release in -Darwin/*) - CFLAGS="${_CUR_CFLAGS}" - LDFLAGS="${_CUR_LDFLAGS}" - ;; -esac - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for hstrerror" >&5 diff --git a/configure.ac b/configure.ac index 87cf10251b2d5..8ea5d491a9674 100644 --- a/configure.ac +++ b/configure.ac @@ -3833,34 +3833,8 @@ fi # Check for compression libraries dnl Check if system zlib has *Copy() functions -dnl -dnl On MacOSX the linker will search for dylibs on the entire linker path -dnl before searching for static libraries. setup.py adds -Wl,-search_paths_first -dnl to revert to a more traditional unix behaviour and make it possible to -dnl override the system libz with a local static library of libz. Temporarily -dnl add that flag to our CFLAGS as well to ensure that we check the version -dnl of libz that will be used by setup.py. -dnl The -L/usr/local/lib is needed as wel to get the same compilation -dnl environment as setup.py (and leaving it out can cause configure to use the -dnl wrong version of the library) -case $ac_sys_system/$ac_sys_release in -Darwin/*) - _CUR_CFLAGS="${CFLAGS}" - _CUR_LDFLAGS="${LDFLAGS}" - CFLAGS="${CFLAGS} -Wl,-search_paths_first" - LDFLAGS="${LDFLAGS} -Wl,-search_paths_first -L/usr/local/lib" - ;; -esac - AC_CHECK_LIB(z, inflateCopy, AC_DEFINE(HAVE_ZLIB_COPY, 1, [Define if the zlib library has inflateCopy])) -case $ac_sys_system/$ac_sys_release in -Darwin/*) - CFLAGS="${_CUR_CFLAGS}" - LDFLAGS="${_CUR_LDFLAGS}" - ;; -esac - PY_CHECK_FUNC([hstrerror], [#include ]) PY_CHECK_FUNC([inet_aton], [ diff --git a/setup.py b/setup.py index fb641bd57d0d6..fa7abef95b054 100644 --- a/setup.py +++ b/setup.py @@ -1118,16 +1118,6 @@ def detect_readline_curses(self): if find_file('readline/rlconf.h', self.inc_dirs, []) is None: do_readline = False if do_readline: - if MACOS and os_release < 9: - # In every directory on the search path search for a dynamic - # library and then a static library, instead of first looking - # for dynamic libraries on the entire path. - # This way a statically linked custom readline gets picked up - # before the (possibly broken) dynamic library in /usr/lib. - readline_extra_link_args = ('-Wl,-search_paths_first',) - else: - readline_extra_link_args = () - readline_libs = [readline_lib] if readline_termcap_library: pass # Issue 7384: Already linked against curses or tinfo. @@ -1139,7 +1129,6 @@ def detect_readline_curses(self): readline_libs.append('termcap') self.add(Extension('readline', ['readline.c'], library_dirs=['/usr/lib/termcap'], - extra_link_args=readline_extra_link_args, libraries=readline_libs)) else: self.missing.append('readline') @@ -1603,16 +1592,6 @@ def detect_sqlite(self): ): raise DistutilsError("System version of SQLite does not support loadable extensions") - if MACOS: - # In every directory on the search path search for a dynamic - # library and then a static library, instead of first looking - # for dynamic libraries on the entire path. - # This way a statically linked custom sqlite gets picked up - # before the dynamic library in /usr/lib. - sqlite_extra_link_args = ('-Wl,-search_paths_first',) - else: - sqlite_extra_link_args = () - include_dirs = ["Modules/_sqlite"] # Only include the directory where sqlite was found if it does # not already exist in set include directories, otherwise you @@ -1626,7 +1605,6 @@ def detect_sqlite(self): define_macros=sqlite_defines, include_dirs=include_dirs, library_dirs=sqlite_libdir, - extra_link_args=sqlite_extra_link_args, libraries=["sqlite3",])) else: self.missing.append('_sqlite3') @@ -1685,13 +1663,8 @@ def detect_compress_exts(self): break if version >= version_req: if (self.compiler.find_library_file(self.lib_dirs, 'z')): - if MACOS: - zlib_extra_link_args = ('-Wl,-search_paths_first',) - else: - zlib_extra_link_args = () self.add(Extension('zlib', ['zlibmodule.c'], - libraries=['z'], - extra_link_args=zlib_extra_link_args)) + libraries=['z'])) have_zlib = True else: self.missing.append('zlib') @@ -1706,24 +1679,16 @@ def detect_compress_exts(self): if have_zlib: extra_compile_args.append('-DUSE_ZLIB_CRC32') libraries = ['z'] - extra_link_args = zlib_extra_link_args else: libraries = [] - extra_link_args = [] self.add(Extension('binascii', ['binascii.c'], extra_compile_args=extra_compile_args, - libraries=libraries, - extra_link_args=extra_link_args)) + libraries=libraries)) # Gustavo Niemeyer's bz2 module. if (self.compiler.find_library_file(self.lib_dirs, 'bz2')): - if MACOS: - bz2_extra_link_args = ('-Wl,-search_paths_first',) - else: - bz2_extra_link_args = () self.add(Extension('_bz2', ['_bz2module.c'], - libraries=['bz2'], - extra_link_args=bz2_extra_link_args)) + libraries=['bz2'])) else: self.missing.append('_bz2') From webhook-mailer at python.org Tue Nov 9 03:56:25 2021 From: webhook-mailer at python.org (tiran) Date: Tue, 09 Nov 2021 08:56:25 -0000 Subject: [Python-checkins] bpo-45743: Remove workaround for zlib CVE from 2002 (GH-29457) Message-ID: https://github.com/python/cpython/commit/6a1cc8bf8a0d88af9c7891c6577508ae9f70e3ef commit: 6a1cc8bf8a0d88af9c7891c6577508ae9f70e3ef branch: main author: Christian Heimes committer: tiran date: 2021-11-09T09:56:05+01:00 summary: bpo-45743: Remove workaround for zlib CVE from 2002 (GH-29457) files: M setup.py diff --git a/setup.py b/setup.py index fa7abef95b054..b125c51f6488b 100644 --- a/setup.py +++ b/setup.py @@ -1633,56 +1633,27 @@ def detect_platform_specific_exts(self): '-framework', 'CoreFoundation'])) def detect_compress_exts(self): - # Andrew Kuchling's zlib module. Note that some versions of zlib - # 1.1.3 have security problems. See CERT Advisory CA-2002-07: - # http://www.cert.org/advisories/CA-2002-07.html - # - # zlib 1.1.4 is fixed, but at least one vendor (RedHat) has decided to - # patch its zlib 1.1.3 package instead of upgrading to 1.1.4. For - # now, we still accept 1.1.3, because we think it's difficult to - # exploit this in Python, and we'd rather make it RedHat's problem - # than our problem . - # - # You can upgrade zlib to version 1.1.4 yourself by going to - # http://www.gzip.org/zlib/ - zlib_inc = find_file('zlib.h', [], self.inc_dirs) - have_zlib = False - if zlib_inc is not None: - zlib_h = zlib_inc[0] + '/zlib.h' - version = '"0.0.0"' - version_req = '"1.1.3"' - if MACOS and is_macosx_sdk_path(zlib_h): - zlib_h = os.path.join(macosx_sdk_root(), zlib_h[1:]) - with open(zlib_h) as fp: - while 1: - line = fp.readline() - if not line: - break - if line.startswith('#define ZLIB_VERSION'): - version = line.split()[2] - break - if version >= version_req: - if (self.compiler.find_library_file(self.lib_dirs, 'z')): - self.add(Extension('zlib', ['zlibmodule.c'], - libraries=['z'])) - have_zlib = True - else: - self.missing.append('zlib') - else: - self.missing.append('zlib') + # Andrew Kuchling's zlib module. + have_zlib = ( + find_file('zlib.h', self.inc_dirs, []) is not None and + self.compiler.find_library_file(self.lib_dirs, 'z') + ) + if have_zlib: + self.add(Extension('zlib', ['zlibmodule.c'], + libraries=['z'])) else: self.missing.append('zlib') # Helper module for various ascii-encoders. Uses zlib for an optimized # crc32 if we have it. Otherwise binascii uses its own. - extra_compile_args = [] if have_zlib: - extra_compile_args.append('-DUSE_ZLIB_CRC32') + define_macros = [('USE_ZLIB_CRC32', None)] libraries = ['z'] else: + define_macros = None libraries = [] self.add(Extension('binascii', ['binascii.c'], - extra_compile_args=extra_compile_args, + define_macros=define_macros, libraries=libraries)) # Gustavo Niemeyer's bz2 module. From webhook-mailer at python.org Tue Nov 9 06:20:04 2021 From: webhook-mailer at python.org (pablogsal) Date: Tue, 09 Nov 2021 11:20:04 -0000 Subject: [Python-checkins] bpo-45637: Remove broken fallback in gdb helpers to obtain frame variable (GH-29257) Message-ID: https://github.com/python/cpython/commit/f4c03484da59049eb62a9bf7777b963e2267d187 commit: f4c03484da59049eb62a9bf7777b963e2267d187 branch: main author: Pablo Galindo Salgado committer: pablogsal date: 2021-11-09T11:19:47Z summary: bpo-45637: Remove broken fallback in gdb helpers to obtain frame variable (GH-29257) files: M Lib/test/test_gdb.py M Tools/gdb/libpython.py diff --git a/Lib/test/test_gdb.py b/Lib/test/test_gdb.py index 2805eaf9f9567..eaeb6fb8ff568 100644 --- a/Lib/test/test_gdb.py +++ b/Lib/test/test_gdb.py @@ -823,6 +823,8 @@ def test_bt_full(self): foo\(1, 2, 3\) ''') + @unittest.skipIf(python_is_optimized(), + "Python was compiled with optimizations") def test_threads(self): 'Verify that "py-bt" indicates threads that are waiting for the GIL' cmd = ''' diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py index 54f72320cdd8b..f4b27f115216b 100755 --- a/Tools/gdb/libpython.py +++ b/Tools/gdb/libpython.py @@ -1801,17 +1801,13 @@ def get_pyop(self): frame = PyFramePtr(frame) if not frame.is_optimized_out(): return frame - # gdb is unable to get the "frame" argument of PyEval_EvalFrameEx() - # because it was "optimized out". Try to get "frame" from the frame - # of the caller, _PyEval_Vector(). - orig_frame = frame - caller = self._gdbframe.older() - if caller: - frame = caller.read_var('frame') - frame = PyFramePtr(frame) - if not frame.is_optimized_out(): - return frame - return orig_frame + cframe = self._gdbframe.read_var('cframe') + if cframe is None: + return None + frame = PyFramePtr(cframe["current_frame"].dereference()) + if frame and not frame.is_optimized_out(): + return frame + return None except ValueError: return None From webhook-mailer at python.org Tue Nov 9 09:03:37 2021 From: webhook-mailer at python.org (miss-islington) Date: Tue, 09 Nov 2021 14:03:37 -0000 Subject: [Python-checkins] bpo-45764: improve error message when missing '(' after 'def' (GH-29484) Message-ID: https://github.com/python/cpython/commit/2819e98d1048238bf94dc2ba88ae2455d01861bc commit: 2819e98d1048238bf94dc2ba88ae2455d01861bc branch: main author: Carl Friedrich Bolz-Tereick committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-09T06:03:32-08:00 summary: bpo-45764: improve error message when missing '(' after 'def' (GH-29484) to achieve this, change the grammar to expect the '(' token after 'def' NAME. Automerge-Triggered-By: GH:pablogsal files: A Misc/NEWS.d/next/Core and Builtins/2021-11-09-12-19-22.bpo-45764.8RLhWL.rst M Grammar/python.gram M Lib/test/test_syntax.py M Parser/parser.c diff --git a/Grammar/python.gram b/Grammar/python.gram index ffe035f037101..d1901a5a9a2bc 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -264,11 +264,11 @@ function_def[stmt_ty]: function_def_raw[stmt_ty]: | invalid_def_raw - | 'def' n=NAME '(' params=[params] ')' a=['->' z=expression { z }] &&':' tc=[func_type_comment] b=block { + | 'def' n=NAME &&'(' params=[params] ')' a=['->' z=expression { z }] &&':' tc=[func_type_comment] b=block { _PyAST_FunctionDef(n->v.Name.id, (params) ? params : CHECK(arguments_ty, _PyPegen_empty_arguments(p)), b, NULL, a, NEW_TYPE_COMMENT(p, tc), EXTRA) } - | ASYNC 'def' n=NAME '(' params=[params] ')' a=['->' z=expression { z }] &&':' tc=[func_type_comment] b=block { + | ASYNC 'def' n=NAME &&'(' params=[params] ')' a=['->' z=expression { z }] &&':' tc=[func_type_comment] b=block { CHECK_VERSION( stmt_ty, 5, diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 014a30aa2a612..65d18e4941be5 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -898,6 +898,17 @@ Traceback (most recent call last): SyntaxError: cannot assign to attribute here. Maybe you meant '==' instead of '='? + +Missing parens after function definition + + >>> def f: + Traceback (most recent call last): + SyntaxError: expected '(' + + >>> async def f: + Traceback (most recent call last): + SyntaxError: expected '(' + Custom error messages for try blocks that are not followed by except/finally >>> try: diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-09-12-19-22.bpo-45764.8RLhWL.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-09-12-19-22.bpo-45764.8RLhWL.rst new file mode 100644 index 0000000000000..d30b6a4a0e869 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-09-12-19-22.bpo-45764.8RLhWL.rst @@ -0,0 +1,9 @@ +The parser now gives a better error message when leaving out the opening +parenthesis ``(`` after a ``def``-statement:: + + >>> def f: + File "", line 1 + def f: + ^ + SyntaxError: expected '(' + diff --git a/Parser/parser.c b/Parser/parser.c index 8ef7980d66b59..b508c1ddec15c 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -4157,8 +4157,8 @@ function_def_rule(Parser *p) // function_def_raw: // | invalid_def_raw -// | 'def' NAME '(' params? ')' ['->' expression] &&':' func_type_comment? block -// | ASYNC 'def' NAME '(' params? ')' ['->' expression] &&':' func_type_comment? block +// | 'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block +// | ASYNC 'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block static stmt_ty function_def_raw_rule(Parser *p) { @@ -4197,12 +4197,12 @@ function_def_raw_rule(Parser *p) D(fprintf(stderr, "%*c%s function_def_raw[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_def_raw")); } - { // 'def' NAME '(' params? ')' ['->' expression] &&':' func_type_comment? block + { // 'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> function_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'def' NAME '(' params? ')' ['->' expression] &&':' func_type_comment? block")); + D(fprintf(stderr, "%*c> function_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block")); Token * _keyword; Token * _literal; Token * _literal_1; @@ -4217,7 +4217,7 @@ function_def_raw_rule(Parser *p) && (n = _PyPegen_name_token(p)) // NAME && - (_literal = _PyPegen_expect_token(p, 7)) // token='(' + (_literal = _PyPegen_expect_forced_token(p, 7, "(")) // forced_token='(' && (params = params_rule(p), !p->error_indicator) // params? && @@ -4232,7 +4232,7 @@ function_def_raw_rule(Parser *p) (b = block_rule(p)) // block ) { - D(fprintf(stderr, "%*c+ function_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'def' NAME '(' params? ')' ['->' expression] &&':' func_type_comment? block")); + D(fprintf(stderr, "%*c+ function_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { D(p->level--); @@ -4252,14 +4252,14 @@ function_def_raw_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s function_def_raw[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'def' NAME '(' params? ')' ['->' expression] &&':' func_type_comment? block")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block")); } - { // ASYNC 'def' NAME '(' params? ')' ['->' expression] &&':' func_type_comment? block + { // ASYNC 'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> function_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC 'def' NAME '(' params? ')' ['->' expression] &&':' func_type_comment? block")); + D(fprintf(stderr, "%*c> function_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC 'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block")); Token * _keyword; Token * _literal; Token * _literal_1; @@ -4277,7 +4277,7 @@ function_def_raw_rule(Parser *p) && (n = _PyPegen_name_token(p)) // NAME && - (_literal = _PyPegen_expect_token(p, 7)) // token='(' + (_literal = _PyPegen_expect_forced_token(p, 7, "(")) // forced_token='(' && (params = params_rule(p), !p->error_indicator) // params? && @@ -4292,7 +4292,7 @@ function_def_raw_rule(Parser *p) (b = block_rule(p)) // block ) { - D(fprintf(stderr, "%*c+ function_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC 'def' NAME '(' params? ')' ['->' expression] &&':' func_type_comment? block")); + D(fprintf(stderr, "%*c+ function_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC 'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { D(p->level--); @@ -4312,7 +4312,7 @@ function_def_raw_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s function_def_raw[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "ASYNC 'def' NAME '(' params? ')' ['->' expression] &&':' func_type_comment? block")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "ASYNC 'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block")); } _res = NULL; done: From webhook-mailer at python.org Tue Nov 9 10:33:11 2021 From: webhook-mailer at python.org (miss-islington) Date: Tue, 09 Nov 2021 15:33:11 -0000 Subject: [Python-checkins] bpo-45723: Remove obsolete AC_EXEEXT from configure.ac (GH-29486) Message-ID: https://github.com/python/cpython/commit/185533639d6eddd42a28f9e3517067bd877e34c5 commit: 185533639d6eddd42a28f9e3517067bd877e34c5 branch: main author: Erlend Egeberg Aasland committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-09T07:32:59-08:00 summary: bpo-45723: Remove obsolete AC_EXEEXT from configure.ac (GH-29486) >From the autoconf docs *Obsolete Macros* section: Defined the output variable EXEEXT based on the output of the compiler, which is now done automatically. Typically set to empty string if Posix and ?.exe? if a DOS variant. files: M configure M configure.ac diff --git a/configure b/configure index 76d9c49936134..45ac189f72752 100755 --- a/configure +++ b/configure @@ -5738,7 +5738,6 @@ atheos*|Linux*/1*) exit 1;; esac - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-suffix" >&5 $as_echo_n "checking for --with-suffix... " >&6; } diff --git a/configure.ac b/configure.ac index 8ea5d491a9674..7361d89a69016 100644 --- a/configure.ac +++ b/configure.ac @@ -947,7 +947,6 @@ atheos*|Linux*/1*) exit 1;; esac -AC_EXEEXT AC_MSG_CHECKING(for --with-suffix) AC_ARG_WITH(suffix, AS_HELP_STRING([--with-suffix=SUFFIX], [set executable suffix to SUFFIX (default is '.exe')]), From webhook-mailer at python.org Tue Nov 9 10:43:02 2021 From: webhook-mailer at python.org (tiran) Date: Tue, 09 Nov 2021 15:43:02 -0000 Subject: [Python-checkins] bpo-45763: Detect compression build deps in configure (GH-29483) Message-ID: https://github.com/python/cpython/commit/5b7c7cb104163a178e9d70cb3c80cbfa6af8fbfc commit: 5b7c7cb104163a178e9d70cb3c80cbfa6af8fbfc branch: main author: Christian Heimes committer: tiran date: 2021-11-09T16:42:53+01:00 summary: bpo-45763: Detect compression build deps in configure (GH-29483) files: A Misc/NEWS.d/next/Build/2021-11-09-10-15-33.bpo-45763.gP-vrX.rst M Doc/whatsnew/3.11.rst M configure M configure.ac M pyconfig.h.in M setup.py diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 7b15ace403170..27062f6162ac8 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -524,6 +524,9 @@ Build Changes (Contributed by Brett Cannon and Christian Heimes in :issue:`45548`, :issue:`45570`, :issue:`45571`, and :issue:`43974`.) +* The build dependencies for :mod:`zlib`, :mod:`bz2`, and :mod:`lzma` are now + detected by :program:`configure`. + (Contributed by Christian Heimes in :issue:`45763`.) C API Changes ============= diff --git a/Misc/NEWS.d/next/Build/2021-11-09-10-15-33.bpo-45763.gP-vrX.rst b/Misc/NEWS.d/next/Build/2021-11-09-10-15-33.bpo-45763.gP-vrX.rst new file mode 100644 index 0000000000000..1d09ae71256ae --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-09-10-15-33.bpo-45763.gP-vrX.rst @@ -0,0 +1,2 @@ +The build dependencies for :mod:`zlib`, :mod:`bz2`, and :mod:`lzma` are now +detected by ``configure``. diff --git a/configure b/configure index 45ac189f72752..a1f5e53018b07 100755 --- a/configure +++ b/configure @@ -12884,8 +12884,62 @@ $as_echo "#define HAVE_LCHFLAGS 1" >>confdefs.h fi -# Check for compression libraries -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflateCopy in -lz" >&5 +for ac_header in zlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" +if test "x$ac_cv_header_zlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ZLIB_H 1 +_ACEOF + + save_LIBS="$LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gzread in -lz" >&5 +$as_echo_n "checking for gzread in -lz... " >&6; } +if ${ac_cv_lib_z_gzread+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lz $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gzread (); +int +main () +{ +return gzread (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_z_gzread=yes +else + ac_cv_lib_z_gzread=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_gzread" >&5 +$as_echo "$ac_cv_lib_z_gzread" >&6; } +if test "x$ac_cv_lib_z_gzread" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBZ 1 +_ACEOF + + LIBS="-lz $LIBS" + +fi + + LIBS="$save_LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflateCopy in -lz" >&5 $as_echo_n "checking for inflateCopy in -lz... " >&6; } if ${ac_cv_lib_z_inflateCopy+:} false; then : $as_echo_n "(cached) " >&6 @@ -12927,6 +12981,134 @@ $as_echo "#define HAVE_ZLIB_COPY 1" >>confdefs.h fi + LIBS="$save_LIBS" + +fi + +done + + +for ac_header in bzlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "bzlib.h" "ac_cv_header_bzlib_h" "$ac_includes_default" +if test "x$ac_cv_header_bzlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_BZLIB_H 1 +_ACEOF + + save_LIBS="$LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BZ2_bzCompress in -lbz2" >&5 +$as_echo_n "checking for BZ2_bzCompress in -lbz2... " >&6; } +if ${ac_cv_lib_bz2_BZ2_bzCompress+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbz2 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char BZ2_bzCompress (); +int +main () +{ +return BZ2_bzCompress (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_bz2_BZ2_bzCompress=yes +else + ac_cv_lib_bz2_BZ2_bzCompress=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bz2_BZ2_bzCompress" >&5 +$as_echo "$ac_cv_lib_bz2_BZ2_bzCompress" >&6; } +if test "x$ac_cv_lib_bz2_BZ2_bzCompress" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBBZ2 1 +_ACEOF + + LIBS="-lbz2 $LIBS" + +fi + + LIBS="$save_LIBS" + +fi + +done + + +for ac_header in lzma.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "lzma.h" "ac_cv_header_lzma_h" "$ac_includes_default" +if test "x$ac_cv_header_lzma_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LZMA_H 1 +_ACEOF + + save_LIBS="$LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lzma_easy_encoder in -llzma" >&5 +$as_echo_n "checking for lzma_easy_encoder in -llzma... " >&6; } +if ${ac_cv_lib_lzma_lzma_easy_encoder+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-llzma $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char lzma_easy_encoder (); +int +main () +{ +return lzma_easy_encoder (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_lzma_lzma_easy_encoder=yes +else + ac_cv_lib_lzma_lzma_easy_encoder=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lzma_lzma_easy_encoder" >&5 +$as_echo "$ac_cv_lib_lzma_lzma_easy_encoder" >&6; } +if test "x$ac_cv_lib_lzma_lzma_easy_encoder" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBLZMA 1 +_ACEOF + + LIBS="-llzma $LIBS" + +fi + + LIBS="$save_LIBS" + +fi + +done + diff --git a/configure.ac b/configure.ac index 7361d89a69016..a7e5f2bd548b7 100644 --- a/configure.ac +++ b/configure.ac @@ -3830,9 +3830,26 @@ if test "$ac_cv_have_lchflags" = yes ; then AC_DEFINE(HAVE_LCHFLAGS, 1, [Define to 1 if you have the 'lchflags' function.]) fi -# Check for compression libraries -dnl Check if system zlib has *Copy() functions -AC_CHECK_LIB(z, inflateCopy, AC_DEFINE(HAVE_ZLIB_COPY, 1, [Define if the zlib library has inflateCopy])) +dnl Check for compression libraries +AC_CHECK_HEADERS([zlib.h], [ + save_LIBS="$LIBS" + AC_CHECK_LIB([z], [gzread]) + LIBS="$save_LIBS" + AC_CHECK_LIB([z], [inflateCopy], [AC_DEFINE(HAVE_ZLIB_COPY, 1, [Define if the zlib library has inflateCopy])]) + LIBS="$save_LIBS" +]) + +AC_CHECK_HEADERS([bzlib.h], [ + save_LIBS="$LIBS" + AC_CHECK_LIB([bz2], [BZ2_bzCompress]) + LIBS="$save_LIBS" +]) + +AC_CHECK_HEADERS([lzma.h], [ + save_LIBS="$LIBS" + AC_CHECK_LIB([lzma], [lzma_easy_encoder]) + LIBS="$save_LIBS" +]) PY_CHECK_FUNC([hstrerror], [#include ]) diff --git a/pyconfig.h.in b/pyconfig.h.in index 45617f25db257..2f71dd1758dcd 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -124,6 +124,9 @@ /* Has builtin __atomic_load_n() and __atomic_store_n() functions */ #undef HAVE_BUILTIN_ATOMIC +/* Define to 1 if you have the header file. */ +#undef HAVE_BZLIB_H + /* Define to 1 if you have the 'chflags' function. */ #undef HAVE_CHFLAGS @@ -580,6 +583,9 @@ /* Define to 1 if you have the `lchown' function. */ #undef HAVE_LCHOWN +/* Define to 1 if you have the `bz2' library (-lbz2). */ +#undef HAVE_LIBBZ2 + /* Define to 1 if you have the `dl' library (-ldl). */ #undef HAVE_LIBDL @@ -592,6 +598,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LIBINTL_H +/* Define to 1 if you have the `lzma' library (-llzma). */ +#undef HAVE_LIBLZMA + /* Define to build the readline module. */ #undef HAVE_LIBREADLINE @@ -607,6 +616,9 @@ /* Define to 1 if you have the `uuid' library (-luuid). */ #undef HAVE_LIBUUID +/* Define to 1 if you have the `z' library (-lz). */ +#undef HAVE_LIBZ + /* Define if you have the 'link' function. */ #undef HAVE_LINK @@ -670,6 +682,9 @@ /* Define to 1 if you have the `lutimes' function. */ #undef HAVE_LUTIMES +/* Define to 1 if you have the header file. */ +#undef HAVE_LZMA_H + /* Define to 1 if you have the `madvise' function. */ #undef HAVE_MADVISE @@ -1342,6 +1357,9 @@ /* Define if the zlib library has inflateCopy */ #undef HAVE_ZLIB_COPY +/* Define to 1 if you have the header file. */ +#undef HAVE_ZLIB_H + /* Define to 1 if you have the `_getpty' function. */ #undef HAVE__GETPTY diff --git a/setup.py b/setup.py index b125c51f6488b..7fe7d27b14ce0 100644 --- a/setup.py +++ b/setup.py @@ -1634,10 +1634,7 @@ def detect_platform_specific_exts(self): def detect_compress_exts(self): # Andrew Kuchling's zlib module. - have_zlib = ( - find_file('zlib.h', self.inc_dirs, []) is not None and - self.compiler.find_library_file(self.lib_dirs, 'z') - ) + have_zlib = sysconfig.get_config_var("HAVE_LIBZ") if have_zlib: self.add(Extension('zlib', ['zlibmodule.c'], libraries=['z'])) @@ -1657,14 +1654,14 @@ def detect_compress_exts(self): libraries=libraries)) # Gustavo Niemeyer's bz2 module. - if (self.compiler.find_library_file(self.lib_dirs, 'bz2')): + if sysconfig.get_config_var("HAVE_LIBBZ2"): self.add(Extension('_bz2', ['_bz2module.c'], libraries=['bz2'])) else: self.missing.append('_bz2') # LZMA compression support. - if self.compiler.find_library_file(self.lib_dirs, 'lzma'): + if sysconfig.get_config_var("HAVE_LIBLZMA"): self.add(Extension('_lzma', ['_lzmamodule.c'], libraries=['lzma'])) else: From webhook-mailer at python.org Tue Nov 9 11:30:11 2021 From: webhook-mailer at python.org (rhettinger) Date: Tue, 09 Nov 2021 16:30:11 -0000 Subject: [Python-checkins] Factor-out constant calculation. (GH-29491) Message-ID: https://github.com/python/cpython/commit/c3bc0fe5a6e4ee50bd186eebb638e881b1c4bf54 commit: c3bc0fe5a6e4ee50bd186eebb638e881b1c4bf54 branch: main author: Raymond Hettinger committer: rhettinger date: 2021-11-09T10:30:06-06:00 summary: Factor-out constant calculation. (GH-29491) files: M Lib/statistics.py diff --git a/Lib/statistics.py b/Lib/statistics.py index 13e5fe7fc0e86..e67c51709136a 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -139,6 +139,8 @@ from operator import itemgetter, mul from collections import Counter, namedtuple +_SQRT2 = sqrt(2.0) + # === Exceptions === class StatisticsError(ValueError): @@ -1102,7 +1104,7 @@ def cdf(self, x): "Cumulative distribution function. P(X <= x)" if not self._sigma: raise StatisticsError('cdf() not defined when sigma is zero') - return 0.5 * (1.0 + erf((x - self._mu) / (self._sigma * sqrt(2.0)))) + return 0.5 * (1.0 + erf((x - self._mu) / (self._sigma * _SQRT2))) def inv_cdf(self, p): """Inverse cumulative distribution function. x : P(X <= x) = p @@ -1158,7 +1160,7 @@ def overlap(self, other): dv = Y_var - X_var dm = fabs(Y._mu - X._mu) if not dv: - return 1.0 - erf(dm / (2.0 * X._sigma * sqrt(2.0))) + return 1.0 - erf(dm / (2.0 * X._sigma * _SQRT2)) a = X._mu * Y_var - Y._mu * X_var b = X._sigma * Y._sigma * sqrt(dm * dm + dv * log(Y_var / X_var)) x1 = (a + b) / dv From webhook-mailer at python.org Tue Nov 9 11:47:36 2021 From: webhook-mailer at python.org (zooba) Date: Tue, 09 Nov 2021 16:47:36 -0000 Subject: [Python-checkins] bpo-45732: Update bundled Tcl/Tk on Windows to 8.6.12 (GH-29477) Message-ID: https://github.com/python/cpython/commit/bcc4e46832010469bb35a97c1d1e962a82ee7fd9 commit: bcc4e46832010469bb35a97c1d1e962a82ee7fd9 branch: main author: Steve Dower committer: zooba date: 2021-11-09T16:47:28Z summary: bpo-45732: Update bundled Tcl/Tk on Windows to 8.6.12 (GH-29477) files: A Misc/NEWS.d/next/Windows/2021-11-08-21-53-11.bpo-45732.idl5kx.rst M PCbuild/get_externals.bat M PCbuild/tcltk.props diff --git a/Misc/NEWS.d/next/Windows/2021-11-08-21-53-11.bpo-45732.idl5kx.rst b/Misc/NEWS.d/next/Windows/2021-11-08-21-53-11.bpo-45732.idl5kx.rst new file mode 100644 index 0000000000000..563bcd33a401a --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2021-11-08-21-53-11.bpo-45732.idl5kx.rst @@ -0,0 +1 @@ +Updates bundled Tcl/Tk to 8.6.12. diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index 484543d5999b8..207f91baba537 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -55,8 +55,8 @@ set libraries=%libraries% bzip2-1.0.6 if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.4.2 if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1l set libraries=%libraries% sqlite-3.36.0.0 -if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.11.1 -if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.11.1 +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.2 set libraries=%libraries% zlib-1.2.11 @@ -78,7 +78,7 @@ echo.Fetching external binaries... set binaries= if NOT "%IncludeLibffi%"=="false" set binaries=%binaries% libffi-3.4.2 if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.1l -if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.11.1 +if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.12.0 if NOT "%IncludeSSLSrc%"=="false" set binaries=%binaries% nasm-2.11.06 for %%b in (%binaries%) do ( diff --git a/PCbuild/tcltk.props b/PCbuild/tcltk.props index 228efb34d7399..16dc35d45ebd5 100644 --- a/PCbuild/tcltk.props +++ b/PCbuild/tcltk.props @@ -4,8 +4,8 @@ 8 6 - 11 - 1 + 12 + 0 $(TclMajorVersion) $(TclMinorVersion) $(TclPatchLevel) From webhook-mailer at python.org Tue Nov 9 12:48:58 2021 From: webhook-mailer at python.org (zooba) Date: Tue, 09 Nov 2021 17:48:58 -0000 Subject: [Python-checkins] bpo-45732: Update bundled Tcl/Tk on Windows to 8.6.12 (GH-29477) Message-ID: https://github.com/python/cpython/commit/340ecafdf3bfb1377a1b8584addbb8e7bb423459 commit: 340ecafdf3bfb1377a1b8584addbb8e7bb423459 branch: 3.10 author: Steve Dower committer: zooba date: 2021-11-09T17:48:49Z summary: bpo-45732: Update bundled Tcl/Tk on Windows to 8.6.12 (GH-29477) files: A Misc/NEWS.d/next/Windows/2021-11-08-21-53-11.bpo-45732.idl5kx.rst M PCbuild/get_externals.bat M PCbuild/tcltk.props diff --git a/Misc/NEWS.d/next/Windows/2021-11-08-21-53-11.bpo-45732.idl5kx.rst b/Misc/NEWS.d/next/Windows/2021-11-08-21-53-11.bpo-45732.idl5kx.rst new file mode 100644 index 0000000000000..563bcd33a401a --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2021-11-08-21-53-11.bpo-45732.idl5kx.rst @@ -0,0 +1 @@ +Updates bundled Tcl/Tk to 8.6.12. diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index 53bedf1cd9200..cc01909ed48ec 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -55,8 +55,8 @@ set libraries=%libraries% bzip2-1.0.6 if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.3.0 if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1l set libraries=%libraries% sqlite-3.35.5.0 -if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.11.1 -if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.11.1 +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.2 set libraries=%libraries% zlib-1.2.11 @@ -78,7 +78,7 @@ echo.Fetching external binaries... set binaries= if NOT "%IncludeLibffi%"=="false" set binaries=%binaries% libffi-3.3.0 if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.1l -if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.11.1 +if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.12.0 if NOT "%IncludeSSLSrc%"=="false" set binaries=%binaries% nasm-2.11.06 for %%b in (%binaries%) do ( diff --git a/PCbuild/tcltk.props b/PCbuild/tcltk.props index 228efb34d7399..16dc35d45ebd5 100644 --- a/PCbuild/tcltk.props +++ b/PCbuild/tcltk.props @@ -4,8 +4,8 @@ 8 6 - 11 - 1 + 12 + 0 $(TclMajorVersion) $(TclMinorVersion) $(TclPatchLevel) From webhook-mailer at python.org Tue Nov 9 14:13:01 2021 From: webhook-mailer at python.org (zooba) Date: Tue, 09 Nov 2021 19:13:01 -0000 Subject: [Python-checkins] bpo-45732: Update bundled Tcl/Tk on Windows to 8.6.12 (GH-29477) Message-ID: https://github.com/python/cpython/commit/4d1cdd7006def053c815c354bd6f266b4850bd97 commit: 4d1cdd7006def053c815c354bd6f266b4850bd97 branch: 3.9 author: Steve Dower committer: zooba date: 2021-11-09T19:12:56Z summary: bpo-45732: Update bundled Tcl/Tk on Windows to 8.6.12 (GH-29477) files: A Misc/NEWS.d/next/Windows/2021-11-08-21-53-11.bpo-45732.idl5kx.rst M PCbuild/get_externals.bat M PCbuild/tcltk.props diff --git a/Misc/NEWS.d/next/Windows/2021-11-08-21-53-11.bpo-45732.idl5kx.rst b/Misc/NEWS.d/next/Windows/2021-11-08-21-53-11.bpo-45732.idl5kx.rst new file mode 100644 index 0000000000000..563bcd33a401a --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2021-11-08-21-53-11.bpo-45732.idl5kx.rst @@ -0,0 +1 @@ +Updates bundled Tcl/Tk to 8.6.12. diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index d975f05d8f3a9..cc01909ed48ec 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -55,8 +55,8 @@ set libraries=%libraries% bzip2-1.0.6 if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.3.0 if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1l set libraries=%libraries% sqlite-3.35.5.0 -if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.9.0 -if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.9.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.2 set libraries=%libraries% zlib-1.2.11 @@ -78,7 +78,7 @@ echo.Fetching external binaries... set binaries= if NOT "%IncludeLibffi%"=="false" set binaries=%binaries% libffi-3.3.0 if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.1l -if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.9.0 +if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.12.0 if NOT "%IncludeSSLSrc%"=="false" set binaries=%binaries% nasm-2.11.06 for %%b in (%binaries%) do ( diff --git a/PCbuild/tcltk.props b/PCbuild/tcltk.props index 7fcd3e1c618c4..3874ceb62584d 100644 --- a/PCbuild/tcltk.props +++ b/PCbuild/tcltk.props @@ -4,7 +4,7 @@ 8 6 - 9 + 12 0 $(TclMajorVersion) $(TclMinorVersion) From webhook-mailer at python.org Tue Nov 9 15:07:46 2021 From: webhook-mailer at python.org (iritkatriel) Date: Tue, 09 Nov 2021 20:07:46 -0000 Subject: [Python-checkins] bpo-45757: Fix bug where dis produced an incorrect oparg on EXTENDED_ARG before a no-arg opcode (GH-29480) Message-ID: https://github.com/python/cpython/commit/cb414cf0e207668300c4fe3f310c0bd249153273 commit: cb414cf0e207668300c4fe3f310c0bd249153273 branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-11-09T20:07:38Z summary: bpo-45757: Fix bug where dis produced an incorrect oparg on EXTENDED_ARG before a no-arg opcode (GH-29480) files: A Misc/NEWS.d/next/Library/2021-11-08-23-22-14.bpo-45757.MHZHt3.rst M Lib/dis.py M Lib/test/test_dis.py diff --git a/Lib/dis.py b/Lib/dis.py index 54275648fbb4b..8b429b5b72522 100644 --- a/Lib/dis.py +++ b/Lib/dis.py @@ -523,6 +523,7 @@ def _unpack_opargs(code): extended_arg = (arg << 8) if op == EXTENDED_ARG else 0 else: arg = None + extended_arg = 0 yield (i, op, arg) def findlabels(code): diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index 2a0e3b4e84981..fad2d06f928fe 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -179,6 +179,23 @@ def bug42562(): 2 RETURN_VALUE """ +# Extended arg followed by NOP +code_bug_45757 = bytes([ + 0x90, 0x01, # EXTENDED_ARG 0x01 + 0x09, 0xFF, # NOP 0xFF + 0x90, 0x01, # EXTENDED_ARG 0x01 + 0x64, 0x29, # LOAD_CONST 0x29 + 0x53, 0x00, # RETURN_VALUE 0x00 + ]) + +dis_bug_45757 = """\ + 0 EXTENDED_ARG 1 + 2 NOP + 4 EXTENDED_ARG 1 + 6 LOAD_CONST 297 + 8 RETURN_VALUE +""" + _BIG_LINENO_FORMAT = """\ %3d 0 LOAD_GLOBAL 0 (spam) 2 POP_TOP @@ -547,6 +564,10 @@ def test_bug_1333982(self): def test_bug_42562(self): self.do_disassembly_test(bug42562, dis_bug42562) + def test_bug_45757(self): + # Extended arg followed by NOP + self.do_disassembly_test(code_bug_45757, dis_bug_45757) + def test_big_linenos(self): def func(count): namespace = {} diff --git a/Misc/NEWS.d/next/Library/2021-11-08-23-22-14.bpo-45757.MHZHt3.rst b/Misc/NEWS.d/next/Library/2021-11-08-23-22-14.bpo-45757.MHZHt3.rst new file mode 100644 index 0000000000000..f25638cc68f85 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-08-23-22-14.bpo-45757.MHZHt3.rst @@ -0,0 +1 @@ +Fix bug where :mod:`dis` produced an incorrect oparg when :opcode:`EXTENDED_ARG` is followed by an opcode that does not use its argument. \ No newline at end of file From webhook-mailer at python.org Tue Nov 9 15:13:02 2021 From: webhook-mailer at python.org (zooba) Date: Tue, 09 Nov 2021 20:13:02 -0000 Subject: [Python-checkins] bpo-45220: Ensure RT_MANIFEST is defined when compiling Windows resource files (GH-29501) Message-ID: https://github.com/python/cpython/commit/a56fbad85ea655631bce68d4c0f47f1a8b500abd commit: a56fbad85ea655631bce68d4c0f47f1a8b500abd branch: main author: Steve Dower committer: zooba date: 2021-11-09T20:12:53Z summary: bpo-45220: Ensure RT_MANIFEST is defined when compiling Windows resource files (GH-29501) files: M PC/pylauncher.rc M PC/pyshellext.rc M PC/python_exe.rc M PC/python_nt.rc M PC/pythonw_exe.rc M PC/sqlite3.rc diff --git a/PC/pylauncher.rc b/PC/pylauncher.rc index d21f9b6e9d2ab..ff7e71e0fdb4e 100644 --- a/PC/pylauncher.rc +++ b/PC/pylauncher.rc @@ -2,6 +2,11 @@ #include "python_ver_rc.h" +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif // Include the manifest file that indicates we support all // current versions of Windows. 1 RT_MANIFEST "python.manifest" diff --git a/PC/pyshellext.rc b/PC/pyshellext.rc index fc607e97840fb..af797ce95d507 100644 --- a/PC/pyshellext.rc +++ b/PC/pyshellext.rc @@ -2,6 +2,12 @@ #include "python_ver_rc.h" +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif + // Include the manifest file that indicates we support all // current versions of Windows. 1 RT_MANIFEST "python.manifest" diff --git a/PC/python_exe.rc b/PC/python_exe.rc index 5eba89962b475..c3d3bff019895 100644 --- a/PC/python_exe.rc +++ b/PC/python_exe.rc @@ -2,6 +2,12 @@ #include "python_ver_rc.h" +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif + // Include the manifest file that indicates we support all // current versions of Windows. 1 RT_MANIFEST "python.manifest" diff --git a/PC/python_nt.rc b/PC/python_nt.rc index 6fd872c1a03cc..ae64fbd217af7 100644 --- a/PC/python_nt.rc +++ b/PC/python_nt.rc @@ -2,6 +2,12 @@ #include "python_ver_rc.h" +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif + // Include the manifest file that indicates we support all // current versions of Windows. 2 RT_MANIFEST "python.manifest" diff --git a/PC/pythonw_exe.rc b/PC/pythonw_exe.rc index 562652be18471..38570b74fa3e0 100644 --- a/PC/pythonw_exe.rc +++ b/PC/pythonw_exe.rc @@ -2,6 +2,12 @@ #include "python_ver_rc.h" +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif + // Include the manifest file that indicates we support all // current versions of Windows. 1 RT_MANIFEST "python.manifest" diff --git a/PC/sqlite3.rc b/PC/sqlite3.rc index d2c18f8add8b2..9ae2aa0f6f2f2 100644 --- a/PC/sqlite3.rc +++ b/PC/sqlite3.rc @@ -2,6 +2,12 @@ #include +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif + // Include the manifest file that indicates we support all // current versions of Windows. 2 RT_MANIFEST "python.manifest" From webhook-mailer at python.org Tue Nov 9 15:43:21 2021 From: webhook-mailer at python.org (miss-islington) Date: Tue, 09 Nov 2021 20:43:21 -0000 Subject: [Python-checkins] bpo-45220: Ensure RT_MANIFEST is defined when compiling Windows resource files (GH-29501) Message-ID: https://github.com/python/cpython/commit/d29f591dd6b1dcd4f36b5b49761cf8225be690bd commit: d29f591dd6b1dcd4f36b5b49761cf8225be690bd branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-09T12:43:12-08:00 summary: bpo-45220: Ensure RT_MANIFEST is defined when compiling Windows resource files (GH-29501) (cherry picked from commit a56fbad85ea655631bce68d4c0f47f1a8b500abd) Co-authored-by: Steve Dower files: M PC/pylauncher.rc M PC/pyshellext.rc M PC/python_exe.rc M PC/python_nt.rc M PC/pythonw_exe.rc M PC/sqlite3.rc diff --git a/PC/pylauncher.rc b/PC/pylauncher.rc index d21f9b6e9d2ab..ff7e71e0fdb4e 100644 --- a/PC/pylauncher.rc +++ b/PC/pylauncher.rc @@ -2,6 +2,11 @@ #include "python_ver_rc.h" +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif // Include the manifest file that indicates we support all // current versions of Windows. 1 RT_MANIFEST "python.manifest" diff --git a/PC/pyshellext.rc b/PC/pyshellext.rc index fc607e97840fb..af797ce95d507 100644 --- a/PC/pyshellext.rc +++ b/PC/pyshellext.rc @@ -2,6 +2,12 @@ #include "python_ver_rc.h" +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif + // Include the manifest file that indicates we support all // current versions of Windows. 1 RT_MANIFEST "python.manifest" diff --git a/PC/python_exe.rc b/PC/python_exe.rc index 5eba89962b475..c3d3bff019895 100644 --- a/PC/python_exe.rc +++ b/PC/python_exe.rc @@ -2,6 +2,12 @@ #include "python_ver_rc.h" +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif + // Include the manifest file that indicates we support all // current versions of Windows. 1 RT_MANIFEST "python.manifest" diff --git a/PC/python_nt.rc b/PC/python_nt.rc index 6fd872c1a03cc..ae64fbd217af7 100644 --- a/PC/python_nt.rc +++ b/PC/python_nt.rc @@ -2,6 +2,12 @@ #include "python_ver_rc.h" +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif + // Include the manifest file that indicates we support all // current versions of Windows. 2 RT_MANIFEST "python.manifest" diff --git a/PC/pythonw_exe.rc b/PC/pythonw_exe.rc index 562652be18471..38570b74fa3e0 100644 --- a/PC/pythonw_exe.rc +++ b/PC/pythonw_exe.rc @@ -2,6 +2,12 @@ #include "python_ver_rc.h" +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif + // Include the manifest file that indicates we support all // current versions of Windows. 1 RT_MANIFEST "python.manifest" diff --git a/PC/sqlite3.rc b/PC/sqlite3.rc index d2c18f8add8b2..9ae2aa0f6f2f2 100644 --- a/PC/sqlite3.rc +++ b/PC/sqlite3.rc @@ -2,6 +2,12 @@ #include +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif + // Include the manifest file that indicates we support all // current versions of Windows. 2 RT_MANIFEST "python.manifest" From webhook-mailer at python.org Tue Nov 9 16:06:07 2021 From: webhook-mailer at python.org (miss-islington) Date: Tue, 09 Nov 2021 21:06:07 -0000 Subject: [Python-checkins] bpo-45723: Remove dead code for obsolete `--with-dyld` option (GH-29500) Message-ID: https://github.com/python/cpython/commit/49171aa91ab78c2608a26e5a75cdceab3bad6176 commit: 49171aa91ab78c2608a26e5a75cdceab3bad6176 branch: main author: Erlend Egeberg Aasland committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-09T13:05:58-08:00 summary: bpo-45723: Remove dead code for obsolete `--with-dyld` option (GH-29500) Was commented out by Jack Jansen in 2001-08-15 by commit b6e9cad34ce46a6a733d8aa5bf5b9d389fa1316f: "Ripped out Next/OpenStep support, which was broken anyway" Automerge-Triggered-By: GH:tiran files: M configure M configure.ac diff --git a/configure b/configure index a1f5e53018b07..c67daf752a9d1 100755 --- a/configure +++ b/configure @@ -3315,10 +3315,6 @@ cat >>confdefs.h <<_ACEOF _ACEOF -##AC_ARG_WITH(dyld, -## AS_HELP_STRING([--with-dyld], -## [use (OpenStep|Rhapsody) dynamic linker])) -## # Set name for machine-dependent library files { $as_echo "$as_me:${as_lineno-$LINENO}: checking MACHDEP" >&5 diff --git a/configure.ac b/configure.ac index a7e5f2bd548b7..ae0888bcda053 100644 --- a/configure.ac +++ b/configure.ac @@ -377,10 +377,6 @@ AC_SUBST(FRAMEWORKINSTALLAPPSPREFIX) AC_DEFINE_UNQUOTED(_PYTHONFRAMEWORK, "${PYTHONFRAMEWORK}", [framework name]) -##AC_ARG_WITH(dyld, -## AS_HELP_STRING([--with-dyld], -## [use (OpenStep|Rhapsody) dynamic linker])) -## # Set name for machine-dependent library files AC_ARG_VAR([MACHDEP], [name for machine-dependent library files]) AC_MSG_CHECKING(MACHDEP) From webhook-mailer at python.org Tue Nov 9 17:05:39 2021 From: webhook-mailer at python.org (iritkatriel) Date: Tue, 09 Nov 2021 22:05:39 -0000 Subject: [Python-checkins] [3.10] bpo-45757: Fix bug where dis produced an incorrect oparg on EXTENDED_ARG before a no-arg opcode (GH-29480) (GH-29506) Message-ID: https://github.com/python/cpython/commit/c5bfb88eb6f82111bb1603ae9d78d0476b552d66 commit: c5bfb88eb6f82111bb1603ae9d78d0476b552d66 branch: 3.10 author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-11-09T22:05:30Z summary: [3.10] bpo-45757: Fix bug where dis produced an incorrect oparg on EXTENDED_ARG before a no-arg opcode (GH-29480) (GH-29506) files: A Misc/NEWS.d/next/Library/2021-11-08-23-22-14.bpo-45757.MHZHt3.rst M Lib/dis.py M Lib/test/test_dis.py diff --git a/Lib/dis.py b/Lib/dis.py index 3fee1ce27725c..fe5d24e88058f 100644 --- a/Lib/dis.py +++ b/Lib/dis.py @@ -428,6 +428,7 @@ def _unpack_opargs(code): extended_arg = (arg << 8) if op == EXTENDED_ARG else 0 else: arg = None + extended_arg = 0 yield (i, op, arg) def findlabels(code): diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index 2cb2eff9a6c3f..000549f5b6f11 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -180,6 +180,23 @@ def bug42562(): 2 RETURN_VALUE """ +# Extended arg followed by NOP +code_bug_45757 = bytes([ + 0x90, 0x01, # EXTENDED_ARG 0x01 + 0x09, 0xFF, # NOP 0xFF + 0x90, 0x01, # EXTENDED_ARG 0x01 + 0x64, 0x29, # LOAD_CONST 0x29 + 0x53, 0x00, # RETURN_VALUE 0x00 + ]) + +dis_bug_45757 = """\ + 0 EXTENDED_ARG 1 + 2 NOP + 4 EXTENDED_ARG 1 + 6 LOAD_CONST 297 (297) + 8 RETURN_VALUE +""" + _BIG_LINENO_FORMAT = """\ %3d 0 LOAD_GLOBAL 0 (spam) 2 POP_TOP @@ -534,6 +551,10 @@ def test_bug_1333982(self): def test_bug_42562(self): self.do_disassembly_test(bug42562, dis_bug42562) + def test_bug_45757(self): + # Extended arg followed by NOP + self.do_disassembly_test(code_bug_45757, dis_bug_45757) + def test_big_linenos(self): def func(count): namespace = {} diff --git a/Misc/NEWS.d/next/Library/2021-11-08-23-22-14.bpo-45757.MHZHt3.rst b/Misc/NEWS.d/next/Library/2021-11-08-23-22-14.bpo-45757.MHZHt3.rst new file mode 100644 index 0000000000000..f25638cc68f85 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-08-23-22-14.bpo-45757.MHZHt3.rst @@ -0,0 +1 @@ +Fix bug where :mod:`dis` produced an incorrect oparg when :opcode:`EXTENDED_ARG` is followed by an opcode that does not use its argument. \ No newline at end of file From webhook-mailer at python.org Tue Nov 9 18:01:34 2021 From: webhook-mailer at python.org (rhettinger) Date: Tue, 09 Nov 2021 23:01:34 -0000 Subject: [Python-checkins] bpo-45701: Improve documentation for *typed* parameter (GH-29498) Message-ID: https://github.com/python/cpython/commit/912a4ccc3a523e2990cc501393adfc661614c73a commit: 912a4ccc3a523e2990cc501393adfc661614c73a branch: main author: Raymond Hettinger committer: rhettinger date: 2021-11-09T17:01:29-06:00 summary: bpo-45701: Improve documentation for *typed* parameter (GH-29498) files: M Doc/library/functools.rst diff --git a/Doc/library/functools.rst b/Doc/library/functools.rst index a01b17287878c..c78818bfab1a5 100644 --- a/Doc/library/functools.rst +++ b/Doc/library/functools.rst @@ -160,10 +160,16 @@ The :mod:`functools` module defines the following functions: grow without bound. If *typed* is set to true, function arguments of different types will be - cached separately. For example, ``f(3)`` and ``f(3.0)`` will always be - treated as distinct calls with distinct results. If *typed* is false, - the implementation will usually but not always regard them as equivalent - calls and only cache a single result. + cached separately. If *typed* is false, the implementation will usually + regard them as equivalent calls and only cache a single result. (Some + types such as *str* and *int* may be cached separately even when *typed* + is false.) + + Note, type specificity applies only to the function's immediate arguments + rather than their contents. The scalar arguments, ``Decimal(42)`` and + ``Fraction(42)`` are be treated as distinct calls with distinct results. + In contrast, the tuple arguments ``('answer', Decimal(42))`` and + ``('answer', Fraction(42))`` are treated as equivalent. The wrapped function is instrumented with a :func:`cache_parameters` function that returns a new :class:`dict` showing the values for *maxsize* From webhook-mailer at python.org Tue Nov 9 18:49:47 2021 From: webhook-mailer at python.org (jaraco) Date: Tue, 09 Nov 2021 23:49:47 -0000 Subject: [Python-checkins] [bpo-45765] Fix distribution discovery on empty path. (#29487) Message-ID: https://github.com/python/cpython/commit/6ec0dec7b7b50d4fee5b2b66cf38e4291bcdf44c commit: 6ec0dec7b7b50d4fee5b2b66cf38e4291bcdf44c branch: main author: Jason R. Coombs committer: jaraco date: 2021-11-09T18:49:43-05:00 summary: [bpo-45765] Fix distribution discovery on empty path. (#29487) files: A Misc/NEWS.d/next/Library/2021-11-09-09-04-19.bpo-45765.JVobxK.rst M Lib/importlib/metadata/__init__.py diff --git a/Lib/importlib/metadata/__init__.py b/Lib/importlib/metadata/__init__.py index f5172eefc1841..b3e8fb05f1d98 100644 --- a/Lib/importlib/metadata/__init__.py +++ b/Lib/importlib/metadata/__init__.py @@ -748,7 +748,7 @@ def joinpath(self, child): def children(self): with suppress(Exception): - return os.listdir(self.root or '') + return os.listdir(self.root or '.') with suppress(Exception): return self.zip_children() return [] diff --git a/Misc/NEWS.d/next/Library/2021-11-09-09-04-19.bpo-45765.JVobxK.rst b/Misc/NEWS.d/next/Library/2021-11-09-09-04-19.bpo-45765.JVobxK.rst new file mode 100644 index 0000000000000..a1f4a1f7aa91c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-09-09-04-19.bpo-45765.JVobxK.rst @@ -0,0 +1 @@ +In importlib.metadata, fix distribution discovery for an empty path. From webhook-mailer at python.org Wed Nov 10 08:41:32 2021 From: webhook-mailer at python.org (pablogsal) Date: Wed, 10 Nov 2021 13:41:32 -0000 Subject: [Python-checkins] bpo-45637: Fix cframe-based fallback in the gdb helpers (GH-29515) Message-ID: https://github.com/python/cpython/commit/20205ad2b5be7eb3361224fd2502d1ba09c8ae4a commit: 20205ad2b5be7eb3361224fd2502d1ba09c8ae4a branch: main author: Pablo Galindo Salgado committer: pablogsal date: 2021-11-10T13:41:22Z summary: bpo-45637: Fix cframe-based fallback in the gdb helpers (GH-29515) files: M Tools/gdb/libpython.py diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py index f4b27f115216b..71c99b516b34f 100755 --- a/Tools/gdb/libpython.py +++ b/Tools/gdb/libpython.py @@ -1797,14 +1797,14 @@ def is_gc_collect(self): def get_pyop(self): try: - frame = self._gdbframe.read_var('frame') - frame = PyFramePtr(frame) - if not frame.is_optimized_out(): - return frame + # frame = self._gdbframe.read_var('frame') + # frame = PyFramePtr(frame) + # if not frame.is_optimized_out(): + # return frame cframe = self._gdbframe.read_var('cframe') if cframe is None: return None - frame = PyFramePtr(cframe["current_frame"].dereference()) + frame = PyFramePtr(cframe["current_frame"]) if frame and not frame.is_optimized_out(): return frame return None From webhook-mailer at python.org Wed Nov 10 10:30:29 2021 From: webhook-mailer at python.org (tiran) Date: Wed, 10 Nov 2021 15:30:29 -0000 Subject: [Python-checkins] bpo-45723: Improve and simplify more configure.ac checks (GH-29485) Message-ID: https://github.com/python/cpython/commit/76d14fac72479e0f5f5b144d6968ecd9e594db34 commit: 76d14fac72479e0f5f5b144d6968ecd9e594db34 branch: main author: Erlend Egeberg Aasland committer: tiran date: 2021-11-10T16:30:18+01:00 summary: bpo-45723: Improve and simplify more configure.ac checks (GH-29485) files: M configure M configure.ac diff --git a/configure b/configure index c67daf752a9d1..d9c41226a3550 100755 --- a/configure +++ b/configure @@ -5659,9 +5659,13 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -Wl,--no-as-needed" >&5 $as_echo_n "checking for -Wl,--no-as-needed... " >&6; } -save_LDFLAGS="$LDFLAGS" -LDFLAGS="$LDFLAGS -Wl,--no-as-needed" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ${ac_cv_wl_no_as_needed+:} false; then : + $as_echo_n "(cached) " >&6 +else + + save_LDFLAGS="$LDFLAGS" + as_fn_append LDFLAGS -Wl,--no-as-needed + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -5674,16 +5678,18 @@ main () _ACEOF if ac_fn_c_try_link "$LINENO"; then : NO_AS_NEEDED="-Wl,--no-as-needed" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } + ac_cv_wl_no_as_needed=yes else NO_AS_NEEDED="" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + ac_cv_wl_no_as_needed=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -LDFLAGS="$save_LDFLAGS" + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_wl_no_as_needed" >&5 +$as_echo "$ac_cv_wl_no_as_needed" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the Android API level" >&5 @@ -7072,15 +7078,16 @@ yes) CFLAGS_NODIST="$CFLAGS_NODIST -std=c99" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Wextra" >&5 $as_echo_n "checking if we can add -Wextra... " >&6; } - - py_cflags=$CFLAGS - CFLAGS="$CFLAGS -Wextra -Werror" - if ${ac_cv_enable_extra_warning+:} false; then : +if ${ac_cv_enable_extra_warning+:} false; then : $as_echo_n "(cached) " >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + + py_cflags=$CFLAGS + as_fn_append CFLAGS "-Wextra -Werror" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -7097,11 +7104,10 @@ else ac_cv_enable_extra_warning=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$py_cflags fi - - CFLAGS=$py_cflags - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_extra_warning" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_extra_warning" >&5 $as_echo "$ac_cv_enable_extra_warning" >&6; } @@ -7113,12 +7119,12 @@ fi # GCC produce warnings for legal Python code. Enable # -fno-strict-aliasing on versions of GCC that support but produce # warnings. See Issue3326 - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts and needs -fno-strict-aliasing" >&5 -$as_echo_n "checking whether $CC accepts and needs -fno-strict-aliasing... " >&6; } ac_save_cc="$CC" CC="$CC -fno-strict-aliasing" save_CFLAGS="$CFLAGS" - if ${ac_cv_no_strict_aliasing+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts and needs -fno-strict-aliasing" >&5 +$as_echo_n "checking whether $CC accepts and needs -fno-strict-aliasing... " >&6; } +if ${ac_cv_no_strict_aliasing+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -7169,11 +7175,10 @@ else fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_no_strict_aliasing" >&5 +$as_echo "$ac_cv_no_strict_aliasing" >&6; } CFLAGS="$save_CFLAGS" CC="$ac_save_cc" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_no_strict_aliasing" >&5 -$as_echo "$ac_cv_no_strict_aliasing" >&6; } if test "x$ac_cv_no_strict_aliasing" = xyes; then : BASECFLAGS="$BASECFLAGS -fno-strict-aliasing" fi @@ -7184,15 +7189,16 @@ fi *icc*) : ac_cv_disable_unused_result_warning=no + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can disable $CC unused-result warning" >&5 $as_echo_n "checking if we can disable $CC unused-result warning... " >&6; } - - py_cflags=$CFLAGS - CFLAGS="$CFLAGS -Wunused-result -Werror" - if ${ac_cv_disable_unused_result_warning+:} false; then : +if ${ac_cv_disable_unused_result_warning+:} false; then : $as_echo_n "(cached) " >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + + py_cflags=$CFLAGS + as_fn_append CFLAGS "-Wunused-result -Werror" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -7209,11 +7215,10 @@ else ac_cv_disable_unused_result_warning=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$py_cflags fi - - CFLAGS=$py_cflags - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_disable_unused_result_warning" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_disable_unused_result_warning" >&5 $as_echo "$ac_cv_disable_unused_result_warning" >&6; } ;; #( @@ -7226,15 +7231,16 @@ esac fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can disable $CC unused-parameter warning" >&5 $as_echo_n "checking if we can disable $CC unused-parameter warning... " >&6; } - - py_cflags=$CFLAGS - CFLAGS="$CFLAGS -Wunused-parameter -Werror" - if ${ac_cv_disable_unused_parameter_warning+:} false; then : +if ${ac_cv_disable_unused_parameter_warning+:} false; then : $as_echo_n "(cached) " >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + + py_cflags=$CFLAGS + as_fn_append CFLAGS "-Wunused-parameter -Werror" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -7251,11 +7257,10 @@ else ac_cv_disable_unused_parameter_warning=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$py_cflags fi - - CFLAGS=$py_cflags - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_disable_unused_parameter_warning" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_disable_unused_parameter_warning" >&5 $as_echo "$ac_cv_disable_unused_parameter_warning" >&6; } @@ -7264,15 +7269,16 @@ $as_echo "$ac_cv_disable_unused_parameter_warning" >&6; } fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can disable $CC missing-field-initializers warning" >&5 $as_echo_n "checking if we can disable $CC missing-field-initializers warning... " >&6; } - - py_cflags=$CFLAGS - CFLAGS="$CFLAGS -Wmissing-field-initializers -Werror" - if ${ac_cv_disable_missing_field_initializers_warning+:} false; then : +if ${ac_cv_disable_missing_field_initializers_warning+:} false; then : $as_echo_n "(cached) " >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + + py_cflags=$CFLAGS + as_fn_append CFLAGS "-Wmissing-field-initializers -Werror" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -7289,11 +7295,10 @@ else ac_cv_disable_missing_field_initializers_warning=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$py_cflags fi - - CFLAGS=$py_cflags - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_disable_missing_field_initializers_warning" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_disable_missing_field_initializers_warning" >&5 $as_echo "$ac_cv_disable_missing_field_initializers_warning" >&6; } @@ -7302,15 +7307,16 @@ $as_echo "$ac_cv_disable_missing_field_initializers_warning" >&6; } fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can enable $CC sign-compare warning" >&5 $as_echo_n "checking if we can enable $CC sign-compare warning... " >&6; } - - py_cflags=$CFLAGS - CFLAGS="$CFLAGS -Wsign-compare -Werror" - if ${ac_cv_enable_sign_compare_warning+:} false; then : +if ${ac_cv_enable_sign_compare_warning+:} false; then : $as_echo_n "(cached) " >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + + py_cflags=$CFLAGS + as_fn_append CFLAGS "-Wsign-compare -Werror" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -7327,11 +7333,10 @@ else ac_cv_enable_sign_compare_warning=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$py_cflags fi - - CFLAGS=$py_cflags - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_sign_compare_warning" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_sign_compare_warning" >&5 $as_echo "$ac_cv_enable_sign_compare_warning" >&6; } @@ -7340,15 +7345,16 @@ $as_echo "$ac_cv_enable_sign_compare_warning" >&6; } fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can enable $CC unreachable-code warning" >&5 $as_echo_n "checking if we can enable $CC unreachable-code warning... " >&6; } - - py_cflags=$CFLAGS - CFLAGS="$CFLAGS -Wunreachable-code -Werror" - if ${ac_cv_enable_unreachable_code_warning+:} false; then : +if ${ac_cv_enable_unreachable_code_warning+:} false; then : $as_echo_n "(cached) " >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + + py_cflags=$CFLAGS + as_fn_append CFLAGS "-Wunreachable-code -Werror" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -7365,11 +7371,10 @@ else ac_cv_enable_unreachable_code_warning=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$py_cflags fi - - CFLAGS=$py_cflags - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_unreachable_code_warning" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_unreachable_code_warning" >&5 $as_echo "$ac_cv_enable_unreachable_code_warning" >&6; } @@ -7390,15 +7395,16 @@ $as_echo "$ac_cv_enable_unreachable_code_warning" >&6; } fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can enable $CC strict-prototypes warning" >&5 $as_echo_n "checking if we can enable $CC strict-prototypes warning... " >&6; } - - py_cflags=$CFLAGS - CFLAGS="$CFLAGS -Wstrict-prototypes -Werror" - if ${ac_cv_enable_strict_prototypes_warning+:} false; then : +if ${ac_cv_enable_strict_prototypes_warning+:} false; then : $as_echo_n "(cached) " >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + + py_cflags=$CFLAGS + as_fn_append CFLAGS "-Wstrict-prototypes -Werror" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -7415,11 +7421,10 @@ else ac_cv_enable_strict_prototypes_warning=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$py_cflags fi - - CFLAGS=$py_cflags - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_strict_prototypes_warning" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_strict_prototypes_warning" >&5 $as_echo "$ac_cv_enable_strict_prototypes_warning" >&6; } @@ -7427,11 +7432,11 @@ $as_echo "$ac_cv_enable_strict_prototypes_warning" >&6; } CFLAGS_NODIST="$CFLAGS_NODIST -Wstrict-prototypes" fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can make implicit function declaration an error in $CC" >&5 -$as_echo_n "checking if we can make implicit function declaration an error in $CC... " >&6; } ac_save_cc="$CC" CC="$CC -Werror=implicit-function-declaration" - if ${ac_cv_enable_implicit_function_declaration_error+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can make implicit function declaration an error in $CC" >&5 +$as_echo_n "checking if we can make implicit function declaration an error in $CC... " >&6; } +if ${ac_cv_enable_implicit_function_declaration_error+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -7458,20 +7463,19 @@ else fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - - CC="$ac_save_cc" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_implicit_function_declaration_error" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_implicit_function_declaration_error" >&5 $as_echo "$ac_cv_enable_implicit_function_declaration_error" >&6; } + CC="$ac_save_cc" if test "x$ac_cv_enable_implicit_function_declaration_error" = xyes; then : CFLAGS_NODIST="$CFLAGS_NODIST -Werror=implicit-function-declaration" fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can use visibility in $CC" >&5 -$as_echo_n "checking if we can use visibility in $CC... " >&6; } ac_save_cc="$CC" CC="$CC -fvisibility=hidden" - if ${ac_cv_enable_visibility+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can use visibility in $CC" >&5 +$as_echo_n "checking if we can use visibility in $CC... " >&6; } +if ${ac_cv_enable_visibility+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -7498,10 +7502,9 @@ else fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - - CC="$ac_save_cc" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_visibility" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_visibility" >&5 $as_echo "$ac_cv_enable_visibility" >&6; } + CC="$ac_save_cc" if test "x$ac_cv_enable_visibility" = xyes; then : CFLAGS_NODIST="$CFLAGS_NODIST -fvisibility=hidden" @@ -7764,7 +7767,6 @@ fi fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_pthread_is_default" >&5 $as_echo "$ac_cv_pthread_is_default" >&6; } @@ -7816,7 +7818,6 @@ fi CC="$ac_save_cc" fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_kpthread" >&5 $as_echo "$ac_cv_kpthread" >&6; } fi @@ -7866,7 +7867,6 @@ fi CC="$ac_save_cc" fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_kthread" >&5 $as_echo "$ac_cv_kthread" >&6; } fi @@ -7916,7 +7916,6 @@ fi CC="$ac_save_cc" fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_pthread" >&5 $as_echo "$ac_cv_pthread" >&6; } fi @@ -10315,7 +10314,6 @@ fi fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_aligned_required" >&5 $as_echo "$ac_cv_aligned_required" >&6; } if test "$ac_cv_aligned_required" = yes ; then @@ -11211,7 +11209,7 @@ $as_echo "#define HAVE_BROKEN_POSIX_SEMAPHORES 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking if PTHREAD_SCOPE_SYSTEM is supported" >&5 $as_echo_n "checking if PTHREAD_SCOPE_SYSTEM is supported... " >&6; } - if ${ac_cv_pthread_system_supported+:} false; then : +if ${ac_cv_pthread_system_supported+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : @@ -11245,8 +11243,7 @@ fi fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_pthread_system_supported" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_pthread_system_supported" >&5 $as_echo "$ac_cv_pthread_system_supported" >&6; } if test "$ac_cv_pthread_system_supported" = "yes"; then @@ -14083,7 +14080,7 @@ if test "x$ac_cv_func_getaddrinfo" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking getaddrinfo bug" >&5 $as_echo_n "checking getaddrinfo bug... " >&6; } - if ${ac_cv_buggy_getaddrinfo+:} false; then : +if ${ac_cv_buggy_getaddrinfo+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : @@ -14197,14 +14194,12 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ fi fi - +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_buggy_getaddrinfo" >&5 +$as_echo "$ac_cv_buggy_getaddrinfo" >&6; } fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_buggy_getaddrinfo" >&5 -$as_echo "$ac_cv_buggy_getaddrinfo" >&6; } - if test "$ac_cv_func_getaddrinfo" = no -o "$ac_cv_buggy_getaddrinfo" = yes then if test $ipv6 = yes @@ -14467,7 +14462,6 @@ fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time_altzone" >&5 $as_echo "$ac_cv_header_time_altzone" >&6; } if test $ac_cv_header_time_altzone = yes; then @@ -14499,7 +14493,6 @@ else fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_addrinfo" >&5 $as_echo "$ac_cv_struct_addrinfo" >&6; } if test $ac_cv_struct_addrinfo = yes; then @@ -14533,7 +14526,6 @@ else fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_sockaddr_storage" >&5 $as_echo "$ac_cv_struct_sockaddr_storage" >&6; } if test $ac_cv_struct_sockaddr_storage = yes; then @@ -14568,7 +14560,6 @@ else fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_sockaddr_alg" >&5 $as_echo "$ac_cv_struct_sockaddr_alg" >&6; } if test $ac_cv_struct_sockaddr_alg = yes; then @@ -15497,7 +15488,6 @@ fi fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_posix_semaphores_enabled" >&5 $as_echo "$ac_cv_posix_semaphores_enabled" >&6; } if test $ac_cv_posix_semaphores_enabled = no @@ -15552,7 +15542,6 @@ fi fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_broken_sem_getvalue" >&5 $as_echo "$ac_cv_broken_sem_getvalue" >&6; } if test $ac_cv_broken_sem_getvalue = yes @@ -15772,7 +15761,7 @@ then # check whether wchar_t is signed or not { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether wchar_t is signed" >&5 $as_echo_n "checking whether wchar_t is signed... " >&6; } - if ${ac_cv_wchar_t_signed+:} false; then : +if ${ac_cv_wchar_t_signed+:} false; then : $as_echo_n "(cached) " >&6 else @@ -15800,8 +15789,7 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ fi fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_wchar_t_signed" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_wchar_t_signed" >&5 $as_echo "$ac_cv_wchar_t_signed" >&6; } fi @@ -16215,7 +16203,6 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ fi fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_rshift_extends_sign" >&5 $as_echo "$ac_cv_rshift_extends_sign" >&6; } if test "$ac_cv_rshift_extends_sign" = no @@ -16256,7 +16243,6 @@ fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_getc_unlocked" >&5 $as_echo "$ac_cv_have_getc_unlocked" >&6; } if test "$ac_cv_have_getc_unlocked" = yes @@ -16666,7 +16652,6 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ fi fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_broken_nice" >&5 $as_echo "$ac_cv_broken_nice" >&6; } if test "$ac_cv_broken_nice" = yes @@ -16717,7 +16702,6 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ fi fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_broken_poll" >&5 $as_echo "$ac_cv_broken_poll" >&6; } if test "$ac_cv_broken_poll" = yes @@ -16814,7 +16798,6 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ fi fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_tzset" >&5 $as_echo "$ac_cv_working_tzset" >&6; } if test "$ac_cv_working_tzset" = yes @@ -16851,7 +16834,6 @@ else fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_stat_tv_nsec" >&5 $as_echo "$ac_cv_stat_tv_nsec" >&6; } if test "$ac_cv_stat_tv_nsec" = yes @@ -16888,7 +16870,6 @@ else fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_stat_tv_nsec2" >&5 $as_echo "$ac_cv_stat_tv_nsec2" >&6; } if test "$ac_cv_stat_tv_nsec2" = yes @@ -16964,7 +16945,6 @@ else fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_mvwdelch_is_expression" >&5 $as_echo "$ac_cv_mvwdelch_is_expression" >&6; } @@ -17008,7 +16988,6 @@ else fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_window_has_flags" >&5 $as_echo "$ac_cv_window_has_flags" >&6; } @@ -17653,7 +17632,6 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ fi fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_broken_mbstowcs" >&5 $as_echo "$ac_cv_broken_mbstowcs" >&6; } if test "$ac_cv_broken_mbstowcs" = yes @@ -17730,7 +17708,6 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ fi fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_computed_gotos" >&5 $as_echo "$ac_cv_computed_gotos" >&6; } case "$ac_cv_computed_gotos" in yes*) diff --git a/configure.ac b/configure.ac index ae0888bcda053..cfd7184ac3aff 100644 --- a/configure.ac +++ b/configure.ac @@ -893,15 +893,16 @@ if test x$MULTIARCH != x; then fi AC_SUBST(MULTIARCH_CPPFLAGS) -AC_MSG_CHECKING([for -Wl,--no-as-needed]) -save_LDFLAGS="$LDFLAGS" -LDFLAGS="$LDFLAGS -Wl,--no-as-needed" -AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])], - [NO_AS_NEEDED="-Wl,--no-as-needed" - AC_MSG_RESULT([yes])], - [NO_AS_NEEDED="" - AC_MSG_RESULT([no])]) -LDFLAGS="$save_LDFLAGS" +AC_CACHE_CHECK([for -Wl,--no-as-needed], [ac_cv_wl_no_as_needed], [ + save_LDFLAGS="$LDFLAGS" + AS_VAR_APPEND([LDFLAGS], [-Wl,--no-as-needed]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [NO_AS_NEEDED="-Wl,--no-as-needed" + ac_cv_wl_no_as_needed=yes], + [NO_AS_NEEDED="" + ac_cv_wl_no_as_needed=no]) + LDFLAGS="$save_LDFLAGS" +]) AC_SUBST(NO_AS_NEEDED) AC_MSG_CHECKING([for the Android API level]) @@ -1635,20 +1636,15 @@ AC_SUBST(UNIVERSAL_ARCH_FLAGS) dnl PY_CHECK_CC_WARNING(ENABLE, WARNING, [MSG]) AC_DEFUN([PY_CHECK_CC_WARNING], [ - AC_MSG_CHECKING(m4_ifblank([$3], [if we can $1 $CC $2 warning], [$3])) AS_VAR_PUSHDEF([py_var], [ac_cv_$1_]m4_normalize($2)[_warning]) - AS_VAR_COPY([py_cflags], [CFLAGS]) - AS_VAR_SET([CFLAGS], ["$CFLAGS -W$2 -Werror"]) - AC_CACHE_VAL( - [py_var], - [AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM([[]], [[]])], - [AS_VAR_SET([py_var], [yes])], - [AS_VAR_SET([py_var], [no])], - )] - ) - AS_VAR_COPY([CFLAGS], [py_cflags]) - AC_MSG_RESULT([$py_var]) + AC_CACHE_CHECK(m4_ifblank([$3], [if we can $1 $CC $2 warning], [$3]), [py_var], [ + AS_VAR_COPY([py_cflags], [CFLAGS]) + AS_VAR_APPEND([CFLAGS], ["-W$2 -Werror"]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [AS_VAR_SET([py_var], [yes])], + [AS_VAR_SET([py_var], [no])]) + AS_VAR_COPY([CFLAGS], [py_cflags]) + ]) AS_VAR_POPDEF([py_var]) ]) @@ -1665,11 +1661,11 @@ yes) # GCC produce warnings for legal Python code. Enable # -fno-strict-aliasing on versions of GCC that support but produce # warnings. See Issue3326 - AC_MSG_CHECKING(whether $CC accepts and needs -fno-strict-aliasing) ac_save_cc="$CC" CC="$CC -fno-strict-aliasing" save_CFLAGS="$CFLAGS" - AC_CACHE_VAL(ac_cv_no_strict_aliasing, + AC_CACHE_CHECK([whether $CC accepts and needs -fno-strict-aliasing], + [ac_cv_no_strict_aliasing], AC_COMPILE_IFELSE( [ AC_LANG_PROGRAM([[]], [[]]) @@ -1690,7 +1686,6 @@ yes) ])) CFLAGS="$save_CFLAGS" CC="$ac_save_cc" - AC_MSG_RESULT($ac_cv_no_strict_aliasing) AS_VAR_IF([ac_cv_no_strict_aliasing], [yes], [BASECFLAGS="$BASECFLAGS -fno-strict-aliasing"]) @@ -1736,10 +1731,10 @@ yes) AS_VAR_IF([ac_cv_enable_strict_prototypes_warning], [yes], [CFLAGS_NODIST="$CFLAGS_NODIST -Wstrict-prototypes"]) - AC_MSG_CHECKING(if we can make implicit function declaration an error in $CC) ac_save_cc="$CC" CC="$CC -Werror=implicit-function-declaration" - AC_CACHE_VAL(ac_cv_enable_implicit_function_declaration_error, + AC_CACHE_CHECK([if we can make implicit function declaration an error in $CC], + [ac_cv_enable_implicit_function_declaration_error], AC_COMPILE_IFELSE( [ AC_LANG_PROGRAM([[]], [[]]) @@ -1749,15 +1744,13 @@ yes) ac_cv_enable_implicit_function_declaration_error=no ])) CC="$ac_save_cc" - AC_MSG_RESULT($ac_cv_enable_implicit_function_declaration_error) AS_VAR_IF([ac_cv_enable_implicit_function_declaration_error], [yes], [CFLAGS_NODIST="$CFLAGS_NODIST -Werror=implicit-function-declaration"]) - AC_MSG_CHECKING(if we can use visibility in $CC) ac_save_cc="$CC" CC="$CC -fvisibility=hidden" - AC_CACHE_VAL(ac_cv_enable_visibility, + AC_CACHE_CHECK([if we can use visibility in $CC], [ac_cv_enable_visibility], AC_COMPILE_IFELSE( [ AC_LANG_PROGRAM([[]], [[]]) @@ -1767,7 +1760,6 @@ yes) ac_cv_enable_visibility=no ])) CC="$ac_save_cc" - AC_MSG_RESULT($ac_cv_enable_visibility) AS_VAR_IF([ac_cv_enable_visibility], [yes], [CFLAGS_NODIST="$CFLAGS_NODIST -fvisibility=hidden"]) @@ -1967,8 +1959,8 @@ fi # complain if unaccepted options are passed (e.g. gcc on Mac OS X). # So we have to see first whether pthreads are available without # options before we can check whether -Kpthread improves anything. -AC_MSG_CHECKING(whether pthreads are available without options) -AC_CACHE_VAL(ac_cv_pthread_is_default, +AC_CACHE_CHECK([whether pthreads are available without options], + [ac_cv_pthread_is_default], [AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include @@ -1988,7 +1980,6 @@ int main(){ ac_cv_pthread=no ],[ac_cv_pthread_is_default=no],[ac_cv_pthread_is_default=no]) ]) -AC_MSG_RESULT($ac_cv_pthread_is_default) if test $ac_cv_pthread_is_default = yes @@ -2000,8 +1991,7 @@ else # Some compilers won't report that they do not support -Kpthread, # so we need to run a program to see whether it really made the # function available. -AC_MSG_CHECKING(whether $CC accepts -Kpthread) -AC_CACHE_VAL(ac_cv_kpthread, +AC_CACHE_CHECK([whether $CC accepts -Kpthread], [ac_cv_kpthread], [ac_save_cc="$CC" CC="$CC -Kpthread" AC_RUN_IFELSE([AC_LANG_SOURCE([[ @@ -2019,7 +2009,6 @@ int main(){ } ]])],[ac_cv_kpthread=yes],[ac_cv_kpthread=no],[ac_cv_kpthread=no]) CC="$ac_save_cc"]) -AC_MSG_RESULT($ac_cv_kpthread) fi if test $ac_cv_kpthread = no -a $ac_cv_pthread_is_default = no @@ -2029,8 +2018,7 @@ then # Some compilers won't report that they do not support -Kthread, # so we need to run a program to see whether it really made the # function available. -AC_MSG_CHECKING(whether $CC accepts -Kthread) -AC_CACHE_VAL(ac_cv_kthread, +AC_CACHE_CHECK([whether $CC accepts -Kthread], [ac_cv_kthread], [ac_save_cc="$CC" CC="$CC -Kthread" AC_RUN_IFELSE([AC_LANG_SOURCE([[ @@ -2048,7 +2036,6 @@ int main(){ } ]])],[ac_cv_kthread=yes],[ac_cv_kthread=no],[ac_cv_kthread=no]) CC="$ac_save_cc"]) -AC_MSG_RESULT($ac_cv_kthread) fi if test $ac_cv_kthread = no -a $ac_cv_pthread_is_default = no @@ -2058,8 +2045,7 @@ then # Some compilers won't report that they do not support -pthread, # so we need to run a program to see whether it really made the # function available. -AC_MSG_CHECKING(whether $CC accepts -pthread) -AC_CACHE_VAL(ac_cv_pthread, +AC_CACHE_CHECK([whether $CC accepts -pthread], [ac_cv_pthread], [ac_save_cc="$CC" CC="$CC -pthread" AC_RUN_IFELSE([AC_LANG_SOURCE([[ @@ -2077,7 +2063,6 @@ int main(){ } ]])],[ac_cv_pthread=yes],[ac_cv_pthread=no],[ac_cv_pthread=no]) CC="$ac_save_cc"]) -AC_MSG_RESULT($ac_cv_pthread) fi # If we have set a CC compiler flag for thread support then @@ -2886,8 +2871,7 @@ dnl The AIX_BUILDDATE is obtained from the kernel fileset - bos.mp64 esac # check for systems that require aligned memory access -AC_MSG_CHECKING(aligned memory access is required) -AC_CACHE_VAL(ac_cv_aligned_required, +AC_CACHE_CHECK([aligned memory access is required], [ac_cv_aligned_required], [AC_RUN_IFELSE([AC_LANG_SOURCE([[ int main() { @@ -2905,7 +2889,6 @@ int main() [ac_cv_aligned_required=yes], [ac_cv_aligned_required=yes]) ]) -AC_MSG_RESULT($ac_cv_aligned_required) if test "$ac_cv_aligned_required" = yes ; then AC_DEFINE([HAVE_ALIGNED_REQUIRED], [1], [Define if aligned memory access is required]) @@ -3247,8 +3230,7 @@ if test "$posix_threads" = "yes"; then ;; esac - AC_MSG_CHECKING(if PTHREAD_SCOPE_SYSTEM is supported) - AC_CACHE_VAL(ac_cv_pthread_system_supported, + AC_CACHE_CHECK([if PTHREAD_SCOPE_SYSTEM is supported], [ac_cv_pthread_system_supported], [AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include @@ -3267,7 +3249,6 @@ if test "$posix_threads" = "yes"; then [ac_cv_pthread_system_supported=no], [ac_cv_pthread_system_supported=no]) ]) - AC_MSG_RESULT($ac_cv_pthread_system_supported) if test "$ac_cv_pthread_system_supported" = "yes"; then AC_DEFINE(PTHREAD_SYSTEM_SCHED_SUPPORTED, 1, [Defined if PTHREAD_SCOPE_SYSTEM supported.]) fi @@ -3991,8 +3972,7 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ ]) AS_VAR_IF([ac_cv_func_getaddrinfo], [yes], [ - AC_MSG_CHECKING(getaddrinfo bug) - AC_CACHE_VAL(ac_cv_buggy_getaddrinfo, + AC_CACHE_CHECK([getaddrinfo bug], [ac_cv_buggy_getaddrinfo], AC_RUN_IFELSE([AC_LANG_SOURCE([[[ #include #include @@ -4095,8 +4075,6 @@ fi])) dnl if ac_cv_func_getaddrinfo ]) -AC_MSG_RESULT($ac_cv_buggy_getaddrinfo) - if test "$ac_cv_func_getaddrinfo" = no -o "$ac_cv_buggy_getaddrinfo" = yes then if test $ipv6 = yes @@ -4133,48 +4111,40 @@ AC_CHECK_MEMBERS([struct passwd.pw_gecos, struct passwd.pw_passwd], [], [], [[ # Issue #21085: In Cygwin, siginfo_t does not have si_band field. AC_CHECK_MEMBERS([siginfo_t.si_band], [], [], [[#include ]]) -AC_MSG_CHECKING(for time.h that defines altzone) -AC_CACHE_VAL(ac_cv_header_time_altzone,[ +AC_CACHE_CHECK([for time.h that defines altzone], [ac_cv_header_time_altzone], [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[return altzone;]])], [ac_cv_header_time_altzone=yes], [ac_cv_header_time_altzone=no]) ]) -AC_MSG_RESULT($ac_cv_header_time_altzone) if test $ac_cv_header_time_altzone = yes; then AC_DEFINE(HAVE_ALTZONE, 1, [Define this if your time.h defines altzone.]) fi -AC_MSG_CHECKING(for addrinfo) -AC_CACHE_VAL(ac_cv_struct_addrinfo, +AC_CACHE_CHECK([for addrinfo], [ac_cv_struct_addrinfo], AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[struct addrinfo a]])], [ac_cv_struct_addrinfo=yes], [ac_cv_struct_addrinfo=no])) -AC_MSG_RESULT($ac_cv_struct_addrinfo) if test $ac_cv_struct_addrinfo = yes; then AC_DEFINE(HAVE_ADDRINFO, 1, [struct addrinfo (netdb.h)]) fi -AC_MSG_CHECKING(for sockaddr_storage) -AC_CACHE_VAL(ac_cv_struct_sockaddr_storage, +AC_CACHE_CHECK([for sockaddr_storage], [ac_cv_struct_sockaddr_storage], AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ # include # include ]], [[struct sockaddr_storage s]])], [ac_cv_struct_sockaddr_storage=yes], [ac_cv_struct_sockaddr_storage=no])) -AC_MSG_RESULT($ac_cv_struct_sockaddr_storage) if test $ac_cv_struct_sockaddr_storage = yes; then AC_DEFINE(HAVE_SOCKADDR_STORAGE, 1, [struct sockaddr_storage (sys/socket.h)]) fi -AC_MSG_CHECKING(for sockaddr_alg) -AC_CACHE_VAL(ac_cv_struct_sockaddr_alg, +AC_CACHE_CHECK([for sockaddr_alg], [ac_cv_struct_sockaddr_alg], AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ # include # include # include ]], [[struct sockaddr_alg s]])], [ac_cv_struct_sockaddr_alg=yes], [ac_cv_struct_sockaddr_alg=no])) -AC_MSG_RESULT($ac_cv_struct_sockaddr_alg) if test $ac_cv_struct_sockaddr_alg = yes; then AC_DEFINE(HAVE_SOCKADDR_ALG, 1, [struct sockaddr_alg (linux/if_alg.h)]) fi @@ -4496,8 +4466,7 @@ LIBS=$LIBS_SAVE # the kernel module that provides POSIX semaphores # isn't loaded by default, so an attempt to call # sem_open results in a 'Signal 12' error. -AC_MSG_CHECKING(whether POSIX semaphores are enabled) -AC_CACHE_VAL(ac_cv_posix_semaphores_enabled, +AC_CACHE_CHECK([whether POSIX semaphores are enabled], [ac_cv_posix_semaphores_enabled], AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include @@ -4520,7 +4489,6 @@ int main(void) { [ac_cv_posix_semaphores_enabled=no], [ac_cv_posix_semaphores_enabled=yes]) ) -AC_MSG_RESULT($ac_cv_posix_semaphores_enabled) if test $ac_cv_posix_semaphores_enabled = no then AC_DEFINE(POSIX_SEMAPHORES_NOT_ENABLED, 1, @@ -4528,8 +4496,7 @@ then fi # Multiprocessing check for broken sem_getvalue -AC_MSG_CHECKING(for broken sem_getvalue) -AC_CACHE_VAL(ac_cv_broken_sem_getvalue, +AC_CACHE_CHECK([for broken sem_getvalue], [ac_cv_broken_sem_getvalue], AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include @@ -4556,7 +4523,6 @@ int main(void){ [ac_cv_broken_sem_getvalue=yes], [ac_cv_broken_sem_getvalue=yes]) ) -AC_MSG_RESULT($ac_cv_broken_sem_getvalue) if test $ac_cv_broken_sem_getvalue = yes then AC_DEFINE(HAVE_BROKEN_SEM_GETVALUE, 1, @@ -4615,8 +4581,7 @@ AC_MSG_RESULT($have_ucs4_tcl) if test "$wchar_h" = yes then # check whether wchar_t is signed or not - AC_MSG_CHECKING(whether wchar_t is signed) - AC_CACHE_VAL(ac_cv_wchar_t_signed, [ + AC_CACHE_CHECK([whether wchar_t is signed], [ac_cv_wchar_t_signed], [ AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include int main() @@ -4628,7 +4593,6 @@ then [ac_cv_wchar_t_signed=yes], [ac_cv_wchar_t_signed=no], [ac_cv_wchar_t_signed=yes])]) - AC_MSG_RESULT($ac_cv_wchar_t_signed) fi AC_MSG_CHECKING(whether wchar_t is usable) @@ -4766,8 +4730,7 @@ fi], # Check whether right shifting a negative integer extends the sign bit # or fills with zeros (like the Cray J90, according to Tim Peters). -AC_MSG_CHECKING(whether right shift extends the sign bit) -AC_CACHE_VAL(ac_cv_rshift_extends_sign, [ +AC_CACHE_CHECK([whether right shift extends the sign bit], [ac_cv_rshift_extends_sign], [ AC_RUN_IFELSE([AC_LANG_SOURCE([[ int main() { @@ -4777,7 +4740,6 @@ int main() [ac_cv_rshift_extends_sign=yes], [ac_cv_rshift_extends_sign=no], [ac_cv_rshift_extends_sign=yes])]) -AC_MSG_RESULT($ac_cv_rshift_extends_sign) if test "$ac_cv_rshift_extends_sign" = no then AC_DEFINE(SIGNED_RIGHT_SHIFT_ZERO_FILLS, 1, @@ -4786,15 +4748,13 @@ then fi # check for getc_unlocked and related locking functions -AC_MSG_CHECKING(for getc_unlocked() and friends) -AC_CACHE_VAL(ac_cv_have_getc_unlocked, [ +AC_CACHE_CHECK([for getc_unlocked() and friends], [ac_cv_have_getc_unlocked], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ FILE *f = fopen("/dev/null", "r"); flockfile(f); getc_unlocked(f); funlockfile(f); ]])],[ac_cv_have_getc_unlocked=yes],[ac_cv_have_getc_unlocked=no])]) -AC_MSG_RESULT($ac_cv_have_getc_unlocked) if test "$ac_cv_have_getc_unlocked" = yes then AC_DEFINE(HAVE_GETC_UNLOCKED, 1, @@ -4923,8 +4883,7 @@ fi # End of readline checks: restore LIBS LIBS=$LIBS_no_readline -AC_MSG_CHECKING(for broken nice()) -AC_CACHE_VAL(ac_cv_broken_nice, [ +AC_CACHE_CHECK([for broken nice()], [ac_cv_broken_nice], [ AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include @@ -4939,15 +4898,13 @@ int main() [ac_cv_broken_nice=yes], [ac_cv_broken_nice=no], [ac_cv_broken_nice=no])]) -AC_MSG_RESULT($ac_cv_broken_nice) if test "$ac_cv_broken_nice" = yes then AC_DEFINE(HAVE_BROKEN_NICE, 1, [Define if nice() returns success/failure instead of the new priority.]) fi -AC_MSG_CHECKING(for broken poll()) -AC_CACHE_VAL(ac_cv_broken_poll, +AC_CACHE_CHECK([for broken poll()], [ac_cv_broken_poll], AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include @@ -4971,7 +4928,6 @@ int main() [ac_cv_broken_poll=yes], [ac_cv_broken_poll=no], [ac_cv_broken_poll=no])) -AC_MSG_RESULT($ac_cv_broken_poll) if test "$ac_cv_broken_poll" = yes then AC_DEFINE(HAVE_BROKEN_POLL, 1, @@ -4979,8 +4935,7 @@ then fi # check tzset(3) exists and works like we expect it to -AC_MSG_CHECKING(for working tzset()) -AC_CACHE_VAL(ac_cv_working_tzset, [ +AC_CACHE_CHECK([for working tzset()], [ac_cv_working_tzset], [ AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include @@ -5048,7 +5003,6 @@ int main() [ac_cv_working_tzset=yes], [ac_cv_working_tzset=no], [ac_cv_working_tzset=no])]) -AC_MSG_RESULT($ac_cv_working_tzset) if test "$ac_cv_working_tzset" = yes then AC_DEFINE(HAVE_WORKING_TZSET, 1, @@ -5056,15 +5010,13 @@ then fi # Look for subsecond timestamps in struct stat -AC_MSG_CHECKING(for tv_nsec in struct stat) -AC_CACHE_VAL(ac_cv_stat_tv_nsec, +AC_CACHE_CHECK([for tv_nsec in struct stat], [ac_cv_stat_tv_nsec], AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ struct stat st; st.st_mtim.tv_nsec = 1; ]])], [ac_cv_stat_tv_nsec=yes], [ac_cv_stat_tv_nsec=no])) -AC_MSG_RESULT($ac_cv_stat_tv_nsec) if test "$ac_cv_stat_tv_nsec" = yes then AC_DEFINE(HAVE_STAT_TV_NSEC, 1, @@ -5072,15 +5024,13 @@ then fi # Look for BSD style subsecond timestamps in struct stat -AC_MSG_CHECKING(for tv_nsec2 in struct stat) -AC_CACHE_VAL(ac_cv_stat_tv_nsec2, +AC_CACHE_CHECK([for tv_nsec2 in struct stat], [ac_cv_stat_tv_nsec2], AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ struct stat st; st.st_mtimespec.tv_nsec = 1; ]])], [ac_cv_stat_tv_nsec2=yes], [ac_cv_stat_tv_nsec2=no])) -AC_MSG_RESULT($ac_cv_stat_tv_nsec2) if test "$ac_cv_stat_tv_nsec2" = yes then AC_DEFINE(HAVE_STAT_TV_NSEC2, 1, @@ -5103,15 +5053,13 @@ AC_CHECK_HEADERS(term.h,,,[ ]) # On HP/UX 11.0, mvwdelch is a block with a return statement -AC_MSG_CHECKING(whether mvwdelch is an expression) -AC_CACHE_VAL(ac_cv_mvwdelch_is_expression, +AC_CACHE_CHECK([whether mvwdelch is an expression], [ac_cv_mvwdelch_is_expression], AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ int rtn; rtn = mvwdelch(0,0,0); ]])], [ac_cv_mvwdelch_is_expression=yes], [ac_cv_mvwdelch_is_expression=no])) -AC_MSG_RESULT($ac_cv_mvwdelch_is_expression) if test "$ac_cv_mvwdelch_is_expression" = yes then @@ -5123,8 +5071,7 @@ fi # structs since version 5.7. If the macro is defined as zero before including # [n]curses.h, ncurses will expose fields of the structs regardless of the # configuration. -AC_MSG_CHECKING(whether WINDOW has _flags) -AC_CACHE_VAL(ac_cv_window_has_flags, +AC_CACHE_CHECK([whether WINDOW has _flags], [ac_cv_window_has_flags], AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #define NCURSES_OPAQUE 0 #include @@ -5134,7 +5081,6 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ]])], [ac_cv_window_has_flags=yes], [ac_cv_window_has_flags=no])) -AC_MSG_RESULT($ac_cv_window_has_flags) if test "$ac_cv_window_has_flags" = yes @@ -5270,8 +5216,7 @@ AC_CHECK_TYPE(socklen_t,, #endif ]) -AC_MSG_CHECKING(for broken mbstowcs) -AC_CACHE_VAL(ac_cv_broken_mbstowcs, +AC_CACHE_CHECK([for broken mbstowcs], [ac_cv_broken_mbstowcs], AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include @@ -5285,7 +5230,6 @@ int main() { [ac_cv_broken_mbstowcs=no], [ac_cv_broken_mbstowcs=yes], [ac_cv_broken_mbstowcs=no])) -AC_MSG_RESULT($ac_cv_broken_mbstowcs) if test "$ac_cv_broken_mbstowcs" = yes then AC_DEFINE(HAVE_BROKEN_MBSTOWCS, 1, @@ -5314,8 +5258,7 @@ fi ], [AC_MSG_RESULT(no value specified)]) -AC_MSG_CHECKING(whether $CC supports computed gotos) -AC_CACHE_VAL(ac_cv_computed_gotos, +AC_CACHE_CHECK([whether $CC supports computed gotos], [ac_cv_computed_gotos], AC_RUN_IFELSE([AC_LANG_SOURCE([[[ int main(int argc, char **argv) { @@ -5335,7 +5278,6 @@ LABEL2: else ac_cv_computed_gotos=no fi])) -AC_MSG_RESULT($ac_cv_computed_gotos) case "$ac_cv_computed_gotos" in yes*) AC_DEFINE(HAVE_COMPUTED_GOTOS, 1, [Define if the C compiler supports computed gotos.]) From webhook-mailer at python.org Wed Nov 10 11:57:24 2021 From: webhook-mailer at python.org (iritkatriel) Date: Wed, 10 Nov 2021 16:57:24 -0000 Subject: [Python-checkins] bpo-45711: Use _PyErr_ClearExcState instead of setting only exc_value to NULL (GH-29404) Message-ID: https://github.com/python/cpython/commit/05fbd60147456d77a7aecf29dddd86c5bde5872f commit: 05fbd60147456d77a7aecf29dddd86c5bde5872f branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-11-10T16:57:14Z summary: bpo-45711: Use _PyErr_ClearExcState instead of setting only exc_value to NULL (GH-29404) files: M Modules/_asynciomodule.c diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 8386a50d55826..df6644ba248ed 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -1371,10 +1371,15 @@ _asyncio_Future__make_cancelled_error_impl(FutureObj *self) { PyObject *exc = create_cancelled_error(self->fut_cancel_msg); _PyErr_StackItem *exc_state = &self->fut_cancelled_exc_state; - /* Transfer ownership of exc_value from exc_state to exc since we are - done with it. */ - PyException_SetContext(exc, exc_state->exc_value); - exc_state->exc_value = NULL; + + if (exc_state->exc_value) { + PyException_SetContext(exc, Py_NewRef(exc_state->exc_value)); + _PyErr_ClearExcState(exc_state); + } + else { + assert(exc_state->exc_type == NULL); + assert(exc_state->exc_traceback == NULL); + } return exc; } From webhook-mailer at python.org Wed Nov 10 13:08:43 2021 From: webhook-mailer at python.org (markshannon) Date: Wed, 10 Nov 2021 18:08:43 -0000 Subject: [Python-checkins] bpo-45711: remove unnecessary DUP_TOP and POP in exception handling (GH-29495) Message-ID: https://github.com/python/cpython/commit/4cdeee5978ee3f8ea7fe95172ae04d866cd88177 commit: 4cdeee5978ee3f8ea7fe95172ae04d866cd88177 branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: markshannon date: 2021-11-10T18:08:28Z summary: bpo-45711: remove unnecessary DUP_TOP and POP in exception handling (GH-29495) files: M Lib/importlib/_bootstrap_external.py M Lib/test/test_dis.py M Python/ceval.c M Python/compile.c diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 4edcf9a3ce0cb..e492dc22d911e 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -375,7 +375,7 @@ def _write_atomic(path, data, mode=0o666): # Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array # in PC/launcher.c must also be updated. -MAGIC_NUMBER = (3462).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3463).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c _PYCACHE = '__pycache__' diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index fad2d06f928fe..d0435e494d1e7 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -309,35 +309,34 @@ def bug42562(): 12 RETURN_VALUE >> 14 PUSH_EXC_INFO -%3d 16 DUP_TOP - 18 LOAD_GLOBAL 0 (Exception) - 20 JUMP_IF_NOT_EXC_MATCH 27 (to 54) - 22 POP_TOP - 24 STORE_FAST 0 (e) - 26 POP_TOP - -%3d 28 LOAD_FAST 0 (e) - 30 LOAD_ATTR 1 (__traceback__) - 32 STORE_FAST 1 (tb) - 34 POP_EXCEPT - 36 LOAD_CONST 0 (None) - 38 STORE_FAST 0 (e) - 40 DELETE_FAST 0 (e) - -%3d 42 LOAD_FAST 1 (tb) - 44 RETURN_VALUE - >> 46 LOAD_CONST 0 (None) - 48 STORE_FAST 0 (e) - 50 DELETE_FAST 0 (e) - 52 RERAISE 1 - -%3d >> 54 RERAISE 0 - >> 56 POP_EXCEPT_AND_RERAISE +%3d 16 LOAD_GLOBAL 0 (Exception) + 18 JUMP_IF_NOT_EXC_MATCH 26 (to 52) + 20 POP_TOP + 22 STORE_FAST 0 (e) + 24 POP_TOP + +%3d 26 LOAD_FAST 0 (e) + 28 LOAD_ATTR 1 (__traceback__) + 30 STORE_FAST 1 (tb) + 32 POP_EXCEPT + 34 LOAD_CONST 0 (None) + 36 STORE_FAST 0 (e) + 38 DELETE_FAST 0 (e) + +%3d 40 LOAD_FAST 1 (tb) + 42 RETURN_VALUE + >> 44 LOAD_CONST 0 (None) + 46 STORE_FAST 0 (e) + 48 DELETE_FAST 0 (e) + 50 RERAISE 1 + +%3d >> 52 RERAISE 0 + >> 54 POP_EXCEPT_AND_RERAISE ExceptionTable: 2 to 8 -> 14 [0] - 14 to 26 -> 56 [3] lasti - 28 to 32 -> 46 [3] lasti - 46 to 54 -> 56 [3] lasti + 14 to 24 -> 54 [3] lasti + 26 to 30 -> 44 [3] lasti + 44 to 52 -> 54 [3] lasti """ % (TRACEBACK_CODE.co_firstlineno + 1, TRACEBACK_CODE.co_firstlineno + 2, TRACEBACK_CODE.co_firstlineno + 5, @@ -1104,74 +1103,73 @@ def _prepare_test_cases(): Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=108, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='BINARY_TRUE_DIVIDE', opcode=27, arg=None, argval=None, argrepr='', offset=110, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=112, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=15, argval=146, argrepr='to 146', offset=114, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=14, argval=144, argrepr='to 144', offset=114, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=116, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=118, starts_line=22, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=2, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=120, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_IF_NOT_EXC_MATCH', opcode=121, arg=71, argval=142, argrepr='to 142', offset=122, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=2, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=118, starts_line=22, is_jump_target=False, positions=None), + Instruction(opname='JUMP_IF_NOT_EXC_MATCH', opcode=121, arg=70, argval=140, argrepr='to 140', offset=120, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=122, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=124, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=126, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=128, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=130, starts_line=23, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=132, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=134, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=136, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=138, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=33, argval=208, argrepr='to 208', offset=140, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=142, starts_line=22, is_jump_target=True, positions=None), - Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=144, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=146, starts_line=25, is_jump_target=True, positions=None), - Instruction(opname='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=148, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=150, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=152, starts_line=26, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=154, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=156, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=158, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=160, starts_line=25, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=128, starts_line=23, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=130, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=132, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=134, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=136, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=33, argval=206, argrepr='to 206', offset=138, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=140, starts_line=22, is_jump_target=True, positions=None), + Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=142, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=144, starts_line=25, is_jump_target=True, positions=None), + Instruction(opname='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=146, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=148, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=150, starts_line=26, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=152, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=154, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=156, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=158, starts_line=25, is_jump_target=False, positions=None), + Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=160, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=162, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=164, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=3, argval=3, argrepr='', offset=166, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=168, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=25, argval=222, argrepr='to 222', offset=170, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=172, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=174, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=91, argval=182, argrepr='to 182', offset=176, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=4, argval=4, argrepr='', offset=178, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=180, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=182, starts_line=None, is_jump_target=True, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=3, argval=3, argrepr='', offset=164, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=166, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=25, argval=220, argrepr='to 220', offset=168, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=170, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=172, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=90, argval=180, argrepr='to 180', offset=174, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=4, argval=4, argrepr='', offset=176, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=178, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=180, starts_line=None, is_jump_target=True, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=182, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=184, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=186, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=188, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=186, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=188, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=190, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=192, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=194, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=196, starts_line=28, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=198, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=200, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=202, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=204, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=206, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=208, starts_line=23, is_jump_target=True, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=210, starts_line=28, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=212, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=214, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=216, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=218, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=220, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=222, starts_line=25, is_jump_target=True, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=224, starts_line=28, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=226, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=228, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=230, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=232, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=234, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=236, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=238, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=240, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=242, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=244, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=246, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=248, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=192, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=194, starts_line=28, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=196, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=198, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=200, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=202, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=204, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=206, starts_line=23, is_jump_target=True, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=208, starts_line=28, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=210, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=212, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=214, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=216, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=218, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=220, starts_line=25, is_jump_target=True, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=222, starts_line=28, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=224, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=226, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=228, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=230, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=232, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=234, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=236, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=238, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=240, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=242, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=244, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=246, starts_line=None, is_jump_target=False, positions=None), ] # One last piece of inspect fodder to check the default line number handling diff --git a/Python/ceval.c b/Python/ceval.c index c9f6638afa0e4..fadb97adefb2b 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3907,7 +3907,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr "inherit from BaseException is not " "allowed"; PyObject *right = POP(); - PyObject *left = POP(); + PyObject *left = TOP(); if (PyTuple_Check(right)) { Py_ssize_t i, length; length = PyTuple_GET_SIZE(right); @@ -3916,7 +3916,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr if (!PyExceptionClass_Check(exc)) { _PyErr_SetString(tstate, PyExc_TypeError, cannot_catch_msg); - Py_DECREF(left); Py_DECREF(right); goto error; } @@ -3926,13 +3925,11 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr if (!PyExceptionClass_Check(right)) { _PyErr_SetString(tstate, PyExc_TypeError, cannot_catch_msg); - Py_DECREF(left); Py_DECREF(right); goto error; } } int res = PyErr_GivenExceptionMatches(left, right); - Py_DECREF(left); Py_DECREF(right); if (res > 0) { /* Exception matches -- Do nothing */; diff --git a/Python/compile.c b/Python/compile.c index 28b5c076d50aa..47889abe61223 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1127,7 +1127,7 @@ stack_effect(int opcode, int oparg, int jump) case CONTAINS_OP: return -1; case JUMP_IF_NOT_EXC_MATCH: - return -2; + return -1; case IMPORT_NAME: return -1; case IMPORT_FROM: @@ -3222,16 +3222,15 @@ compiler_try_finally(struct compiler *c, stmt_ty s) [] POP_BLOCK [] JUMP_FORWARD L0 - [tb, val, exc] L1: DUP ) - [tb, val, exc, exc] ) - [tb, val, exc, exc, E1] JUMP_IF_NOT_EXC_MATCH L2 ) only if E1 + [tb, val, exc] L1: ) + [tb, val, exc, E1] JUMP_IF_NOT_EXC_MATCH L2 ) only if E1 [tb, val, exc] POP [tb, val] (or POP if no V1) [tb] POP [] JUMP_FORWARD L0 - [tb, val, exc] L2: DUP + [tb, val, exc] L2: .............................etc....................... [tb, val, exc] Ln+1: RERAISE # re-raise exception @@ -3281,7 +3280,6 @@ compiler_try_except(struct compiler *c, stmt_ty s) if (except == NULL) return 0; if (handler->v.ExceptHandler.type) { - ADDOP(c, DUP_TOP); VISIT(c, expr, handler->v.ExceptHandler.type); ADDOP_JUMP(c, JUMP_IF_NOT_EXC_MATCH, except); NEXT_BLOCK(c); From webhook-mailer at python.org Wed Nov 10 13:46:21 2021 From: webhook-mailer at python.org (pablogsal) Date: Wed, 10 Nov 2021 18:46:21 -0000 Subject: [Python-checkins] bpo-45754: Use correct SQLite limit when checking statement length (GH-29489) Message-ID: https://github.com/python/cpython/commit/c1323d4b8cb010a06c11bace6e681bea7f895851 commit: c1323d4b8cb010a06c11bace6e681bea7f895851 branch: main author: Erlend Egeberg Aasland committer: pablogsal date: 2021-11-10T18:46:11Z summary: bpo-45754: Use correct SQLite limit when checking statement length (GH-29489) files: A Misc/NEWS.d/next/Library/2021-11-09-15-48-38.bpo-45754.c-JDto.rst M Lib/test/test_sqlite3/test_dbapi.py M Lib/test/test_sqlite3/test_regression.py M Modules/_sqlite/cursor.c M Modules/_sqlite/statement.c diff --git a/Lib/test/test_sqlite3/test_dbapi.py b/Lib/test/test_sqlite3/test_dbapi.py index 6628eee975d35..a5ec66fe22a2a 100644 --- a/Lib/test/test_sqlite3/test_dbapi.py +++ b/Lib/test/test_sqlite3/test_dbapi.py @@ -55,7 +55,7 @@ def memory_database(): # Temporarily limit a database connection parameter @contextlib.contextmanager -def cx_limit(cx, category=sqlite.SQLITE_LIMIT_LENGTH, limit=128): +def cx_limit(cx, category=sqlite.SQLITE_LIMIT_SQL_LENGTH, limit=128): try: _prev = cx.setlimit(category, limit) yield limit @@ -495,7 +495,7 @@ def test_connection_limits(self): prev_limit = self.cx.setlimit(category, new_limit) self.assertEqual(saved_limit, prev_limit) self.assertEqual(self.cx.getlimit(category), new_limit) - msg = "string or blob too big" + msg = "query string is too large" self.assertRaisesRegex(sqlite.DataError, msg, self.cx.execute, "select 1 as '16'") finally: # restore saved limit @@ -1063,9 +1063,9 @@ def test_cursor_executescript_with_surrogates(self): def test_cursor_executescript_too_large_script(self): msg = "query string is too large" with memory_database() as cx, cx_limit(cx) as lim: - cx.executescript("select 'almost too large'".ljust(lim-1)) + cx.executescript("select 'almost too large'".ljust(lim)) with self.assertRaisesRegex(sqlite.DataError, msg): - cx.executescript("select 'too large'".ljust(lim)) + cx.executescript("select 'too large'".ljust(lim+1)) def test_cursor_executescript_tx_control(self): con = sqlite.connect(":memory:") diff --git a/Lib/test/test_sqlite3/test_regression.py b/Lib/test/test_sqlite3/test_regression.py index 158f4cf86f55c..eb34069d3e554 100644 --- a/Lib/test/test_sqlite3/test_regression.py +++ b/Lib/test/test_sqlite3/test_regression.py @@ -362,11 +362,11 @@ def test_large_sql(self): with memory_database() as cx, cx_limit(cx) as lim: cu = cx.cursor() - cx("select 1".ljust(lim-1)) + cx("select 1".ljust(lim)) # use a different SQL statement; don't reuse from the LRU cache - cu.execute("select 2".ljust(lim-1)) + cu.execute("select 2".ljust(lim)) - sql = "select 3".ljust(lim) + sql = "select 3".ljust(lim+1) self.assertRaisesRegex(sqlite.DataError, msg, cx, sql) self.assertRaisesRegex(sqlite.DataError, msg, cu.execute, sql) diff --git a/Misc/NEWS.d/next/Library/2021-11-09-15-48-38.bpo-45754.c-JDto.rst b/Misc/NEWS.d/next/Library/2021-11-09-15-48-38.bpo-45754.c-JDto.rst new file mode 100644 index 0000000000000..196bfc9eb27dd --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-09-15-48-38.bpo-45754.c-JDto.rst @@ -0,0 +1,3 @@ +Fix a regression in Python 3.11a1 and 3.11a2 where :mod:`sqlite3` +incorrectly would use ``SQLITE_LIMIT_LENGTH`` when checking SQL statement +lengths. Now, ``SQLITE_LIMIT_SQL_LENGTH`` is used. Patch by Erlend E. Aasland. diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index 1d7c0b46a616d..3ee1c5da9d0b4 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -729,8 +729,8 @@ pysqlite_cursor_executescript_impl(pysqlite_Cursor *self, size_t sql_len = strlen(sql_script); int max_length = sqlite3_limit(self->connection->db, - SQLITE_LIMIT_LENGTH, -1); - if (sql_len >= (unsigned)max_length) { + SQLITE_LIMIT_SQL_LENGTH, -1); + if (sql_len > (unsigned)max_length) { PyErr_SetString(self->connection->DataError, "query string is too large"); return NULL; diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c index b20c91da3179c..66fadb63e53ca 100644 --- a/Modules/_sqlite/statement.c +++ b/Modules/_sqlite/statement.c @@ -60,8 +60,8 @@ pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql) } sqlite3 *db = connection->db; - int max_length = sqlite3_limit(db, SQLITE_LIMIT_LENGTH, -1); - if (size >= max_length) { + int max_length = sqlite3_limit(db, SQLITE_LIMIT_SQL_LENGTH, -1); + if (size > max_length) { PyErr_SetString(connection->DataError, "query string is too large"); return NULL; From webhook-mailer at python.org Wed Nov 10 14:27:05 2021 From: webhook-mailer at python.org (tiran) Date: Wed, 10 Nov 2021 19:27:05 -0000 Subject: [Python-checkins] bpo-45747: Detect gdbm/dbm dependencies in configure (GH-29467) Message-ID: https://github.com/python/cpython/commit/0a9f69539be27acf1cddf1b58d02a88d02e5008d commit: 0a9f69539be27acf1cddf1b58d02a88d02e5008d branch: main author: Christian Heimes committer: tiran date: 2021-11-10T20:26:55+01:00 summary: bpo-45747: Detect gdbm/dbm dependencies in configure (GH-29467) Co-authored-by: Erlend Egeberg Aasland files: A Misc/NEWS.d/next/Build/2021-11-08-11-31-48.bpo-45747.AODmk_.rst M Doc/whatsnew/3.11.rst M Modules/Setup M Modules/_dbmmodule.c M configure M configure.ac M pyconfig.h.in M setup.py diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 27062f6162ac8..c0a6ce4c35ad8 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -528,6 +528,10 @@ Build Changes detected by :program:`configure`. (Contributed by Christian Heimes in :issue:`45763`.) +* Build dependencies for :mod:`dbm` are now detected by :program:`configure`. + ``libdb`` 3.x and 4.x are no longer supported. + (Contributed by Christian Heimes in :issue:`45747`.) + C API Changes ============= diff --git a/Misc/NEWS.d/next/Build/2021-11-08-11-31-48.bpo-45747.AODmk_.rst b/Misc/NEWS.d/next/Build/2021-11-08-11-31-48.bpo-45747.AODmk_.rst new file mode 100644 index 0000000000000..f60b83fd5aff1 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-08-11-31-48.bpo-45747.AODmk_.rst @@ -0,0 +1 @@ +gdbm and dbm build dependencies are now detected by ``configure``. diff --git a/Modules/Setup b/Modules/Setup index 57584f38fd8e7..49c6903121616 100644 --- a/Modules/Setup +++ b/Modules/Setup @@ -216,7 +216,7 @@ time timemodule.c #_bz2 _bz2module.c -lbz2 #_ctypes _ctypes/_ctypes.c _ctypes/callbacks.c _ctypes/callproc.c _ctypes/stgdict.c _ctypes/cfield.c -ldl -lffi -DHAVE_FFI_PREP_CIF_VAR -DHAVE_FFI_PREP_CLOSURE_LOC -DHAVE_FFI_CLOSURE_ALLOC # The _dbm module supports NDBM, GDBM with compat module, and Berkeley DB. -#_dbm _dbmmodule.c -lgdbm_compat -DHAVE_NDBM_H +#_dbm _dbmmodule.c -lgdbm_compat -DUSE_GDBM_COMPAT #_gdbm _gdbmmodule.c -lgdbm #_lzma _lzmamodule.c -llzma #_sqlite3 _sqlite/connection.c _sqlite/cursor.c _sqlite/microprotocols.c _sqlite/module.c _sqlite/prepare_protocol.c _sqlite/row.c _sqlite/statement.c _sqlite/util.c -lsqlite3 diff --git a/Modules/_dbmmodule.c b/Modules/_dbmmodule.c index 4cbbac3326a8a..c0371fb3f3b20 100644 --- a/Modules/_dbmmodule.c +++ b/Modules/_dbmmodule.c @@ -12,20 +12,26 @@ /* Some Linux systems install gdbm/ndbm.h, but not ndbm.h. This supports * whichever configure was able to locate. */ -#if defined(HAVE_NDBM_H) -#include -static const char which_dbm[] = "GNU gdbm"; /* EMX port of GDBM */ -#elif defined(HAVE_GDBM_NDBM_H) -#include -static const char which_dbm[] = "GNU gdbm"; -#elif defined(HAVE_GDBM_DASH_NDBM_H) -#include -static const char which_dbm[] = "GNU gdbm"; -#elif defined(HAVE_BERKDB_H) -#include -static const char which_dbm[] = "Berkeley DB"; +#if defined(USE_NDBM) + #include + static const char which_dbm[] = "GNU gdbm"; /* EMX port of GDBM */ +#elif defined(USE_GDBM_COMPAT) + #ifdef HAVE_GDBM_NDBM_H + #include + #elif HAVE_GDBM_DASH_NDBM_H + #include + #else + #error "No gdbm/ndbm.h or gdbm-ndbm.h available" + #endif + static const char which_dbm[] = "GNU gdbm"; +#elif defined(USE_BERKDB) + #ifndef DB_DBM_HSEARCH + #define DB_DBM_HSEARCH 1 + #endif + #include + static const char which_dbm[] = "Berkeley DB"; #else -#error "No ndbm.h available!" + #error "No ndbm.h available!" #endif typedef struct { diff --git a/configure b/configure index d9c41226a3550..2a89703d29475 100755 --- a/configure +++ b/configure @@ -10822,6 +10822,340 @@ else TCLTK_LIBS="$with_tcltk_libs" fi +# check for _gdbmmodulec dependencies +for ac_header in gdbm.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "gdbm.h" "ac_cv_header_gdbm_h" "$ac_includes_default" +if test "x$ac_cv_header_gdbm_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GDBM_H 1 +_ACEOF + + LIBS_SAVE=$LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gdbm_open in -lgdbm" >&5 +$as_echo_n "checking for gdbm_open in -lgdbm... " >&6; } +if ${ac_cv_lib_gdbm_gdbm_open+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgdbm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gdbm_open (); +int +main () +{ +return gdbm_open (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_gdbm_gdbm_open=yes +else + ac_cv_lib_gdbm_gdbm_open=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gdbm_gdbm_open" >&5 +$as_echo "$ac_cv_lib_gdbm_gdbm_open" >&6; } +if test "x$ac_cv_lib_gdbm_gdbm_open" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBGDBM 1 +_ACEOF + + LIBS="-lgdbm $LIBS" + +fi + + LIBS=$LIBS_SAVE + +fi + +done + + +# check for _dbmmodule.c dependencies +for ac_header in ndbm.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "ndbm.h" "ac_cv_header_ndbm_h" "$ac_includes_default" +if test "x$ac_cv_header_ndbm_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_NDBM_H 1 +_ACEOF + + LIBS_SAVE="$LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm_open in -lndbm" >&5 +$as_echo_n "checking for dbm_open in -lndbm... " >&6; } +if ${ac_cv_lib_ndbm_dbm_open+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lndbm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dbm_open (); +int +main () +{ +return dbm_open (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ndbm_dbm_open=yes +else + ac_cv_lib_ndbm_dbm_open=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ndbm_dbm_open" >&5 +$as_echo "$ac_cv_lib_ndbm_dbm_open" >&6; } +if test "x$ac_cv_lib_ndbm_dbm_open" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBNDBM 1 +_ACEOF + + LIBS="-lndbm $LIBS" + +fi + + LIBS="$LIBS_SAVE" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm_open in -lgdbm_compat" >&5 +$as_echo_n "checking for dbm_open in -lgdbm_compat... " >&6; } +if ${ac_cv_lib_gdbm_compat_dbm_open+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgdbm_compat $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dbm_open (); +int +main () +{ +return dbm_open (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_gdbm_compat_dbm_open=yes +else + ac_cv_lib_gdbm_compat_dbm_open=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gdbm_compat_dbm_open" >&5 +$as_echo "$ac_cv_lib_gdbm_compat_dbm_open" >&6; } +if test "x$ac_cv_lib_gdbm_compat_dbm_open" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBGDBM_COMPAT 1 +_ACEOF + + LIBS="-lgdbm_compat $LIBS" + +fi + + LIBS="$LIBS_SAVE" + +fi + +done + + +# "gdbm-ndbm.h" and "gdbm/ndbm.h" are both normalized to "gdbm_ndbm_h" +# unset ac_cv_header_gdbm_ndbm_h to prevent false positive cache hits. +{ ac_cv_header_gdbm_ndbm_h=; unset ac_cv_header_gdbm_ndbm_h;} +if ${ac_cv_header_gdbm_slash_ndbm_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_fn_c_check_header_mongrel "$LINENO" "gdbm/ndbm.h" "ac_cv_header_gdbm_ndbm_h" "$ac_includes_default" +if test "x$ac_cv_header_gdbm_ndbm_h" = xyes; then : + ac_cv_header_gdbm_slash_ndbm_h=yes +else + ac_cv_header_gdbm_slash_ndbm_h=no + +fi + + + +fi + +if test "x$ac_cv_header_gdbm_slash_ndbm_h" = xyes; then : + + +$as_echo "#define HAVE_GDBM_NDBM_H 1" >>confdefs.h + + +fi + +{ ac_cv_header_gdbm_ndbm_h=; unset ac_cv_header_gdbm_ndbm_h;} +if ${ac_cv_header_gdbm_dash_ndbm_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_fn_c_check_header_mongrel "$LINENO" "gdbm-ndbm.h" "ac_cv_header_gdbm_ndbm_h" "$ac_includes_default" +if test "x$ac_cv_header_gdbm_ndbm_h" = xyes; then : + ac_cv_header_gdbm_dash_ndbm_h=yes +else + ac_cv_header_gdbm_dash_ndbm_h=no + +fi + + + +fi + +if test "x$ac_cv_header_gdbm_dash_ndbm_h" = xyes; then : + + +$as_echo "#define HAVE_GDBM_DASH_NDBM_H 1" >>confdefs.h + + +fi +{ ac_cv_header_gdbm_ndbm_h=; unset ac_cv_header_gdbm_ndbm_h;} + +if test "$ac_cv_header_gdbm_slash_ndbm_h" = yes -o "$ac_cv_header_gdbm_dash_ndbm_h" = yes; then + LIBS_SAVE="$LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm_open in -lgdbm_compat" >&5 +$as_echo_n "checking for dbm_open in -lgdbm_compat... " >&6; } +if ${ac_cv_lib_gdbm_compat_dbm_open+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgdbm_compat $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dbm_open (); +int +main () +{ +return dbm_open (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_gdbm_compat_dbm_open=yes +else + ac_cv_lib_gdbm_compat_dbm_open=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gdbm_compat_dbm_open" >&5 +$as_echo "$ac_cv_lib_gdbm_compat_dbm_open" >&6; } +if test "x$ac_cv_lib_gdbm_compat_dbm_open" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBGDBM_COMPAT 1 +_ACEOF + + LIBS="-lgdbm_compat $LIBS" + +fi + + LIBS="$LIBS_SAVE" +fi + +# Check for libdb >= 5 with dbm_open() +# db.h re-defines the name of the function +for ac_header in db.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "db.h" "ac_cv_header_db_h" "$ac_includes_default" +if test "x$ac_cv_header_db_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DB_H 1 +_ACEOF + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libdb" >&5 +$as_echo_n "checking for libdb... " >&6; } +if ${ac_cv_have_libdb+:} false; then : + $as_echo_n "(cached) " >&6 +else + + LIBS_SAVE="$LIBS" + LIBS="$LIBS -ldb" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #define DB_DBM_HSEARCH 1 + #include + #if DB_VERSION_MAJOR < 5 + #error "dh.h: DB_VERSION_MAJOR < 5 is not supported." + #endif + +int +main () +{ +DBM *dbm = dbm_open(NULL, 0, 0) + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_have_libdb=yes +else + ac_cv_have_libdb=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$LIBS_SAVE" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_libdb" >&5 +$as_echo "$ac_cv_have_libdb" >&6; } + if test "x$ac_cv_have_libdb" = xyes; then : + + +$as_echo "#define HAVE_LIBDB 1" >>confdefs.h + + +fi + +fi + +done + + # Check for --with-dbmliborder { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-dbmliborder" >&5 $as_echo_n "checking for --with-dbmliborder... " >&6; } @@ -10833,12 +11167,15 @@ if test x$with_dbmliborder = xyes then as_fn_error $? "proper usage is --with-dbmliborder=db1:db2:..." "$LINENO" 5 else - for db in `echo $with_dbmliborder | sed 's/:/ /g'`; do + as_save_IFS=$IFS + IFS=: + for db in $with_dbmliborder; do if test x$db != xndbm && test x$db != xgdbm && test x$db != xbdb then as_fn_error $? "proper usage is --with-dbmliborder=db1:db2:..." "$LINENO" 5 fi done + IFS=$as_save_IFS fi fi diff --git a/configure.ac b/configure.ac index cfd7184ac3aff..4817422178df7 100644 --- a/configure.ac +++ b/configure.ac @@ -3094,6 +3094,74 @@ else TCLTK_LIBS="$with_tcltk_libs" fi +# check for _gdbmmodulec dependencies +AC_CHECK_HEADERS([gdbm.h], [ + LIBS_SAVE=$LIBS + AC_CHECK_LIB([gdbm], [gdbm_open]) + LIBS=$LIBS_SAVE +]) + +# check for _dbmmodule.c dependencies +AC_CHECK_HEADERS([ndbm.h], [ + LIBS_SAVE="$LIBS" + AC_CHECK_LIB([ndbm], [dbm_open]) + LIBS="$LIBS_SAVE" + AC_CHECK_LIB([gdbm_compat], [dbm_open]) + LIBS="$LIBS_SAVE" +]) + +# "gdbm-ndbm.h" and "gdbm/ndbm.h" are both normalized to "gdbm_ndbm_h" +# unset ac_cv_header_gdbm_ndbm_h to prevent false positive cache hits. +AS_UNSET([ac_cv_header_gdbm_ndbm_h]) +AC_CACHE_VAL([ac_cv_header_gdbm_slash_ndbm_h], [ + AC_CHECK_HEADER( + [gdbm/ndbm.h], + [ac_cv_header_gdbm_slash_ndbm_h=yes], [ac_cv_header_gdbm_slash_ndbm_h=no] + ) +]) +AS_VAR_IF([ac_cv_header_gdbm_slash_ndbm_h], [yes], [ + AC_DEFINE([HAVE_GDBM_NDBM_H], [1], [Define to 1 if you have the header file.]) +]) + +AS_UNSET([ac_cv_header_gdbm_ndbm_h]) +AC_CACHE_VAL([ac_cv_header_gdbm_dash_ndbm_h], [ + AC_CHECK_HEADER( + [gdbm-ndbm.h], + [ac_cv_header_gdbm_dash_ndbm_h=yes], [ac_cv_header_gdbm_dash_ndbm_h=no] + ) +]) +AS_VAR_IF([ac_cv_header_gdbm_dash_ndbm_h], [yes], [ + AC_DEFINE([HAVE_GDBM_DASH_NDBM_H], [1], [Define to 1 if you have the header file.]) +]) +AS_UNSET([ac_cv_header_gdbm_ndbm_h]) + +if test "$ac_cv_header_gdbm_slash_ndbm_h" = yes -o "$ac_cv_header_gdbm_dash_ndbm_h" = yes; then + LIBS_SAVE="$LIBS" + AC_CHECK_LIB([gdbm_compat], [dbm_open]) + LIBS="$LIBS_SAVE" +fi + +# Check for libdb >= 5 with dbm_open() +# db.h re-defines the name of the function +AC_CHECK_HEADERS([db.h], [ + AC_CACHE_CHECK([for libdb], [ac_cv_have_libdb], [ + LIBS_SAVE="$LIBS" + LIBS="$LIBS -ldb" + AC_LINK_IFELSE([AC_LANG_PROGRAM([ + #define DB_DBM_HSEARCH 1 + #include + #if DB_VERSION_MAJOR < 5 + #error "dh.h: DB_VERSION_MAJOR < 5 is not supported." + #endif + ], [DBM *dbm = dbm_open(NULL, 0, 0)]) + ], [ac_cv_have_libdb=yes], [ac_cv_have_libdb=no]) + LIBS="$LIBS_SAVE" + ]) + AS_VAR_IF([ac_cv_have_libdb], [yes], [ + AC_DEFINE([HAVE_LIBDB], [1], [Define to 1 if you have the `db' library (-ldb).]) + ]) +]) + # Check for --with-dbmliborder AC_MSG_CHECKING(for --with-dbmliborder) AC_ARG_WITH(dbmliborder, @@ -3103,12 +3171,15 @@ if test x$with_dbmliborder = xyes then AC_MSG_ERROR([proper usage is --with-dbmliborder=db1:db2:...]) else - for db in `echo $with_dbmliborder | sed 's/:/ /g'`; do + as_save_IFS=$IFS + IFS=: + for db in $with_dbmliborder; do if test x$db != xndbm && test x$db != xgdbm && test x$db != xbdb then AC_MSG_ERROR([proper usage is --with-dbmliborder=db1:db2:...]) fi done + IFS=$as_save_IFS fi]) AC_MSG_RESULT($with_dbmliborder) diff --git a/pyconfig.h.in b/pyconfig.h.in index 2f71dd1758dcd..cbab59b739f31 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -214,6 +214,9 @@ /* Define if you have the 'wchgat' function. */ #undef HAVE_CURSES_WCHGAT +/* Define to 1 if you have the header file. */ +#undef HAVE_DB_H + /* Define to 1 if you have the declaration of `RTLD_DEEPBIND', and to 0 if you don't. */ #undef HAVE_DECL_RTLD_DEEPBIND @@ -420,6 +423,15 @@ /* Define if your compiler provides __uint128_t */ #undef HAVE_GCC_UINT128_T +/* Define to 1 if you have the header file. */ +#undef HAVE_GDBM_DASH_NDBM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GDBM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GDBM_NDBM_H + /* Define if you have the getaddrinfo function. */ #undef HAVE_GETADDRINFO @@ -586,12 +598,21 @@ /* Define to 1 if you have the `bz2' library (-lbz2). */ #undef HAVE_LIBBZ2 +/* Define to 1 if you have the `db' library (-ldb). */ +#undef HAVE_LIBDB + /* Define to 1 if you have the `dl' library (-ldl). */ #undef HAVE_LIBDL /* Define to 1 if you have the `dld' library (-ldld). */ #undef HAVE_LIBDLD +/* Define to 1 if you have the `gdbm' library (-lgdbm). */ +#undef HAVE_LIBGDBM + +/* Define to 1 if you have the `gdbm_compat' library (-lgdbm_compat). */ +#undef HAVE_LIBGDBM_COMPAT + /* Define to 1 if you have the `ieee' library (-lieee). */ #undef HAVE_LIBIEEE @@ -601,6 +622,9 @@ /* Define to 1 if you have the `lzma' library (-llzma). */ #undef HAVE_LIBLZMA +/* Define to 1 if you have the `ndbm' library (-lndbm). */ +#undef HAVE_LIBNDBM + /* Define to build the readline module. */ #undef HAVE_LIBREADLINE @@ -733,6 +757,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_NCURSES_H +/* Define to 1 if you have the header file. */ +#undef HAVE_NDBM_H + /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_NDIR_H diff --git a/setup.py b/setup.py index 7fe7d27b14ce0..771ab5656311e 100644 --- a/setup.py +++ b/setup.py @@ -1221,208 +1221,19 @@ def detect_dbm_gdbm(self): # implementation independent wrapper for these; dbm/dumb.py provides # similar functionality (but slower of course) implemented in Python. - # Sleepycat^WOracle Berkeley DB interface. - # https://www.oracle.com/database/technologies/related/berkeleydb.html - # - # This requires the Sleepycat^WOracle DB code. The supported versions - # are set below. Visit the URL above to download - # a release. Most open source OSes come with one or more - # versions of BerkeleyDB already installed. - - max_db_ver = (5, 3) - min_db_ver = (3, 3) - db_setup_debug = False # verbose debug prints from this script? - - def allow_db_ver(db_ver): - """Returns a boolean if the given BerkeleyDB version is acceptable. - - Args: - db_ver: A tuple of the version to verify. - """ - if not (min_db_ver <= db_ver <= max_db_ver): - return False - return True - - def gen_db_minor_ver_nums(major): - if major == 4: - for x in range(max_db_ver[1]+1): - if allow_db_ver((4, x)): - yield x - elif major == 3: - for x in (3,): - if allow_db_ver((3, x)): - yield x - else: - raise ValueError("unknown major BerkeleyDB version", major) - - # construct a list of paths to look for the header file in on - # top of the normal inc_dirs. - db_inc_paths = [ - '/usr/include/db4', - '/usr/local/include/db4', - '/opt/sfw/include/db4', - '/usr/include/db3', - '/usr/local/include/db3', - '/opt/sfw/include/db3', - # Fink defaults (https://www.finkproject.org/) - '/sw/include/db4', - '/sw/include/db3', - ] - # 4.x minor number specific paths - for x in gen_db_minor_ver_nums(4): - db_inc_paths.append('/usr/include/db4%d' % x) - db_inc_paths.append('/usr/include/db4.%d' % x) - db_inc_paths.append('/usr/local/BerkeleyDB.4.%d/include' % x) - db_inc_paths.append('/usr/local/include/db4%d' % x) - db_inc_paths.append('/pkg/db-4.%d/include' % x) - db_inc_paths.append('/opt/db-4.%d/include' % x) - # MacPorts default (https://www.macports.org/) - db_inc_paths.append('/opt/local/include/db4%d' % x) - # 3.x minor number specific paths - for x in gen_db_minor_ver_nums(3): - db_inc_paths.append('/usr/include/db3%d' % x) - db_inc_paths.append('/usr/local/BerkeleyDB.3.%d/include' % x) - db_inc_paths.append('/usr/local/include/db3%d' % x) - db_inc_paths.append('/pkg/db-3.%d/include' % x) - db_inc_paths.append('/opt/db-3.%d/include' % x) - - if CROSS_COMPILING: - db_inc_paths = [] - - # Add some common subdirectories for Sleepycat DB to the list, - # based on the standard include directories. This way DB3/4 gets - # picked up when it is installed in a non-standard prefix and - # the user has added that prefix into inc_dirs. - std_variants = [] - for dn in self.inc_dirs: - std_variants.append(os.path.join(dn, 'db3')) - std_variants.append(os.path.join(dn, 'db4')) - for x in gen_db_minor_ver_nums(4): - std_variants.append(os.path.join(dn, "db4%d"%x)) - std_variants.append(os.path.join(dn, "db4.%d"%x)) - for x in gen_db_minor_ver_nums(3): - std_variants.append(os.path.join(dn, "db3%d"%x)) - std_variants.append(os.path.join(dn, "db3.%d"%x)) - - db_inc_paths = std_variants + db_inc_paths - db_inc_paths = [p for p in db_inc_paths if os.path.exists(p)] - - db_ver_inc_map = {} - - if MACOS: - sysroot = macosx_sdk_root() - - class db_found(Exception): pass - try: - # See whether there is a Sleepycat header in the standard - # search path. - for d in self.inc_dirs + db_inc_paths: - f = os.path.join(d, "db.h") - if MACOS and is_macosx_sdk_path(d): - f = os.path.join(sysroot, d[1:], "db.h") - - if db_setup_debug: print("db: looking for db.h in", f) - if os.path.exists(f): - with open(f, 'rb') as file: - f = file.read() - m = re.search(br"#define\WDB_VERSION_MAJOR\W(\d+)", f) - if m: - db_major = int(m.group(1)) - m = re.search(br"#define\WDB_VERSION_MINOR\W(\d+)", f) - db_minor = int(m.group(1)) - db_ver = (db_major, db_minor) - - # Avoid 4.6 prior to 4.6.21 due to a BerkeleyDB bug - if db_ver == (4, 6): - m = re.search(br"#define\WDB_VERSION_PATCH\W(\d+)", f) - db_patch = int(m.group(1)) - if db_patch < 21: - print("db.h:", db_ver, "patch", db_patch, - "being ignored (4.6.x must be >= 4.6.21)") - continue - - if ( (db_ver not in db_ver_inc_map) and - allow_db_ver(db_ver) ): - # save the include directory with the db.h version - # (first occurrence only) - db_ver_inc_map[db_ver] = d - if db_setup_debug: - print("db.h: found", db_ver, "in", d) - else: - # we already found a header for this library version - if db_setup_debug: print("db.h: ignoring", d) - else: - # ignore this header, it didn't contain a version number - if db_setup_debug: - print("db.h: no version number version in", d) - - db_found_vers = list(db_ver_inc_map.keys()) - db_found_vers.sort() - - while db_found_vers: - db_ver = db_found_vers.pop() - db_incdir = db_ver_inc_map[db_ver] - - # check lib directories parallel to the location of the header - db_dirs_to_check = [ - db_incdir.replace("include", 'lib64'), - db_incdir.replace("include", 'lib'), - ] - - if not MACOS: - db_dirs_to_check = list(filter(os.path.isdir, db_dirs_to_check)) - - else: - # Same as other branch, but takes OSX SDK into account - tmp = [] - for dn in db_dirs_to_check: - if is_macosx_sdk_path(dn): - if os.path.isdir(os.path.join(sysroot, dn[1:])): - tmp.append(dn) - else: - if os.path.isdir(dn): - tmp.append(dn) - db_dirs_to_check = tmp - - db_dirs_to_check = tmp - - # Look for a version specific db-X.Y before an ambiguous dbX - # XXX should we -ever- look for a dbX name? Do any - # systems really not name their library by version and - # symlink to more general names? - for dblib in (('db-%d.%d' % db_ver), - ('db%d%d' % db_ver), - ('db%d' % db_ver[0])): - dblib_file = self.compiler.find_library_file( - db_dirs_to_check + self.lib_dirs, dblib ) - if dblib_file: - dblib_dir = [ os.path.abspath(os.path.dirname(dblib_file)) ] - raise db_found - else: - if db_setup_debug: print("db lib: ", dblib, "not found") - - except db_found: - if db_setup_debug: - print("bsddb using BerkeleyDB lib:", db_ver, dblib) - print("bsddb lib dir:", dblib_dir, " inc dir:", db_incdir) - dblibs = [dblib] - # Only add the found library and include directories if they aren't - # already being searched. This avoids an explicit runtime library - # dependency. - if db_incdir in self.inc_dirs: - db_incs = None - else: - db_incs = [db_incdir] - if dblib_dir[0] in self.lib_dirs: - dblib_dir = None - else: - if db_setup_debug: print("db: no appropriate library found") - db_incs = None - dblibs = [] - dblib_dir = None - dbm_setup_debug = False # verbose debug prints from this script? dbm_order = ['gdbm'] + + # libdb, gdbm and ndbm headers and libraries + have_ndbm_h = sysconfig.get_config_var("HAVE_NDBM_H") + have_gdbm_h = sysconfig.get_config_var("HAVE_GDBM_H") + have_gdbm_ndbm_h = sysconfig.get_config_var("HAVE_GDBM_NDBM_H") + have_gdbm_dash_ndbm_h = sysconfig.get_config_var("HAVE_GDBM_DASH_NDBM_H") + have_libndbm = sysconfig.get_config_var("HAVE_LIBNDBM") + have_libgdbm = sysconfig.get_config_var("HAVE_LIBGDBM") + have_libgdbm_compat = sysconfig.get_config_var("HAVE_LIBGDBM_COMPAT") + have_libdb = sysconfig.get_config_var("HAVE_LIBDB") + # The standard Unix dbm module: if not CYGWIN: config_args = [arg.strip("'") @@ -1436,61 +1247,40 @@ class db_found(Exception): pass dbmext = None for cand in dbm_order: if cand == "ndbm": - if find_file("ndbm.h", self.inc_dirs, []) is not None: + if have_ndbm_h: # Some systems have -lndbm, others have -lgdbm_compat, # others don't have either - if self.compiler.find_library_file(self.lib_dirs, - 'ndbm'): + if have_libndbm: ndbm_libs = ['ndbm'] - elif self.compiler.find_library_file(self.lib_dirs, - 'gdbm_compat'): + elif have_libgdbm_compat: ndbm_libs = ['gdbm_compat'] else: ndbm_libs = [] if dbm_setup_debug: print("building dbm using ndbm") - dbmext = Extension('_dbm', ['_dbmmodule.c'], - define_macros=[ - ('HAVE_NDBM_H',None), - ], - libraries=ndbm_libs) + dbmext = Extension( + '_dbm', ['_dbmmodule.c'], + define_macros=[('USE_NDBM', None)], + libraries=ndbm_libs + ) break - elif cand == "gdbm": - if self.compiler.find_library_file(self.lib_dirs, 'gdbm'): - gdbm_libs = ['gdbm'] - if self.compiler.find_library_file(self.lib_dirs, - 'gdbm_compat'): - gdbm_libs.append('gdbm_compat') - if find_file("gdbm/ndbm.h", self.inc_dirs, []) is not None: - if dbm_setup_debug: print("building dbm using gdbm") - dbmext = Extension( - '_dbm', ['_dbmmodule.c'], - define_macros=[ - ('HAVE_GDBM_NDBM_H', None), - ], - libraries = gdbm_libs) - break - if find_file("gdbm-ndbm.h", self.inc_dirs, []) is not None: - if dbm_setup_debug: print("building dbm using gdbm") - dbmext = Extension( - '_dbm', ['_dbmmodule.c'], - define_macros=[ - ('HAVE_GDBM_DASH_NDBM_H', None), - ], - libraries = gdbm_libs) - break + # dbm_open() is provided by libgdbm_compat, which wraps libgdbm + if have_libgdbm_compat and (have_gdbm_ndbm_h or have_gdbm_dash_ndbm_h): + if dbm_setup_debug: print("building dbm using gdbm") + dbmext = Extension( + '_dbm', ['_dbmmodule.c'], + define_macros=[('USE_GDBM_COMPAT', None)], + libraries=['gdbm_compat'] + ) + break elif cand == "bdb": - if dblibs: + if have_libdb: if dbm_setup_debug: print("building dbm using bdb") - dbmext = Extension('_dbm', ['_dbmmodule.c'], - library_dirs=dblib_dir, - runtime_library_dirs=dblib_dir, - include_dirs=db_incs, - define_macros=[ - ('HAVE_BERKDB_H', None), - ('DB_DBM_HSEARCH', None), - ], - libraries=dblibs) + dbmext = Extension( + '_dbm', ['_dbmmodule.c'], + define_macros=[('USE_BERKDB', None)], + libraries=['db'] + ) break if dbmext is not None: self.add(dbmext) @@ -1498,8 +1288,7 @@ class db_found(Exception): pass self.missing.append('_dbm') # Anthony Baxter's gdbm module. GNU dbm(3) will require -lgdbm: - if ('gdbm' in dbm_order and - self.compiler.find_library_file(self.lib_dirs, 'gdbm')): + if 'gdbm' in dbm_order and have_libgdbm: self.add(Extension('_gdbm', ['_gdbmmodule.c'], libraries=['gdbm'])) else: From webhook-mailer at python.org Wed Nov 10 17:02:28 2021 From: webhook-mailer at python.org (tiran) Date: Wed, 10 Nov 2021 22:02:28 -0000 Subject: [Python-checkins] bpo-45723: Add --with-pkg-config to configure (GH-29517) Message-ID: https://github.com/python/cpython/commit/fc9b62281931da8d20f85d5ed44cfc24f068d3f4 commit: fc9b62281931da8d20f85d5ed44cfc24f068d3f4 branch: main author: Christian Heimes committer: tiran date: 2021-11-10T23:02:19+01:00 summary: bpo-45723: Add --with-pkg-config to configure (GH-29517) Co-authored-by: Erlend Egeberg Aasland files: A Misc/NEWS.d/next/Build/2021-11-10-16-13-02.bpo-45723.B5gCB1.rst M Doc/using/configure.rst M configure M configure.ac diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index 75f572c61877f..f00766dfc4f76 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -116,6 +116,17 @@ General Options .. versionadded:: 3.10 +.. cmdoption:: --with-pkg-config=[check|yes|no] + + Whether configure should use :program:`pkg-config` to detect build + dependencies. + + * ``check`` (default): :program:`pkg-config` is optional + * ``yes``: :program:`pkg-config` is mandatory + * ``no``: configure does not use :program:`pkg-config` even when present + + .. versionadded:: 3.11 + Install Options --------------- diff --git a/Misc/NEWS.d/next/Build/2021-11-10-16-13-02.bpo-45723.B5gCB1.rst b/Misc/NEWS.d/next/Build/2021-11-10-16-13-02.bpo-45723.B5gCB1.rst new file mode 100644 index 0000000000000..49636183c2c68 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-10-16-13-02.bpo-45723.B5gCB1.rst @@ -0,0 +1,2 @@ +:program:`configure` has a new option ``--with-pkg-config`` to disable or +require pkg-config. diff --git a/configure b/configure index 2a89703d29475..3c5a5dabb0792 100755 --- a/configure +++ b/configure @@ -661,9 +661,6 @@ DTRACE TCLTK_LIBS TCLTK_INCLUDES LIBFFI_INCLUDEDIR -PKG_CONFIG_LIBDIR -PKG_CONFIG_PATH -PKG_CONFIG TZPATH SHLIBS CFLAGSFORSHARED @@ -756,6 +753,9 @@ LIPO_INTEL64_FLAGS LIPO_32BIT_FLAGS ARCH_RUN_32BIT UNIVERSALSDK +PKG_CONFIG_LIBDIR +PKG_CONFIG_PATH +PKG_CONFIG CONFIG_ARGS SOVERSION VERSION @@ -816,6 +816,7 @@ SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking +with_pkg_config enable_universalsdk with_universal_archs with_framework_name @@ -869,6 +870,9 @@ enable_test_modules ac_precious_vars='build_alias host_alias target_alias +PKG_CONFIG +PKG_CONFIG_PATH +PKG_CONFIG_LIBDIR MACHDEP CC CFLAGS @@ -876,10 +880,7 @@ LDFLAGS LIBS CPPFLAGS CPP -PROFILE_TASK -PKG_CONFIG -PKG_CONFIG_PATH -PKG_CONFIG_LIBDIR' +PROFILE_TASK' # Initialize some variables set by options. @@ -1532,6 +1533,8 @@ Optional Features: Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-pkg-config use pkg-config to detect build options (default is + check) --with-universal-archs=ARCH specify the kind of macOS universal binary that should be created. This option is only valid when @@ -1634,6 +1637,11 @@ Optional Packages: install python.o (default is yes) Some influential environment variables: + PKG_CONFIG path to pkg-config utility + PKG_CONFIG_PATH + directories to add to pkg-config's search path + PKG_CONFIG_LIBDIR + path overriding pkg-config's built-in search path MACHDEP name for machine-dependent library files CC C compiler command CFLAGS C compiler flags @@ -1645,11 +1653,6 @@ Some influential environment variables: CPP C preprocessor PROFILE_TASK Python args for PGO generation task - PKG_CONFIG path to pkg-config utility - PKG_CONFIG_PATH - directories to add to pkg-config's search path - PKG_CONFIG_LIBDIR - path overriding pkg-config's built-in search path Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. @@ -3079,6 +3082,158 @@ define_xopen_source=yes CONFIG_ARGS="$ac_configure_args" + +# Check whether --with-pkg-config was given. +if test "${with_pkg_config+set}" = set; then : + withval=$with_pkg_config; +else + with_pkg_config=check + +fi + +case $with_pkg_config in #( + yes|check) : + + if test -z "$PKG_CONFIG"; then + { PKG_CONFIG=; unset PKG_CONFIG;} + { ac_cv_path_ac_pt_PKG_CONFIG=; unset ac_cv_path_ac_pt_PKG_CONFIG;} + { ac_cv_prog_ac_ct_PKG_CONFIG=; unset ac_cv_prog_ac_ct_PKG_CONFIG;} + fi + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi + ;; #( + no) : + + PKG_CONFIG='' + ac_cv_path_ac_pt_PKG_CONFIG='' + ac_cv_prog_ac_ct_PKG_CONFIG='' + ;; #( + *) : + as_fn_error $? "invalid argument --with-pkg-config=$with_pkg_config" "$LINENO" 5 + ;; +esac +if test "$with_pkg_config" = yes -a -z "$PKG_CONFIG"; then + as_fn_error $? "pkg-config is required" "$LINENO" 5] +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --enable-universalsdk" >&5 $as_echo_n "checking for --enable-universalsdk... " >&6; } # Check whether --enable-universalsdk was given. @@ -10541,127 +10696,6 @@ $as_echo "no" >&6; } fi - - - - - - - -if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. -set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_PKG_CONFIG+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $PKG_CONFIG in - [\\/]* | ?:[\\/]*) - ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -PKG_CONFIG=$ac_cv_path_PKG_CONFIG -if test -n "$PKG_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 -$as_echo "$PKG_CONFIG" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_path_PKG_CONFIG"; then - ac_pt_PKG_CONFIG=$PKG_CONFIG - # Extract the first word of "pkg-config", so it can be a program name with args. -set dummy pkg-config; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $ac_pt_PKG_CONFIG in - [\\/]* | ?:[\\/]*) - ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG -if test -n "$ac_pt_PKG_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 -$as_echo "$ac_pt_PKG_CONFIG" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_pt_PKG_CONFIG" = x; then - PKG_CONFIG="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - PKG_CONFIG=$ac_pt_PKG_CONFIG - fi -else - PKG_CONFIG="$ac_cv_path_PKG_CONFIG" -fi - -fi -if test -n "$PKG_CONFIG"; then - _pkg_min_version=0.9.0 - { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 -$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } - if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - PKG_CONFIG="" - fi -fi - # Check for use of the system expat library { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-system-expat" >&5 $as_echo_n "checking for --with-system-expat... " >&6; } diff --git a/configure.ac b/configure.ac index 4817422178df7..898c2ba632015 100644 --- a/configure.ac +++ b/configure.ac @@ -155,6 +155,36 @@ define_xopen_source=yes AC_SUBST(CONFIG_ARGS) CONFIG_ARGS="$ac_configure_args" +dnl Allow users to disable pkg-config or require pkg-config +AC_ARG_WITH( + [pkg-config], + [AS_HELP_STRING([[--with-pkg-config=[yes|no|check]]], + [use pkg-config to detect build options (default is check)])], + [], + [with_pkg_config=check] +) +AS_CASE([$with_pkg_config], + [yes|check], [ + if test -z "$PKG_CONFIG"; then + dnl invalidate stale config.cache values + AS_UNSET([PKG_CONFIG]) + AS_UNSET([ac_cv_path_ac_pt_PKG_CONFIG]) + AS_UNSET([ac_cv_prog_ac_ct_PKG_CONFIG]) + fi + PKG_PROG_PKG_CONFIG + ], + [no], [ + PKG_CONFIG='' + dnl force AX_CHECK_OPENSSL to ignore pkg-config + ac_cv_path_ac_pt_PKG_CONFIG='' + ac_cv_prog_ac_ct_PKG_CONFIG='' + ], + [AC_MSG_ERROR([invalid argument --with-pkg-config=$with_pkg_config])] +) +if test "$with_pkg_config" = yes -a -z "$PKG_CONFIG"; then + AC_MSG_ERROR([pkg-config is required])] +fi + AC_MSG_CHECKING([for --enable-universalsdk]) AC_ARG_ENABLE(universalsdk, AS_HELP_STRING([--enable-universalsdk@<:@=SDKDIR@:>@], @@ -2978,8 +3008,6 @@ LIBS="$withval $LIBS" ], [AC_MSG_RESULT(no)]) -PKG_PROG_PKG_CONFIG - # Check for use of the system expat library AC_MSG_CHECKING(for --with-system-expat) AC_ARG_WITH(system_expat, From webhook-mailer at python.org Wed Nov 10 21:02:11 2021 From: webhook-mailer at python.org (gvanrossum) Date: Thu, 11 Nov 2021 02:02:11 -0000 Subject: [Python-checkins] bpo-45696: Deep-freeze selected modules (GH-29118) Message-ID: https://github.com/python/cpython/commit/1cbaa505d007e11c4a1f0d2073d72b6c02c7147c commit: 1cbaa505d007e11c4a1f0d2073d72b6c02c7147c branch: main author: Guido van Rossum committer: gvanrossum date: 2021-11-10T18:01:53-08:00 summary: bpo-45696: Deep-freeze selected modules (GH-29118) This gains 10% or more in startup time for `python -c pass` on UNIX-ish systems. The Makefile.pre.in generating code builds on Eric's work for bpo-45020, but the .c file generator is new. Windows version TBD. files: A Misc/NEWS.d/next/Build/2021-11-03-00-19-50.bpo-45696.eKs46f.rst A Python/bootstrap_frozen.c A Python/deepfreeze/README.txt A Tools/scripts/deepfreeze.py M .gitattributes M .gitignore M Doc/library/ctypes.rst M Include/cpython/import.h M Lib/ctypes/test/test_values.py M Makefile.pre.in M Python/frozen.c M Python/import.c M Tools/freeze/test/freeze.py M Tools/scripts/freeze_modules.py M configure M configure.ac diff --git a/.gitattributes b/.gitattributes index cf8d7822e522c..3363ea8e4e744 100644 --- a/.gitattributes +++ b/.gitattributes @@ -46,6 +46,7 @@ Modules/clinic/*.h linguist-generated=true Objects/clinic/*.h linguist-generated=true PC/clinic/*.h linguist-generated=true Python/clinic/*.h linguist-generated=true +Python/deepfreeze/*.c linguist-generated=true Python/frozen_modules/*.h linguist-generated=true Python/frozen_modules/MANIFEST linguist-generated=true Include/internal/pycore_ast.h linguist-generated=true diff --git a/.gitignore b/.gitignore index 98a3d58dcd172..e261d6c997135 100644 --- a/.gitignore +++ b/.gitignore @@ -59,6 +59,7 @@ Lib/distutils/command/*.pdb Lib/lib2to3/*.pickle Lib/test/data/* !Lib/test/data/README +/_bootstrap_python /Makefile /Makefile.pre Mac/Makefile @@ -115,6 +116,7 @@ Tools/unicode/data/ /platform /profile-clean-stamp /profile-run-stamp +/Python/deepfreeze/*.c /pybuilddir.txt /pyconfig.h /python-config diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst index 74611144123b0..b58b961a30de6 100644 --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -1087,7 +1087,9 @@ size, we show only how this table can be read with :mod:`ctypes`:: >>> class struct_frozen(Structure): ... _fields_ = [("name", c_char_p), ... ("code", POINTER(c_ubyte)), - ... ("size", c_int)] + ... ("size", c_int), + ... ("get_code", POINTER(c_ubyte)), # Function pointer + ... ] ... >>> diff --git a/Include/cpython/import.h b/Include/cpython/import.h index bad68f0e0980d..5ec637e7ab3b8 100644 --- a/Include/cpython/import.h +++ b/Include/cpython/import.h @@ -32,6 +32,7 @@ struct _frozen { const char *name; /* ASCII encoded string */ const unsigned char *code; int size; + PyObject *(*get_code)(void); }; /* Embedding apps may change this pointer to point to their favorite diff --git a/Lib/ctypes/test/test_values.py b/Lib/ctypes/test/test_values.py index 5f9fa066c4a41..3e8b13768b421 100644 --- a/Lib/ctypes/test/test_values.py +++ b/Lib/ctypes/test/test_values.py @@ -53,7 +53,9 @@ def test_frozentable(self): class struct_frozen(Structure): _fields_ = [("name", c_char_p), ("code", POINTER(c_ubyte)), - ("size", c_int)] + ("size", c_int), + ("get_code", POINTER(c_ubyte)), # Function ptr + ] FrozenTable = POINTER(struct_frozen) modules = [] diff --git a/Makefile.pre.in b/Makefile.pre.in index 7e959b01906bc..6968ae4f5d865 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -259,6 +259,7 @@ LIBOBJS= @LIBOBJS@ PYTHON= python$(EXE) BUILDPYTHON= python$(BUILDEXE) +BOOTSTRAP= _bootstrap_python PYTHON_FOR_REGEN?=@PYTHON_FOR_REGEN@ UPDATE_FILE=$(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/update_file.py @@ -448,6 +449,30 @@ OBJECT_OBJS= \ Objects/unionobject.o \ Objects/weakrefobject.o +# DEEPFREEZE_OBJS is auto-generated by Tools/scripts/freeze_modules.py. +DEEPFREEZE_OBJS = \ + Python/deepfreeze/importlib._bootstrap.o \ + Python/deepfreeze/importlib._bootstrap_external.o \ + Python/deepfreeze/zipimport.o \ + Python/deepfreeze/abc.o \ + Python/deepfreeze/codecs.o \ + Python/deepfreeze/io.o \ + Python/deepfreeze/_collections_abc.o \ + Python/deepfreeze/_sitebuiltins.o \ + Python/deepfreeze/genericpath.o \ + Python/deepfreeze/ntpath.o \ + Python/deepfreeze/posixpath.o \ + Python/deepfreeze/os.o \ + Python/deepfreeze/site.o \ + Python/deepfreeze/stat.o \ + Python/deepfreeze/__hello__.o \ + Python/deepfreeze/__phello__.o \ + Python/deepfreeze/__phello__.ham.o \ + Python/deepfreeze/__phello__.ham.eggs.o \ + Python/deepfreeze/__phello__.spam.o \ + Python/deepfreeze/frozen_only.o +# End DEEPFREEZE_OBJS + ########################################################################## # objects that get linked into the Python library LIBRARY_OBJS_OMIT_FROZEN= \ @@ -460,6 +485,7 @@ LIBRARY_OBJS_OMIT_FROZEN= \ LIBRARY_OBJS= \ $(LIBRARY_OBJS_OMIT_FROZEN) \ + $(DEEPFREEZE_OBJS) \ Python/frozen.o ########################################################################## @@ -602,9 +628,9 @@ platform: $(BUILDPYTHON) pybuilddir.txt # problems by creating a dummy pybuilddir.txt just to allow interpreter # initialization to succeed. It will be overwritten by generate-posix-vars # or removed in case of failure. -pybuilddir.txt: $(BUILDPYTHON) +pybuilddir.txt: $(BOOTSTRAP) @echo "none" > ./pybuilddir.txt - $(RUNSHARED) $(PYTHON_FOR_BUILD) -S -m sysconfig --generate-posix-vars ;\ + ./$(BOOTSTRAP) -S -m sysconfig --generate-posix-vars ;\ if test $$? -ne 0 ; then \ echo "generate-posix-vars failed" ; \ rm -f ./pybuilddir.txt ; \ @@ -738,6 +764,158 @@ regen-test-frozenmain: $(BUILDPYTHON) Programs/_testembed: Programs/_testembed.o $(LIBRARY_DEPS) $(LINKCC) $(PY_CORE_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/_testembed.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) +############################################################################ +# "Bootstrap Python" used to run deepfreeze.py + +BOOTSTRAP_HEADERS = \ + Python/frozen_modules/importlib._bootstrap.h \ + Python/frozen_modules/importlib._bootstrap_external.h \ + Python/frozen_modules/zipimport.h + +Python/bootstrap_frozen.o: Python/bootstrap_frozen.c Include/cpython/import.h $(BOOTSTRAP_HEADERS) + +$(BOOTSTRAP): $(LIBRARY_OBJS_OMIT_FROZEN) \ + Python/bootstrap_frozen.o Programs/python.o + $(LINKCC) $(PY_CORE_LDFLAGS) -o $@ $(LIBRARY_OBJS_OMIT_FROZEN) \ + Python/bootstrap_frozen.o \ + Programs/python.o \ + $(LIBS) $(MODLIBS) $(SYSLIBS) + +############################################################################ +# Deepfreeze targets + +.PHONY: regen-deepfreeze +regen-deepfreeze: $(DEEPFREEZE_OBJS) + +DEEPFREEZE_DEPS = \ + $(BOOTSTRAP) \ + pybuilddir.txt \ + $(srcdir)/Tools/scripts/deepfreeze.py + +# BEGIN: deepfreeze modules + +Python/deepfreeze/importlib._bootstrap.c: $(srcdir)/Lib/importlib/_bootstrap.py $(DEEPFREEZE_DEPS) + @echo "Deepfreezing Python/deepfreeze/importlib._bootstrap.c from Lib/importlib/_bootstrap.py" + @./$(BOOTSTRAP) \ + $(srcdir)/Tools/scripts/deepfreeze.py \ + $(srcdir)/Lib/importlib/_bootstrap.py -m importlib._bootstrap -o Python/deepfreeze/importlib._bootstrap.c + +Python/deepfreeze/importlib._bootstrap_external.c: $(srcdir)/Lib/importlib/_bootstrap_external.py $(DEEPFREEZE_DEPS) + @echo "Deepfreezing Python/deepfreeze/importlib._bootstrap_external.c from Lib/importlib/_bootstrap_external.py" + @./$(BOOTSTRAP) \ + $(srcdir)/Tools/scripts/deepfreeze.py \ + $(srcdir)/Lib/importlib/_bootstrap_external.py -m importlib._bootstrap_external -o Python/deepfreeze/importlib._bootstrap_external.c + +Python/deepfreeze/zipimport.c: $(srcdir)/Lib/zipimport.py $(DEEPFREEZE_DEPS) + @echo "Deepfreezing Python/deepfreeze/zipimport.c from Lib/zipimport.py" + @./$(BOOTSTRAP) \ + $(srcdir)/Tools/scripts/deepfreeze.py \ + $(srcdir)/Lib/zipimport.py -m zipimport -o Python/deepfreeze/zipimport.c + +Python/deepfreeze/abc.c: $(srcdir)/Lib/abc.py $(DEEPFREEZE_DEPS) + @echo "Deepfreezing Python/deepfreeze/abc.c from Lib/abc.py" + @./$(BOOTSTRAP) \ + $(srcdir)/Tools/scripts/deepfreeze.py \ + $(srcdir)/Lib/abc.py -m abc -o Python/deepfreeze/abc.c + +Python/deepfreeze/codecs.c: $(srcdir)/Lib/codecs.py $(DEEPFREEZE_DEPS) + @echo "Deepfreezing Python/deepfreeze/codecs.c from Lib/codecs.py" + @./$(BOOTSTRAP) \ + $(srcdir)/Tools/scripts/deepfreeze.py \ + $(srcdir)/Lib/codecs.py -m codecs -o Python/deepfreeze/codecs.c + +Python/deepfreeze/io.c: $(srcdir)/Lib/io.py $(DEEPFREEZE_DEPS) + @echo "Deepfreezing Python/deepfreeze/io.c from Lib/io.py" + @./$(BOOTSTRAP) \ + $(srcdir)/Tools/scripts/deepfreeze.py \ + $(srcdir)/Lib/io.py -m io -o Python/deepfreeze/io.c + +Python/deepfreeze/_collections_abc.c: $(srcdir)/Lib/_collections_abc.py $(DEEPFREEZE_DEPS) + @echo "Deepfreezing Python/deepfreeze/_collections_abc.c from Lib/_collections_abc.py" + @./$(BOOTSTRAP) \ + $(srcdir)/Tools/scripts/deepfreeze.py \ + $(srcdir)/Lib/_collections_abc.py -m _collections_abc -o Python/deepfreeze/_collections_abc.c + +Python/deepfreeze/_sitebuiltins.c: $(srcdir)/Lib/_sitebuiltins.py $(DEEPFREEZE_DEPS) + @echo "Deepfreezing Python/deepfreeze/_sitebuiltins.c from Lib/_sitebuiltins.py" + @./$(BOOTSTRAP) \ + $(srcdir)/Tools/scripts/deepfreeze.py \ + $(srcdir)/Lib/_sitebuiltins.py -m _sitebuiltins -o Python/deepfreeze/_sitebuiltins.c + +Python/deepfreeze/genericpath.c: $(srcdir)/Lib/genericpath.py $(DEEPFREEZE_DEPS) + @echo "Deepfreezing Python/deepfreeze/genericpath.c from Lib/genericpath.py" + @./$(BOOTSTRAP) \ + $(srcdir)/Tools/scripts/deepfreeze.py \ + $(srcdir)/Lib/genericpath.py -m genericpath -o Python/deepfreeze/genericpath.c + +Python/deepfreeze/ntpath.c: $(srcdir)/Lib/ntpath.py $(DEEPFREEZE_DEPS) + @echo "Deepfreezing Python/deepfreeze/ntpath.c from Lib/ntpath.py" + @./$(BOOTSTRAP) \ + $(srcdir)/Tools/scripts/deepfreeze.py \ + $(srcdir)/Lib/ntpath.py -m ntpath -o Python/deepfreeze/ntpath.c + +Python/deepfreeze/posixpath.c: $(srcdir)/Lib/posixpath.py $(DEEPFREEZE_DEPS) + @echo "Deepfreezing Python/deepfreeze/posixpath.c from Lib/posixpath.py" + @./$(BOOTSTRAP) \ + $(srcdir)/Tools/scripts/deepfreeze.py \ + $(srcdir)/Lib/posixpath.py -m posixpath -o Python/deepfreeze/posixpath.c + +Python/deepfreeze/os.c: $(srcdir)/Lib/os.py $(DEEPFREEZE_DEPS) + @echo "Deepfreezing Python/deepfreeze/os.c from Lib/os.py" + @./$(BOOTSTRAP) \ + $(srcdir)/Tools/scripts/deepfreeze.py \ + $(srcdir)/Lib/os.py -m os -o Python/deepfreeze/os.c + +Python/deepfreeze/site.c: $(srcdir)/Lib/site.py $(DEEPFREEZE_DEPS) + @echo "Deepfreezing Python/deepfreeze/site.c from Lib/site.py" + @./$(BOOTSTRAP) \ + $(srcdir)/Tools/scripts/deepfreeze.py \ + $(srcdir)/Lib/site.py -m site -o Python/deepfreeze/site.c + +Python/deepfreeze/stat.c: $(srcdir)/Lib/stat.py $(DEEPFREEZE_DEPS) + @echo "Deepfreezing Python/deepfreeze/stat.c from Lib/stat.py" + @./$(BOOTSTRAP) \ + $(srcdir)/Tools/scripts/deepfreeze.py \ + $(srcdir)/Lib/stat.py -m stat -o Python/deepfreeze/stat.c + +Python/deepfreeze/__hello__.c: $(srcdir)/Lib/__hello__.py $(DEEPFREEZE_DEPS) + @echo "Deepfreezing Python/deepfreeze/__hello__.c from Lib/__hello__.py" + @./$(BOOTSTRAP) \ + $(srcdir)/Tools/scripts/deepfreeze.py \ + $(srcdir)/Lib/__hello__.py -m __hello__ -o Python/deepfreeze/__hello__.c + +Python/deepfreeze/__phello__.c: $(srcdir)/Lib/__phello__/__init__.py $(DEEPFREEZE_DEPS) + @echo "Deepfreezing Python/deepfreeze/__phello__.c from Lib/__phello__/__init__.py" + @./$(BOOTSTRAP) \ + $(srcdir)/Tools/scripts/deepfreeze.py \ + $(srcdir)/Lib/__phello__/__init__.py -m __phello__ -o Python/deepfreeze/__phello__.c + +Python/deepfreeze/__phello__.ham.c: $(srcdir)/Lib/__phello__/ham/__init__.py $(DEEPFREEZE_DEPS) + @echo "Deepfreezing Python/deepfreeze/__phello__.ham.c from Lib/__phello__/ham/__init__.py" + @./$(BOOTSTRAP) \ + $(srcdir)/Tools/scripts/deepfreeze.py \ + $(srcdir)/Lib/__phello__/ham/__init__.py -m __phello__.ham -o Python/deepfreeze/__phello__.ham.c + +Python/deepfreeze/__phello__.ham.eggs.c: $(srcdir)/Lib/__phello__/ham/eggs.py $(DEEPFREEZE_DEPS) + @echo "Deepfreezing Python/deepfreeze/__phello__.ham.eggs.c from Lib/__phello__/ham/eggs.py" + @./$(BOOTSTRAP) \ + $(srcdir)/Tools/scripts/deepfreeze.py \ + $(srcdir)/Lib/__phello__/ham/eggs.py -m __phello__.ham.eggs -o Python/deepfreeze/__phello__.ham.eggs.c + +Python/deepfreeze/__phello__.spam.c: $(srcdir)/Lib/__phello__/spam.py $(DEEPFREEZE_DEPS) + @echo "Deepfreezing Python/deepfreeze/__phello__.spam.c from Lib/__phello__/spam.py" + @./$(BOOTSTRAP) \ + $(srcdir)/Tools/scripts/deepfreeze.py \ + $(srcdir)/Lib/__phello__/spam.py -m __phello__.spam -o Python/deepfreeze/__phello__.spam.c + +Python/deepfreeze/frozen_only.c: $(srcdir)/Tools/freeze/flag.py $(DEEPFREEZE_DEPS) + @echo "Deepfreezing Python/deepfreeze/frozen_only.c from Tools/freeze/flag.py" + @./$(BOOTSTRAP) \ + $(srcdir)/Tools/scripts/deepfreeze.py \ + $(srcdir)/Tools/freeze/flag.py -m frozen_only -o Python/deepfreeze/frozen_only.c + +# END: deepfreeze modules + ############################################################################ # frozen modules (including importlib) @@ -2017,7 +2195,8 @@ clean-retain-profile: pycremoval find build -name '*.py[co]' -exec rm -f {} ';' || true -rm -f pybuilddir.txt -rm -f Lib/lib2to3/*Grammar*.pickle - -rm -f Programs/_testembed Programs/_freeze_module + -rm -f Programs/_testembed Programs/_freeze_module $(BOOTSTRAP) + -rm -f Python/deepfreeze/*.[co] -find build -type f -a ! -name '*.gc??' -exec rm -f {} ';' -rm -f Include/pydtrace_probes.h -rm -f profile-gen-stamp diff --git a/Misc/NEWS.d/next/Build/2021-11-03-00-19-50.bpo-45696.eKs46f.rst b/Misc/NEWS.d/next/Build/2021-11-03-00-19-50.bpo-45696.eKs46f.rst new file mode 100644 index 0000000000000..6f6996d9fad2f --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-03-00-19-50.bpo-45696.eKs46f.rst @@ -0,0 +1 @@ +Skip the marshal step for frozen modules by generating C code that produces a set of ready-to-use code objects. This speeds up startup time by another 10% or more. \ No newline at end of file diff --git a/Python/bootstrap_frozen.c b/Python/bootstrap_frozen.c new file mode 100644 index 0000000000000..68ba147a72710 --- /dev/null +++ b/Python/bootstrap_frozen.c @@ -0,0 +1,45 @@ + +/* Frozen modules bootstrap */ + +/* This file is linked with "bootstrap Python" + which is used (only) to run Tools/scripts/deepfreeze.py. */ + +#include "Python.h" +#include "pycore_import.h" + +/* Includes for frozen modules: */ +#include "frozen_modules/importlib._bootstrap.h" +#include "frozen_modules/importlib._bootstrap_external.h" +#include "frozen_modules/zipimport.h" +/* End includes */ + +/* Note that a negative size indicates a package. */ + +static const struct _frozen bootstrap_modules[] = { + {"_frozen_importlib", _Py_M__importlib__bootstrap, (int)sizeof(_Py_M__importlib__bootstrap)}, + {"_frozen_importlib_external", _Py_M__importlib__bootstrap_external, (int)sizeof(_Py_M__importlib__bootstrap_external)}, + {"zipimport", _Py_M__zipimport, (int)sizeof(_Py_M__zipimport)}, + {0, 0, 0} /* bootstrap sentinel */ +}; +static const struct _frozen stdlib_modules[] = { + {0, 0, 0} /* stdlib sentinel */ +}; +static const struct _frozen test_modules[] = { + {0, 0, 0} /* test sentinel */ +}; +const struct _frozen *_PyImport_FrozenBootstrap = bootstrap_modules; +const struct _frozen *_PyImport_FrozenStdlib = stdlib_modules; +const struct _frozen *_PyImport_FrozenTest = test_modules; + +static const struct _module_alias aliases[] = { + {"_frozen_importlib", "importlib._bootstrap"}, + {"_frozen_importlib_external", "importlib._bootstrap_external"}, + {0, 0} /* aliases sentinel */ +}; +const struct _module_alias *_PyImport_FrozenAliases = aliases; + + +/* Embedding apps may change this pointer to point to their favorite + collection of frozen modules: */ + +const struct _frozen *PyImport_FrozenModules = NULL; diff --git a/Python/deepfreeze/README.txt b/Python/deepfreeze/README.txt new file mode 100644 index 0000000000000..da55d4e7c7469 --- /dev/null +++ b/Python/deepfreeze/README.txt @@ -0,0 +1,6 @@ +This directory contains the generated .c files for all the deep-frozen +modules. Python/frozen.c depends on these files. + +None of these files are committed into the repo. + +See Tools/scripts/freeze_modules.py for more info. diff --git a/Python/frozen.c b/Python/frozen.c index 15baa97b9d055..1565c9a3d73f7 100644 --- a/Python/frozen.c +++ b/Python/frozen.c @@ -61,50 +61,80 @@ #include "frozen_modules/frozen_only.h" /* End includes */ +#ifdef MS_WINDOWS +/* Deepfreeze isn't supported on Windows yet. */ +#define GET_CODE(name) NULL +#else +#define GET_CODE(name) _Py_get_##name##_toplevel +#endif + +/* Start extern declarations */ +extern PyObject *_Py_get_importlib__bootstrap_toplevel(void); +extern PyObject *_Py_get_importlib__bootstrap_external_toplevel(void); +extern PyObject *_Py_get_zipimport_toplevel(void); +extern PyObject *_Py_get_abc_toplevel(void); +extern PyObject *_Py_get_codecs_toplevel(void); +extern PyObject *_Py_get_io_toplevel(void); +extern PyObject *_Py_get__collections_abc_toplevel(void); +extern PyObject *_Py_get__sitebuiltins_toplevel(void); +extern PyObject *_Py_get_genericpath_toplevel(void); +extern PyObject *_Py_get_ntpath_toplevel(void); +extern PyObject *_Py_get_posixpath_toplevel(void); +extern PyObject *_Py_get_posixpath_toplevel(void); +extern PyObject *_Py_get_os_toplevel(void); +extern PyObject *_Py_get_site_toplevel(void); +extern PyObject *_Py_get_stat_toplevel(void); +extern PyObject *_Py_get___hello___toplevel(void); +extern PyObject *_Py_get___hello___toplevel(void); +extern PyObject *_Py_get___hello___toplevel(void); +extern PyObject *_Py_get___hello___toplevel(void); +extern PyObject *_Py_get___phello___toplevel(void); +extern PyObject *_Py_get___phello___toplevel(void); +extern PyObject *_Py_get___phello___ham_toplevel(void); +extern PyObject *_Py_get___phello___ham_toplevel(void); +extern PyObject *_Py_get___phello___ham_eggs_toplevel(void); +extern PyObject *_Py_get___phello___spam_toplevel(void); +extern PyObject *_Py_get_frozen_only_toplevel(void); +/* End extern declarations */ + /* Note that a negative size indicates a package. */ static const struct _frozen bootstrap_modules[] = { - {"_frozen_importlib", _Py_M__importlib__bootstrap, - (int)sizeof(_Py_M__importlib__bootstrap)}, - {"_frozen_importlib_external", _Py_M__importlib__bootstrap_external, - (int)sizeof(_Py_M__importlib__bootstrap_external)}, - {"zipimport", _Py_M__zipimport, (int)sizeof(_Py_M__zipimport)}, + {"_frozen_importlib", _Py_M__importlib__bootstrap, (int)sizeof(_Py_M__importlib__bootstrap), GET_CODE(importlib__bootstrap)}, + {"_frozen_importlib_external", _Py_M__importlib__bootstrap_external, (int)sizeof(_Py_M__importlib__bootstrap_external), GET_CODE(importlib__bootstrap_external)}, + {"zipimport", _Py_M__zipimport, (int)sizeof(_Py_M__zipimport), GET_CODE(zipimport)}, {0, 0, 0} /* bootstrap sentinel */ }; static const struct _frozen stdlib_modules[] = { /* stdlib - startup, without site (python -S) */ - {"abc", _Py_M__abc, (int)sizeof(_Py_M__abc)}, - {"codecs", _Py_M__codecs, (int)sizeof(_Py_M__codecs)}, - {"io", _Py_M__io, (int)sizeof(_Py_M__io)}, + {"abc", _Py_M__abc, (int)sizeof(_Py_M__abc), GET_CODE(abc)}, + {"codecs", _Py_M__codecs, (int)sizeof(_Py_M__codecs), GET_CODE(codecs)}, + {"io", _Py_M__io, (int)sizeof(_Py_M__io), GET_CODE(io)}, /* stdlib - startup, with site */ - {"_collections_abc", _Py_M___collections_abc, - (int)sizeof(_Py_M___collections_abc)}, - {"_sitebuiltins", _Py_M___sitebuiltins, (int)sizeof(_Py_M___sitebuiltins)}, - {"genericpath", _Py_M__genericpath, (int)sizeof(_Py_M__genericpath)}, - {"ntpath", _Py_M__ntpath, (int)sizeof(_Py_M__ntpath)}, - {"posixpath", _Py_M__posixpath, (int)sizeof(_Py_M__posixpath)}, - {"os.path", _Py_M__posixpath, (int)sizeof(_Py_M__posixpath)}, - {"os", _Py_M__os, (int)sizeof(_Py_M__os)}, - {"site", _Py_M__site, (int)sizeof(_Py_M__site)}, - {"stat", _Py_M__stat, (int)sizeof(_Py_M__stat)}, + {"_collections_abc", _Py_M___collections_abc, (int)sizeof(_Py_M___collections_abc), GET_CODE(_collections_abc)}, + {"_sitebuiltins", _Py_M___sitebuiltins, (int)sizeof(_Py_M___sitebuiltins), GET_CODE(_sitebuiltins)}, + {"genericpath", _Py_M__genericpath, (int)sizeof(_Py_M__genericpath), GET_CODE(genericpath)}, + {"ntpath", _Py_M__ntpath, (int)sizeof(_Py_M__ntpath), GET_CODE(ntpath)}, + {"posixpath", _Py_M__posixpath, (int)sizeof(_Py_M__posixpath), GET_CODE(posixpath)}, + {"os.path", _Py_M__posixpath, (int)sizeof(_Py_M__posixpath), GET_CODE(posixpath)}, + {"os", _Py_M__os, (int)sizeof(_Py_M__os), GET_CODE(os)}, + {"site", _Py_M__site, (int)sizeof(_Py_M__site), GET_CODE(site)}, + {"stat", _Py_M__stat, (int)sizeof(_Py_M__stat), GET_CODE(stat)}, {0, 0, 0} /* stdlib sentinel */ }; static const struct _frozen test_modules[] = { - {"__hello__", _Py_M____hello__, (int)sizeof(_Py_M____hello__)}, - {"__hello_alias__", _Py_M____hello__, (int)sizeof(_Py_M____hello__)}, - {"__phello_alias__", _Py_M____hello__, -(int)sizeof(_Py_M____hello__)}, - {"__phello_alias__.spam", _Py_M____hello__, (int)sizeof(_Py_M____hello__)}, - {"__phello__", _Py_M____phello__, -(int)sizeof(_Py_M____phello__)}, - {"__phello__.__init__", _Py_M____phello__, (int)sizeof(_Py_M____phello__)}, - {"__phello__.ham", _Py_M____phello___ham, -(int)sizeof(_Py_M____phello___ham)}, - {"__phello__.ham.__init__", _Py_M____phello___ham, - (int)sizeof(_Py_M____phello___ham)}, - {"__phello__.ham.eggs", _Py_M____phello___ham_eggs, - (int)sizeof(_Py_M____phello___ham_eggs)}, - {"__phello__.spam", _Py_M____phello___spam, - (int)sizeof(_Py_M____phello___spam)}, - {"__hello_only__", _Py_M__frozen_only, (int)sizeof(_Py_M__frozen_only)}, + {"__hello__", _Py_M____hello__, (int)sizeof(_Py_M____hello__), GET_CODE(__hello__)}, + {"__hello_alias__", _Py_M____hello__, (int)sizeof(_Py_M____hello__), GET_CODE(__hello__)}, + {"__phello_alias__", _Py_M____hello__, -(int)sizeof(_Py_M____hello__), GET_CODE(__hello__)}, + {"__phello_alias__.spam", _Py_M____hello__, (int)sizeof(_Py_M____hello__), GET_CODE(__hello__)}, + {"__phello__", _Py_M____phello__, -(int)sizeof(_Py_M____phello__), GET_CODE(__phello__)}, + {"__phello__.__init__", _Py_M____phello__, (int)sizeof(_Py_M____phello__), GET_CODE(__phello__)}, + {"__phello__.ham", _Py_M____phello___ham, -(int)sizeof(_Py_M____phello___ham), GET_CODE(__phello___ham)}, + {"__phello__.ham.__init__", _Py_M____phello___ham, (int)sizeof(_Py_M____phello___ham), GET_CODE(__phello___ham)}, + {"__phello__.ham.eggs", _Py_M____phello___ham_eggs, (int)sizeof(_Py_M____phello___ham_eggs), GET_CODE(__phello___ham_eggs)}, + {"__phello__.spam", _Py_M____phello___spam, (int)sizeof(_Py_M____phello___spam), GET_CODE(__phello___spam)}, + {"__hello_only__", _Py_M__frozen_only, (int)sizeof(_Py_M__frozen_only), GET_CODE(frozen_only)}, {0, 0, 0} /* test sentinel */ }; const struct _frozen *_PyImport_FrozenBootstrap = bootstrap_modules; diff --git a/Python/import.c b/Python/import.c index cdcb903c88207..225fbf43a3054 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1262,6 +1262,7 @@ look_up_frozen(const char *name) struct frozen_info { PyObject *nameobj; const char *data; + PyObject *(*get_code)(void); Py_ssize_t size; bool is_package; bool is_alias; @@ -1295,6 +1296,7 @@ find_frozen(PyObject *nameobj, struct frozen_info *info) if (info != NULL) { info->nameobj = nameobj; // borrowed info->data = (const char *)p->code; + info->get_code = p->get_code; info->size = p->size < 0 ? -(p->size) : p->size; info->is_package = p->size < 0 ? true : false; info->origname = name; @@ -1316,6 +1318,11 @@ find_frozen(PyObject *nameobj, struct frozen_info *info) static PyObject * unmarshal_frozen_code(struct frozen_info *info) { + if (info->get_code) { + PyObject *code = info->get_code(); + assert(code != NULL); + return code; + } PyObject *co = PyMarshal_ReadObjectFromString(info->data, info->size); if (co == NULL) { /* Does not contain executable code. */ diff --git a/Tools/freeze/test/freeze.py b/Tools/freeze/test/freeze.py index 18a5d27cebf2e..387f1ff70b234 100644 --- a/Tools/freeze/test/freeze.py +++ b/Tools/freeze/test/freeze.py @@ -22,13 +22,23 @@ class UnsupportedError(Exception): def _run_quiet(cmd, cwd=None): #print(f'# {" ".join(shlex.quote(a) for a in cmd)}') - return subprocess.run( - cmd, - cwd=cwd, - capture_output=True, - text=True, - check=True, - ) + try: + return subprocess.run( + cmd, + cwd=cwd, + capture_output=True, + text=True, + check=True, + ) + except subprocess.CalledProcessError as err: + # Don't be quiet if things fail + print(f"{err.__class__.__name__}: {err}") + print("--- STDOUT ---") + print(err.stdout) + print("--- STDERR ---") + print(err.stderr) + print("---- END ----") + raise def _run_stdout(cmd, cwd=None): diff --git a/Tools/scripts/deepfreeze.py b/Tools/scripts/deepfreeze.py new file mode 100644 index 0000000000000..074127f949298 --- /dev/null +++ b/Tools/scripts/deepfreeze.py @@ -0,0 +1,418 @@ +import argparse +import builtins +import collections +import contextlib +import os +import sys +import time +import types +import typing + +verbose = False + + +def make_string_literal(b: bytes) -> str: + res = ['"'] + if b.isascii() and b.decode("ascii").isprintable(): + res.append(b.decode("ascii").replace("\\", "\\\\").replace("\"", "\\\"")) + else: + for i in b: + res.append(f"\\x{i:02x}") + res.append('"') + return "".join(res) + + +CO_FAST_LOCAL = 0x20 +CO_FAST_CELL = 0x40 +CO_FAST_FREE = 0x80 + + +def get_localsplus(code: types.CodeType): + a = collections.defaultdict(int) + for name in code.co_varnames: + a[name] |= CO_FAST_LOCAL + for name in code.co_cellvars: + a[name] |= CO_FAST_CELL + for name in code.co_freevars: + a[name] |= CO_FAST_FREE + return tuple(a.keys()), bytes(a.values()) + + +def get_localsplus_counts(code: types.CodeType, + names: tuple[str, ...], + kinds: bytes) -> tuple[int, int, int, int]: + nlocals = 0 + nplaincellvars = 0 + ncellvars = 0 + nfreevars = 0 + for name, kind in zip(names, kinds, strict=True): + if kind & CO_FAST_LOCAL: + nlocals += 1 + if kind & CO_FAST_CELL: + ncellvars += 1 + elif kind & CO_FAST_CELL: + ncellvars += 1 + nplaincellvars += 1 + elif kind & CO_FAST_FREE: + nfreevars += 1 + assert nlocals == len(code.co_varnames) == code.co_nlocals + assert ncellvars == len(code.co_cellvars) + assert nfreevars == len(code.co_freevars) + assert len(names) == nlocals + nplaincellvars + nfreevars + return nlocals, nplaincellvars, ncellvars, nfreevars + + +PyUnicode_1BYTE_KIND = 1 +PyUnicode_2BYTE_KIND = 2 +PyUnicode_4BYTE_KIND = 4 + + +def analyze_character_width(s: str) -> tuple[int, bool]: + maxchar = ' ' + for c in s: + maxchar = max(maxchar, c) + ascii = False + if maxchar <= '\xFF': + kind = PyUnicode_1BYTE_KIND + ascii = maxchar <= '\x7F' + elif maxchar <= '\uFFFF': + kind = PyUnicode_2BYTE_KIND + else: + kind = PyUnicode_4BYTE_KIND + return kind, ascii + + +class Printer: + + def __init__(self, file: typing.TextIO): + self.level = 0 + self.file = file + self.cache: dict[tuple[type, object], str] = {} + self.hits, self.misses = 0, 0 + self.patchups: list[str] = [] + self.write('#include "Python.h"') + self.write('#include "internal/pycore_gc.h"') + self.write('#include "internal/pycore_code.h"') + self.write("") + + @contextlib.contextmanager + def indent(self) -> None: + save_level = self.level + try: + self.level += 1 + yield + finally: + self.level = save_level + + def write(self, arg: str) -> None: + self.file.writelines((" "*self.level, arg, "\n")) + + @contextlib.contextmanager + def block(self, prefix: str, suffix: str = "") -> None: + self.write(prefix + " {") + with self.indent(): + yield + self.write("}" + suffix) + + def object_head(self, typename: str) -> None: + with self.block(".ob_base =", ","): + self.write(f".ob_refcnt = 999999999,") + self.write(f".ob_type = &{typename},") + + def object_var_head(self, typename: str, size: int) -> None: + with self.block(".ob_base =", ","): + self.object_head(typename) + self.write(f".ob_size = {size},") + + def field(self, obj: object, name: str) -> None: + self.write(f".{name} = {getattr(obj, name)},") + + def generate_bytes(self, name: str, b: bytes) -> str: + self.write("static") + with self.indent(): + with self.block("struct"): + self.write("PyObject_VAR_HEAD") + self.write("Py_hash_t ob_shash;") + self.write(f"char ob_sval[{len(b) + 1}];") + with self.block(f"{name} =", ";"): + self.object_var_head("PyBytes_Type", len(b)) + self.write(".ob_shash = -1,") + self.write(f".ob_sval = {make_string_literal(b)},") + return f"& {name}.ob_base.ob_base" + + def generate_unicode(self, name: str, s: str) -> str: + kind, ascii = analyze_character_width(s) + if kind == PyUnicode_1BYTE_KIND: + datatype = "uint8_t" + elif kind == PyUnicode_2BYTE_KIND: + datatype = "uint16_t" + else: + datatype = "uint32_t" + self.write("static") + with self.indent(): + with self.block("struct"): + if ascii: + self.write("PyASCIIObject _ascii;") + else: + self.write("PyCompactUnicodeObject _compact;") + self.write(f"{datatype} _data[{len(s)+1}];") + with self.block(f"{name} =", ";"): + if ascii: + with self.block("._ascii =", ","): + self.object_head("PyUnicode_Type") + self.write(f".length = {len(s)},") + self.write(".hash = -1,") + with self.block(".state =", ","): + self.write(".kind = 1,") + self.write(".compact = 1,") + self.write(".ascii = 1,") + self.write(".ready = 1,") + self.write(f"._data = {make_string_literal(s.encode('ascii'))},") + return f"& {name}._ascii.ob_base" + else: + with self.block("._compact =", ","): + with self.block("._base =", ","): + self.object_head("PyUnicode_Type") + self.write(f".length = {len(s)},") + self.write(".hash = -1,") + with self.block(".state =", ","): + self.write(f".kind = {kind},") + self.write(".compact = 1,") + self.write(".ascii = 0,") + self.write(".ready = 1,") + with self.block(f"._data =", ","): + for i in range(0, len(s), 16): + data = s[i:i+16] + self.write(", ".join(map(str, map(ord, data))) + ",") + if kind == PyUnicode_2BYTE_KIND: + self.patchups.append("if (sizeof(wchar_t) == 2) {") + self.patchups.append(f" {name}._compact._base.wstr = (wchar_t *) {name}._data;") + self.patchups.append(f" {name}._compact.wstr_length = {len(s)};") + self.patchups.append("}") + if kind == PyUnicode_4BYTE_KIND: + self.patchups.append("if (sizeof(wchar_t) == 4) {") + self.patchups.append(f" {name}._compact._base.wstr = (wchar_t *) {name}._data;") + self.patchups.append(f" {name}._compact.wstr_length = {len(s)};") + self.patchups.append("}") + return f"& {name}._compact._base.ob_base" + + + def generate_code(self, name: str, code: types.CodeType) -> str: + # The ordering here matches PyCode_NewWithPosOnlyArgs() + # (but see below). + co_code = self.generate(name + "_code", code.co_code) + co_consts = self.generate(name + "_consts", code.co_consts) + co_names = self.generate(name + "_names", code.co_names) + co_varnames = self.generate(name + "_varnames", code.co_varnames) + co_freevars = self.generate(name + "_freevars", code.co_freevars) + co_cellvars = self.generate(name + "_cellvars", code.co_cellvars) + co_filename = self.generate(name + "_filename", code.co_filename) + co_name = self.generate(name + "_name", code.co_name) + co_qualname = self.generate(name + "_qualname", code.co_qualname) + co_linetable = self.generate(name + "_linetable", code.co_linetable) + co_endlinetable = self.generate(name + "_endlinetable", code.co_endlinetable) + co_columntable = self.generate(name + "_columntable", code.co_columntable) + co_exceptiontable = self.generate(name + "_exceptiontable", code.co_exceptiontable) + # These fields are not directly accessible + localsplusnames, localspluskinds = get_localsplus(code) + co_localsplusnames = self.generate(name + "_localsplusnames", localsplusnames) + co_localspluskinds = self.generate(name + "_localspluskinds", localspluskinds) + # Derived values + nlocals, nplaincellvars, ncellvars, nfreevars = \ + get_localsplus_counts(code, localsplusnames, localspluskinds) + with self.block(f"static struct PyCodeObject {name} =", ";"): + self.object_head("PyCode_Type") + # But the ordering here must match that in cpython/code.h + # (which is a pain because we tend to reorder those for perf) + # otherwise MSVC doesn't like it. + self.write(f".co_consts = {co_consts},") + self.write(f".co_names = {co_names},") + self.write(f".co_firstinstr = (_Py_CODEUNIT *) {co_code.removesuffix('.ob_base.ob_base')}.ob_sval,") + self.write(f".co_exceptiontable = {co_exceptiontable},") + self.field(code, "co_flags") + self.write(".co_warmup = QUICKENING_INITIAL_WARMUP_VALUE,") + self.field(code, "co_argcount") + self.field(code, "co_posonlyargcount") + self.field(code, "co_kwonlyargcount") + self.field(code, "co_stacksize") + self.field(code, "co_firstlineno") + self.write(f".co_code = {co_code},") + self.write(f".co_localsplusnames = {co_localsplusnames},") + self.write(f".co_localspluskinds = {co_localspluskinds},") + self.write(f".co_filename = {co_filename},") + self.write(f".co_name = {co_name},") + self.write(f".co_qualname = {co_qualname},") + self.write(f".co_linetable = {co_linetable},") + self.write(f".co_endlinetable = {co_endlinetable},") + self.write(f".co_columntable = {co_columntable},") + self.write(f".co_nlocalsplus = {len(localsplusnames)},") + self.field(code, "co_nlocals") + self.write(f".co_nplaincellvars = {nplaincellvars},") + self.write(f".co_ncellvars = {ncellvars},") + self.write(f".co_nfreevars = {nfreevars},") + self.write(f".co_varnames = {co_varnames},") + self.write(f".co_cellvars = {co_cellvars},") + self.write(f".co_freevars = {co_freevars},") + return f"& {name}.ob_base" + + def generate_tuple(self, name: str, t: tuple[object, ...]) -> str: + items = [self.generate(f"{name}_{i}", it) for i, it in enumerate(t)] + self.write("static") + with self.indent(): + with self.block("struct"): + self.write("PyGC_Head _gc_head;") + with self.block("struct", "_object;"): + self.write("PyObject_VAR_HEAD") + if t: + self.write(f"PyObject *ob_item[{len(t)}];") + with self.block(f"{name} =", ";"): + with self.block("._object =", ","): + self.object_var_head("PyTuple_Type", len(t)) + if items: + with self.block(f".ob_item =", ","): + for item in items: + self.write(item + ",") + return f"& {name}._object.ob_base.ob_base" + + def generate_int(self, name: str, i: int) -> str: + maxint = sys.maxsize + if maxint == 2**31 - 1: + digit = 2**15 + elif maxint == 2**63 - 1: + digit = 2**30 + else: + assert False, f"What int size is this system?!? {maxint=}" + sign = -1 if i < 0 else 0 if i == 0 else +1 + i = abs(i) + digits: list[int] = [] + while i: + i, rem = divmod(i, digit) + digits.append(rem) + self.write("static") + with self.indent(): + with self.block("struct"): + self.write("PyObject_VAR_HEAD") + self.write(f"digit ob_digit[{max(1, len(digits))}];") + with self.block(f"{name} =", ";"): + self.object_var_head("PyLong_Type", sign*len(digits)) + if digits: + ds = ", ".join(map(str, digits)) + self.write(f".ob_digit = {{ {ds} }},") + return f"& {name}.ob_base.ob_base" + + def generate_float(self, name: str, x: float) -> str: + with self.block(f"static PyFloatObject {name} =", ";"): + self.object_head("PyFloat_Type") + self.write(f".ob_fval = {x},") + return f"&{name}.ob_base" + + def generate_complex(self, name: str, z: complex) -> str: + with self.block(f"static PyComplexObject {name} =", ";"): + self.object_head("PyComplex_Type") + self.write(f".cval = {{ {z.real}, {z.imag} }},") + return f"&{name}.ob_base" + + def generate_frozenset(self, name: str, fs: frozenset[object]) -> str: + ret = self.generate_tuple(name, tuple(sorted(fs))) + self.write("// TODO: The above tuple should be a frozenset") + return ret + + def generate(self, name: str, obj: object) -> str: + # Use repr() in the key to distinguish -0.0 from +0.0 + key = (type(obj), obj, repr(obj)) + if key in self.cache: + self.hits += 1 + # print(f"Cache hit {key!r:.40}: {self.cache[key]!r:.40}") + return self.cache[key] + self.misses += 1 + match obj: + case types.CodeType() as code: + val = self.generate_code(name, code) + case tuple(t): + val = self.generate_tuple(name, t) + case str(s): + val = self.generate_unicode(name, s) + case bytes(b): + val = self.generate_bytes(name, b) + case True: + return "Py_True" + case False: + return "Py_False" + case int(i): + val = self.generate_int(name, i) + case float(x): + val = self.generate_float(name, x) + case complex() as z: + val = self.generate_complex(name, z) + case frozenset(fs): + val = self.generate_frozenset(name, fs) + case builtins.Ellipsis: + return "Py_Ellipsis" + case None: + return "Py_None" + case _: + raise TypeError( + f"Cannot generate code for {type(obj).__name__} object") + # print(f"Cache store {key!r:.40}: {val!r:.40}") + self.cache[key] = val + return val + + +EPILOGUE = """ +PyObject * +_Py_get_%%NAME%%_toplevel(void) +{ + do_patchups(); + return (PyObject *) &toplevel; +} +""" + +def generate(source: str, filename: str, modname: str, file: typing.TextIO) -> None: + code = compile(source, filename, "exec") + printer = Printer(file) + printer.generate("toplevel", code) + printer.write("") + with printer.block("static void do_patchups()"): + for p in printer.patchups: + printer.write(p) + here = os.path.dirname(__file__) + printer.write(EPILOGUE.replace("%%NAME%%", modname.replace(".", "_"))) + if verbose: + print(f"Cache hits: {printer.hits}, misses: {printer.misses}") + + +parser = argparse.ArgumentParser() +parser.add_argument("-m", "--module", help="Defaults to basename(file)") +parser.add_argument("-o", "--output", help="Defaults to MODULE.c") +parser.add_argument("-v", "--verbose", action="store_true", help="Print diagnostics") +parser.add_argument("file", help="Input file (required)") + + + at contextlib.contextmanager +def report_time(label: str): + t0 = time.time() + try: + yield + finally: + t1 = time.time() + if verbose: + print(f"{label}: {t1-t0:.3f} sec") + + +def main() -> None: + global verbose + args = parser.parse_args() + verbose = args.verbose + with open(args.file, encoding="utf-8") as f: + source = f.read() + modname = args.module or os.path.basename(args.file).removesuffix(".py") + output = args.output or modname + ".c" + with open(output, "w", encoding="utf-8") as file: + with report_time("generate"): + generate(source, f"", modname, file) + if verbose: + print(f"Wrote {os.path.getsize(output)} bytes to {output}") + + +if __name__ == "__main__": + main() diff --git a/Tools/scripts/freeze_modules.py b/Tools/scripts/freeze_modules.py index 36142625ca609..ccea4e11ab6ca 100644 --- a/Tools/scripts/freeze_modules.py +++ b/Tools/scripts/freeze_modules.py @@ -528,6 +528,7 @@ def regen_frozen(modules): header = relpath_for_posix_display(src.frozenfile, parentdir) headerlines.append(f'#include "{header}"') + externlines = [] bootstraplines = [] stdliblines = [] testlines = [] @@ -547,17 +548,18 @@ def regen_frozen(modules): lines.append(f'/* {mod.section} */') lastsection = mod.section + # Also add a extern declaration for the corresponding + # deepfreeze-generated function. + orig_name = mod.source.id + code_name = orig_name.replace(".", "_") + get_code_name = "_Py_get_%s_toplevel" % code_name + externlines.append("extern PyObject *%s(void);" % get_code_name) + symbol = mod.symbol pkg = '-' if mod.ispkg else '' - line = ('{"%s", %s, %s(int)sizeof(%s)},' - ) % (mod.name, symbol, pkg, symbol) - # TODO: Consider not folding lines - if len(line) < 80: - lines.append(line) - else: - line1, _, line2 = line.rpartition(' ') - lines.append(line1) - lines.append(indent + line2) + line = ('{"%s", %s, %s(int)sizeof(%s), GET_CODE(%s)},' + ) % (mod.name, symbol, pkg, symbol, code_name) + lines.append(line) if mod.isalias: if not mod.orig: @@ -588,6 +590,13 @@ def regen_frozen(modules): headerlines, FROZEN_FILE, ) + lines = replace_block( + lines, + "/* Start extern declarations */", + "/* End extern declarations */", + externlines, + FROZEN_FILE, + ) lines = replace_block( lines, "static const struct _frozen bootstrap_modules[] =", @@ -622,7 +631,30 @@ def regen_frozen(modules): def regen_makefile(modules): pyfiles = [] frozenfiles = [] + deepfreezefiles = [] rules = [''] + deepfreezerules = [''] + + # TODO: Merge the two loops + for src in _iter_sources(modules): + header = relpath_for_posix_display(src.frozenfile, ROOT_DIR) + relfile = header.replace('\\', '/') + _pyfile = relpath_for_posix_display(src.pyfile, ROOT_DIR) + + # TODO: This is a bit hackish + xfile = relfile.replace("/frozen_modules/", "/deepfreeze/") + cfile = xfile[:-2] + ".c" + ofile = xfile[:-2] + ".o" + deepfreezefiles.append(f"\t\t{ofile} \\") + + # Also add a deepfreeze rule. + deepfreezerules.append(f'{cfile}: $(srcdir)/{_pyfile} $(DEEPFREEZE_DEPS)') + deepfreezerules.append(f'\t at echo "Deepfreezing {cfile} from {_pyfile}"') + deepfreezerules.append(f"\t at ./$(BOOTSTRAP) \\") + deepfreezerules.append(f"\t\t$(srcdir)/Tools/scripts/deepfreeze.py \\") + deepfreezerules.append(f"\t\t$(srcdir)/{_pyfile} -m {src.frozenid} -o {cfile}") + deepfreezerules.append('') + for src in _iter_sources(modules): header = relpath_for_posix_display(src.frozenfile, ROOT_DIR) frozenfiles.append(f'\t\t{header} \\') @@ -639,6 +671,7 @@ def regen_makefile(modules): ]) pyfiles[-1] = pyfiles[-1].rstrip(" \\") frozenfiles[-1] = frozenfiles[-1].rstrip(" \\") + deepfreezefiles[-1] = deepfreezefiles[-1].rstrip(" \\") print(f'# Updating {os.path.relpath(MAKEFILE)}') with updating_file_with_tmpfile(MAKEFILE) as (infile, outfile): @@ -657,6 +690,13 @@ def regen_makefile(modules): frozenfiles, MAKEFILE, ) + lines = replace_block( + lines, + "DEEPFREEZE_OBJS =", + "# End DEEPFREEZE_OBJS", + deepfreezefiles, + MAKEFILE, + ) lines = replace_block( lines, "# BEGIN: freezing modules", @@ -664,6 +704,13 @@ def regen_makefile(modules): rules, MAKEFILE, ) + lines = replace_block( + lines, + "# BEGIN: deepfreeze modules", + "# END: deepfreeze modules", + deepfreezerules, + MAKEFILE, + ) outfile.writelines(lines) @@ -721,7 +768,6 @@ def freeze_module(modname, pyfile=None, destdir=MODULES_DIR): def _freeze_module(frozenid, pyfile, frozenfile, tmpsuffix): tmpfile = f'{frozenfile}.{int(time.time())}' - print(tmpfile) argv = [TOOL, frozenid, pyfile, tmpfile] print('#', ' '.join(os.path.relpath(a) for a in argv), flush=True) diff --git a/configure b/configure index 3c5a5dabb0792..edc9000338e31 100755 --- a/configure +++ b/configure @@ -18119,7 +18119,8 @@ SRCDIRS="\ Objects \ Parser \ Programs \ - Python" + Python \ + Python/deepfreeze" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for build directories" >&5 $as_echo_n "checking for build directories... " >&6; } for dir in $SRCDIRS; do diff --git a/configure.ac b/configure.ac index 898c2ba632015..5a1ed51a6a9ae 100644 --- a/configure.ac +++ b/configure.ac @@ -5412,7 +5412,8 @@ SRCDIRS="\ Objects \ Parser \ Programs \ - Python" + Python \ + Python/deepfreeze" AC_MSG_CHECKING(for build directories) for dir in $SRCDIRS; do if test ! -d $dir; then From webhook-mailer at python.org Thu Nov 11 01:56:36 2021 From: webhook-mailer at python.org (brandtbucher) Date: Thu, 11 Nov 2021 06:56:36 -0000 Subject: [Python-checkins] bpo-45636: Merge all numeric operators (GH-29482) Message-ID: https://github.com/python/cpython/commit/9178f533ff5ea7462a2ca22cfa67afd78dad433b commit: 9178f533ff5ea7462a2ca22cfa67afd78dad433b branch: main author: Brandt Bucher committer: brandtbucher date: 2021-11-10T22:56:22-08:00 summary: bpo-45636: Merge all numeric operators (GH-29482) files: A Misc/NEWS.d/next/Core and Builtins/2021-10-27-15-14-31.bpo-45636.K2X7QS.rst M Doc/library/dis.rst M Doc/whatsnew/3.11.rst M Include/internal/pycore_code.h M Include/opcode.h M Lib/dis.py M Lib/importlib/_bootstrap_external.py M Lib/opcode.py M Lib/test/test_compile.py M Lib/test/test_dis.py M Lib/test/test_peepholer.py M Python/ceval.c M Python/compile.c M Python/opcode_targets.h M Python/specialize.c M Tools/scripts/generate_opcode_h.py diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 85cc4afb7e48c..4a804044df000 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -406,156 +406,29 @@ result back on the stack. .. versionadded:: 3.5 -**Binary operations** +**Binary and in-place operations** Binary operations remove the top of the stack (TOS) and the second top-most stack item (TOS1) from the stack. They perform the operation, and put the result back on the stack. -.. opcode:: BINARY_POWER - - Implements ``TOS = TOS1 ** TOS``. - - -.. opcode:: BINARY_MULTIPLY - - Implements ``TOS = TOS1 * TOS``. - - -.. opcode:: BINARY_MATRIX_MULTIPLY - - Implements ``TOS = TOS1 @ TOS``. - - .. versionadded:: 3.5 - - -.. opcode:: BINARY_FLOOR_DIVIDE - - Implements ``TOS = TOS1 // TOS``. - - -.. opcode:: BINARY_TRUE_DIVIDE - - Implements ``TOS = TOS1 / TOS``. - - -.. opcode:: BINARY_MODULO - - Implements ``TOS = TOS1 % TOS``. - - -.. opcode:: BINARY_ADD - - Implements ``TOS = TOS1 + TOS``. - - -.. opcode:: BINARY_SUBTRACT - - Implements ``TOS = TOS1 - TOS``. - - -.. opcode:: BINARY_SUBSCR - - Implements ``TOS = TOS1[TOS]``. - - -.. opcode:: BINARY_LSHIFT - - Implements ``TOS = TOS1 << TOS``. - - -.. opcode:: BINARY_RSHIFT - - Implements ``TOS = TOS1 >> TOS``. - - -.. opcode:: BINARY_AND - - Implements ``TOS = TOS1 & TOS``. - - -.. opcode:: BINARY_XOR - - Implements ``TOS = TOS1 ^ TOS``. - - -.. opcode:: BINARY_OR - - Implements ``TOS = TOS1 | TOS``. - - -**In-place operations** - In-place operations are like binary operations, in that they remove TOS and TOS1, and push the result back on the stack, but the operation is done in-place when TOS1 supports it, and the resulting TOS may be (but does not have to be) the original TOS1. -.. opcode:: INPLACE_POWER - - Implements in-place ``TOS = TOS1 ** TOS``. - - -.. opcode:: INPLACE_MULTIPLY - - Implements in-place ``TOS = TOS1 * TOS``. - - -.. opcode:: INPLACE_MATRIX_MULTIPLY - - Implements in-place ``TOS = TOS1 @ TOS``. - - .. versionadded:: 3.5 - - -.. opcode:: INPLACE_FLOOR_DIVIDE - - Implements in-place ``TOS = TOS1 // TOS``. - - -.. opcode:: INPLACE_TRUE_DIVIDE - - Implements in-place ``TOS = TOS1 / TOS``. - -.. opcode:: INPLACE_MODULO +.. opcode:: BINARY_OP (op) - Implements in-place ``TOS = TOS1 % TOS``. + Implements the binary and in-place operators (depending on the value of + *op*). - -.. opcode:: INPLACE_ADD - - Implements in-place ``TOS = TOS1 + TOS``. - - -.. opcode:: INPLACE_SUBTRACT - - Implements in-place ``TOS = TOS1 - TOS``. - - -.. opcode:: INPLACE_LSHIFT - - Implements in-place ``TOS = TOS1 << TOS``. - - -.. opcode:: INPLACE_RSHIFT - - Implements in-place ``TOS = TOS1 >> TOS``. - - -.. opcode:: INPLACE_AND - - Implements in-place ``TOS = TOS1 & TOS``. - - -.. opcode:: INPLACE_XOR - - Implements in-place ``TOS = TOS1 ^ TOS``. + .. versionadded:: 3.11 -.. opcode:: INPLACE_OR +.. opcode:: BINARY_SUBSCR - Implements in-place ``TOS = TOS1 | TOS``. + Implements ``TOS = TOS1[TOS]``. .. opcode:: STORE_SUBSCR diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index c0a6ce4c35ad8..59a230f26ab42 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -315,6 +315,9 @@ Optimizations CPython bytecode changes ======================== +* Replaced all numeric ``BINARY_*`` and ``INPLACE_*`` instructions with a single + :opcode:`BINARY_OP` implementation. + * Added a new :opcode:`CALL_METHOD_KW` opcode. Calls a method in a similar fashion as :opcode:`CALL_METHOD`, but also supports keyword arguments. Works in tandem with :opcode:`LOAD_METHOD`. diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index 622829fccdd0d..7fe9e74b21cfe 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -267,9 +267,9 @@ int _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *nam int _Py_Specialize_LoadGlobal(PyObject *globals, PyObject *builtins, _Py_CODEUNIT *instr, PyObject *name, SpecializedCacheEntry *cache); int _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name, SpecializedCacheEntry *cache); int _Py_Specialize_BinarySubscr(PyObject *sub, PyObject *container, _Py_CODEUNIT *instr); -int _Py_Specialize_BinaryAdd(PyObject *left, PyObject *right, _Py_CODEUNIT *instr); -int _Py_Specialize_BinaryMultiply(PyObject *left, PyObject *right, _Py_CODEUNIT *instr); int _Py_Specialize_CallFunction(PyObject *callable, _Py_CODEUNIT *instr, int nargs, SpecializedCacheEntry *cache, PyObject *builtins); +void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, + SpecializedCacheEntry *cache); #define PRINT_SPECIALIZATION_STATS 0 #define PRINT_SPECIALIZATION_STATS_DETAILED 0 diff --git a/Include/opcode.h b/Include/opcode.h index 87ed32c019909..c7354de9a0687 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -6,178 +6,152 @@ extern "C" { #endif - /* Instruction opcodes for compiled code */ -#define POP_TOP 1 -#define ROT_TWO 2 -#define ROT_THREE 3 -#define DUP_TOP 4 -#define DUP_TOP_TWO 5 -#define ROT_FOUR 6 -#define NOP 9 -#define UNARY_POSITIVE 10 -#define UNARY_NEGATIVE 11 -#define UNARY_NOT 12 -#define UNARY_INVERT 15 -#define BINARY_MATRIX_MULTIPLY 16 -#define INPLACE_MATRIX_MULTIPLY 17 -#define BINARY_POWER 19 -#define BINARY_MULTIPLY 20 -#define BINARY_MODULO 22 -#define BINARY_ADD 23 -#define BINARY_SUBTRACT 24 -#define BINARY_SUBSCR 25 -#define BINARY_FLOOR_DIVIDE 26 -#define BINARY_TRUE_DIVIDE 27 -#define INPLACE_FLOOR_DIVIDE 28 -#define INPLACE_TRUE_DIVIDE 29 -#define GET_LEN 30 -#define MATCH_MAPPING 31 -#define MATCH_SEQUENCE 32 -#define MATCH_KEYS 33 -#define PUSH_EXC_INFO 35 -#define POP_EXCEPT_AND_RERAISE 37 -#define WITH_EXCEPT_START 49 -#define GET_AITER 50 -#define GET_ANEXT 51 -#define BEFORE_ASYNC_WITH 52 -#define BEFORE_WITH 53 -#define END_ASYNC_FOR 54 -#define INPLACE_ADD 55 -#define INPLACE_SUBTRACT 56 -#define INPLACE_MULTIPLY 57 -#define INPLACE_MODULO 59 -#define STORE_SUBSCR 60 -#define DELETE_SUBSCR 61 -#define BINARY_LSHIFT 62 -#define BINARY_RSHIFT 63 -#define BINARY_AND 64 -#define BINARY_XOR 65 -#define BINARY_OR 66 -#define INPLACE_POWER 67 -#define GET_ITER 68 -#define GET_YIELD_FROM_ITER 69 -#define PRINT_EXPR 70 -#define LOAD_BUILD_CLASS 71 -#define YIELD_FROM 72 -#define GET_AWAITABLE 73 -#define LOAD_ASSERTION_ERROR 74 -#define INPLACE_LSHIFT 75 -#define INPLACE_RSHIFT 76 -#define INPLACE_AND 77 -#define INPLACE_XOR 78 -#define INPLACE_OR 79 -#define LIST_TO_TUPLE 82 -#define RETURN_VALUE 83 -#define IMPORT_STAR 84 -#define SETUP_ANNOTATIONS 85 -#define YIELD_VALUE 86 -#define POP_EXCEPT 89 -#define HAVE_ARGUMENT 90 -#define STORE_NAME 90 -#define DELETE_NAME 91 -#define UNPACK_SEQUENCE 92 -#define FOR_ITER 93 -#define UNPACK_EX 94 -#define STORE_ATTR 95 -#define DELETE_ATTR 96 -#define STORE_GLOBAL 97 -#define DELETE_GLOBAL 98 -#define ROT_N 99 -#define LOAD_CONST 100 -#define LOAD_NAME 101 -#define BUILD_TUPLE 102 -#define BUILD_LIST 103 -#define BUILD_SET 104 -#define BUILD_MAP 105 -#define LOAD_ATTR 106 -#define COMPARE_OP 107 -#define IMPORT_NAME 108 -#define IMPORT_FROM 109 -#define JUMP_FORWARD 110 -#define JUMP_IF_FALSE_OR_POP 111 -#define JUMP_IF_TRUE_OR_POP 112 -#define JUMP_ABSOLUTE 113 -#define POP_JUMP_IF_FALSE 114 -#define POP_JUMP_IF_TRUE 115 -#define LOAD_GLOBAL 116 -#define IS_OP 117 -#define CONTAINS_OP 118 -#define RERAISE 119 -#define COPY 120 -#define JUMP_IF_NOT_EXC_MATCH 121 -#define LOAD_FAST 124 -#define STORE_FAST 125 -#define DELETE_FAST 126 -#define GEN_START 129 -#define RAISE_VARARGS 130 -#define CALL_FUNCTION 131 -#define MAKE_FUNCTION 132 -#define BUILD_SLICE 133 -#define MAKE_CELL 135 -#define LOAD_CLOSURE 136 -#define LOAD_DEREF 137 -#define STORE_DEREF 138 -#define DELETE_DEREF 139 -#define CALL_FUNCTION_KW 141 -#define CALL_FUNCTION_EX 142 -#define EXTENDED_ARG 144 -#define LIST_APPEND 145 -#define SET_ADD 146 -#define MAP_ADD 147 -#define LOAD_CLASSDEREF 148 -#define MATCH_CLASS 152 -#define FORMAT_VALUE 155 -#define BUILD_CONST_KEY_MAP 156 -#define BUILD_STRING 157 -#define LOAD_METHOD 160 -#define CALL_METHOD 161 -#define LIST_EXTEND 162 -#define SET_UPDATE 163 -#define DICT_MERGE 164 -#define DICT_UPDATE 165 -#define CALL_METHOD_KW 166 -#define BINARY_ADD_ADAPTIVE 7 -#define BINARY_ADD_INT 8 -#define BINARY_ADD_FLOAT 13 -#define BINARY_ADD_UNICODE 14 -#define BINARY_ADD_UNICODE_INPLACE_FAST 18 -#define BINARY_MULTIPLY_ADAPTIVE 21 -#define BINARY_MULTIPLY_INT 34 -#define BINARY_MULTIPLY_FLOAT 36 -#define BINARY_SUBSCR_ADAPTIVE 38 -#define BINARY_SUBSCR_LIST_INT 39 -#define BINARY_SUBSCR_TUPLE_INT 40 -#define BINARY_SUBSCR_DICT 41 -#define CALL_FUNCTION_ADAPTIVE 42 -#define CALL_FUNCTION_BUILTIN_O 43 -#define CALL_FUNCTION_BUILTIN_FAST 44 -#define CALL_FUNCTION_LEN 45 -#define CALL_FUNCTION_ISINSTANCE 46 -#define CALL_FUNCTION_PY_SIMPLE 47 -#define JUMP_ABSOLUTE_QUICK 48 -#define LOAD_ATTR_ADAPTIVE 58 -#define LOAD_ATTR_INSTANCE_VALUE 80 -#define LOAD_ATTR_WITH_HINT 81 -#define LOAD_ATTR_SLOT 87 -#define LOAD_ATTR_MODULE 88 -#define LOAD_GLOBAL_ADAPTIVE 122 -#define LOAD_GLOBAL_MODULE 123 -#define LOAD_GLOBAL_BUILTIN 127 -#define LOAD_METHOD_ADAPTIVE 128 -#define LOAD_METHOD_CACHED 134 -#define LOAD_METHOD_CLASS 140 -#define LOAD_METHOD_MODULE 143 -#define LOAD_METHOD_NO_DICT 149 -#define STORE_ATTR_ADAPTIVE 150 -#define STORE_ATTR_INSTANCE_VALUE 151 -#define STORE_ATTR_SLOT 153 -#define STORE_ATTR_WITH_HINT 154 -#define LOAD_FAST__LOAD_FAST 158 -#define STORE_FAST__LOAD_FAST 159 -#define LOAD_FAST__LOAD_CONST 167 -#define LOAD_CONST__LOAD_FAST 168 -#define STORE_FAST__STORE_FAST 169 -#define DO_TRACING 255 +/* Instruction opcodes for compiled code */ +#define POP_TOP 1 +#define ROT_TWO 2 +#define ROT_THREE 3 +#define DUP_TOP 4 +#define DUP_TOP_TWO 5 +#define ROT_FOUR 6 +#define NOP 9 +#define UNARY_POSITIVE 10 +#define UNARY_NEGATIVE 11 +#define UNARY_NOT 12 +#define UNARY_INVERT 15 +#define BINARY_SUBSCR 25 +#define GET_LEN 30 +#define MATCH_MAPPING 31 +#define MATCH_SEQUENCE 32 +#define MATCH_KEYS 33 +#define PUSH_EXC_INFO 35 +#define POP_EXCEPT_AND_RERAISE 37 +#define WITH_EXCEPT_START 49 +#define GET_AITER 50 +#define GET_ANEXT 51 +#define BEFORE_ASYNC_WITH 52 +#define BEFORE_WITH 53 +#define END_ASYNC_FOR 54 +#define STORE_SUBSCR 60 +#define DELETE_SUBSCR 61 +#define GET_ITER 68 +#define GET_YIELD_FROM_ITER 69 +#define PRINT_EXPR 70 +#define LOAD_BUILD_CLASS 71 +#define YIELD_FROM 72 +#define GET_AWAITABLE 73 +#define LOAD_ASSERTION_ERROR 74 +#define LIST_TO_TUPLE 82 +#define RETURN_VALUE 83 +#define IMPORT_STAR 84 +#define SETUP_ANNOTATIONS 85 +#define YIELD_VALUE 86 +#define POP_EXCEPT 89 +#define HAVE_ARGUMENT 90 +#define STORE_NAME 90 +#define DELETE_NAME 91 +#define UNPACK_SEQUENCE 92 +#define FOR_ITER 93 +#define UNPACK_EX 94 +#define STORE_ATTR 95 +#define DELETE_ATTR 96 +#define STORE_GLOBAL 97 +#define DELETE_GLOBAL 98 +#define ROT_N 99 +#define LOAD_CONST 100 +#define LOAD_NAME 101 +#define BUILD_TUPLE 102 +#define BUILD_LIST 103 +#define BUILD_SET 104 +#define BUILD_MAP 105 +#define LOAD_ATTR 106 +#define COMPARE_OP 107 +#define IMPORT_NAME 108 +#define IMPORT_FROM 109 +#define JUMP_FORWARD 110 +#define JUMP_IF_FALSE_OR_POP 111 +#define JUMP_IF_TRUE_OR_POP 112 +#define JUMP_ABSOLUTE 113 +#define POP_JUMP_IF_FALSE 114 +#define POP_JUMP_IF_TRUE 115 +#define LOAD_GLOBAL 116 +#define IS_OP 117 +#define CONTAINS_OP 118 +#define RERAISE 119 +#define COPY 120 +#define JUMP_IF_NOT_EXC_MATCH 121 +#define BINARY_OP 122 +#define LOAD_FAST 124 +#define STORE_FAST 125 +#define DELETE_FAST 126 +#define GEN_START 129 +#define RAISE_VARARGS 130 +#define CALL_FUNCTION 131 +#define MAKE_FUNCTION 132 +#define BUILD_SLICE 133 +#define MAKE_CELL 135 +#define LOAD_CLOSURE 136 +#define LOAD_DEREF 137 +#define STORE_DEREF 138 +#define DELETE_DEREF 139 +#define CALL_FUNCTION_KW 141 +#define CALL_FUNCTION_EX 142 +#define EXTENDED_ARG 144 +#define LIST_APPEND 145 +#define SET_ADD 146 +#define MAP_ADD 147 +#define LOAD_CLASSDEREF 148 +#define MATCH_CLASS 152 +#define FORMAT_VALUE 155 +#define BUILD_CONST_KEY_MAP 156 +#define BUILD_STRING 157 +#define LOAD_METHOD 160 +#define CALL_METHOD 161 +#define LIST_EXTEND 162 +#define SET_UPDATE 163 +#define DICT_MERGE 164 +#define DICT_UPDATE 165 +#define CALL_METHOD_KW 166 +#define BINARY_OP_ADAPTIVE 7 +#define BINARY_OP_ADD_INT 8 +#define BINARY_OP_ADD_FLOAT 13 +#define BINARY_OP_ADD_UNICODE 14 +#define BINARY_OP_INPLACE_ADD_UNICODE 16 +#define BINARY_OP_MULTIPLY_INT 17 +#define BINARY_OP_MULTIPLY_FLOAT 18 +#define BINARY_SUBSCR_ADAPTIVE 19 +#define BINARY_SUBSCR_LIST_INT 20 +#define BINARY_SUBSCR_TUPLE_INT 21 +#define BINARY_SUBSCR_DICT 22 +#define CALL_FUNCTION_ADAPTIVE 23 +#define CALL_FUNCTION_BUILTIN_O 24 +#define CALL_FUNCTION_BUILTIN_FAST 26 +#define CALL_FUNCTION_LEN 27 +#define CALL_FUNCTION_ISINSTANCE 28 +#define CALL_FUNCTION_PY_SIMPLE 29 +#define JUMP_ABSOLUTE_QUICK 34 +#define LOAD_ATTR_ADAPTIVE 36 +#define LOAD_ATTR_INSTANCE_VALUE 38 +#define LOAD_ATTR_WITH_HINT 39 +#define LOAD_ATTR_SLOT 40 +#define LOAD_ATTR_MODULE 41 +#define LOAD_GLOBAL_ADAPTIVE 42 +#define LOAD_GLOBAL_MODULE 43 +#define LOAD_GLOBAL_BUILTIN 44 +#define LOAD_METHOD_ADAPTIVE 45 +#define LOAD_METHOD_CACHED 46 +#define LOAD_METHOD_CLASS 47 +#define LOAD_METHOD_MODULE 48 +#define LOAD_METHOD_NO_DICT 55 +#define STORE_ATTR_ADAPTIVE 56 +#define STORE_ATTR_INSTANCE_VALUE 57 +#define STORE_ATTR_SLOT 58 +#define STORE_ATTR_WITH_HINT 59 +#define LOAD_FAST__LOAD_FAST 62 +#define STORE_FAST__LOAD_FAST 63 +#define LOAD_FAST__LOAD_CONST 64 +#define LOAD_CONST__LOAD_FAST 65 +#define STORE_FAST__STORE_FAST 66 +#define DO_TRACING 255 #ifdef NEED_OPCODE_JUMP_TABLES static uint32_t _PyOpcode_RelativeJump[8] = { 0U, @@ -205,6 +179,33 @@ static uint32_t _PyOpcode_Jump[8] = { || ((op) == 100) \ ) +#define NB_ADD 0 +#define NB_AND 1 +#define NB_FLOOR_DIVIDE 2 +#define NB_LSHIFT 3 +#define NB_MATRIX_MULTIPLY 4 +#define NB_MULTIPLY 5 +#define NB_REMAINDER 6 +#define NB_OR 7 +#define NB_POWER 8 +#define NB_RSHIFT 9 +#define NB_SUBTRACT 10 +#define NB_TRUE_DIVIDE 11 +#define NB_XOR 12 +#define NB_INPLACE_ADD 13 +#define NB_INPLACE_AND 14 +#define NB_INPLACE_FLOOR_DIVIDE 15 +#define NB_INPLACE_LSHIFT 16 +#define NB_INPLACE_MATRIX_MULTIPLY 17 +#define NB_INPLACE_MULTIPLY 18 +#define NB_INPLACE_REMAINDER 19 +#define NB_INPLACE_OR 20 +#define NB_INPLACE_POWER 21 +#define NB_INPLACE_RSHIFT 22 +#define NB_INPLACE_SUBTRACT 23 +#define NB_INPLACE_TRUE_DIVIDE 24 +#define NB_INPLACE_XOR 25 + #define HAS_ARG(op) ((op) >= HAVE_ARGUMENT) /* Reserve some bytecodes for internal use in the compiler. diff --git a/Lib/dis.py b/Lib/dis.py index 8b429b5b72522..ac0c6e7f04c45 100644 --- a/Lib/dis.py +++ b/Lib/dis.py @@ -7,6 +7,7 @@ from opcode import * from opcode import __all__ as _opcodes_all +from opcode import _nb_ops __all__ = ["code_info", "dis", "disassemble", "distb", "disco", "findlinestarts", "findlabels", "show_code", @@ -27,6 +28,7 @@ MAKE_FUNCTION_FLAGS = ('defaults', 'kwdefaults', 'annotations', 'closure') LOAD_CONST = opmap['LOAD_CONST'] +BINARY_OP = opmap['BINARY_OP'] def _try_compile(source, name): """Attempts to compile the given source, first as an expression and @@ -446,6 +448,8 @@ def _get_instructions_bytes(code, varname_from_oparg=None, elif op == MAKE_FUNCTION: argrepr = ', '.join(s for i, s in enumerate(MAKE_FUNCTION_FLAGS) if arg & (1<>"), + ("NB_SUBTRACT", "-"), + ("NB_TRUE_DIVIDE", "/"), + ("NB_XOR", "^"), + ("NB_INPLACE_ADD", "+="), + ("NB_INPLACE_AND", "&="), + ("NB_INPLACE_FLOOR_DIVIDE", "//="), + ("NB_INPLACE_LSHIFT", "<<="), + ("NB_INPLACE_MATRIX_MULTIPLY", "@="), + ("NB_INPLACE_MULTIPLY", "*="), + ("NB_INPLACE_REMAINDER", "%="), + ("NB_INPLACE_OR", "|="), + ("NB_INPLACE_POWER", "**="), + ("NB_INPLACE_RSHIFT", ">>="), + ("NB_INPLACE_SUBTRACT", "-="), + ("NB_INPLACE_TRUE_DIVIDE", "/="), + ("NB_INPLACE_XOR", "^="), +] + _specialized_instructions = [ - "BINARY_ADD_ADAPTIVE", - "BINARY_ADD_INT", - "BINARY_ADD_FLOAT", - "BINARY_ADD_UNICODE", - "BINARY_ADD_UNICODE_INPLACE_FAST", - "BINARY_MULTIPLY_ADAPTIVE", - "BINARY_MULTIPLY_INT", - "BINARY_MULTIPLY_FLOAT", + "BINARY_OP_ADAPTIVE", + "BINARY_OP_ADD_INT", + "BINARY_OP_ADD_FLOAT", + "BINARY_OP_ADD_UNICODE", + "BINARY_OP_INPLACE_ADD_UNICODE", + "BINARY_OP_MULTIPLY_INT", + "BINARY_OP_MULTIPLY_FLOAT", "BINARY_SUBSCR_ADAPTIVE", "BINARY_SUBSCR_LIST_INT", "BINARY_SUBSCR_TUPLE_INT", diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index 495a223fc3da7..f72c7ca68f363 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -1048,15 +1048,17 @@ def generic_visit(self, node): return code, ast_tree def assertOpcodeSourcePositionIs(self, code, opcode, - line, end_line, column, end_column): + line, end_line, column, end_column, occurrence=1): for instr, position in zip(dis.Bytecode(code), code.co_positions()): if instr.opname == opcode: - self.assertEqual(position[0], line) - self.assertEqual(position[1], end_line) - self.assertEqual(position[2], column) - self.assertEqual(position[3], end_column) - return + occurrence -= 1 + if not occurrence: + self.assertEqual(position[0], line) + self.assertEqual(position[1], end_line) + self.assertEqual(position[2], column) + self.assertEqual(position[3], end_column) + return self.fail(f"Opcode {opcode} not found in code") @@ -1077,12 +1079,12 @@ def test_compiles_to_extended_op_arg(self): compiled_code, _ = self.check_positions_against_ast(snippet) - self.assertOpcodeSourcePositionIs(compiled_code, 'INPLACE_SUBTRACT', + self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_OP', line=10_000 + 2, end_line=10_000 + 2, - column=2, end_column=8) - self.assertOpcodeSourcePositionIs(compiled_code, 'INPLACE_ADD', + column=2, end_column=8, occurrence=1) + self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_OP', line=10_000 + 4, end_line=10_000 + 4, - column=2, end_column=9) + column=2, end_column=9, occurrence=2) def test_multiline_expression(self): snippet = """\ @@ -1110,14 +1112,14 @@ def test_complex_single_line_expression(self): compiled_code, _ = self.check_positions_against_ast(snippet) self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_SUBSCR', line=1, end_line=1, column=13, end_column=21) - self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_MULTIPLY', - line=1, end_line=1, column=9, end_column=21) - self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_ADD', - line=1, end_line=1, column=9, end_column=26) - self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_MATRIX_MULTIPLY', - line=1, end_line=1, column=4, end_column=27) - self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_SUBTRACT', - line=1, end_line=1, column=0, end_column=27) + self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_OP', + line=1, end_line=1, column=9, end_column=21, occurrence=1) + self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_OP', + line=1, end_line=1, column=9, end_column=26, occurrence=2) + self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_OP', + line=1, end_line=1, column=4, end_column=27, occurrence=3) + self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_OP', + line=1, end_line=1, column=0, end_column=27, occurrence=4) class TestExpressionStackSize(unittest.TestCase): diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index d0435e494d1e7..3b8ebb5dba95b 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -156,7 +156,7 @@ def bug1333982(x=[]): %3d 12 LOAD_CONST 3 (1) -%3d 14 BINARY_ADD +%3d 14 BINARY_OP 0 (+) 16 CALL_FUNCTION 1 18 RAISE_VARARGS 1 """ % (bug1333982.__code__.co_firstlineno + 1, @@ -226,7 +226,7 @@ def bug42562(): dis_expr_str = """\ 1 0 LOAD_NAME 0 (x) 2 LOAD_CONST 0 (1) - 4 BINARY_ADD + 4 BINARY_OP 0 (+) 6 RETURN_VALUE """ @@ -235,7 +235,7 @@ def bug42562(): dis_simple_stmt_str = """\ 1 0 LOAD_NAME 0 (x) 2 LOAD_CONST 0 (1) - 4 BINARY_ADD + 4 BINARY_OP 0 (+) 6 STORE_NAME 0 (x) 8 LOAD_CONST 1 (None) 10 RETURN_VALUE @@ -291,7 +291,7 @@ def bug42562(): 3 >> 6 LOAD_NAME 0 (x) 8 LOAD_CONST 1 (1) - 10 INPLACE_ADD + 10 BINARY_OP 13 (+=) 12 STORE_NAME 0 (x) 2 14 JUMP_ABSOLUTE 3 (to 6) @@ -302,7 +302,7 @@ def bug42562(): %3d 2 LOAD_CONST 1 (1) 4 LOAD_CONST 2 (0) - --> 6 BINARY_TRUE_DIVIDE + --> 6 BINARY_OP 11 (/) 8 POP_TOP %3d 10 LOAD_FAST 1 (tb) @@ -485,7 +485,7 @@ def foo(x): 6 STORE_FAST 1 (z) 8 LOAD_DEREF 2 (x) 10 LOAD_FAST 1 (z) - 12 BINARY_ADD + 12 BINARY_OP 0 (+) 14 LIST_APPEND 2 16 JUMP_ABSOLUTE 2 (to 4) >> 18 RETURN_VALUE @@ -602,7 +602,7 @@ def expected(count, w): s = ['''\ %*d LOAD_FAST 0 (x) %*d LOAD_CONST 1 (1) - %*d BINARY_ADD + %*d BINARY_OP 0 (+) %*d STORE_FAST 0 (x) ''' % (w, 8*i, w, 8*i + 2, w, 8*i + 4, w, 8*i + 6) for i in range(count)] @@ -1080,7 +1080,7 @@ def _prepare_test_cases(): Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=62, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=64, starts_line=13, is_jump_target=False, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=66, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='INPLACE_SUBTRACT', opcode=56, arg=None, argval=None, argrepr='', offset=68, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='BINARY_OP', opcode=122, arg=23, argval=23, argrepr='-=', offset=68, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=70, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=72, starts_line=14, is_jump_target=False, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=74, starts_line=None, is_jump_target=False, positions=None), @@ -1101,7 +1101,7 @@ def _prepare_test_cases(): Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=104, starts_line=20, is_jump_target=True, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=106, starts_line=21, is_jump_target=False, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=108, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='BINARY_TRUE_DIVIDE', opcode=27, arg=None, argval=None, argrepr='', offset=110, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='BINARY_OP', opcode=122, arg=11, argval=11, argrepr='/', offset=110, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=112, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='JUMP_FORWARD', opcode=110, arg=14, argval=144, argrepr='to 144', offset=114, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=116, starts_line=None, is_jump_target=False, positions=None), diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index 9478c47f7c3b3..7086a42b09560 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -424,7 +424,7 @@ def f(): def g()->1+1: pass return g - self.assertNotInBytecode(f, 'BINARY_ADD') + self.assertNotInBytecode(f, 'BINARY_OP') self.check_lnotab(f) def test_constant_folding(self): diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-27-15-14-31.bpo-45636.K2X7QS.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-27-15-14-31.bpo-45636.K2X7QS.rst new file mode 100644 index 0000000000000..ca687687e79f2 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-10-27-15-14-31.bpo-45636.K2X7QS.rst @@ -0,0 +1,2 @@ +Replace all numeric ``BINARY_*`` and ``INPLACE_*`` instructions with a single +:opcode:`BINARY_OP` implementation. diff --git a/Python/ceval.c b/Python/ceval.c index fadb97adefb2b..030d98396780b 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -92,8 +92,6 @@ static PyObject * import_from(PyThreadState *, PyObject *, PyObject *); static int import_all_from(PyThreadState *, PyObject *, PyObject *); static void format_exc_check_arg(PyThreadState *, PyObject *, const char *, PyObject *); static void format_exc_unbound(PyThreadState *tstate, PyCodeObject *co, int oparg); -static PyObject * unicode_concatenate(PyThreadState *, PyObject *, PyObject *, - InterpreterFrame *, const _Py_CODEUNIT *); static int check_args_iterable(PyThreadState *, PyObject *func, PyObject *vararg); static void format_kwargs_error(PyThreadState *, PyObject *func, PyObject *kwargs); static void format_awaitable_error(PyThreadState *, PyTypeObject *, int, int); @@ -1921,57 +1919,12 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr DISPATCH(); } - TARGET(BINARY_POWER) { - PyObject *exp = POP(); - PyObject *base = TOP(); - PyObject *res = PyNumber_Power(base, exp, Py_None); - Py_DECREF(base); - Py_DECREF(exp); - SET_TOP(res); - if (res == NULL) - goto error; - DISPATCH(); - } - - TARGET(BINARY_MULTIPLY) { - PREDICTED(BINARY_MULTIPLY); - STAT_INC(BINARY_MULTIPLY, unquickened); - PyObject *right = POP(); - PyObject *left = TOP(); - PyObject *res = PyNumber_Multiply(left, right); - Py_DECREF(left); - Py_DECREF(right); - SET_TOP(res); - if (res == NULL) { - goto error; - } - DISPATCH(); - } - - TARGET(BINARY_MULTIPLY_ADAPTIVE) { - if (oparg == 0) { - PyObject *left = SECOND(); - PyObject *right = TOP(); - next_instr--; - if (_Py_Specialize_BinaryMultiply(left, right, next_instr) < 0) { - goto error; - } - DISPATCH(); - } - else { - STAT_INC(BINARY_MULTIPLY, deferred); - UPDATE_PREV_INSTR_OPARG(next_instr, oparg - 1); - STAT_DEC(BINARY_MULTIPLY, unquickened); - JUMP_TO_INSTRUCTION(BINARY_MULTIPLY); - } - } - - TARGET(BINARY_MULTIPLY_INT) { + TARGET(BINARY_OP_MULTIPLY_INT) { PyObject *left = SECOND(); PyObject *right = TOP(); - DEOPT_IF(!PyLong_CheckExact(left), BINARY_MULTIPLY); - DEOPT_IF(!PyLong_CheckExact(right), BINARY_MULTIPLY); - STAT_INC(BINARY_MULTIPLY, hit); + DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP); + DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP); + STAT_INC(BINARY_OP, hit); PyObject *prod = _PyLong_Multiply((PyLongObject *)left, (PyLongObject *)right); SET_SECOND(prod); Py_DECREF(right); @@ -1983,12 +1936,12 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr DISPATCH(); } - TARGET(BINARY_MULTIPLY_FLOAT) { + TARGET(BINARY_OP_MULTIPLY_FLOAT) { PyObject *left = SECOND(); PyObject *right = TOP(); - DEOPT_IF(!PyFloat_CheckExact(left), BINARY_MULTIPLY); - DEOPT_IF(!PyFloat_CheckExact(right), BINARY_MULTIPLY); - STAT_INC(BINARY_MULTIPLY, hit); + DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP); + DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP); + STAT_INC(BINARY_OP, hit); double dprod = ((PyFloatObject *)left)->ob_fval * ((PyFloatObject *)right)->ob_fval; PyObject *prod = PyFloat_FromDouble(dprod); @@ -2002,101 +1955,12 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr DISPATCH(); } - TARGET(BINARY_MATRIX_MULTIPLY) { - PyObject *right = POP(); - PyObject *left = TOP(); - PyObject *res = PyNumber_MatrixMultiply(left, right); - Py_DECREF(left); - Py_DECREF(right); - SET_TOP(res); - if (res == NULL) - goto error; - DISPATCH(); - } - - TARGET(BINARY_TRUE_DIVIDE) { - PyObject *divisor = POP(); - PyObject *dividend = TOP(); - PyObject *quotient = PyNumber_TrueDivide(dividend, divisor); - Py_DECREF(dividend); - Py_DECREF(divisor); - SET_TOP(quotient); - if (quotient == NULL) - goto error; - DISPATCH(); - } - - TARGET(BINARY_FLOOR_DIVIDE) { - PyObject *divisor = POP(); - PyObject *dividend = TOP(); - PyObject *quotient = PyNumber_FloorDivide(dividend, divisor); - Py_DECREF(dividend); - Py_DECREF(divisor); - SET_TOP(quotient); - if (quotient == NULL) - goto error; - DISPATCH(); - } - - TARGET(BINARY_MODULO) { - PyObject *divisor = POP(); - PyObject *dividend = TOP(); - PyObject *res; - if (PyUnicode_CheckExact(dividend) && ( - !PyUnicode_Check(divisor) || PyUnicode_CheckExact(divisor))) { - // fast path; string formatting, but not if the RHS is a str subclass - // (see issue28598) - res = PyUnicode_Format(dividend, divisor); - } else { - res = PyNumber_Remainder(dividend, divisor); - } - Py_DECREF(divisor); - Py_DECREF(dividend); - SET_TOP(res); - if (res == NULL) - goto error; - DISPATCH(); - } - - TARGET(BINARY_ADD) { - PREDICTED(BINARY_ADD); - STAT_INC(BINARY_ADD, unquickened); - PyObject *right = POP(); - PyObject *left = TOP(); - PyObject *sum = PyNumber_Add(left, right); - SET_TOP(sum); - Py_DECREF(left); - Py_DECREF(right); - if (sum == NULL) { - goto error; - } - DISPATCH(); - } - - TARGET(BINARY_ADD_ADAPTIVE) { - if (oparg == 0) { - PyObject *left = SECOND(); - PyObject *right = TOP(); - next_instr--; - if (_Py_Specialize_BinaryAdd(left, right, next_instr) < 0) { - goto error; - } - DISPATCH(); - } - else { - STAT_INC(BINARY_ADD, deferred); - UPDATE_PREV_INSTR_OPARG(next_instr, oparg - 1); - STAT_DEC(BINARY_ADD, unquickened); - JUMP_TO_INSTRUCTION(BINARY_ADD); - } - } - - TARGET(BINARY_ADD_UNICODE) { + TARGET(BINARY_OP_ADD_UNICODE) { PyObject *left = SECOND(); PyObject *right = TOP(); - DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_ADD); - DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_ADD); - STAT_INC(BINARY_ADD, hit); + DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP); + DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP); + STAT_INC(BINARY_OP, hit); PyObject *res = PyUnicode_Concat(left, right); STACK_SHRINK(1); SET_TOP(res); @@ -2108,12 +1972,12 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr DISPATCH(); } - TARGET(BINARY_ADD_UNICODE_INPLACE_FAST) { + TARGET(BINARY_OP_INPLACE_ADD_UNICODE) { PyObject *left = SECOND(); PyObject *right = TOP(); - DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_ADD); - DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_ADD); - DEOPT_IF(Py_REFCNT(left) != 2, BINARY_ADD); + DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP); + DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP); + DEOPT_IF(Py_REFCNT(left) != 2, BINARY_OP); int next_oparg = _Py_OPARG(*next_instr); assert(_Py_OPCODE(*next_instr) == STORE_FAST); /* In the common case, there are 2 references to the value @@ -2123,8 +1987,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr * the refcnt to 1. */ PyObject *var = GETLOCAL(next_oparg); - DEOPT_IF(var != left, BINARY_ADD); - STAT_INC(BINARY_ADD, hit); + DEOPT_IF(var != left, BINARY_OP); + STAT_INC(BINARY_OP, hit); GETLOCAL(next_oparg) = NULL; Py_DECREF(left); STACK_SHRINK(1); @@ -2136,12 +2000,12 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr DISPATCH(); } - TARGET(BINARY_ADD_FLOAT) { + TARGET(BINARY_OP_ADD_FLOAT) { PyObject *left = SECOND(); PyObject *right = TOP(); - DEOPT_IF(!PyFloat_CheckExact(left), BINARY_ADD); - DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_ADD); - STAT_INC(BINARY_ADD, hit); + DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP); + DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP); + STAT_INC(BINARY_OP, hit); double dsum = ((PyFloatObject *)left)->ob_fval + ((PyFloatObject *)right)->ob_fval; PyObject *sum = PyFloat_FromDouble(dsum); @@ -2155,12 +2019,12 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr DISPATCH(); } - TARGET(BINARY_ADD_INT) { + TARGET(BINARY_OP_ADD_INT) { PyObject *left = SECOND(); PyObject *right = TOP(); - DEOPT_IF(!PyLong_CheckExact(left), BINARY_ADD); - DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_ADD); - STAT_INC(BINARY_ADD, hit); + DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP); + DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP); + STAT_INC(BINARY_OP, hit); PyObject *sum = _PyLong_Add((PyLongObject *)left, (PyLongObject *)right); SET_SECOND(sum); Py_DECREF(right); @@ -2172,18 +2036,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr DISPATCH(); } - TARGET(BINARY_SUBTRACT) { - PyObject *right = POP(); - PyObject *left = TOP(); - PyObject *diff = PyNumber_Subtract(left, right); - Py_DECREF(right); - Py_DECREF(left); - SET_TOP(diff); - if (diff == NULL) - goto error; - DISPATCH(); - } - TARGET(BINARY_SUBSCR) { PREDICTED(BINARY_SUBSCR); STAT_INC(BINARY_SUBSCR, unquickened); @@ -2282,66 +2134,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr DISPATCH(); } - TARGET(BINARY_LSHIFT) { - PyObject *right = POP(); - PyObject *left = TOP(); - PyObject *res = PyNumber_Lshift(left, right); - Py_DECREF(left); - Py_DECREF(right); - SET_TOP(res); - if (res == NULL) - goto error; - DISPATCH(); - } - - TARGET(BINARY_RSHIFT) { - PyObject *right = POP(); - PyObject *left = TOP(); - PyObject *res = PyNumber_Rshift(left, right); - Py_DECREF(left); - Py_DECREF(right); - SET_TOP(res); - if (res == NULL) - goto error; - DISPATCH(); - } - - TARGET(BINARY_AND) { - PyObject *right = POP(); - PyObject *left = TOP(); - PyObject *res = PyNumber_And(left, right); - Py_DECREF(left); - Py_DECREF(right); - SET_TOP(res); - if (res == NULL) - goto error; - DISPATCH(); - } - - TARGET(BINARY_XOR) { - PyObject *right = POP(); - PyObject *left = TOP(); - PyObject *res = PyNumber_Xor(left, right); - Py_DECREF(left); - Py_DECREF(right); - SET_TOP(res); - if (res == NULL) - goto error; - DISPATCH(); - } - - TARGET(BINARY_OR) { - PyObject *right = POP(); - PyObject *left = TOP(); - PyObject *res = PyNumber_Or(left, right); - Py_DECREF(left); - Py_DECREF(right); - SET_TOP(res); - if (res == NULL) - goto error; - DISPATCH(); - } - TARGET(LIST_APPEND) { PyObject *v = POP(); PyObject *list = PEEK(oparg); @@ -2366,169 +2158,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr DISPATCH(); } - TARGET(INPLACE_POWER) { - PyObject *exp = POP(); - PyObject *base = TOP(); - PyObject *res = PyNumber_InPlacePower(base, exp, Py_None); - Py_DECREF(base); - Py_DECREF(exp); - SET_TOP(res); - if (res == NULL) - goto error; - DISPATCH(); - } - - TARGET(INPLACE_MULTIPLY) { - PyObject *right = POP(); - PyObject *left = TOP(); - PyObject *res = PyNumber_InPlaceMultiply(left, right); - Py_DECREF(left); - Py_DECREF(right); - SET_TOP(res); - if (res == NULL) - goto error; - DISPATCH(); - } - - TARGET(INPLACE_MATRIX_MULTIPLY) { - PyObject *right = POP(); - PyObject *left = TOP(); - PyObject *res = PyNumber_InPlaceMatrixMultiply(left, right); - Py_DECREF(left); - Py_DECREF(right); - SET_TOP(res); - if (res == NULL) - goto error; - DISPATCH(); - } - - TARGET(INPLACE_TRUE_DIVIDE) { - PyObject *divisor = POP(); - PyObject *dividend = TOP(); - PyObject *quotient = PyNumber_InPlaceTrueDivide(dividend, divisor); - Py_DECREF(dividend); - Py_DECREF(divisor); - SET_TOP(quotient); - if (quotient == NULL) - goto error; - DISPATCH(); - } - - TARGET(INPLACE_FLOOR_DIVIDE) { - PyObject *divisor = POP(); - PyObject *dividend = TOP(); - PyObject *quotient = PyNumber_InPlaceFloorDivide(dividend, divisor); - Py_DECREF(dividend); - Py_DECREF(divisor); - SET_TOP(quotient); - if (quotient == NULL) - goto error; - DISPATCH(); - } - - TARGET(INPLACE_MODULO) { - PyObject *right = POP(); - PyObject *left = TOP(); - PyObject *mod = PyNumber_InPlaceRemainder(left, right); - Py_DECREF(left); - Py_DECREF(right); - SET_TOP(mod); - if (mod == NULL) - goto error; - DISPATCH(); - } - - TARGET(INPLACE_ADD) { - PyObject *right = POP(); - PyObject *left = TOP(); - PyObject *sum; - if (PyUnicode_CheckExact(left) && PyUnicode_CheckExact(right)) { - sum = unicode_concatenate(tstate, left, right, frame, next_instr); - /* unicode_concatenate consumed the ref to left */ - } - else { - sum = PyNumber_InPlaceAdd(left, right); - Py_DECREF(left); - } - Py_DECREF(right); - SET_TOP(sum); - if (sum == NULL) - goto error; - DISPATCH(); - } - - TARGET(INPLACE_SUBTRACT) { - PyObject *right = POP(); - PyObject *left = TOP(); - PyObject *diff = PyNumber_InPlaceSubtract(left, right); - Py_DECREF(left); - Py_DECREF(right); - SET_TOP(diff); - if (diff == NULL) - goto error; - DISPATCH(); - } - - TARGET(INPLACE_LSHIFT) { - PyObject *right = POP(); - PyObject *left = TOP(); - PyObject *res = PyNumber_InPlaceLshift(left, right); - Py_DECREF(left); - Py_DECREF(right); - SET_TOP(res); - if (res == NULL) - goto error; - DISPATCH(); - } - - TARGET(INPLACE_RSHIFT) { - PyObject *right = POP(); - PyObject *left = TOP(); - PyObject *res = PyNumber_InPlaceRshift(left, right); - Py_DECREF(left); - Py_DECREF(right); - SET_TOP(res); - if (res == NULL) - goto error; - DISPATCH(); - } - - TARGET(INPLACE_AND) { - PyObject *right = POP(); - PyObject *left = TOP(); - PyObject *res = PyNumber_InPlaceAnd(left, right); - Py_DECREF(left); - Py_DECREF(right); - SET_TOP(res); - if (res == NULL) - goto error; - DISPATCH(); - } - - TARGET(INPLACE_XOR) { - PyObject *right = POP(); - PyObject *left = TOP(); - PyObject *res = PyNumber_InPlaceXor(left, right); - Py_DECREF(left); - Py_DECREF(right); - SET_TOP(res); - if (res == NULL) - goto error; - DISPATCH(); - } - - TARGET(INPLACE_OR) { - PyObject *right = POP(); - PyObject *left = TOP(); - PyObject *res = PyNumber_InPlaceOr(left, right); - Py_DECREF(left); - Py_DECREF(right); - SET_TOP(res); - if (res == NULL) - goto error; - DISPATCH(); - } - TARGET(STORE_SUBSCR) { PyObject *sub = TOP(); PyObject *container = SECOND(); @@ -5032,6 +4661,130 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr DISPATCH(); } + TARGET(BINARY_OP) { + PREDICTED(BINARY_OP); + STAT_INC(BINARY_OP, unquickened); + PyObject *rhs = POP(); + PyObject *lhs = TOP(); + PyObject *res; + switch (oparg) { + case NB_ADD: + res = PyNumber_Add(lhs, rhs); + break; + case NB_AND: + res = PyNumber_And(lhs, rhs); + break; + case NB_FLOOR_DIVIDE: + res = PyNumber_FloorDivide(lhs, rhs); + break; + case NB_LSHIFT: + res = PyNumber_Lshift(lhs, rhs); + break; + case NB_MATRIX_MULTIPLY: + res = PyNumber_MatrixMultiply(lhs, rhs); + break; + case NB_MULTIPLY: + res = PyNumber_Multiply(lhs, rhs); + break; + case NB_REMAINDER: + if (PyUnicode_CheckExact(lhs) && + (!PyUnicode_Check(rhs) || PyUnicode_CheckExact(rhs))) + { + // bpo-28598: Fast path for string formatting (but not + // if the RHS is a str subclass). + res = PyUnicode_Format(lhs, rhs); + break; + } + res = PyNumber_Remainder(lhs, rhs); + break; + case NB_OR: + res = PyNumber_Or(lhs, rhs); + break; + case NB_POWER: + res = PyNumber_Power(lhs, rhs, Py_None); + break; + case NB_RSHIFT: + res = PyNumber_Rshift(lhs, rhs); + break; + case NB_SUBTRACT: + res = PyNumber_Subtract(lhs, rhs); + break; + case NB_TRUE_DIVIDE: + res = PyNumber_TrueDivide(lhs, rhs); + break; + case NB_XOR: + res = PyNumber_Xor(lhs, rhs); + break; + case NB_INPLACE_ADD: + res = PyNumber_InPlaceAdd(lhs, rhs); + break; + case NB_INPLACE_AND: + res = PyNumber_InPlaceAnd(lhs, rhs); + break; + case NB_INPLACE_FLOOR_DIVIDE: + res = PyNumber_InPlaceFloorDivide(lhs, rhs); + break; + case NB_INPLACE_LSHIFT: + res = PyNumber_InPlaceLshift(lhs, rhs); + break; + case NB_INPLACE_MATRIX_MULTIPLY: + res = PyNumber_InPlaceMatrixMultiply(lhs, rhs); + break; + case NB_INPLACE_MULTIPLY: + res = PyNumber_InPlaceMultiply(lhs, rhs); + break; + case NB_INPLACE_REMAINDER: + res = PyNumber_InPlaceRemainder(lhs, rhs); + break; + case NB_INPLACE_OR: + res = PyNumber_InPlaceOr(lhs, rhs); + break; + case NB_INPLACE_POWER: + res = PyNumber_InPlacePower(lhs, rhs, Py_None); + break; + case NB_INPLACE_RSHIFT: + res = PyNumber_InPlaceRshift(lhs, rhs); + break; + case NB_INPLACE_SUBTRACT: + res = PyNumber_InPlaceSubtract(lhs, rhs); + break; + case NB_INPLACE_TRUE_DIVIDE: + res = PyNumber_InPlaceTrueDivide(lhs, rhs); + break; + case NB_INPLACE_XOR: + res = PyNumber_InPlaceXor(lhs, rhs); + break; + default: + Py_UNREACHABLE(); + } + Py_DECREF(lhs); + Py_DECREF(rhs); + SET_TOP(res); + if (res == NULL) { + goto error; + } + DISPATCH(); + } + + TARGET(BINARY_OP_ADAPTIVE) { + assert(cframe.use_tracing == 0); + SpecializedCacheEntry *cache = GET_CACHE(); + if (cache->adaptive.counter == 0) { + PyObject *lhs = SECOND(); + PyObject *rhs = TOP(); + next_instr--; + _Py_Specialize_BinaryOp(lhs, rhs, next_instr, cache); + DISPATCH(); + } + else { + STAT_INC(BINARY_OP, deferred); + cache->adaptive.counter--; + oparg = cache->adaptive.original_oparg; + STAT_DEC(BINARY_OP, unquickened); + JUMP_TO_INSTRUCTION(BINARY_OP); + } + } + TARGET(EXTENDED_ARG) { int oldoparg = oparg; NEXTOPARG(); @@ -5137,9 +4890,8 @@ MISS_WITH_CACHE(STORE_ATTR) MISS_WITH_CACHE(LOAD_GLOBAL) MISS_WITH_CACHE(LOAD_METHOD) MISS_WITH_CACHE(CALL_FUNCTION) +MISS_WITH_CACHE(BINARY_OP) MISS_WITH_OPARG_COUNTER(BINARY_SUBSCR) -MISS_WITH_OPARG_COUNTER(BINARY_ADD) -MISS_WITH_OPARG_COUNTER(BINARY_MULTIPLY) binary_subscr_dict_error: { @@ -7173,60 +6925,6 @@ format_awaitable_error(PyThreadState *tstate, PyTypeObject *type, int prevprevop } } -static PyObject * -unicode_concatenate(PyThreadState *tstate, PyObject *v, PyObject *w, - InterpreterFrame *frame, const _Py_CODEUNIT *next_instr) -{ - PyObject *res; - if (Py_REFCNT(v) == 2) { - /* In the common case, there are 2 references to the value - * stored in 'variable' when the += is performed: one on the - * value stack (in 'v') and one still stored in the - * 'variable'. We try to delete the variable now to reduce - * the refcnt to 1. - */ - int opcode, oparg; - NEXTOPARG(); - next_instr++; - switch (opcode) { - case STORE_FAST: - { - if (GETLOCAL(oparg) == v) - SETLOCAL(oparg, NULL); - break; - } - case STORE_DEREF: - { - PyObject *c = _PyFrame_GetLocalsArray(frame)[oparg]; - if (PyCell_GET(c) == v) { - PyCell_SET(c, NULL); - Py_DECREF(v); - } - break; - } - case STORE_NAME: - { - PyObject *names = frame->f_code->co_names; - PyObject *name = GETITEM(names, oparg); - PyObject *locals = frame->f_locals; - if (locals && PyDict_CheckExact(locals)) { - PyObject *w = PyDict_GetItemWithError(locals, name); - if ((w == v && PyDict_DelItem(locals, name) != 0) || - (w == NULL && _PyErr_Occurred(tstate))) - { - Py_DECREF(v); - return NULL; - } - } - break; - } - } - } - res = v; - PyUnicode_Append(&res, w); - return res; -} - #ifdef DYNAMIC_EXECUTION_PROFILE static PyObject * diff --git a/Python/compile.c b/Python/compile.c index 47889abe61223..8135f18755980 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -309,7 +309,6 @@ static int compiler_annassign(struct compiler *, stmt_ty); static int compiler_subscript(struct compiler *, expr_ty); static int compiler_slice(struct compiler *, expr_ty); -static int inplace_binop(operator_ty); static int are_all_items_const(asdl_expr_seq *, Py_ssize_t, Py_ssize_t); @@ -1022,40 +1021,13 @@ stack_effect(int opcode, int oparg, int jump) case MAP_ADD: return -2; - /* Binary operators */ - case BINARY_POWER: - case BINARY_MULTIPLY: - case BINARY_MATRIX_MULTIPLY: - case BINARY_MODULO: - case BINARY_ADD: - case BINARY_SUBTRACT: case BINARY_SUBSCR: - case BINARY_FLOOR_DIVIDE: - case BINARY_TRUE_DIVIDE: - return -1; - case INPLACE_FLOOR_DIVIDE: - case INPLACE_TRUE_DIVIDE: - return -1; - - case INPLACE_ADD: - case INPLACE_SUBTRACT: - case INPLACE_MULTIPLY: - case INPLACE_MATRIX_MULTIPLY: - case INPLACE_MODULO: return -1; case STORE_SUBSCR: return -3; case DELETE_SUBSCR: return -2; - case BINARY_LSHIFT: - case BINARY_RSHIFT: - case BINARY_AND: - case BINARY_XOR: - case BINARY_OR: - return -1; - case INPLACE_POWER: - return -1; case GET_ITER: return 0; @@ -1063,12 +1035,6 @@ stack_effect(int opcode, int oparg, int jump) return -1; case LOAD_BUILD_CLASS: return 1; - case INPLACE_LSHIFT: - case INPLACE_RSHIFT: - case INPLACE_AND: - case INPLACE_XOR: - case INPLACE_OR: - return -1; case RETURN_VALUE: return -1; @@ -1259,6 +1225,8 @@ stack_effect(int opcode, int oparg, int jump) return 0; case COPY: return 1; + case BINARY_OP: + return -1; default: return PY_INVALID_STACK_EFFECT; } @@ -1685,6 +1653,12 @@ compiler_addop_j_noline(struct compiler *c, int opcode, basicblock *b) return 0; \ } +#define ADDOP_BINARY(C, BINOP) \ + RETURN_IF_FALSE(addop_binary((C), (BINOP), false)) + +#define ADDOP_INPLACE(C, BINOP) \ + RETURN_IF_FALSE(addop_binary((C), (BINOP), true)) + /* VISIT and VISIT_SEQ takes an ASDL type as their second argument. They use the ASDL name to synthesize the name of the C type and the visit function. */ @@ -3693,77 +3667,56 @@ unaryop(unaryop_ty op) } static int -binop(operator_ty op) -{ - switch (op) { - case Add: - return BINARY_ADD; - case Sub: - return BINARY_SUBTRACT; - case Mult: - return BINARY_MULTIPLY; - case MatMult: - return BINARY_MATRIX_MULTIPLY; - case Div: - return BINARY_TRUE_DIVIDE; - case Mod: - return BINARY_MODULO; - case Pow: - return BINARY_POWER; - case LShift: - return BINARY_LSHIFT; - case RShift: - return BINARY_RSHIFT; - case BitOr: - return BINARY_OR; - case BitXor: - return BINARY_XOR; - case BitAnd: - return BINARY_AND; - case FloorDiv: - return BINARY_FLOOR_DIVIDE; - default: - PyErr_Format(PyExc_SystemError, - "binary op %d should not be possible", op); - return 0; - } -} - -static int -inplace_binop(operator_ty op) +addop_binary(struct compiler *c, operator_ty binop, bool inplace) { - switch (op) { - case Add: - return INPLACE_ADD; - case Sub: - return INPLACE_SUBTRACT; - case Mult: - return INPLACE_MULTIPLY; - case MatMult: - return INPLACE_MATRIX_MULTIPLY; - case Div: - return INPLACE_TRUE_DIVIDE; - case Mod: - return INPLACE_MODULO; - case Pow: - return INPLACE_POWER; - case LShift: - return INPLACE_LSHIFT; - case RShift: - return INPLACE_RSHIFT; - case BitOr: - return INPLACE_OR; - case BitXor: - return INPLACE_XOR; - case BitAnd: - return INPLACE_AND; - case FloorDiv: - return INPLACE_FLOOR_DIVIDE; - default: - PyErr_Format(PyExc_SystemError, - "inplace binary op %d should not be possible", op); - return 0; + int oparg; + switch (binop) { + case Add: + oparg = inplace ? NB_INPLACE_ADD : NB_ADD; + break; + case Sub: + oparg = inplace ? NB_INPLACE_SUBTRACT : NB_SUBTRACT; + break; + case Mult: + oparg = inplace ? NB_INPLACE_MULTIPLY : NB_MULTIPLY; + break; + case MatMult: + oparg = inplace ? NB_INPLACE_MATRIX_MULTIPLY : NB_MATRIX_MULTIPLY; + break; + case Div: + oparg = inplace ? NB_INPLACE_TRUE_DIVIDE : NB_TRUE_DIVIDE; + break; + case Mod: + oparg = inplace ? NB_INPLACE_REMAINDER : NB_REMAINDER; + break; + case Pow: + oparg = inplace ? NB_INPLACE_POWER : NB_POWER; + break; + case LShift: + oparg = inplace ? NB_INPLACE_LSHIFT : NB_LSHIFT; + break; + case RShift: + oparg = inplace ? NB_INPLACE_RSHIFT : NB_RSHIFT; + break; + case BitOr: + oparg = inplace ? NB_INPLACE_OR : NB_OR; + break; + case BitXor: + oparg = inplace ? NB_INPLACE_XOR : NB_XOR; + break; + case BitAnd: + oparg = inplace ? NB_INPLACE_AND : NB_AND; + break; + case FloorDiv: + oparg = inplace ? NB_INPLACE_FLOOR_DIVIDE : NB_FLOOR_DIVIDE; + break; + default: + PyErr_Format(PyExc_SystemError, "%s op %d should not be possible", + inplace ? "inplace" : "binary", binop); + return 0; } + ADDOP_I(c, BINARY_OP, oparg); + return 1; } static int @@ -5354,7 +5307,7 @@ compiler_visit_expr1(struct compiler *c, expr_ty e) case BinOp_kind: VISIT(c, expr, e->v.BinOp.left); VISIT(c, expr, e->v.BinOp.right); - ADDOP(c, binop(e->v.BinOp.op)); + ADDOP_BINARY(c, e->v.BinOp.op); break; case UnaryOp_kind: VISIT(c, expr, e->v.UnaryOp.operand); @@ -5540,7 +5493,7 @@ compiler_augassign(struct compiler *c, stmt_ty s) c->u->u_end_col_offset = old_end_col_offset; VISIT(c, expr, s->v.AugAssign.value); - ADDOP(c, inplace_binop(s->v.AugAssign.op)); + ADDOP_INPLACE(c, s->v.AugAssign.op); SET_LOC(c, e); @@ -6000,7 +5953,7 @@ pattern_helper_sequence_subscr(struct compiler *c, asdl_pattern_seq *patterns, // nonnegative index: ADDOP(c, GET_LEN); ADDOP_LOAD_CONST_NEW(c, PyLong_FromSsize_t(size - i)); - ADDOP(c, BINARY_SUBTRACT); + ADDOP_BINARY(c, Sub); } ADDOP(c, BINARY_SUBSCR); RETURN_IF_FALSE(compiler_pattern_subpattern(c, pattern, pc)); diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 93a9e4ab42cfb..a57617e022e1d 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -6,67 +6,67 @@ static void *opcode_targets[256] = { &&TARGET_DUP_TOP, &&TARGET_DUP_TOP_TWO, &&TARGET_ROT_FOUR, - &&TARGET_BINARY_ADD_ADAPTIVE, - &&TARGET_BINARY_ADD_INT, + &&TARGET_BINARY_OP_ADAPTIVE, + &&TARGET_BINARY_OP_ADD_INT, &&TARGET_NOP, &&TARGET_UNARY_POSITIVE, &&TARGET_UNARY_NEGATIVE, &&TARGET_UNARY_NOT, - &&TARGET_BINARY_ADD_FLOAT, - &&TARGET_BINARY_ADD_UNICODE, + &&TARGET_BINARY_OP_ADD_FLOAT, + &&TARGET_BINARY_OP_ADD_UNICODE, &&TARGET_UNARY_INVERT, - &&TARGET_BINARY_MATRIX_MULTIPLY, - &&TARGET_INPLACE_MATRIX_MULTIPLY, - &&TARGET_BINARY_ADD_UNICODE_INPLACE_FAST, - &&TARGET_BINARY_POWER, - &&TARGET_BINARY_MULTIPLY, - &&TARGET_BINARY_MULTIPLY_ADAPTIVE, - &&TARGET_BINARY_MODULO, - &&TARGET_BINARY_ADD, - &&TARGET_BINARY_SUBTRACT, - &&TARGET_BINARY_SUBSCR, - &&TARGET_BINARY_FLOOR_DIVIDE, - &&TARGET_BINARY_TRUE_DIVIDE, - &&TARGET_INPLACE_FLOOR_DIVIDE, - &&TARGET_INPLACE_TRUE_DIVIDE, - &&TARGET_GET_LEN, - &&TARGET_MATCH_MAPPING, - &&TARGET_MATCH_SEQUENCE, - &&TARGET_MATCH_KEYS, - &&TARGET_BINARY_MULTIPLY_INT, - &&TARGET_PUSH_EXC_INFO, - &&TARGET_BINARY_MULTIPLY_FLOAT, - &&TARGET_POP_EXCEPT_AND_RERAISE, + &&TARGET_BINARY_OP_INPLACE_ADD_UNICODE, + &&TARGET_BINARY_OP_MULTIPLY_INT, + &&TARGET_BINARY_OP_MULTIPLY_FLOAT, &&TARGET_BINARY_SUBSCR_ADAPTIVE, &&TARGET_BINARY_SUBSCR_LIST_INT, &&TARGET_BINARY_SUBSCR_TUPLE_INT, &&TARGET_BINARY_SUBSCR_DICT, &&TARGET_CALL_FUNCTION_ADAPTIVE, &&TARGET_CALL_FUNCTION_BUILTIN_O, + &&TARGET_BINARY_SUBSCR, &&TARGET_CALL_FUNCTION_BUILTIN_FAST, &&TARGET_CALL_FUNCTION_LEN, &&TARGET_CALL_FUNCTION_ISINSTANCE, &&TARGET_CALL_FUNCTION_PY_SIMPLE, + &&TARGET_GET_LEN, + &&TARGET_MATCH_MAPPING, + &&TARGET_MATCH_SEQUENCE, + &&TARGET_MATCH_KEYS, &&TARGET_JUMP_ABSOLUTE_QUICK, + &&TARGET_PUSH_EXC_INFO, + &&TARGET_LOAD_ATTR_ADAPTIVE, + &&TARGET_POP_EXCEPT_AND_RERAISE, + &&TARGET_LOAD_ATTR_INSTANCE_VALUE, + &&TARGET_LOAD_ATTR_WITH_HINT, + &&TARGET_LOAD_ATTR_SLOT, + &&TARGET_LOAD_ATTR_MODULE, + &&TARGET_LOAD_GLOBAL_ADAPTIVE, + &&TARGET_LOAD_GLOBAL_MODULE, + &&TARGET_LOAD_GLOBAL_BUILTIN, + &&TARGET_LOAD_METHOD_ADAPTIVE, + &&TARGET_LOAD_METHOD_CACHED, + &&TARGET_LOAD_METHOD_CLASS, + &&TARGET_LOAD_METHOD_MODULE, &&TARGET_WITH_EXCEPT_START, &&TARGET_GET_AITER, &&TARGET_GET_ANEXT, &&TARGET_BEFORE_ASYNC_WITH, &&TARGET_BEFORE_WITH, &&TARGET_END_ASYNC_FOR, - &&TARGET_INPLACE_ADD, - &&TARGET_INPLACE_SUBTRACT, - &&TARGET_INPLACE_MULTIPLY, - &&TARGET_LOAD_ATTR_ADAPTIVE, - &&TARGET_INPLACE_MODULO, + &&TARGET_LOAD_METHOD_NO_DICT, + &&TARGET_STORE_ATTR_ADAPTIVE, + &&TARGET_STORE_ATTR_INSTANCE_VALUE, + &&TARGET_STORE_ATTR_SLOT, + &&TARGET_STORE_ATTR_WITH_HINT, &&TARGET_STORE_SUBSCR, &&TARGET_DELETE_SUBSCR, - &&TARGET_BINARY_LSHIFT, - &&TARGET_BINARY_RSHIFT, - &&TARGET_BINARY_AND, - &&TARGET_BINARY_XOR, - &&TARGET_BINARY_OR, - &&TARGET_INPLACE_POWER, + &&TARGET_LOAD_FAST__LOAD_FAST, + &&TARGET_STORE_FAST__LOAD_FAST, + &&TARGET_LOAD_FAST__LOAD_CONST, + &&TARGET_LOAD_CONST__LOAD_FAST, + &&TARGET_STORE_FAST__STORE_FAST, + &&_unknown_opcode, &&TARGET_GET_ITER, &&TARGET_GET_YIELD_FROM_ITER, &&TARGET_PRINT_EXPR, @@ -74,20 +74,20 @@ static void *opcode_targets[256] = { &&TARGET_YIELD_FROM, &&TARGET_GET_AWAITABLE, &&TARGET_LOAD_ASSERTION_ERROR, - &&TARGET_INPLACE_LSHIFT, - &&TARGET_INPLACE_RSHIFT, - &&TARGET_INPLACE_AND, - &&TARGET_INPLACE_XOR, - &&TARGET_INPLACE_OR, - &&TARGET_LOAD_ATTR_INSTANCE_VALUE, - &&TARGET_LOAD_ATTR_WITH_HINT, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, &&TARGET_LIST_TO_TUPLE, &&TARGET_RETURN_VALUE, &&TARGET_IMPORT_STAR, &&TARGET_SETUP_ANNOTATIONS, &&TARGET_YIELD_VALUE, - &&TARGET_LOAD_ATTR_SLOT, - &&TARGET_LOAD_ATTR_MODULE, + &&_unknown_opcode, + &&_unknown_opcode, &&TARGET_POP_EXCEPT, &&TARGET_STORE_NAME, &&TARGET_DELETE_NAME, @@ -121,44 +121,44 @@ static void *opcode_targets[256] = { &&TARGET_RERAISE, &&TARGET_COPY, &&TARGET_JUMP_IF_NOT_EXC_MATCH, - &&TARGET_LOAD_GLOBAL_ADAPTIVE, - &&TARGET_LOAD_GLOBAL_MODULE, + &&TARGET_BINARY_OP, + &&_unknown_opcode, &&TARGET_LOAD_FAST, &&TARGET_STORE_FAST, &&TARGET_DELETE_FAST, - &&TARGET_LOAD_GLOBAL_BUILTIN, - &&TARGET_LOAD_METHOD_ADAPTIVE, + &&_unknown_opcode, + &&_unknown_opcode, &&TARGET_GEN_START, &&TARGET_RAISE_VARARGS, &&TARGET_CALL_FUNCTION, &&TARGET_MAKE_FUNCTION, &&TARGET_BUILD_SLICE, - &&TARGET_LOAD_METHOD_CACHED, + &&_unknown_opcode, &&TARGET_MAKE_CELL, &&TARGET_LOAD_CLOSURE, &&TARGET_LOAD_DEREF, &&TARGET_STORE_DEREF, &&TARGET_DELETE_DEREF, - &&TARGET_LOAD_METHOD_CLASS, + &&_unknown_opcode, &&TARGET_CALL_FUNCTION_KW, &&TARGET_CALL_FUNCTION_EX, - &&TARGET_LOAD_METHOD_MODULE, + &&_unknown_opcode, &&TARGET_EXTENDED_ARG, &&TARGET_LIST_APPEND, &&TARGET_SET_ADD, &&TARGET_MAP_ADD, &&TARGET_LOAD_CLASSDEREF, - &&TARGET_LOAD_METHOD_NO_DICT, - &&TARGET_STORE_ATTR_ADAPTIVE, - &&TARGET_STORE_ATTR_INSTANCE_VALUE, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, &&TARGET_MATCH_CLASS, - &&TARGET_STORE_ATTR_SLOT, - &&TARGET_STORE_ATTR_WITH_HINT, + &&_unknown_opcode, + &&_unknown_opcode, &&TARGET_FORMAT_VALUE, &&TARGET_BUILD_CONST_KEY_MAP, &&TARGET_BUILD_STRING, - &&TARGET_LOAD_FAST__LOAD_FAST, - &&TARGET_STORE_FAST__LOAD_FAST, + &&_unknown_opcode, + &&_unknown_opcode, &&TARGET_LOAD_METHOD, &&TARGET_CALL_METHOD, &&TARGET_LIST_EXTEND, @@ -166,9 +166,9 @@ static void *opcode_targets[256] = { &&TARGET_DICT_MERGE, &&TARGET_DICT_UPDATE, &&TARGET_CALL_METHOD_KW, - &&TARGET_LOAD_FAST__LOAD_CONST, - &&TARGET_LOAD_CONST__LOAD_FAST, - &&TARGET_STORE_FAST__STORE_FAST, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, diff --git a/Python/specialize.c b/Python/specialize.c index 162728314e100..7e72013cd8359 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -124,11 +124,10 @@ _Py_GetSpecializationStats(void) { err += add_stat_dict(stats, LOAD_ATTR, "load_attr"); err += add_stat_dict(stats, LOAD_GLOBAL, "load_global"); err += add_stat_dict(stats, LOAD_METHOD, "load_method"); - err += add_stat_dict(stats, BINARY_ADD, "binary_add"); - err += add_stat_dict(stats, BINARY_MULTIPLY, "binary_multiply"); err += add_stat_dict(stats, BINARY_SUBSCR, "binary_subscr"); err += add_stat_dict(stats, STORE_ATTR, "store_attr"); err += add_stat_dict(stats, CALL_FUNCTION, "call_function"); + err += add_stat_dict(stats, BINARY_OP, "binary_op"); if (err < 0) { Py_DECREF(stats); return NULL; @@ -182,11 +181,10 @@ _Py_PrintSpecializationStats(void) print_stats(out, &_specialization_stats[LOAD_ATTR], "load_attr"); print_stats(out, &_specialization_stats[LOAD_GLOBAL], "load_global"); print_stats(out, &_specialization_stats[LOAD_METHOD], "load_method"); - print_stats(out, &_specialization_stats[BINARY_ADD], "binary_add"); - print_stats(out, &_specialization_stats[BINARY_MULTIPLY], "binary_multiply"); print_stats(out, &_specialization_stats[BINARY_SUBSCR], "binary_subscr"); print_stats(out, &_specialization_stats[STORE_ATTR], "store_attr"); print_stats(out, &_specialization_stats[CALL_FUNCTION], "call_function"); + print_stats(out, &_specialization_stats[BINARY_OP], "binary_op"); if (out != stderr) { fclose(out); } @@ -234,11 +232,10 @@ static uint8_t adaptive_opcodes[256] = { [LOAD_ATTR] = LOAD_ATTR_ADAPTIVE, [LOAD_GLOBAL] = LOAD_GLOBAL_ADAPTIVE, [LOAD_METHOD] = LOAD_METHOD_ADAPTIVE, - [BINARY_ADD] = BINARY_ADD_ADAPTIVE, - [BINARY_MULTIPLY] = BINARY_MULTIPLY_ADAPTIVE, [BINARY_SUBSCR] = BINARY_SUBSCR_ADAPTIVE, [CALL_FUNCTION] = CALL_FUNCTION_ADAPTIVE, [STORE_ATTR] = STORE_ATTR_ADAPTIVE, + [BINARY_OP] = BINARY_OP_ADAPTIVE, }; /* The number of cache entries required for a "family" of instructions. */ @@ -246,11 +243,10 @@ static uint8_t cache_requirements[256] = { [LOAD_ATTR] = 2, /* _PyAdaptiveEntry and _PyAttrCache */ [LOAD_GLOBAL] = 2, /* _PyAdaptiveEntry and _PyLoadGlobalCache */ [LOAD_METHOD] = 3, /* _PyAdaptiveEntry, _PyAttrCache and _PyObjectCache */ - [BINARY_ADD] = 0, - [BINARY_MULTIPLY] = 0, [BINARY_SUBSCR] = 0, [CALL_FUNCTION] = 2, /* _PyAdaptiveEntry and _PyObjectCache/_PyCallCache */ [STORE_ATTR] = 2, /* _PyAdaptiveEntry and _PyAttrCache */ + [BINARY_OP] = 1, // _PyAdaptiveEntry }; /* Return the oparg for the cache_offset and instruction index. @@ -1183,76 +1179,6 @@ _Py_Specialize_BinarySubscr( return 0; } -int -_Py_Specialize_BinaryAdd(PyObject *left, PyObject *right, _Py_CODEUNIT *instr) -{ - PyTypeObject *left_type = Py_TYPE(left); - if (left_type != Py_TYPE(right)) { - SPECIALIZATION_FAIL(BINARY_ADD, SPEC_FAIL_DIFFERENT_TYPES); - goto fail; - } - if (left_type == &PyUnicode_Type) { - int next_opcode = _Py_OPCODE(instr[1]); - if (next_opcode == STORE_FAST) { - *instr = _Py_MAKECODEUNIT(BINARY_ADD_UNICODE_INPLACE_FAST, initial_counter_value()); - } - else { - *instr = _Py_MAKECODEUNIT(BINARY_ADD_UNICODE, initial_counter_value()); - } - goto success; - } - else if (left_type == &PyLong_Type) { - *instr = _Py_MAKECODEUNIT(BINARY_ADD_INT, initial_counter_value()); - goto success; - } - else if (left_type == &PyFloat_Type) { - *instr = _Py_MAKECODEUNIT(BINARY_ADD_FLOAT, initial_counter_value()); - goto success; - - } - else { - SPECIALIZATION_FAIL(BINARY_ADD, SPEC_FAIL_OTHER); - } -fail: - STAT_INC(BINARY_ADD, specialization_failure); - assert(!PyErr_Occurred()); - *instr = _Py_MAKECODEUNIT(_Py_OPCODE(*instr), ADAPTIVE_CACHE_BACKOFF); - return 0; -success: - STAT_INC(BINARY_ADD, specialization_success); - assert(!PyErr_Occurred()); - return 0; -} - -int -_Py_Specialize_BinaryMultiply(PyObject *left, PyObject *right, _Py_CODEUNIT *instr) -{ - if (!Py_IS_TYPE(left, Py_TYPE(right))) { - SPECIALIZATION_FAIL(BINARY_MULTIPLY, SPEC_FAIL_DIFFERENT_TYPES); - goto fail; - } - if (PyLong_CheckExact(left)) { - *instr = _Py_MAKECODEUNIT(BINARY_MULTIPLY_INT, initial_counter_value()); - goto success; - } - else if (PyFloat_CheckExact(left)) { - *instr = _Py_MAKECODEUNIT(BINARY_MULTIPLY_FLOAT, initial_counter_value()); - goto success; - } - else { - SPECIALIZATION_FAIL(BINARY_MULTIPLY, SPEC_FAIL_OTHER); - } -fail: - STAT_INC(BINARY_MULTIPLY, specialization_failure); - assert(!PyErr_Occurred()); - *instr = _Py_MAKECODEUNIT(_Py_OPCODE(*instr), ADAPTIVE_CACHE_BACKOFF); - return 0; -success: - STAT_INC(BINARY_MULTIPLY, specialization_success); - assert(!PyErr_Occurred()); - return 0; -} - static int specialize_class_call( PyObject *callable, _Py_CODEUNIT *instr, @@ -1448,3 +1374,64 @@ _Py_Specialize_CallFunction( } return 0; } + +void +_Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, + SpecializedCacheEntry *cache) +{ + _PyAdaptiveEntry *adaptive = &cache->adaptive; + if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) { + SPECIALIZATION_FAIL(BINARY_OP, SPEC_FAIL_DIFFERENT_TYPES); + goto failure; + } + switch (adaptive->original_oparg) { + case NB_ADD: + case NB_INPLACE_ADD: + if (PyUnicode_CheckExact(lhs)) { + if (_Py_OPCODE(instr[1]) == STORE_FAST && Py_REFCNT(lhs) == 2) { + *instr = _Py_MAKECODEUNIT(BINARY_OP_INPLACE_ADD_UNICODE, + _Py_OPARG(*instr)); + goto success; + } + *instr = _Py_MAKECODEUNIT(BINARY_OP_ADD_UNICODE, + _Py_OPARG(*instr)); + goto success; + } + if (PyLong_CheckExact(lhs)) { + *instr = _Py_MAKECODEUNIT(BINARY_OP_ADD_INT, _Py_OPARG(*instr)); + goto success; + } + if (PyFloat_CheckExact(lhs)) { + *instr = _Py_MAKECODEUNIT(BINARY_OP_ADD_FLOAT, + _Py_OPARG(*instr)); + goto success; + } + break; + case NB_MULTIPLY: + case NB_INPLACE_MULTIPLY: + if (PyLong_CheckExact(lhs)) { + *instr = _Py_MAKECODEUNIT(BINARY_OP_MULTIPLY_INT, + _Py_OPARG(*instr)); + goto success; + } + if (PyFloat_CheckExact(lhs)) { + *instr = _Py_MAKECODEUNIT(BINARY_OP_MULTIPLY_FLOAT, + _Py_OPARG(*instr)); + goto success; + } + break; + default: + // These operators don't have any available specializations. Rather + // than repeatedly attempting to specialize them, just convert them + // back to BINARY_OP (while still recording a failure, of course)! + *instr = _Py_MAKECODEUNIT(BINARY_OP, adaptive->original_oparg); + } + SPECIALIZATION_FAIL(BINARY_OP, SPEC_FAIL_OTHER); +failure: + STAT_INC(BINARY_OP, specialization_failure); + cache_backoff(adaptive); + return; +success: + STAT_INC(BINARY_OP, specialization_success); + adaptive->counter = initial_counter_value(); +} diff --git a/Tools/scripts/generate_opcode_h.py b/Tools/scripts/generate_opcode_h.py index dca9bbcfcbc83..0ee4b95bbfdeb 100644 --- a/Tools/scripts/generate_opcode_h.py +++ b/Tools/scripts/generate_opcode_h.py @@ -12,7 +12,7 @@ #endif - /* Instruction opcodes for compiled code */ +/* Instruction opcodes for compiled code */ """.lstrip() footer = """ @@ -28,6 +28,8 @@ #endif /* !Py_OPCODE_H */ """ +DEFINE = "#define {:<31} {:>3}\n" + UINT32_MASK = (1<<32)-1 def write_int_array_from_ops(name, ops, out): @@ -62,17 +64,16 @@ def main(opcode_py, outfile='Include/opcode.h'): fobj.write(header) for name in opcode['opname']: if name in opmap: - fobj.write("#define %-23s %3s\n" % (name, opmap[name])) + fobj.write(DEFINE.format(name, opmap[name])) if name == 'POP_EXCEPT': # Special entry for HAVE_ARGUMENT - fobj.write("#define %-23s %3d\n" % - ('HAVE_ARGUMENT', opcode['HAVE_ARGUMENT'])) + fobj.write(DEFINE.format("HAVE_ARGUMENT", opcode["HAVE_ARGUMENT"])) for name in opcode['_specialized_instructions']: while used[next_op]: next_op += 1 - fobj.write("#define %-23s %3s\n" % (name, next_op)) + fobj.write(DEFINE.format(name, next_op)) used[next_op] = True - fobj.write("#define DO_TRACING 255\n") + fobj.write(DEFINE.format('DO_TRACING', 255)) fobj.write("#ifdef NEED_OPCODE_JUMP_TABLES\n") write_int_array_from_ops("_PyOpcode_RelativeJump", opcode['hasjrel'], fobj) write_int_array_from_ops("_PyOpcode_Jump", opcode['hasjrel'] + opcode['hasjabs'], fobj) @@ -84,10 +85,14 @@ def main(opcode_py, outfile='Include/opcode.h'): fobj.write(f"\n || ((op) == {op}) \\") fobj.write("\n )\n") + fobj.write("\n") + for i, (op, _) in enumerate(opcode["_nb_ops"]): + fobj.write(DEFINE.format(op, i)) + fobj.write(footer) - print("%s regenerated from %s" % (outfile, opcode_py)) + print(f"{outfile} regenerated from {opcode_py}") if __name__ == '__main__': From webhook-mailer at python.org Thu Nov 11 14:44:40 2021 From: webhook-mailer at python.org (brandtbucher) Date: Thu, 11 Nov 2021 19:44:40 -0000 Subject: [Python-checkins] bpo-45773: Stop "optimizing" certain jump patterns (GH-29505) Message-ID: https://github.com/python/cpython/commit/27b69e60daa7b191ee6bc76fb6d5fb7d793062ab commit: 27b69e60daa7b191ee6bc76fb6d5fb7d793062ab branch: main author: Brandt Bucher committer: brandtbucher date: 2021-11-11T11:44:34-08:00 summary: bpo-45773: Stop "optimizing" certain jump patterns (GH-29505) files: A Misc/NEWS.d/next/Core and Builtins/2021-11-09-13-01-35.bpo-45773.POU8A4.rst M Lib/test/test_peepholer.py M Python/compile.c diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index 7086a42b09560..8306c896a57f4 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -600,5 +600,12 @@ def test_bpo_42057(self): except Exception or Exception: pass + def test_bpo_45773_pop_jump_if_true(self): + compile("while True or spam: pass", "", "exec") + + def test_bpo_45773_pop_jump_if_false(self): + compile("while True or not spam: pass", "", "exec") + + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-09-13-01-35.bpo-45773.POU8A4.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-09-13-01-35.bpo-45773.POU8A4.rst new file mode 100644 index 0000000000000..2b9ba81be233f --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-09-13-01-35.bpo-45773.POU8A4.rst @@ -0,0 +1 @@ +Fix a compiler hang when attempting to optimize certain jump patterns. diff --git a/Python/compile.c b/Python/compile.c index 8135f18755980..1ae4b6575a7f4 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -8052,29 +8052,24 @@ fold_rotations(struct instr *inst, int n) } } - -static int -eliminate_jump_to_jump(basicblock *bb, int opcode) { - assert (bb->b_iused > 0); - struct instr *inst = &bb->b_instr[bb->b_iused-1]; - assert (is_jump(inst)); - assert (inst->i_target->b_iused > 0); - struct instr *target = &inst->i_target->b_instr[0]; - if (inst->i_target == target->i_target) { - /* Nothing to do */ - return 0; - } - int lineno = target->i_lineno; - int end_lineno = target->i_end_lineno; - int col_offset = target->i_col_offset; - int end_col_offset = target->i_end_col_offset; - if (add_jump_to_block(bb, opcode, lineno, end_lineno, col_offset, - end_col_offset, target->i_target) == 0) { - return -1; +// Attempt to eliminate jumps to jumps by updating inst to jump to +// target->i_target using the provided opcode. Return whether or not the +// optimization was successful. +static bool +jump_thread(struct instr *inst, struct instr *target, int opcode) +{ + assert(is_jump(inst)); + assert(is_jump(target)); + // bpo-45773: If inst->i_target == target->i_target, then nothing actually + // changes (and we fall into an infinite loop): + if (inst->i_lineno == target->i_lineno && + inst->i_target != target->i_target) + { + inst->i_target = target->i_target; + inst->i_opcode = opcode; + return true; } - assert (bb->b_iused >= 2); - bb->b_instr[bb->b_iused-2].i_opcode = NOP; - return 0; + return false; } /* Maximum size of basic block that should be copied in optimizer */ @@ -8199,25 +8194,21 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) where y+1 is the instruction following the second test. */ case JUMP_IF_FALSE_OR_POP: - switch(target->i_opcode) { + switch (target->i_opcode) { case POP_JUMP_IF_FALSE: - if (inst->i_lineno == target->i_lineno) { - *inst = *target; - i--; - } + i -= jump_thread(inst, target, POP_JUMP_IF_FALSE); break; case JUMP_ABSOLUTE: case JUMP_FORWARD: case JUMP_IF_FALSE_OR_POP: - if (inst->i_lineno == target->i_lineno && - inst->i_target != target->i_target) { - inst->i_target = target->i_target; - i--; - } + i -= jump_thread(inst, target, JUMP_IF_FALSE_OR_POP); break; case JUMP_IF_TRUE_OR_POP: - assert (inst->i_target->b_iused == 1); + case POP_JUMP_IF_TRUE: if (inst->i_lineno == target->i_lineno) { + // We don't need to bother checking for loops here, + // since a block's b_next cannot point to itself: + assert(inst->i_target != inst->i_target->b_next); inst->i_opcode = POP_JUMP_IF_FALSE; inst->i_target = inst->i_target->b_next; --i; @@ -8225,27 +8216,22 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) break; } break; - case JUMP_IF_TRUE_OR_POP: - switch(target->i_opcode) { + switch (target->i_opcode) { case POP_JUMP_IF_TRUE: - if (inst->i_lineno == target->i_lineno) { - *inst = *target; - i--; - } + i -= jump_thread(inst, target, POP_JUMP_IF_TRUE); break; case JUMP_ABSOLUTE: case JUMP_FORWARD: case JUMP_IF_TRUE_OR_POP: - if (inst->i_lineno == target->i_lineno && - inst->i_target != target->i_target) { - inst->i_target = target->i_target; - i--; - } + i -= jump_thread(inst, target, JUMP_IF_TRUE_OR_POP); break; case JUMP_IF_FALSE_OR_POP: - assert (inst->i_target->b_iused == 1); + case POP_JUMP_IF_FALSE: if (inst->i_lineno == target->i_lineno) { + // We don't need to bother checking for loops here, + // since a block's b_next cannot point to itself: + assert(inst->i_target != inst->i_target->b_next); inst->i_opcode = POP_JUMP_IF_TRUE; inst->i_target = inst->i_target->b_next; --i; @@ -8253,54 +8239,33 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) break; } break; - case POP_JUMP_IF_FALSE: - switch(target->i_opcode) { + switch (target->i_opcode) { case JUMP_ABSOLUTE: case JUMP_FORWARD: - if (inst->i_lineno == target->i_lineno) { - inst->i_target = target->i_target; - i--; - } - break; + case JUMP_IF_FALSE_OR_POP: + i -= jump_thread(inst, target, POP_JUMP_IF_FALSE); } break; - case POP_JUMP_IF_TRUE: - switch(target->i_opcode) { + switch (target->i_opcode) { case JUMP_ABSOLUTE: case JUMP_FORWARD: - if (inst->i_lineno == target->i_lineno) { - inst->i_target = target->i_target; - i--; - } - break; + case JUMP_IF_TRUE_OR_POP: + i -= jump_thread(inst, target, POP_JUMP_IF_TRUE); } break; - case JUMP_ABSOLUTE: case JUMP_FORWARD: - assert (i == bb->b_iused-1); - switch(target->i_opcode) { - case JUMP_FORWARD: - if (eliminate_jump_to_jump(bb, inst->i_opcode)) { - goto error; - } - break; - + switch (target->i_opcode) { case JUMP_ABSOLUTE: - if (eliminate_jump_to_jump(bb, JUMP_ABSOLUTE)) { - goto error; - } - break; + case JUMP_FORWARD: + i -= jump_thread(inst, target, JUMP_ABSOLUTE); } break; case FOR_ITER: - assert (i == bb->b_iused-1); if (target->i_opcode == JUMP_FORWARD) { - if (eliminate_jump_to_jump(bb, inst->i_opcode)) { - goto error; - } + i -= jump_thread(inst, target, FOR_ITER); } break; case ROT_N: From webhook-mailer at python.org Thu Nov 11 16:52:48 2021 From: webhook-mailer at python.org (brandtbucher) Date: Thu, 11 Nov 2021 21:52:48 -0000 Subject: [Python-checkins] [3.10] bpo-45773: Stop "optimizing" certain jump patterns (GH-29526) Message-ID: https://github.com/python/cpython/commit/a89bbde83fe7f8cc347341e7ec57cda3ba312530 commit: a89bbde83fe7f8cc347341e7ec57cda3ba312530 branch: 3.10 author: Brandt Bucher committer: brandtbucher date: 2021-11-11T13:52:43-08:00 summary: [3.10] bpo-45773: Stop "optimizing" certain jump patterns (GH-29526) files: A Misc/NEWS.d/next/Core and Builtins/2021-11-09-13-01-35.bpo-45773.POU8A4.rst M Lib/test/test_peepholer.py M Python/compile.c M Python/importlib.h M Python/importlib_external.h M Python/importlib_zipimport.h diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index 4034154e4dcfb..11a4d1740b8dc 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -514,5 +514,12 @@ def test_bpo_42057(self): except Exception or Exception: pass + def test_bpo_45773_pop_jump_if_true(self): + compile("while True or spam: pass", "", "exec") + + def test_bpo_45773_pop_jump_if_false(self): + compile("while True or not spam: pass", "", "exec") + + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-09-13-01-35.bpo-45773.POU8A4.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-09-13-01-35.bpo-45773.POU8A4.rst new file mode 100644 index 0000000000000..2b9ba81be233f --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-09-13-01-35.bpo-45773.POU8A4.rst @@ -0,0 +1 @@ +Fix a compiler hang when attempting to optimize certain jump patterns. diff --git a/Python/compile.c b/Python/compile.c index 90861038e07da..3eb34d89cc55f 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -21,6 +21,8 @@ * objects. */ +#include + #include "Python.h" #include "pycore_ast.h" // _PyAST_GetDocString() #include "pycore_compile.h" // _PyFuture_FromAST() @@ -7264,25 +7266,24 @@ fold_rotations(struct instr *inst, int n) } } - -static int -eliminate_jump_to_jump(basicblock *bb, int opcode) { - assert (bb->b_iused > 0); - struct instr *inst = &bb->b_instr[bb->b_iused-1]; - assert (is_jump(inst)); - assert (inst->i_target->b_iused > 0); - struct instr *target = &inst->i_target->b_instr[0]; - if (inst->i_target == target->i_target) { - /* Nothing to do */ - return 0; - } - int lineno = target->i_lineno; - if (add_jump_to_block(bb, opcode, lineno, target->i_target) == 0) { - return -1; +// Attempt to eliminate jumps to jumps by updating inst to jump to +// target->i_target using the provided opcode. Return whether or not the +// optimization was successful. +static bool +jump_thread(struct instr *inst, struct instr *target, int opcode) +{ + assert(is_jump(inst)); + assert(is_jump(target)); + // bpo-45773: If inst->i_target == target->i_target, then nothing actually + // changes (and we fall into an infinite loop): + if (inst->i_lineno == target->i_lineno && + inst->i_target != target->i_target) + { + inst->i_target = target->i_target; + inst->i_opcode = opcode; + return true; } - assert (bb->b_iused >= 2); - bb->b_instr[bb->b_iused-2].i_opcode = NOP; - return 0; + return false; } /* Maximum size of basic block that should be copied in optimizer */ @@ -7399,25 +7400,21 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) where y+1 is the instruction following the second test. */ case JUMP_IF_FALSE_OR_POP: - switch(target->i_opcode) { + switch (target->i_opcode) { case POP_JUMP_IF_FALSE: - if (inst->i_lineno == target->i_lineno) { - *inst = *target; - i--; - } + i -= jump_thread(inst, target, POP_JUMP_IF_FALSE); break; case JUMP_ABSOLUTE: case JUMP_FORWARD: case JUMP_IF_FALSE_OR_POP: - if (inst->i_lineno == target->i_lineno && - inst->i_target != target->i_target) { - inst->i_target = target->i_target; - i--; - } + i -= jump_thread(inst, target, JUMP_IF_FALSE_OR_POP); break; case JUMP_IF_TRUE_OR_POP: - assert (inst->i_target->b_iused == 1); + case POP_JUMP_IF_TRUE: if (inst->i_lineno == target->i_lineno) { + // We don't need to bother checking for loops here, + // since a block's b_next cannot point to itself: + assert(inst->i_target != inst->i_target->b_next); inst->i_opcode = POP_JUMP_IF_FALSE; inst->i_target = inst->i_target->b_next; --i; @@ -7425,27 +7422,22 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) break; } break; - case JUMP_IF_TRUE_OR_POP: - switch(target->i_opcode) { + switch (target->i_opcode) { case POP_JUMP_IF_TRUE: - if (inst->i_lineno == target->i_lineno) { - *inst = *target; - i--; - } + i -= jump_thread(inst, target, POP_JUMP_IF_TRUE); break; case JUMP_ABSOLUTE: case JUMP_FORWARD: case JUMP_IF_TRUE_OR_POP: - if (inst->i_lineno == target->i_lineno && - inst->i_target != target->i_target) { - inst->i_target = target->i_target; - i--; - } + i -= jump_thread(inst, target, JUMP_IF_TRUE_OR_POP); break; case JUMP_IF_FALSE_OR_POP: - assert (inst->i_target->b_iused == 1); + case POP_JUMP_IF_FALSE: if (inst->i_lineno == target->i_lineno) { + // We don't need to bother checking for loops here, + // since a block's b_next cannot point to itself: + assert(inst->i_target != inst->i_target->b_next); inst->i_opcode = POP_JUMP_IF_TRUE; inst->i_target = inst->i_target->b_next; --i; @@ -7453,54 +7445,33 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) break; } break; - case POP_JUMP_IF_FALSE: - switch(target->i_opcode) { + switch (target->i_opcode) { case JUMP_ABSOLUTE: case JUMP_FORWARD: - if (inst->i_lineno == target->i_lineno) { - inst->i_target = target->i_target; - i--; - } - break; + case JUMP_IF_FALSE_OR_POP: + i -= jump_thread(inst, target, POP_JUMP_IF_FALSE); } break; - case POP_JUMP_IF_TRUE: - switch(target->i_opcode) { + switch (target->i_opcode) { case JUMP_ABSOLUTE: case JUMP_FORWARD: - if (inst->i_lineno == target->i_lineno) { - inst->i_target = target->i_target; - i--; - } - break; + case JUMP_IF_TRUE_OR_POP: + i -= jump_thread(inst, target, POP_JUMP_IF_TRUE); } break; - case JUMP_ABSOLUTE: case JUMP_FORWARD: - assert (i == bb->b_iused-1); - switch(target->i_opcode) { - case JUMP_FORWARD: - if (eliminate_jump_to_jump(bb, inst->i_opcode)) { - goto error; - } - break; - + switch (target->i_opcode) { case JUMP_ABSOLUTE: - if (eliminate_jump_to_jump(bb, JUMP_ABSOLUTE)) { - goto error; - } - break; + case JUMP_FORWARD: + i -= jump_thread(inst, target, JUMP_ABSOLUTE); } break; case FOR_ITER: - assert (i == bb->b_iused-1); if (target->i_opcode == JUMP_FORWARD) { - if (eliminate_jump_to_jump(bb, inst->i_opcode)) { - goto error; - } + i -= jump_thread(inst, target, FOR_ITER); } break; case ROT_N: diff --git a/Python/importlib.h b/Python/importlib.h index dd1a9f172c04f..ab3e69b22b662 100644 --- a/Python/importlib.h +++ b/Python/importlib.h @@ -782,8 +782,8 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 103,0,110,1,100,2,125,5,124,4,124,0,124,1,124,5, 100,4,141,3,83,0,124,3,100,2,117,0,114,67,116,0, 124,1,100,5,131,2,114,65,122,7,124,1,160,4,124,0, - 161,1,125,3,87,0,110,13,4,0,116,5,121,64,1,0, - 1,0,1,0,100,2,125,3,89,0,110,3,119,0,100,6, + 161,1,125,3,87,0,113,67,4,0,116,5,121,64,1,0, + 1,0,1,0,100,2,125,3,89,0,113,67,119,0,100,6, 125,3,116,6,124,0,124,1,124,2,124,3,100,7,141,4, 83,0,41,8,122,53,82,101,116,117,114,110,32,97,32,109, 111,100,117,108,101,32,115,112,101,99,32,98,97,115,101,100, @@ -812,9 +812,9 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 122,5,124,0,106,4,125,5,87,0,110,11,4,0,116,1, 121,59,1,0,1,0,1,0,100,0,125,5,89,0,110,1, 119,0,124,2,100,0,117,0,114,87,124,5,100,0,117,0, - 114,85,122,5,124,1,106,5,125,2,87,0,110,13,4,0, + 114,85,122,5,124,1,106,5,125,2,87,0,113,87,4,0, 116,1,121,84,1,0,1,0,1,0,100,0,125,2,89,0, - 110,3,119,0,124,5,125,2,122,5,124,0,106,6,125,6, + 113,87,119,0,124,5,125,2,122,5,124,0,106,6,125,6, 87,0,110,11,4,0,116,1,121,103,1,0,1,0,1,0, 100,0,125,6,89,0,110,1,119,0,122,7,116,7,124,0, 106,8,131,1,125,7,87,0,110,11,4,0,116,1,121,122, diff --git a/Python/importlib_external.h b/Python/importlib_external.h index 90c8d89d63074..bd4d95a61e00a 100644 --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -977,8 +977,8 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 8,0,0,0,67,0,0,0,115,54,1,0,0,124,1,100, 1,117,0,114,29,100,2,125,1,116,0,124,2,100,3,131, 2,114,28,122,7,124,2,160,1,124,0,161,1,125,1,87, - 0,110,38,4,0,116,2,121,27,1,0,1,0,1,0,89, - 0,110,30,119,0,110,28,116,3,160,4,124,1,161,1,125, + 0,113,57,4,0,116,2,121,27,1,0,1,0,1,0,89, + 0,113,57,119,0,110,28,116,3,160,4,124,1,161,1,125, 1,116,5,124,1,131,1,115,57,122,9,116,6,116,3,160, 7,161,0,124,1,131,2,125,1,87,0,110,9,4,0,116, 8,121,56,1,0,1,0,1,0,89,0,110,1,119,0,116, @@ -990,7 +990,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 1,83,0,124,3,116,16,117,0,114,131,116,0,124,2,100, 6,131,2,114,130,122,7,124,2,160,17,124,0,161,1,125, 7,87,0,110,9,4,0,116,2,121,124,1,0,1,0,1, - 0,89,0,110,10,119,0,124,7,114,130,103,0,124,4,95, + 0,89,0,113,134,119,0,124,7,114,130,103,0,124,4,95, 18,110,3,124,3,124,4,95,18,124,4,106,18,103,0,107, 2,114,153,124,1,114,153,116,19,124,1,131,1,100,7,25, 0,125,8,124,4,106,18,160,20,124,8,161,1,1,0,124, diff --git a/Python/importlib_zipimport.h b/Python/importlib_zipimport.h index bb870c3a0353a..07c9dd574040f 100644 --- a/Python/importlib_zipimport.h +++ b/Python/importlib_zipimport.h @@ -1004,9 +1004,9 @@ const unsigned char _Py_M__zipimport[] = { 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, + 124,1,124,10,131,5,125,11,87,0,113,96,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, + 89,0,100,0,125,12,126,12,113,96,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, From webhook-mailer at python.org Thu Nov 11 22:53:34 2021 From: webhook-mailer at python.org (rhettinger) Date: Fri, 12 Nov 2021 03:53:34 -0000 Subject: [Python-checkins] bpo-45235: Revert an argparse bugfix that caused a regression (GH-29525) Message-ID: https://github.com/python/cpython/commit/807f839bbfd5805fb76eb3436c9252a0441296eb commit: 807f839bbfd5805fb76eb3436c9252a0441296eb branch: main author: Raymond Hettinger committer: rhettinger date: 2021-11-11T21:53:23-06:00 summary: bpo-45235: Revert an argparse bugfix that caused a regression (GH-29525) * Revert "bpo-45235: Fix argparse overrides namespace with subparser defaults (GH-28420) (GH-28443)" This reverts commit a18d52269ab6071a605d6c72f6af585a4c533ca4. files: A Misc/NEWS.d/next/Library/2021-11-11-13-03-17.bpo-45235.8ZbkHa.rst M Lib/argparse.py M Lib/test/test_argparse.py diff --git a/Lib/argparse.py b/Lib/argparse.py index 4cc14f2372246..b44fa4f0f65c3 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1210,8 +1210,7 @@ def __call__(self, parser, namespace, values, option_string=None): # namespace for the relevant parts. subnamespace, arg_strings = parser.parse_known_args(arg_strings, None) for key, value in vars(subnamespace).items(): - if not hasattr(namespace, key): - setattr(namespace, key, value) + setattr(namespace, key, value) if arg_strings: vars(namespace).setdefault(_UNRECOGNIZED_ARGS_ATTR, []) @@ -1845,6 +1844,11 @@ def parse_known_args(self, args=None, namespace=None): if action.default is not SUPPRESS: setattr(namespace, action.dest, action.default) + # add any parser defaults that aren't present + for dest in self._defaults: + if not hasattr(namespace, dest): + setattr(namespace, dest, self._defaults[dest]) + # parse the arguments and exit if there are any errors if self.exit_on_error: try: @@ -1855,11 +1859,6 @@ def parse_known_args(self, args=None, namespace=None): else: namespace, args = self._parse_known_args(args, namespace) - # add any parser defaults that aren't present - for dest in self._defaults: - if not hasattr(namespace, dest): - setattr(namespace, dest, self._defaults[dest]) - if hasattr(namespace, _UNRECOGNIZED_ARGS_ATTR): args.extend(getattr(namespace, _UNRECOGNIZED_ARGS_ATTR)) delattr(namespace, _UNRECOGNIZED_ARGS_ATTR) diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index 21732d14604c0..f3edde3de8eef 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -3114,12 +3114,6 @@ def test_set_defaults_on_parent_and_subparser(self): xparser.set_defaults(foo=2) self.assertEqual(NS(foo=2), parser.parse_args(['X'])) - def test_set_defaults_on_subparser_with_namespace(self): - parser = argparse.ArgumentParser() - xparser = parser.add_subparsers().add_parser('X') - xparser.set_defaults(foo=1) - self.assertEqual(NS(foo=2), parser.parse_args(['X'], NS(foo=2))) - def test_set_defaults_same_as_add_argument(self): parser = ErrorRaisingArgumentParser() parser.set_defaults(w='W', x='X', y='Y', z='Z') diff --git a/Misc/NEWS.d/next/Library/2021-11-11-13-03-17.bpo-45235.8ZbkHa.rst b/Misc/NEWS.d/next/Library/2021-11-11-13-03-17.bpo-45235.8ZbkHa.rst new file mode 100644 index 0000000000000..f73589ccc8872 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-11-13-03-17.bpo-45235.8ZbkHa.rst @@ -0,0 +1,3 @@ +Reverted an argparse bugfix that caused regression in the handling of +default arguments for subparsers. This prevented leaf level arguments from +taking precedence over root level arguments. From webhook-mailer at python.org Fri Nov 12 04:48:06 2021 From: webhook-mailer at python.org (asvetlov) Date: Fri, 12 Nov 2021 09:48:06 -0000 Subject: [Python-checkins] bpo-45792: Fix contextvar.Token's intersphinx FQN (GH-29533) Message-ID: https://github.com/python/cpython/commit/e501d70b347c5093018d12482c30a7a98aab86d0 commit: e501d70b347c5093018d12482c30a7a98aab86d0 branch: main author: Hynek Schlawack committer: asvetlov date: 2021-11-12T11:47:55+02:00 summary: bpo-45792: Fix contextvar.Token's intersphinx FQN (GH-29533) Since `.. module:: contextvars` sets the module using `.. class:: contextvars.Token`, intersphinx records it as `contextvars.contextvars.Token`. files: M Doc/library/contextvars.rst diff --git a/Doc/library/contextvars.rst b/Doc/library/contextvars.rst index 14ac47f4c9eb1..be1dd0c9eb57e 100644 --- a/Doc/library/contextvars.rst +++ b/Doc/library/contextvars.rst @@ -94,7 +94,7 @@ Context Variables # var.get() would raise a LookupError. -.. class:: contextvars.Token +.. class:: Token *Token* objects are returned by the :meth:`ContextVar.set` method. They can be passed to the :meth:`ContextVar.reset` method to revert From webhook-mailer at python.org Fri Nov 12 05:20:08 2021 From: webhook-mailer at python.org (asvetlov) Date: Fri, 12 Nov 2021 10:20:08 -0000 Subject: [Python-checkins] bpo-45792: Fix contextvar.Token's intersphinx FQN (GH-29533) (GH-29535) Message-ID: https://github.com/python/cpython/commit/628667ac9a634c7a7fa7f681dd2f98ff5841c843 commit: 628667ac9a634c7a7fa7f681dd2f98ff5841c843 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: asvetlov date: 2021-11-12T12:19:52+02:00 summary: bpo-45792: Fix contextvar.Token's intersphinx FQN (GH-29533) (GH-29535) Since `.. module:: contextvars` sets the module using `.. class:: contextvars.Token`, intersphinx records it as `contextvars.contextvars.Token`. (cherry picked from commit e501d70b347c5093018d12482c30a7a98aab86d0) Co-authored-by: Hynek Schlawack Co-authored-by: Hynek Schlawack files: M Doc/library/contextvars.rst diff --git a/Doc/library/contextvars.rst b/Doc/library/contextvars.rst index 14ac47f4c9eb1..be1dd0c9eb57e 100644 --- a/Doc/library/contextvars.rst +++ b/Doc/library/contextvars.rst @@ -94,7 +94,7 @@ Context Variables # var.get() would raise a LookupError. -.. class:: contextvars.Token +.. class:: Token *Token* objects are returned by the :meth:`ContextVar.set` method. They can be passed to the :meth:`ContextVar.reset` method to revert From webhook-mailer at python.org Fri Nov 12 05:20:26 2021 From: webhook-mailer at python.org (asvetlov) Date: Fri, 12 Nov 2021 10:20:26 -0000 Subject: [Python-checkins] bpo-45792: Fix contextvar.Token's intersphinx FQN (GH-29533) (GH-29536) Message-ID: https://github.com/python/cpython/commit/8b6a474071bcc88ec3453e16f079181e551513c3 commit: 8b6a474071bcc88ec3453e16f079181e551513c3 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: asvetlov date: 2021-11-12T12:20:20+02:00 summary: bpo-45792: Fix contextvar.Token's intersphinx FQN (GH-29533) (GH-29536) Since `.. module:: contextvars` sets the module using `.. class:: contextvars.Token`, intersphinx records it as `contextvars.contextvars.Token`. (cherry picked from commit e501d70b347c5093018d12482c30a7a98aab86d0) Co-authored-by: Hynek Schlawack Co-authored-by: Hynek Schlawack files: M Doc/library/contextvars.rst diff --git a/Doc/library/contextvars.rst b/Doc/library/contextvars.rst index 14ac47f4c9eb1..be1dd0c9eb57e 100644 --- a/Doc/library/contextvars.rst +++ b/Doc/library/contextvars.rst @@ -94,7 +94,7 @@ Context Variables # var.get() would raise a LookupError. -.. class:: contextvars.Token +.. class:: Token *Token* objects are returned by the :meth:`ContextVar.set` method. They can be passed to the :meth:`ContextVar.reset` method to revert From webhook-mailer at python.org Fri Nov 12 08:21:54 2021 From: webhook-mailer at python.org (iritkatriel) Date: Fri, 12 Nov 2021 13:21:54 -0000 Subject: [Python-checkins] bpo-45711: Re-bump the magic number and update doc (GH-29528) Message-ID: https://github.com/python/cpython/commit/8f1b71de731dda668aede7c9b34d0ad7afb8f6a8 commit: 8f1b71de731dda668aede7c9b34d0ad7afb8f6a8 branch: main author: Brandt Bucher committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-11-12T13:21:45Z summary: bpo-45711: Re-bump the magic number and update doc (GH-29528) files: M Doc/library/dis.rst M Doc/whatsnew/3.11.rst M Lib/importlib/_bootstrap_external.py diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 4a804044df000..5fe9f65f46a71 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -873,10 +873,13 @@ All of the following opcodes use their arguments. .. opcode:: JUMP_IF_NOT_EXC_MATCH (target) Tests whether the second value on the stack is an exception matching TOS, - and jumps if it is not. Pops two values from the stack. + and jumps if it is not. Pops one value from the stack. .. versionadded:: 3.9 + .. versionchanged:: 3.11 + This opcode no longer pops the active exception. + .. opcode:: JUMP_IF_TRUE_OR_POP (target) diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 59a230f26ab42..0767a6a03ac2a 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -332,6 +332,8 @@ CPython bytecode changes * Added :opcode:`COPY`, which pushes the *i*-th item to the top of the stack. The item is not removed from its original location. +* :opcode:`JUMP_IF_NOT_EXC_MATCH` no longer pops the active exception. + Deprecated ========== diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index f6f54af68488f..303ca728ec892 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -366,7 +366,10 @@ def _write_atomic(path, data, mode=0o666): # Python 3.11a1 3461 (JUMP_ABSOLUTE must jump backwards) # Python 3.11a2 3462 (bpo-44511: remove COPY_DICT_WITHOUT_KEYS, change # MATCH_CLASS and MATCH_KEYS, and add COPY) -# Python 3.11a3 3463 (Merge numeric BINARY_*/INPLACE_* into BINARY_OP) +# Python 3.11a3 3463 (bpo-45711: JUMP_IF_NOT_EXC_MATCH no longer pops the +# active exception) +# Python 3.11a3 3464 (bpo-45636: Merge numeric BINARY_*/INPLACE_* into +# BINARY_OP) # # MAGIC must change whenever the bytecode emitted by the compiler may no @@ -376,7 +379,7 @@ def _write_atomic(path, data, mode=0o666): # Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array # in PC/launcher.c must also be updated. -MAGIC_NUMBER = (3463).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3464).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c _PYCACHE = '__pycache__' From webhook-mailer at python.org Fri Nov 12 10:19:24 2021 From: webhook-mailer at python.org (vstinner) Date: Fri, 12 Nov 2021 15:19:24 -0000 Subject: [Python-checkins] bpo-45745: Remove regrtest --findleaks options (GH-29514) Message-ID: https://github.com/python/cpython/commit/9d3271438431c37c29c359f5b73e8094b5f82912 commit: 9d3271438431c37c29c359f5b73e8094b5f82912 branch: main author: Victor Stinner committer: vstinner date: 2021-11-12T16:19:09+01:00 summary: bpo-45745: Remove regrtest --findleaks options (GH-29514) Remove the --findleaks command line option of regrtest: use the --fail-env-changed option instead. Since Python 3.7, it was a deprecated alias to the --fail-env-changed option. files: A Misc/NEWS.d/next/Tests/2021-11-10-12-01-28.bpo-45745.wX5B3K.rst M Lib/test/libregrtest/cmdline.py M Lib/test/libregrtest/main.py M Lib/test/libregrtest/runtest.py M Lib/test/test_regrtest.py diff --git a/Lib/test/libregrtest/cmdline.py b/Lib/test/libregrtest/cmdline.py index 6e6ff1201d81c..11fa0f940bb71 100644 --- a/Lib/test/libregrtest/cmdline.py +++ b/Lib/test/libregrtest/cmdline.py @@ -149,7 +149,6 @@ def __init__(self, **kwargs) -> None: self.single = False self.randomize = False self.fromfile = None - self.findleaks = 1 self.fail_env_changed = False self.use_resources = None self.trace = False @@ -266,9 +265,6 @@ def _create_parser(): '(instead of the Python stdlib test suite)') group = parser.add_argument_group('Special runs') - group.add_argument('-l', '--findleaks', action='store_const', const=2, - default=1, - help='deprecated alias to --fail-env-changed') group.add_argument('-L', '--runleaks', action='store_true', help='run the leaks(1) command just before exit.' + more_details) @@ -370,9 +366,6 @@ def _parse_args(args, **kwargs): parser.error("unrecognized arguments: %s" % arg) sys.exit(1) - if ns.findleaks > 1: - # --findleaks implies --fail-env-changed - ns.fail_env_changed = True if ns.single and ns.fromfile: parser.error("-s and -f don't go together!") if ns.use_mp is not None and ns.trace: diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index 52cc065da115d..fc3c2b9692055 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -46,7 +46,7 @@ class Regrtest: files beginning with test_ will be used. The other default arguments (verbose, quiet, exclude, - single, randomize, findleaks, use_resources, trace, coverdir, + single, randomize, use_resources, trace, coverdir, print_slow, and random_seed) allow programmers calling main() directly to set the values that would normally be set by flags on the command line. diff --git a/Lib/test/libregrtest/runtest.py b/Lib/test/libregrtest/runtest.py index 23970410a28fb..83c5f249841cc 100644 --- a/Lib/test/libregrtest/runtest.py +++ b/Lib/test/libregrtest/runtest.py @@ -138,7 +138,7 @@ def __str__(self) -> str: NOTTESTS = set() -# used by --findleaks, store for gc.garbage +# Storage of uncollectable objects FOUND_GARBAGE = [] @@ -279,7 +279,7 @@ def save_env(ns: Namespace, test_name: str): def _runtest_inner2(ns: Namespace, test_name: str) -> bool: # Load the test function, run the test function, handle huntrleaks - # and findleaks to detect leaks + # to detect leaks. abstest = get_abs_module(ns, test_name) diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py index dcc795de1a4b6..08e2c87e15c4d 100644 --- a/Lib/test/test_regrtest.py +++ b/Lib/test/test_regrtest.py @@ -1178,7 +1178,7 @@ def test_other_bug(self): no_test_ran=[testname]) @support.cpython_only - def test_findleaks(self): + def test_uncollectable(self): code = textwrap.dedent(r""" import _testcapi import gc @@ -1203,12 +1203,6 @@ def test_garbage(self): env_changed=[testname], fail_env_changed=True) - # --findleaks is now basically an alias to --fail-env-changed - output = self.run_tests("--findleaks", testname, exitcode=3) - self.check_executed_tests(output, [testname], - env_changed=[testname], - fail_env_changed=True) - def test_multiprocessing_timeout(self): code = textwrap.dedent(r""" import time diff --git a/Misc/NEWS.d/next/Tests/2021-11-10-12-01-28.bpo-45745.wX5B3K.rst b/Misc/NEWS.d/next/Tests/2021-11-10-12-01-28.bpo-45745.wX5B3K.rst new file mode 100644 index 0000000000000..c3ef6800a0353 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-11-10-12-01-28.bpo-45745.wX5B3K.rst @@ -0,0 +1,3 @@ +Remove the ``--findleaks`` command line option of regrtest: use the +``--fail-env-changed`` option instead. Since Python 3.7, it was a deprecated +alias to the ``--fail-env-changed`` option. From webhook-mailer at python.org Fri Nov 12 13:44:34 2021 From: webhook-mailer at python.org (rhettinger) Date: Fri, 12 Nov 2021 18:44:34 -0000 Subject: [Python-checkins] bpo-45235: Revert an argparse bugfix that caused a regression (GH-29525) (GH-29531) Message-ID: https://github.com/python/cpython/commit/587ff7f50bcbfd8346c6d5db459a1628a350c04d commit: 587ff7f50bcbfd8346c6d5db459a1628a350c04d branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: rhettinger date: 2021-11-12T12:44:25-06:00 summary: bpo-45235: Revert an argparse bugfix that caused a regression (GH-29525) (GH-29531) files: A Misc/NEWS.d/next/Library/2021-11-11-13-03-17.bpo-45235.8ZbkHa.rst M Lib/argparse.py M Lib/test/test_argparse.py diff --git a/Lib/argparse.py b/Lib/argparse.py index cb5345d555afe..7c28547f3e522 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1209,8 +1209,7 @@ def __call__(self, parser, namespace, values, option_string=None): # namespace for the relevant parts. subnamespace, arg_strings = parser.parse_known_args(arg_strings, None) for key, value in vars(subnamespace).items(): - if not hasattr(namespace, key): - setattr(namespace, key, value) + setattr(namespace, key, value) if arg_strings: vars(namespace).setdefault(_UNRECOGNIZED_ARGS_ATTR, []) @@ -1844,6 +1843,11 @@ def parse_known_args(self, args=None, namespace=None): if action.default is not SUPPRESS: setattr(namespace, action.dest, action.default) + # add any parser defaults that aren't present + for dest in self._defaults: + if not hasattr(namespace, dest): + setattr(namespace, dest, self._defaults[dest]) + # parse the arguments and exit if there are any errors if self.exit_on_error: try: @@ -1854,11 +1858,6 @@ def parse_known_args(self, args=None, namespace=None): else: namespace, args = self._parse_known_args(args, namespace) - # add any parser defaults that aren't present - for dest in self._defaults: - if not hasattr(namespace, dest): - setattr(namespace, dest, self._defaults[dest]) - if hasattr(namespace, _UNRECOGNIZED_ARGS_ATTR): args.extend(getattr(namespace, _UNRECOGNIZED_ARGS_ATTR)) delattr(namespace, _UNRECOGNIZED_ARGS_ATTR) diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index c3c3a75fafff7..d79ac5a4651d9 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -3095,12 +3095,6 @@ def test_set_defaults_on_parent_and_subparser(self): xparser.set_defaults(foo=2) self.assertEqual(NS(foo=2), parser.parse_args(['X'])) - def test_set_defaults_on_subparser_with_namespace(self): - parser = argparse.ArgumentParser() - xparser = parser.add_subparsers().add_parser('X') - xparser.set_defaults(foo=1) - self.assertEqual(NS(foo=2), parser.parse_args(['X'], NS(foo=2))) - def test_set_defaults_same_as_add_argument(self): parser = ErrorRaisingArgumentParser() parser.set_defaults(w='W', x='X', y='Y', z='Z') diff --git a/Misc/NEWS.d/next/Library/2021-11-11-13-03-17.bpo-45235.8ZbkHa.rst b/Misc/NEWS.d/next/Library/2021-11-11-13-03-17.bpo-45235.8ZbkHa.rst new file mode 100644 index 0000000000000..f73589ccc8872 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-11-13-03-17.bpo-45235.8ZbkHa.rst @@ -0,0 +1,3 @@ +Reverted an argparse bugfix that caused regression in the handling of +default arguments for subparsers. This prevented leaf level arguments from +taking precedence over root level arguments. From webhook-mailer at python.org Fri Nov 12 13:45:00 2021 From: webhook-mailer at python.org (rhettinger) Date: Fri, 12 Nov 2021 18:45:00 -0000 Subject: [Python-checkins] bpo-45235: Revert an argparse bugfix that caused a regression (GH-29525) (GH-29530) Message-ID: https://github.com/python/cpython/commit/e4c5a5eabadd1dcd0b522ffbd70157cd95506ad1 commit: e4c5a5eabadd1dcd0b522ffbd70157cd95506ad1 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: rhettinger date: 2021-11-12T12:44:55-06:00 summary: bpo-45235: Revert an argparse bugfix that caused a regression (GH-29525) (GH-29530) files: A Misc/NEWS.d/next/Library/2021-11-11-13-03-17.bpo-45235.8ZbkHa.rst M Lib/argparse.py M Lib/test/test_argparse.py diff --git a/Lib/argparse.py b/Lib/argparse.py index f1f6f3227bd17..9eed24c2a2a76 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1209,8 +1209,7 @@ def __call__(self, parser, namespace, values, option_string=None): # namespace for the relevant parts. subnamespace, arg_strings = parser.parse_known_args(arg_strings, None) for key, value in vars(subnamespace).items(): - if not hasattr(namespace, key): - setattr(namespace, key, value) + setattr(namespace, key, value) if arg_strings: vars(namespace).setdefault(_UNRECOGNIZED_ARGS_ATTR, []) @@ -1844,6 +1843,11 @@ def parse_known_args(self, args=None, namespace=None): if action.default is not SUPPRESS: setattr(namespace, action.dest, action.default) + # add any parser defaults that aren't present + for dest in self._defaults: + if not hasattr(namespace, dest): + setattr(namespace, dest, self._defaults[dest]) + # parse the arguments and exit if there are any errors if self.exit_on_error: try: @@ -1854,11 +1858,6 @@ def parse_known_args(self, args=None, namespace=None): else: namespace, args = self._parse_known_args(args, namespace) - # add any parser defaults that aren't present - for dest in self._defaults: - if not hasattr(namespace, dest): - setattr(namespace, dest, self._defaults[dest]) - if hasattr(namespace, _UNRECOGNIZED_ARGS_ATTR): args.extend(getattr(namespace, _UNRECOGNIZED_ARGS_ATTR)) delattr(namespace, _UNRECOGNIZED_ARGS_ATTR) diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index 6680feb016a4d..ec49b2acbbb85 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -3095,12 +3095,6 @@ def test_set_defaults_on_parent_and_subparser(self): xparser.set_defaults(foo=2) self.assertEqual(NS(foo=2), parser.parse_args(['X'])) - def test_set_defaults_on_subparser_with_namespace(self): - parser = argparse.ArgumentParser() - xparser = parser.add_subparsers().add_parser('X') - xparser.set_defaults(foo=1) - self.assertEqual(NS(foo=2), parser.parse_args(['X'], NS(foo=2))) - def test_set_defaults_same_as_add_argument(self): parser = ErrorRaisingArgumentParser() parser.set_defaults(w='W', x='X', y='Y', z='Z') diff --git a/Misc/NEWS.d/next/Library/2021-11-11-13-03-17.bpo-45235.8ZbkHa.rst b/Misc/NEWS.d/next/Library/2021-11-11-13-03-17.bpo-45235.8ZbkHa.rst new file mode 100644 index 0000000000000..f73589ccc8872 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-11-13-03-17.bpo-45235.8ZbkHa.rst @@ -0,0 +1,3 @@ +Reverted an argparse bugfix that caused regression in the handling of +default arguments for subparsers. This prevented leaf level arguments from +taking precedence over root level arguments. From webhook-mailer at python.org Fri Nov 12 16:37:37 2021 From: webhook-mailer at python.org (iritkatriel) Date: Fri, 12 Nov 2021 21:37:37 -0000 Subject: [Python-checkins] bpo-45711: assert that the type of exc_info is redundant (GH-29518) Message-ID: https://github.com/python/cpython/commit/de3db1448b1b983eeb9f4498d07e3d2f1fb6d29d commit: de3db1448b1b983eeb9f4498d07e3d2f1fb6d29d branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-11-12T21:37:26Z summary: bpo-45711: assert that the type of exc_info is redundant (GH-29518) files: M Python/ceval.c diff --git a/Python/ceval.c b/Python/ceval.c index 030d98396780b..0b24cbdcc2cc4 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1058,6 +1058,23 @@ match_class(PyThreadState *tstate, PyObject *subject, PyObject *type, static int do_raise(PyThreadState *tstate, PyObject *exc, PyObject *cause); static int unpack_iterable(PyThreadState *, PyObject *, int, int, PyObject **); +#ifdef Py_DEBUG +static void +_assert_exception_type_is_redundant(PyObject* type, PyObject* val) +{ + if (type == NULL || type == Py_None) { + assert(val == NULL || val == Py_None); + } + else { + assert(PyExceptionInstance_Check(val)); + assert(PyExceptionInstance_Class(val) == type); + } +} + +#define ASSERT_EXC_TYPE_IS_REDUNDANT(t, v) _assert_exception_type_is_redundant(t, v) +#else +#define ASSERT_EXC_TYPE_IS_REDUNDANT(t, v) +#endif PyObject * PyEval_EvalCode(PyObject *co, PyObject *globals, PyObject *locals) @@ -2476,6 +2493,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr exc_info->exc_type = POP(); exc_info->exc_value = POP(); exc_info->exc_traceback = POP(); + ASSERT_EXC_TYPE_IS_REDUNDANT(exc_info->exc_type, exc_info->exc_value); Py_XDECREF(type); Py_XDECREF(value); Py_XDECREF(traceback); @@ -2497,6 +2515,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr type = POP(); value = POP(); traceback = POP(); + ASSERT_EXC_TYPE_IS_REDUNDANT(type, value); Py_DECREF(POP()); /* lasti */ _PyErr_Restore(tstate, type, value, traceback); exc_info = tstate->exc_info; @@ -2506,6 +2525,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr exc_info->exc_type = POP(); exc_info->exc_value = POP(); exc_info->exc_traceback = POP(); + ASSERT_EXC_TYPE_IS_REDUNDANT(exc_info->exc_type, exc_info->exc_value); Py_XDECREF(type); Py_XDECREF(value); Py_XDECREF(traceback); @@ -2528,6 +2548,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr PyObject *exc = POP(); PyObject *val = POP(); PyObject *tb = POP(); + ASSERT_EXC_TYPE_IS_REDUNDANT(exc, val); assert(PyExceptionClass_Check(exc)); _PyErr_Restore(tstate, exc, val, tb); goto exception_unwind; @@ -2537,6 +2558,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr PyObject *exc = POP(); PyObject *val = POP(); PyObject *tb = POP(); + ASSERT_EXC_TYPE_IS_REDUNDANT(exc, val); assert(PyExceptionClass_Check(exc)); if (PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) { Py_DECREF(exc); @@ -3991,6 +4013,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr exc = TOP(); val = SECOND(); tb = THIRD(); + ASSERT_EXC_TYPE_IS_REDUNDANT(exc, val); assert(!Py_IsNone(exc)); assert(!PyLong_Check(exc)); assert(PyLong_Check(PEEK(7))); @@ -4009,6 +4032,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr PyObject *type = TOP(); PyObject *value = SECOND(); PyObject *tb = THIRD(); + ASSERT_EXC_TYPE_IS_REDUNDANT(type, value); _PyErr_StackItem *exc_info = tstate->exc_info; SET_THIRD(exc_info->exc_traceback); SET_SECOND(exc_info->exc_value); @@ -4990,6 +5014,7 @@ MISS_WITH_OPARG_COUNTER(BINARY_SUBSCR) PUSH(tb); PUSH(val); PUSH(exc); + ASSERT_EXC_TYPE_IS_REDUNDANT(exc, val); JUMPTO(handler); /* Resume normal execution */ frame->f_state = FRAME_EXECUTING; From webhook-mailer at python.org Sat Nov 13 01:02:13 2021 From: webhook-mailer at python.org (asvetlov) Date: Sat, 13 Nov 2021 06:02:13 -0000 Subject: [Python-checkins] bpo-45772: socket.socket should be a class instead of a function (GH-23960) Message-ID: https://github.com/python/cpython/commit/4c792f39e688b11c7c19e411ed4f76a7baa44638 commit: 4c792f39e688b11c7c19e411ed4f76a7baa44638 branch: main author: Hong Xu committer: asvetlov date: 2021-11-13T08:02:04+02:00 summary: bpo-45772: socket.socket should be a class instead of a function (GH-23960) * bpo-45772: socket.socket should be a class instead of a function Currently `socket.socket` is documented as a function, but it is really a class (and thus has function-like usage to construct an object). This correction would ensure that Python projects that are interlinking Python's documentation can properly locate `socket.socket` as a type. files: A Misc/NEWS.d/next/Documentation/2021-11-09-13-10-55.bpo-45772.EdrM3t.rst M Doc/library/socket.rst diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index 831821bbda77c..d6edc057f5e9c 100755 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -562,7 +562,7 @@ Creating sockets The following functions all create :ref:`socket objects `. -.. function:: socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None) +.. class:: socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None) Create a new socket using the given address family, socket type and protocol number. The address family should be :const:`AF_INET` (the default), diff --git a/Misc/NEWS.d/next/Documentation/2021-11-09-13-10-55.bpo-45772.EdrM3t.rst b/Misc/NEWS.d/next/Documentation/2021-11-09-13-10-55.bpo-45772.EdrM3t.rst new file mode 100644 index 0000000000000..47679521df30b --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-09-13-10-55.bpo-45772.EdrM3t.rst @@ -0,0 +1 @@ +``socket.socket`` documentation is corrected to a class from a function. From webhook-mailer at python.org Sat Nov 13 01:23:31 2021 From: webhook-mailer at python.org (miss-islington) Date: Sat, 13 Nov 2021 06:23:31 -0000 Subject: [Python-checkins] [3.10] bpo-45772: socket.socket should be a class instead of a function (GH-23960) (GH-29542) Message-ID: https://github.com/python/cpython/commit/3f15792d60011639d9b170d8a76c6db7f6e83665 commit: 3f15792d60011639d9b170d8a76c6db7f6e83665 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-12T22:23:23-08:00 summary: [3.10] bpo-45772: socket.socket should be a class instead of a function (GH-23960) (GH-29542) * [bpo-45772](): socket.socket should be a class instead of a function Currently `socket.socket` is documented as a function, but it is really a class (and thus has function-like usage to construct an object). This correction would ensure that Python projects that are interlinking Python's documentation can properly locate `socket.socket` as a type. (cherry picked from commit 4c792f39e688b11c7c19e411ed4f76a7baa44638) Co-authored-by: Hong Xu Automerge-Triggered-By: GH:asvetlov files: A Misc/NEWS.d/next/Documentation/2021-11-09-13-10-55.bpo-45772.EdrM3t.rst M Doc/library/socket.rst diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index c69a50266f60f..7ce8e5b0d8038 100755 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -562,7 +562,7 @@ Creating sockets The following functions all create :ref:`socket objects `. -.. function:: socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None) +.. class:: socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None) Create a new socket using the given address family, socket type and protocol number. The address family should be :const:`AF_INET` (the default), diff --git a/Misc/NEWS.d/next/Documentation/2021-11-09-13-10-55.bpo-45772.EdrM3t.rst b/Misc/NEWS.d/next/Documentation/2021-11-09-13-10-55.bpo-45772.EdrM3t.rst new file mode 100644 index 0000000000000..47679521df30b --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-09-13-10-55.bpo-45772.EdrM3t.rst @@ -0,0 +1 @@ +``socket.socket`` documentation is corrected to a class from a function. From webhook-mailer at python.org Sat Nov 13 01:29:09 2021 From: webhook-mailer at python.org (miss-islington) Date: Sat, 13 Nov 2021 06:29:09 -0000 Subject: [Python-checkins] [3.9] bpo-45772: socket.socket should be a class instead of a function (GH-23960) (GH-29543) Message-ID: https://github.com/python/cpython/commit/b952f60213c60f89a50e4538783a18ced64ca91f commit: b952f60213c60f89a50e4538783a18ced64ca91f branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-12T22:29:01-08:00 summary: [3.9] bpo-45772: socket.socket should be a class instead of a function (GH-23960) (GH-29543) * [bpo-45772](): socket.socket should be a class instead of a function Currently `socket.socket` is documented as a function, but it is really a class (and thus has function-like usage to construct an object). This correction would ensure that Python projects that are interlinking Python's documentation can properly locate `socket.socket` as a type. (cherry picked from commit 4c792f39e688b11c7c19e411ed4f76a7baa44638) Co-authored-by: Hong Xu Automerge-Triggered-By: GH:asvetlov files: A Misc/NEWS.d/next/Documentation/2021-11-09-13-10-55.bpo-45772.EdrM3t.rst M Doc/library/socket.rst diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index db94a2a124575..f0a1338e2b85e 100755 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -552,7 +552,7 @@ Creating sockets The following functions all create :ref:`socket objects `. -.. function:: socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None) +.. class:: socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None) Create a new socket using the given address family, socket type and protocol number. The address family should be :const:`AF_INET` (the default), diff --git a/Misc/NEWS.d/next/Documentation/2021-11-09-13-10-55.bpo-45772.EdrM3t.rst b/Misc/NEWS.d/next/Documentation/2021-11-09-13-10-55.bpo-45772.EdrM3t.rst new file mode 100644 index 0000000000000..47679521df30b --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-09-13-10-55.bpo-45772.EdrM3t.rst @@ -0,0 +1 @@ +``socket.socket`` documentation is corrected to a class from a function. From webhook-mailer at python.org Sat Nov 13 07:56:27 2021 From: webhook-mailer at python.org (tiran) Date: Sat, 13 Nov 2021 12:56:27 -0000 Subject: [Python-checkins] bpo-45798: Move _decimal build setup into configure (GH-29541) Message-ID: https://github.com/python/cpython/commit/0486570f7b2b5a75812e5a01a8dca58bfadc2437 commit: 0486570f7b2b5a75812e5a01a8dca58bfadc2437 branch: main author: Christian Heimes committer: tiran date: 2021-11-13T13:56:16+01:00 summary: bpo-45798: Move _decimal build setup into configure (GH-29541) Settings for :mod:`decimal` internal C extension are now detected by :program:`configure`. The bundled `libmpdec` library is built in ``Makefile``. Signed-off-by: Christian Heimes files: A Misc/NEWS.d/next/Build/2021-11-13-10-18-22.bpo-45798.IraaTs.rst M Makefile.pre.in M Modules/Setup M Modules/makesetup M configure M configure.ac M setup.py diff --git a/Makefile.pre.in b/Makefile.pre.in index 6968ae4f5d865..a17054b6f65de 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -496,6 +496,47 @@ LIBRARY_OBJS= \ DTRACE_DEPS = \ Python/ceval.o Python/import.o Python/sysmodule.o Modules/gcmodule.o +########################################################################## +# decimal's libmpdec + +LIBMPDEC_OBJS= \ + Modules/_decimal/libmpdec/basearith.o \ + Modules/_decimal/libmpdec/constants.o \ + Modules/_decimal/libmpdec/context.o \ + Modules/_decimal/libmpdec/convolute.o \ + Modules/_decimal/libmpdec/crt.o \ + Modules/_decimal/libmpdec/difradix2.o \ + Modules/_decimal/libmpdec/fnt.o \ + Modules/_decimal/libmpdec/fourstep.o \ + Modules/_decimal/libmpdec/io.o \ + Modules/_decimal/libmpdec/mpalloc.o \ + Modules/_decimal/libmpdec/mpdecimal.o \ + Modules/_decimal/libmpdec/numbertheory.o \ + Modules/_decimal/libmpdec/sixstep.o \ + Modules/_decimal/libmpdec/transpose.o + # _decimal does not use signaling API + # Modules/_decimal/libmpdec/mpsignal.o + +LIBMPDEC_HEADERS= \ + $(srcdir)/Modules/_decimal/libmpdec/basearith.h \ + $(srcdir)/Modules/_decimal/libmpdec/bits.h \ + $(srcdir)/Modules/_decimal/libmpdec/constants.h \ + $(srcdir)/Modules/_decimal/libmpdec/convolute.h \ + $(srcdir)/Modules/_decimal/libmpdec/crt.h \ + $(srcdir)/Modules/_decimal/libmpdec/difradix2.h \ + $(srcdir)/Modules/_decimal/libmpdec/fnt.h \ + $(srcdir)/Modules/_decimal/libmpdec/fourstep.h \ + $(srcdir)/Modules/_decimal/libmpdec/io.h \ + $(srcdir)/Modules/_decimal/libmpdec/mpalloc.h \ + $(srcdir)/Modules/_decimal/libmpdec/mpdecimal.h \ + $(srcdir)/Modules/_decimal/libmpdec/numbertheory.h \ + $(srcdir)/Modules/_decimal/libmpdec/sixstep.h \ + $(srcdir)/Modules/_decimal/libmpdec/transpose.h \ + $(srcdir)/Modules/_decimal/libmpdec/typearith.h \ + $(srcdir)/Modules/_decimal/libmpdec/umodarith.h + +LIBMPDEC_A= Modules/_decimal/libmpdec/libmpdec.a + ######################################################################### # Rules @@ -647,7 +688,7 @@ $(srcdir)/Modules/_blake2/blake2s_impl.c: $(srcdir)/Modules/_blake2/blake2b_impl # -s, --silent or --quiet is always the first char. # Under BSD make, MAKEFLAGS might be " -s -v x=y". # Ignore macros passed by GNU make, passed after -- -sharedmods: $(BUILDPYTHON) pybuilddir.txt +sharedmods: $(BUILDPYTHON) pybuilddir.txt @LIBMPDEC_INTERNAL@ @case "`echo X $$MAKEFLAGS | sed 's/^X //;s/ -- .*//'`" in \ *\ -s*|s*) quiet="-q";; \ *) quiet="";; \ @@ -729,6 +770,63 @@ $(DLLLIBRARY) libpython$(LDVERSION).dll.a: $(LIBRARY_OBJS) else true; \ fi +########################################################################## +# Build static libmpdec.a +LIBMPDEC_CFLAGS=$(PY_STDMODULE_CFLAGS) $(CCSHARED) @LIBMPDEC_CFLAGS@ + +# for setup.py +DECIMAL_CFLAGS=@LIBMPDEC_CFLAGS@ +DECIMAL_LDFLAGS=@LIBMPDEC_LDFLAGS@ + +# "%.o: %c" is not portable +Modules/_decimal/libmpdec/basearith.o: $(srcdir)/Modules/_decimal/libmpdec/basearith.c $(LIBMPDEC_HEADERS) $(PYTHON_HEADERS) + $(CC) -c $(LIBMPDEC_CFLAGS) -o $@ $(srcdir)/Modules/_decimal/libmpdec/basearith.c + +Modules/_decimal/libmpdec/constants.o: $(srcdir)/Modules/_decimal/libmpdec/constants.c $(LIBMPDEC_HEADERS) $(PYTHON_HEADERS) + $(CC) -c $(LIBMPDEC_CFLAGS) -o $@ $(srcdir)/Modules/_decimal/libmpdec/constants.c + +Modules/_decimal/libmpdec/context.o: $(srcdir)/Modules/_decimal/libmpdec/context.c $(LIBMPDEC_HEADERS) $(PYTHON_HEADERS) + $(CC) -c $(LIBMPDEC_CFLAGS) -o $@ $(srcdir)/Modules/_decimal/libmpdec/context.c + +Modules/_decimal/libmpdec/convolute.o: $(srcdir)/Modules/_decimal/libmpdec/convolute.c $(LIBMPDEC_HEADERS) $(PYTHON_HEADERS) + $(CC) -c $(LIBMPDEC_CFLAGS) -o $@ $(srcdir)/Modules/_decimal/libmpdec/convolute.c + +Modules/_decimal/libmpdec/crt.o: $(srcdir)/Modules/_decimal/libmpdec/crt.c $(LIBMPDEC_HEADERS) $(PYTHON_HEADERS) + $(CC) -c $(LIBMPDEC_CFLAGS) -o $@ $(srcdir)/Modules/_decimal/libmpdec/crt.c + +Modules/_decimal/libmpdec/difradix2.o: $(srcdir)/Modules/_decimal/libmpdec/difradix2.c $(LIBMPDEC_HEADERS) $(PYTHON_HEADERS) + $(CC) -c $(LIBMPDEC_CFLAGS) -o $@ $(srcdir)/Modules/_decimal/libmpdec/difradix2.c + +Modules/_decimal/libmpdec/fnt.o: $(srcdir)/Modules/_decimal/libmpdec/fnt.c $(LIBMPDEC_HEADERS) $(PYTHON_HEADERS) + $(CC) -c $(LIBMPDEC_CFLAGS) -o $@ $(srcdir)/Modules/_decimal/libmpdec/fnt.c + +Modules/_decimal/libmpdec/fourstep.o: $(srcdir)/Modules/_decimal/libmpdec/fourstep.c $(LIBMPDEC_HEADERS) $(PYTHON_HEADERS) + $(CC) -c $(LIBMPDEC_CFLAGS) -o $@ $(srcdir)/Modules/_decimal/libmpdec/fourstep.c + +Modules/_decimal/libmpdec/io.o: $(srcdir)/Modules/_decimal/libmpdec/io.c $(LIBMPDEC_HEADERS) $(PYTHON_HEADERS) + $(CC) -c $(LIBMPDEC_CFLAGS) -o $@ $(srcdir)/Modules/_decimal/libmpdec/io.c + +Modules/_decimal/libmpdec/mpalloc.o: $(srcdir)/Modules/_decimal/libmpdec/mpalloc.c $(LIBMPDEC_HEADERS) $(PYTHON_HEADERS) + $(CC) -c $(LIBMPDEC_CFLAGS) -o $@ $(srcdir)/Modules/_decimal/libmpdec/mpalloc.c + +Modules/_decimal/libmpdec/mpdecimal.o: $(srcdir)/Modules/_decimal/libmpdec/mpdecimal.c $(LIBMPDEC_HEADERS) $(PYTHON_HEADERS) + $(CC) -c $(LIBMPDEC_CFLAGS) -o $@ $(srcdir)/Modules/_decimal/libmpdec/mpdecimal.c + +Modules/_decimal/libmpdec/mpsignal.o: $(srcdir)/Modules/_decimal/libmpdec/mpsignal.c $(LIBMPDEC_HEADERS) $(PYTHON_HEADERS) + $(CC) -c $(LIBMPDEC_CFLAGS) -o $@ $(srcdir)/Modules/_decimal/libmpdec/mpsignal.c + +Modules/_decimal/libmpdec/numbertheory.o: $(srcdir)/Modules/_decimal/libmpdec/numbertheory.c $(LIBMPDEC_HEADERS) $(PYTHON_HEADERS) + $(CC) -c $(LIBMPDEC_CFLAGS) -o $@ $(srcdir)/Modules/_decimal/libmpdec/numbertheory.c + +Modules/_decimal/libmpdec/sixstep.o: $(srcdir)/Modules/_decimal/libmpdec/sixstep.c $(LIBMPDEC_HEADERS) $(PYTHON_HEADERS) + $(CC) -c $(LIBMPDEC_CFLAGS) -o $@ $(srcdir)/Modules/_decimal/libmpdec/sixstep.c + +Modules/_decimal/libmpdec/transpose.o: $(srcdir)/Modules/_decimal/libmpdec/transpose.c $(LIBMPDEC_HEADERS) $(PYTHON_HEADERS) + $(CC) -c $(LIBMPDEC_CFLAGS) -o $@ $(srcdir)/Modules/_decimal/libmpdec/transpose.c + +$(LIBMPDEC_A): $(LIBMPDEC_OBJS) + -rm -f $@ + $(AR) $(ARFLAGS) $@ $(LIBMPDEC_OBJS) # create relative links from build/lib.platform/egg.so to Modules/egg.so # pybuilddir.txt is created too late. We cannot use it in Makefile @@ -2313,7 +2411,7 @@ MODULE_PYEXPAT_DEPS=$(srcdir)/Modules/expat/ascii.h $(srcdir)/Modules/expat/asci MODULE_UNICODEDATA_DEPS=$(srcdir)/Modules/unicodedata_db.h $(srcdir)/Modules/unicodename_db.h MODULE__BLAKE2_DEPS=$(srcdir)/Modules/_blake2/impl/blake2-config.h $(srcdir)/Modules/_blake2/impl/blake2-dispatch.c $(srcdir)/Modules/_blake2/impl/blake2-impl.h $(srcdir)/Modules/_blake2/impl/blake2-kat.h $(srcdir)/Modules/_blake2/impl/blake2.h $(srcdir)/Modules/_blake2/impl/blake2b-load-sse2.h $(srcdir)/Modules/_blake2/impl/blake2b-load-sse41.h $(srcdir)/Modules/_blake2/impl/blake2b-ref.c $(srcdir)/Modules/_blake2/impl/blake2b-round.h $(srcdir)/Modules/_blake2/impl/blake2b-test.c $(srcdir)/Modules/_blake2/impl/blake2b.c $(srcdir)/Modules/_blake2/impl/blake2bp-test.c $(srcdir)/Modules/_blake2/impl/blake2bp.c $(srcdir)/Modules/_blake2/impl/blake2s-load-sse2.h $(srcdir)/Modules/_blake2/impl/blake2s-load-sse41.h $(srcdir)/Modules/_blake2/impl/blake2s-load-xop.h $(srcdir)/Modules/_blake2/impl/blake2s-ref.c $(srcdir)/Modules/_blake2/impl/blake2s-round.h $(srcdir)/Modules/_blake2/impl/blake2s-test.c $(srcdir)/Modules/_blake2/impl/blake2s.c $(srcdir)/Modules/_blake2/impl/blake2sp-test.c $(srcdir)/Modules/_blake2/impl/blake2sp.c $(srcdir)/Modules/hashlib.h MODULE__CTYPES_DEPS=$(srcdir)/Modules/_ctypes/ctypes.h -MODULE__DECIMAL_DEPS=$(srcdir)/Modules/_decimal/docstrings.h $(srcdir)/Modules/_decimal/libmpdec/basearith.h $(srcdir)/Modules/_decimal/libmpdec/bits.h $(srcdir)/Modules/_decimal/libmpdec/constants.h $(srcdir)/Modules/_decimal/libmpdec/convolute.h $(srcdir)/Modules/_decimal/libmpdec/crt.h $(srcdir)/Modules/_decimal/libmpdec/difradix2.h $(srcdir)/Modules/_decimal/libmpdec/fnt.h $(srcdir)/Modules/_decimal/libmpdec/fourstep.h $(srcdir)/Modules/_decimal/libmpdec/io.h $(srcdir)/Modules/_decimal/libmpdec/mpalloc.h $(srcdir)/Modules/_decimal/libmpdec/mpdecimal.h $(srcdir)/Modules/_decimal/libmpdec/numbertheory.h $(srcdir)/Modules/_decimal/libmpdec/sixstep.h $(srcdir)/Modules/_decimal/libmpdec/transpose.h $(srcdir)/Modules/_decimal/libmpdec/typearith.h $(srcdir)/Modules/_decimal/libmpdec/umodarith.h +MODULE__DECIMAL_DEPS=$(srcdir)/Modules/_decimal/docstrings.h $(LIBMPDEC_HEADERS) @LIBMPDEC_INTERNAL@ MODULE__ELEMENTTREE_DEPS=$(srcdir)/Modules/expat/ascii.h $(srcdir)/Modules/expat/asciitab.h $(srcdir)/Modules/expat/expat.h $(srcdir)/Modules/expat/expat_config.h $(srcdir)/Modules/expat/expat_external.h $(srcdir)/Modules/expat/internal.h $(srcdir)/Modules/expat/latin1tab.h $(srcdir)/Modules/expat/utf8tab.h $(srcdir)/Modules/expat/xmlparse.c $(srcdir)/Modules/expat/xmlrole.c $(srcdir)/Modules/expat/xmlrole.h $(srcdir)/Modules/expat/xmltok.c $(srcdir)/Modules/expat/xmltok.h $(srcdir)/Modules/expat/xmltok_impl.h $(srcdir)/Modules/pyexpat.c MODULE__HASHLIB_DEPS=$(srcdir)/Modules/hashlib.h MODULE__IO_DEPS=$(srcdir)/Modules/_io/_iomodule.h diff --git a/Misc/NEWS.d/next/Build/2021-11-13-10-18-22.bpo-45798.IraaTs.rst b/Misc/NEWS.d/next/Build/2021-11-13-10-18-22.bpo-45798.IraaTs.rst new file mode 100644 index 0000000000000..865d8a07f93eb --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-13-10-18-22.bpo-45798.IraaTs.rst @@ -0,0 +1,2 @@ +Settings for :mod:`decimal` internal C extension are now detected by +``configure``. The bundled ``libmpdec`` library is built in ``Makefile``. diff --git a/Modules/Setup b/Modules/Setup index 49c6903121616..39dc39d534494 100644 --- a/Modules/Setup +++ b/Modules/Setup @@ -149,8 +149,7 @@ time timemodule.c #_contextvars _contextvarsmodule.c #_csv _csv.c #_datetime _datetimemodule.c -# UNIVERSAL: let mpdecimal.h detect settings -#_decimal -DUNIVERSAL -I$(srcdir)/Modules/_decimal/libmpdec _decimal/_decimal.c _decimal/libmpdec/basearith.c _decimal/libmpdec/constants.c _decimal/libmpdec/context.c _decimal/libmpdec/convolute.c _decimal/libmpdec/crt.c _decimal/libmpdec/difradix2.c _decimal/libmpdec/fnt.c _decimal/libmpdec/fourstep.c _decimal/libmpdec/io.c _decimal/libmpdec/mpalloc.c _decimal/libmpdec/mpdecimal.c _decimal/libmpdec/numbertheory.c _decimal/libmpdec/sixstep.c _decimal/libmpdec/transpose.c +#_decimal _decimal/_decimal.c $(DECIMAL_CFLAGS) $(DECIMAL_LDFLAGS) #_heapq _heapqmodule.c #_json _json.c #_lsprof _lsprof.c rotatingtree.c diff --git a/Modules/makesetup b/Modules/makesetup index 543992c4a0294..a8817fffb7c84 100755 --- a/Modules/makesetup +++ b/Modules/makesetup @@ -184,6 +184,11 @@ sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' | *.c++) srcs="$srcs $arg";; *.cxx) srcs="$srcs $arg";; *.cpp) srcs="$srcs $arg";; + \$\(*_CFLAGS\)) cpps="$cpps $arg";; + \$\(*_INCLUDES\)) cpps="$cpps $arg";; + \$\(*_LIBS\)) libs="$libs $arg";; + \$\(*_LDFLAGS\)) libs="$libs $arg";; + \$\(*_RPATH\)) libs="$libs $arg";; \$*) libs="$libs $arg" cpps="$cpps $arg";; *.*) echo 1>&2 "bad word $arg in $line" diff --git a/configure b/configure index edc9000338e31..43516a4f79736 100755 --- a/configure +++ b/configure @@ -660,6 +660,9 @@ DFLAGS DTRACE TCLTK_LIBS TCLTK_INCLUDES +LIBMPDEC_INTERNAL +LIBMPDEC_LDFLAGS +LIBMPDEC_CFLAGS LIBFFI_INCLUDEDIR TZPATH SHLIBS @@ -1533,7 +1536,8 @@ Optional Features: Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --with-pkg-config use pkg-config to detect build options (default is + --with-pkg-config=[yes|no|check] + use pkg-config to detect build options (default is check) --with-universal-archs=ARCH specify the kind of macOS universal binary that @@ -10764,10 +10768,27 @@ else with_system_libmpdec="no" fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_system_libmpdec" >&5 $as_echo "$with_system_libmpdec" >&6; } +if test "x$with_system_libmpdec" = xyes; then : + + LIBMPDEC_CFLAGS="" + LIBMPDEC_LDFLAGS="-lmpdec" + LIBMPDEC_INTERNAL= + +else + + LIBMPDEC_CFLAGS="-I\$(srcdir)/Modules/_decimal/libmpdec" + LIBMPDEC_LDFLAGS="-lm \$(LIBMPDEC_A)" + LIBMPDEC_INTERNAL="\$(LIBMPDEC_A)" + +fi + + + + + # Check whether _decimal should use a coroutine-local or thread-local context { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-decimal-contextvar" >&5 $as_echo_n "checking for --with-decimal-contextvar... " >&6; } @@ -10790,6 +10811,95 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_decimal_contextvar" >&5 $as_echo "$with_decimal_contextvar" >&6; } +# Check for libmpdec machine flavor +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for decimal libmpdec machine" >&5 +$as_echo_n "checking for decimal libmpdec machine... " >&6; } +case $ac_sys_system in #( + Darwin*) : + libmpdec_system=Darwin ;; #( + SunOS*) : + libmpdec_system=sunos ;; #( + *) : + libmpdec_system=other + ;; +esac + +libmpdec_machine=unknown +if test "$libmpdec_system" = Darwin; then + case $MACOSX_DEFAULT_ARCH in #( + i386) : + libmpdec_machine=ansi32 ;; #( + ppc) : + libmpdec_machine=ansi32 ;; #( + x86_64) : + libmpdec_machine=x64 ;; #( + ppc64) : + libmpdec_machine=ansi64 ;; #( + arm64) : + libmpdec_machine=ansi64 ;; #( + *) : + libmpdec_machine=universal + ;; +esac +elif test $ac_cv_sizeof_size_t -eq 8; then + if test "$ac_cv_gcc_asm_for_x64" = yes; then + libmpdec_machine=x64 + elif test "$ac_cv_type___uint128_t" = yes; then + libmpdec_machine=uint128 + else + libmpdec_machine=ansi64 + fi +elif test $ac_cv_sizeof_size_t -eq 4; then + if test "$ac_cv_gcc_asm_for_x87" = yes -a "$libmpdec_system" != sunos; then + case $CC in #( + *gcc*) : + libmpdec_machine=ppro ;; #( + *clang*) : + libmpdec_machine=ppro ;; #( + *) : + libmpdec_machine=ansi32 + ;; +esac + else + libmpdec_machine=ansi32 + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libmpdec_machine" >&5 +$as_echo "$libmpdec_machine" >&6; } + +case $libmpdec_machine in #( + x64) : + as_fn_append LIBMPDEC_CFLAGS " -DCONFIG_64=1 -DASM=1" ;; #( + uint128) : + as_fn_append LIBMPDEC_CFLAGS " -DCONFIG_64=1 -DANSI=1 -DHAVE_UINT128_T=1" ;; #( + ansi64) : + as_fn_append LIBMPDEC_CFLAGS " -DCONFIG_64=1 -DANSI=1" ;; #( + ppro) : + as_fn_append LIBMPDEC_CFLAGS " -DCONFIG_32=1 -DANSI=1 -DASM=1 -Wno-unknown-pragmas" ;; #( + ansi32) : + as_fn_append LIBMPDEC_CFLAGS " -DCONFIG_32=1 -DANSI=1" ;; #( + ansi-legacy) : + as_fn_append LIBMPDEC_CFLAGS " -DCONFIG_32=1 -DANSI=1 -DLEGACY_COMPILER=1" ;; #( + universal) : + as_fn_append LIBMPDEC_CFLAGS " -DUNIVERSAL=1" ;; #( + *) : + as_fn_error $? "_decimal: unsupported architecture" "$LINENO" 5 + ;; +esac + +if test "$have_ipa_pure_const_bug" = yes; then + # Some versions of gcc miscompile inline asm: + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=46491 + # https://gcc.gnu.org/ml/gcc/2010-11/msg00366.html + as_fn_append LIBMPDEC_CFLAGS " -fno-ipa-pure-const" +fi + +if test "$have_glibc_memmove_bug" = yes; then + # _FORTIFY_SOURCE wrappers for memmove and bcopy are incorrect: + # https://sourceware.org/ml/libc-alpha/2010-12/msg00009.html + as_fn_append LIBMPDEC_CFLAGS " -U_FORTIFY_SOURCE" +fi + # Check for support for loadable sqlite extensions { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --enable-loadable-sqlite-extensions" >&5 $as_echo_n "checking for --enable-loadable-sqlite-extensions... " >&6; } diff --git a/configure.ac b/configure.ac index 5a1ed51a6a9ae..c3b52e3910d51 100644 --- a/configure.ac +++ b/configure.ac @@ -3057,9 +3057,22 @@ AC_ARG_WITH(system_libmpdec, AS_HELP_STRING([--with-system-libmpdec], [build _decimal module using an installed libmpdec library, see Doc/library/decimal.rst (default is no)]), [], [with_system_libmpdec="no"]) - AC_MSG_RESULT($with_system_libmpdec) +AS_VAR_IF([with_system_libmpdec], [yes], [ + LIBMPDEC_CFLAGS="" + LIBMPDEC_LDFLAGS="-lmpdec" + LIBMPDEC_INTERNAL= +], [ + LIBMPDEC_CFLAGS="-I\$(srcdir)/Modules/_decimal/libmpdec" + LIBMPDEC_LDFLAGS="-lm \$(LIBMPDEC_A)" + LIBMPDEC_INTERNAL="\$(LIBMPDEC_A)" +]) + +AC_SUBST([LIBMPDEC_CFLAGS]) +AC_SUBST([LIBMPDEC_LDFLAGS]) +AC_SUBST([LIBMPDEC_INTERNAL]) + # Check whether _decimal should use a coroutine-local or thread-local context AC_MSG_CHECKING(for --with-decimal-contextvar) AC_ARG_WITH(decimal_contextvar, @@ -3075,6 +3088,69 @@ fi AC_MSG_RESULT($with_decimal_contextvar) +# Check for libmpdec machine flavor +AC_MSG_CHECKING(for decimal libmpdec machine) +AS_CASE([$ac_sys_system], + [Darwin*], [libmpdec_system=Darwin], + [SunOS*], [libmpdec_system=sunos], + [libmpdec_system=other] +) + +libmpdec_machine=unknown +if test "$libmpdec_system" = Darwin; then + AS_CASE([$MACOSX_DEFAULT_ARCH], + [i386], [libmpdec_machine=ansi32], + [ppc], [libmpdec_machine=ansi32], + [x86_64], [libmpdec_machine=x64], + [ppc64], [libmpdec_machine=ansi64], + [arm64], [libmpdec_machine=ansi64], + [libmpdec_machine=universal] + ) +elif test $ac_cv_sizeof_size_t -eq 8; then + if test "$ac_cv_gcc_asm_for_x64" = yes; then + libmpdec_machine=x64 + elif test "$ac_cv_type___uint128_t" = yes; then + libmpdec_machine=uint128 + else + libmpdec_machine=ansi64 + fi +elif test $ac_cv_sizeof_size_t -eq 4; then + if test "$ac_cv_gcc_asm_for_x87" = yes -a "$libmpdec_system" != sunos; then + AS_CASE([$CC], + [*gcc*], [libmpdec_machine=ppro], + [*clang*], [libmpdec_machine=ppro], + [libmpdec_machine=ansi32] + ) + else + libmpdec_machine=ansi32 + fi +fi +AC_MSG_RESULT([$libmpdec_machine]) + +AS_CASE([$libmpdec_machine], + [x64], [AS_VAR_APPEND([LIBMPDEC_CFLAGS], [" -DCONFIG_64=1 -DASM=1"])], + [uint128], [AS_VAR_APPEND([LIBMPDEC_CFLAGS], [" -DCONFIG_64=1 -DANSI=1 -DHAVE_UINT128_T=1"])], + [ansi64], [AS_VAR_APPEND([LIBMPDEC_CFLAGS], [" -DCONFIG_64=1 -DANSI=1"])], + [ppro], [AS_VAR_APPEND([LIBMPDEC_CFLAGS], [" -DCONFIG_32=1 -DANSI=1 -DASM=1 -Wno-unknown-pragmas"])], + [ansi32], [AS_VAR_APPEND([LIBMPDEC_CFLAGS], [" -DCONFIG_32=1 -DANSI=1"])], + [ansi-legacy], [AS_VAR_APPEND([LIBMPDEC_CFLAGS], [" -DCONFIG_32=1 -DANSI=1 -DLEGACY_COMPILER=1"])], + [universal], [AS_VAR_APPEND([LIBMPDEC_CFLAGS], [" -DUNIVERSAL=1"])], + [AC_MSG_ERROR([_decimal: unsupported architecture])] +) + +if test "$have_ipa_pure_const_bug" = yes; then + # Some versions of gcc miscompile inline asm: + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=46491 + # https://gcc.gnu.org/ml/gcc/2010-11/msg00366.html + AS_VAR_APPEND([LIBMPDEC_CFLAGS], [" -fno-ipa-pure-const"]) +fi + +if test "$have_glibc_memmove_bug" = yes; then + # _FORTIFY_SOURCE wrappers for memmove and bcopy are incorrect: + # https://sourceware.org/ml/libc-alpha/2010-12/msg00009.html + AS_VAR_APPEND([LIBMPDEC_CFLAGS], [" -U_FORTIFY_SOURCE"]) +fi + # Check for support for loadable sqlite extensions AC_MSG_CHECKING(for --enable-loadable-sqlite-extensions) AC_ARG_ENABLE(loadable-sqlite-extensions, diff --git a/setup.py b/setup.py index 771ab5656311e..86ce5d2d91f37 100644 --- a/setup.py +++ b/setup.py @@ -7,6 +7,7 @@ import logging import os import re +import shlex import sys import sysconfig import warnings @@ -2016,117 +2017,27 @@ def detect_ctypes(self): def detect_decimal(self): # Stefan Krah's _decimal module - extra_compile_args = [] - undef_macros = [] - if '--with-system-libmpdec' in sysconfig.get_config_var("CONFIG_ARGS"): - include_dirs = [] - libraries = ['mpdec'] - sources = ['_decimal/_decimal.c'] - depends = ['_decimal/docstrings.h'] - else: - include_dirs = [os.path.abspath(os.path.join(self.srcdir, - 'Modules', - '_decimal', - 'libmpdec'))] - libraries = ['m'] - sources = [ - '_decimal/_decimal.c', - '_decimal/libmpdec/basearith.c', - '_decimal/libmpdec/constants.c', - '_decimal/libmpdec/context.c', - '_decimal/libmpdec/convolute.c', - '_decimal/libmpdec/crt.c', - '_decimal/libmpdec/difradix2.c', - '_decimal/libmpdec/fnt.c', - '_decimal/libmpdec/fourstep.c', - '_decimal/libmpdec/io.c', - '_decimal/libmpdec/mpalloc.c', - '_decimal/libmpdec/mpdecimal.c', - '_decimal/libmpdec/numbertheory.c', - '_decimal/libmpdec/sixstep.c', - '_decimal/libmpdec/transpose.c', - ] - depends = [ - '_decimal/docstrings.h', - '_decimal/libmpdec/basearith.h', - '_decimal/libmpdec/bits.h', - '_decimal/libmpdec/constants.h', - '_decimal/libmpdec/convolute.h', - '_decimal/libmpdec/crt.h', - '_decimal/libmpdec/difradix2.h', - '_decimal/libmpdec/fnt.h', - '_decimal/libmpdec/fourstep.h', - '_decimal/libmpdec/io.h', - '_decimal/libmpdec/mpalloc.h', - '_decimal/libmpdec/mpdecimal.h', - '_decimal/libmpdec/numbertheory.h', - '_decimal/libmpdec/sixstep.h', - '_decimal/libmpdec/transpose.h', - '_decimal/libmpdec/typearith.h', - '_decimal/libmpdec/umodarith.h', - ] - - config = { - 'x64': [('CONFIG_64','1'), ('ASM','1')], - 'uint128': [('CONFIG_64','1'), ('ANSI','1'), ('HAVE_UINT128_T','1')], - 'ansi64': [('CONFIG_64','1'), ('ANSI','1')], - 'ppro': [('CONFIG_32','1'), ('PPRO','1'), ('ASM','1')], - 'ansi32': [('CONFIG_32','1'), ('ANSI','1')], - 'ansi-legacy': [('CONFIG_32','1'), ('ANSI','1'), - ('LEGACY_COMPILER','1')], - 'universal': [('UNIVERSAL','1')] - } - - cc = sysconfig.get_config_var('CC') - sizeof_size_t = sysconfig.get_config_var('SIZEOF_SIZE_T') - machine = os.environ.get('PYTHON_DECIMAL_WITH_MACHINE') - - if machine: - # Override automatic configuration to facilitate testing. - define_macros = config[machine] - elif MACOS: - # Universal here means: build with the same options Python - # was built with. - define_macros = config['universal'] - elif sizeof_size_t == 8: - if sysconfig.get_config_var('HAVE_GCC_ASM_FOR_X64'): - define_macros = config['x64'] - elif sysconfig.get_config_var('HAVE_GCC_UINT128_T'): - define_macros = config['uint128'] - else: - define_macros = config['ansi64'] - elif sizeof_size_t == 4: - ppro = sysconfig.get_config_var('HAVE_GCC_ASM_FOR_X87') - if ppro and ('gcc' in cc or 'clang' in cc) and \ - not 'sunos' in HOST_PLATFORM: - # solaris: problems with register allocation. - # icc >= 11.0 works as well. - define_macros = config['ppro'] - extra_compile_args.append('-Wno-unknown-pragmas') - else: - define_macros = config['ansi32'] - else: - raise DistutilsError("_decimal: unsupported architecture") - - # Workarounds for toolchain bugs: - if sysconfig.get_config_var('HAVE_IPA_PURE_CONST_BUG'): - # Some versions of gcc miscompile inline asm: - # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=46491 - # https://gcc.gnu.org/ml/gcc/2010-11/msg00366.html - extra_compile_args.append('-fno-ipa-pure-const') - if sysconfig.get_config_var('HAVE_GLIBC_MEMMOVE_BUG'): - # _FORTIFY_SOURCE wrappers for memmove and bcopy are incorrect: - # https://sourceware.org/ml/libc-alpha/2010-12/msg00009.html - undef_macros.append('_FORTIFY_SOURCE') + sources = ['_decimal/_decimal.c'] + depends = ['_decimal/docstrings.h'] + define_macros = [] + + cflags = sysconfig.get_config_var("DECIMAL_CFLAGS") + extra_compile_args = shlex.split(cflags) if cflags else None + # ldflags includes either system libmpdec or full path to + # our static libmpdec.a. + ldflags = sysconfig.get_config_var("DECIMAL_LDFLAGS") + extra_link_args = shlex.split(ldflags) if ldflags else None + + libmpdec_a = sysconfig.get_config_var("LIBMPDEC_A") + if libmpdec_a: + depends.append(libmpdec_a) # Uncomment for extra functionality: #define_macros.append(('EXTRA_FUNCTIONALITY', 1)) self.add(Extension('_decimal', - include_dirs=include_dirs, - libraries=libraries, define_macros=define_macros, - undef_macros=undef_macros, extra_compile_args=extra_compile_args, + extra_link_args=extra_link_args, sources=sources, depends=depends)) From webhook-mailer at python.org Sat Nov 13 15:07:31 2021 From: webhook-mailer at python.org (jaraco) Date: Sat, 13 Nov 2021 20:07:31 -0000 Subject: [Python-checkins] [3.9] [bpo-45765] Fix distribution discovery on empty path. (GH-29487). (GH-29511) Message-ID: https://github.com/python/cpython/commit/3e0b830e859ca8792401bfd1402d659f56f99941 commit: 3e0b830e859ca8792401bfd1402d659f56f99941 branch: 3.9 author: Jason R. Coombs committer: jaraco date: 2021-11-13T15:07:22-05:00 summary: [3.9] [bpo-45765] Fix distribution discovery on empty path. (GH-29487). (GH-29511) (cherry picked from commit 6ec0dec7b7b50d4fee5b2b66cf38e4291bcdf44c) Co-authored-by: Jason R. Coombs files: A Misc/NEWS.d/next/Library/2021-11-09-09-04-19.bpo-45765.JVobxK.rst M Lib/importlib/metadata.py diff --git a/Lib/importlib/metadata.py b/Lib/importlib/metadata.py index ffa0cba45706d..c6c7d31aa5d8a 100644 --- a/Lib/importlib/metadata.py +++ b/Lib/importlib/metadata.py @@ -419,7 +419,7 @@ def joinpath(self, child): def children(self): with suppress(Exception): - return os.listdir(self.root or '') + return os.listdir(self.root or '.') with suppress(Exception): return self.zip_children() return [] diff --git a/Misc/NEWS.d/next/Library/2021-11-09-09-04-19.bpo-45765.JVobxK.rst b/Misc/NEWS.d/next/Library/2021-11-09-09-04-19.bpo-45765.JVobxK.rst new file mode 100644 index 0000000000000..a1f4a1f7aa91c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-09-09-04-19.bpo-45765.JVobxK.rst @@ -0,0 +1 @@ +In importlib.metadata, fix distribution discovery for an empty path. From webhook-mailer at python.org Sat Nov 13 15:08:32 2021 From: webhook-mailer at python.org (jaraco) Date: Sat, 13 Nov 2021 20:08:32 -0000 Subject: [Python-checkins] [bpo-45765] Fix distribution discovery on empty path. (GH-29487) (GH-29510) Message-ID: https://github.com/python/cpython/commit/ed55426acd58f030ccc0cf1297e66078f538797c commit: ed55426acd58f030ccc0cf1297e66078f538797c branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: jaraco date: 2021-11-13T15:08:28-05:00 summary: [bpo-45765] Fix distribution discovery on empty path. (GH-29487) (GH-29510) (cherry picked from commit 6ec0dec7b7b50d4fee5b2b66cf38e4291bcdf44c) Co-authored-by: Jason R. Coombs Co-authored-by: Jason R. Coombs files: A Misc/NEWS.d/next/Library/2021-11-09-09-04-19.bpo-45765.JVobxK.rst M Lib/importlib/metadata/__init__.py diff --git a/Lib/importlib/metadata/__init__.py b/Lib/importlib/metadata/__init__.py index f5172eefc1841..b3e8fb05f1d98 100644 --- a/Lib/importlib/metadata/__init__.py +++ b/Lib/importlib/metadata/__init__.py @@ -748,7 +748,7 @@ def joinpath(self, child): def children(self): with suppress(Exception): - return os.listdir(self.root or '') + return os.listdir(self.root or '.') with suppress(Exception): return self.zip_children() return [] diff --git a/Misc/NEWS.d/next/Library/2021-11-09-09-04-19.bpo-45765.JVobxK.rst b/Misc/NEWS.d/next/Library/2021-11-09-09-04-19.bpo-45765.JVobxK.rst new file mode 100644 index 0000000000000..a1f4a1f7aa91c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-09-09-04-19.bpo-45765.JVobxK.rst @@ -0,0 +1 @@ +In importlib.metadata, fix distribution discovery for an empty path. From webhook-mailer at python.org Sat Nov 13 15:16:13 2021 From: webhook-mailer at python.org (miss-islington) Date: Sat, 13 Nov 2021 20:16:13 -0000 Subject: [Python-checkins] bpo-45799: [Doc] improve confusing sentence in __main__.rst (GH-29546) Message-ID: https://github.com/python/cpython/commit/f8da00ef04fdadf7cd9821e8ec4b317ecf3ed663 commit: f8da00ef04fdadf7cd9821e8ec4b317ecf3ed663 branch: main author: Jack DeVries committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-13T12:16:05-08:00 summary: bpo-45799: [Doc] improve confusing sentence in __main__.rst (GH-29546) I was reading this bit last night and thought it was a typo. In the light of day, I realized it wasn't *technically* a typo, but definitely confusing wording. This PR fixes the confusing sentence. Automerge-Triggered-By: GH:ericvsmith files: M Doc/library/__main__.rst diff --git a/Doc/library/__main__.rst b/Doc/library/__main__.rst index d92266e43b961..c5f36a7fcf077 100644 --- a/Doc/library/__main__.rst +++ b/Doc/library/__main__.rst @@ -116,8 +116,8 @@ Idiomatic Usage ^^^^^^^^^^^^^^^ Some modules contain code that is intended for script use only, like parsing -command-line arguments or fetching data from standard input. When a module -like this were to be imported from a different module, for example to unit test +command-line arguments or fetching data from standard input. If a module +like this was imported from a different module, for example to unit test it, the script code would unintentionally execute as well. This is where using the ``if __name__ == '__main__'`` code block comes in From webhook-mailer at python.org Sat Nov 13 15:36:52 2021 From: webhook-mailer at python.org (miss-islington) Date: Sat, 13 Nov 2021 20:36:52 -0000 Subject: [Python-checkins] bpo-45799: [Doc] improve confusing sentence in __main__.rst (GH-29546) Message-ID: https://github.com/python/cpython/commit/28326ac5f87ede140268376f0c87c3b2aba62906 commit: 28326ac5f87ede140268376f0c87c3b2aba62906 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-13T12:36:44-08:00 summary: bpo-45799: [Doc] improve confusing sentence in __main__.rst (GH-29546) I was reading this bit last night and thought it was a typo. In the light of day, I realized it wasn't *technically* a typo, but definitely confusing wording. This PR fixes the confusing sentence. Automerge-Triggered-By: GH:ericvsmith (cherry picked from commit f8da00ef04fdadf7cd9821e8ec4b317ecf3ed663) Co-authored-by: Jack DeVries files: M Doc/library/__main__.rst diff --git a/Doc/library/__main__.rst b/Doc/library/__main__.rst index d92266e43b961..c5f36a7fcf077 100644 --- a/Doc/library/__main__.rst +++ b/Doc/library/__main__.rst @@ -116,8 +116,8 @@ Idiomatic Usage ^^^^^^^^^^^^^^^ Some modules contain code that is intended for script use only, like parsing -command-line arguments or fetching data from standard input. When a module -like this were to be imported from a different module, for example to unit test +command-line arguments or fetching data from standard input. If a module +like this was imported from a different module, for example to unit test it, the script code would unintentionally execute as well. This is where using the ``if __name__ == '__main__'`` code block comes in From webhook-mailer at python.org Sat Nov 13 20:06:50 2021 From: webhook-mailer at python.org (pablogsal) Date: Sun, 14 Nov 2021 01:06:50 -0000 Subject: [Python-checkins] bpo-45738: Fix computation of error location for invalid continuation (GH-29550) Message-ID: https://github.com/python/cpython/commit/25835c518aa7446f3680b62c1fb43827e0f190d9 commit: 25835c518aa7446f3680b62c1fb43827e0f190d9 branch: main author: Pablo Galindo Salgado committer: pablogsal date: 2021-11-14T01:06:41Z summary: bpo-45738: Fix computation of error location for invalid continuation (GH-29550) characters in the parser files: A Misc/NEWS.d/next/Core and Builtins/2021-11-14-00-14-45.bpo-45738.e0cgKd.rst M Lib/test/test_syntax.py M Parser/pegen.c M Parser/tokenizer.c diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 65d18e4941be5..f41df8ca49aa6 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -1505,7 +1505,13 @@ def func2(): def test_invalid_line_continuation_error_position(self): self._check_error(r"a = 3 \ 4", "unexpected character after line continuation character", - lineno=1, offset=9) + lineno=1, offset=8) + self._check_error('1,\\#\n2', + "unexpected character after line continuation character", + lineno=1, offset=4) + self._check_error('\nfgdfgf\n1,\\#\n2\n', + "unexpected character after line continuation character", + lineno=3, offset=4) def test_invalid_line_continuation_left_recursive(self): # Check bpo-42218: SyntaxErrors following left-recursive rules diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-14-00-14-45.bpo-45738.e0cgKd.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-14-00-14-45.bpo-45738.e0cgKd.rst new file mode 100644 index 0000000000000..b238034323c77 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-14-00-14-45.bpo-45738.e0cgKd.rst @@ -0,0 +1,2 @@ +Fix computation of error location for invalid continuation characters in the +parser. Patch by Pablo Galindo. diff --git a/Parser/pegen.c b/Parser/pegen.c index b00eff3432dec..8a3f740c359c0 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -351,14 +351,7 @@ tokenizer_error(Parser *p) msg = "too many levels of indentation"; break; case E_LINECONT: { - char* loc = strrchr(p->tok->buf, '\n'); - const char* last_char = p->tok->cur - 1; - if (loc != NULL && loc != last_char) { - col_offset = p->tok->cur - loc - 1; - p->tok->buf = loc; - } else { - col_offset = last_char - p->tok->buf - 1; - } + col_offset = p->tok->cur - p->tok->buf - 1; msg = "unexpected character after line continuation character"; break; } @@ -366,7 +359,9 @@ tokenizer_error(Parser *p) msg = "unknown parsing error"; } - RAISE_ERROR_KNOWN_LOCATION(p, errtype, p->tok->lineno, col_offset, p->tok->lineno, -1, msg); + RAISE_ERROR_KNOWN_LOCATION(p, errtype, p->tok->lineno, + col_offset >= 0 ? col_offset : 0, + p->tok->lineno, -1, msg); return -1; } @@ -497,7 +492,7 @@ _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, does not physically exist */ assert(p->tok->fp == NULL || p->tok->fp == stdin || p->tok->done == E_EOF || !uses_utf8_codec); - if (p->tok->lineno <= lineno) { + if (p->tok->lineno <= lineno && p->tok->inp > p->tok->buf) { Py_ssize_t size = p->tok->inp - p->tok->buf; error_line = PyUnicode_DecodeUTF8(p->tok->buf, size, "replace"); } diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index 8a19458ec72f4..f281c423d0e0c 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -1970,7 +1970,6 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end) c = tok_nextc(tok); if (c != '\n') { tok->done = E_LINECONT; - tok->cur = tok->inp; return ERRORTOKEN; } c = tok_nextc(tok); From webhook-mailer at python.org Sat Nov 13 20:30:11 2021 From: webhook-mailer at python.org (miss-islington) Date: Sun, 14 Nov 2021 01:30:11 -0000 Subject: [Python-checkins] bpo-45738: Fix computation of error location for invalid continuation (GH-29550) Message-ID: https://github.com/python/cpython/commit/bf26a6da7aaedb526c9eb1cb56b0e46d1c10384c commit: bf26a6da7aaedb526c9eb1cb56b0e46d1c10384c branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-13T17:30:03-08:00 summary: bpo-45738: Fix computation of error location for invalid continuation (GH-29550) characters in the parser (cherry picked from commit 25835c518aa7446f3680b62c1fb43827e0f190d9) Co-authored-by: Pablo Galindo Salgado files: A Misc/NEWS.d/next/Core and Builtins/2021-11-14-00-14-45.bpo-45738.e0cgKd.rst M Lib/test/test_syntax.py M Parser/pegen.c M Parser/tokenizer.c diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 45b2785f34831..3b79b7a0b67b6 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -1487,7 +1487,13 @@ def func2(): def test_invalid_line_continuation_error_position(self): self._check_error(r"a = 3 \ 4", "unexpected character after line continuation character", - lineno=1, offset=9) + lineno=1, offset=8) + self._check_error('1,\\#\n2', + "unexpected character after line continuation character", + lineno=1, offset=4) + self._check_error('\nfgdfgf\n1,\\#\n2\n', + "unexpected character after line continuation character", + lineno=3, offset=4) def test_invalid_line_continuation_left_recursive(self): # Check bpo-42218: SyntaxErrors following left-recursive rules diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-14-00-14-45.bpo-45738.e0cgKd.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-14-00-14-45.bpo-45738.e0cgKd.rst new file mode 100644 index 0000000000000..b238034323c77 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-14-00-14-45.bpo-45738.e0cgKd.rst @@ -0,0 +1,2 @@ +Fix computation of error location for invalid continuation characters in the +parser. Patch by Pablo Galindo. diff --git a/Parser/pegen.c b/Parser/pegen.c index 66e4b1929711f..cfb4b8e8fb157 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -372,14 +372,7 @@ tokenizer_error(Parser *p) msg = "too many levels of indentation"; break; case E_LINECONT: { - char* loc = strrchr(p->tok->buf, '\n'); - const char* last_char = p->tok->cur - 1; - if (loc != NULL && loc != last_char) { - col_offset = p->tok->cur - loc - 1; - p->tok->buf = loc; - } else { - col_offset = last_char - p->tok->buf - 1; - } + col_offset = p->tok->cur - p->tok->buf - 1; msg = "unexpected character after line continuation character"; break; } @@ -387,7 +380,9 @@ tokenizer_error(Parser *p) msg = "unknown parsing error"; } - RAISE_ERROR_KNOWN_LOCATION(p, errtype, p->tok->lineno, col_offset, p->tok->lineno, -1, msg); + RAISE_ERROR_KNOWN_LOCATION(p, errtype, p->tok->lineno, + col_offset >= 0 ? col_offset : 0, + p->tok->lineno, -1, msg); return -1; } @@ -497,7 +492,7 @@ _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, does not physically exist */ assert(p->tok->fp == NULL || p->tok->fp == stdin || p->tok->done == E_EOF || !uses_utf8_codec); - if (p->tok->lineno <= lineno) { + if (p->tok->lineno <= lineno && p->tok->inp > p->tok->buf) { Py_ssize_t size = p->tok->inp - p->tok->buf; error_line = PyUnicode_DecodeUTF8(p->tok->buf, size, "replace"); } diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index 519300f3731f0..76a22dab65994 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -1969,7 +1969,6 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end) c = tok_nextc(tok); if (c != '\n') { tok->done = E_LINECONT; - tok->cur = tok->inp; return ERRORTOKEN; } c = tok_nextc(tok); From webhook-mailer at python.org Sat Nov 13 20:47:35 2021 From: webhook-mailer at python.org (pablogsal) Date: Sun, 14 Nov 2021 01:47:35 -0000 Subject: [Python-checkins] bpo-45738: Fix computation of error location for invalid continuation characters in the parser (GH-29550) (GH-29552) Message-ID: https://github.com/python/cpython/commit/142fcb40b6e460fa9b4a89fe9846b1ce4176354e commit: 142fcb40b6e460fa9b4a89fe9846b1ce4176354e branch: 3.9 author: Pablo Galindo Salgado committer: pablogsal date: 2021-11-14T01:47:27Z summary: bpo-45738: Fix computation of error location for invalid continuation characters in the parser (GH-29550) (GH-29552) (cherry picked from commit 25835c518aa7446f3680b62c1fb43827e0f190d9) files: A Misc/NEWS.d/next/Core and Builtins/2021-11-14-00-14-45.bpo-45738.e0cgKd.rst M Lib/test/test_syntax.py M Parser/pegen/pegen.c M Parser/tokenizer.c diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index eaa94ea92b5cd..46f27d0444364 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -953,7 +953,13 @@ def func2(): def test_invalid_line_continuation_error_position(self): self._check_error(r"a = 3 \ 4", "unexpected character after line continuation character", - lineno=1, offset=(10 if support.use_old_parser() else 9)) + lineno=1, offset=8) + self._check_error('1,\\#\n2', + "unexpected character after line continuation character", + lineno=1, offset=4) + self._check_error('\nfgdfgf\n1,\\#\n2\n', + "unexpected character after line continuation character", + lineno=3, offset=4) def test_invalid_line_continuation_left_recursive(self): # Check bpo-42218: SyntaxErrors following left-recursive rules diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-14-00-14-45.bpo-45738.e0cgKd.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-14-00-14-45.bpo-45738.e0cgKd.rst new file mode 100644 index 0000000000000..b238034323c77 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-14-00-14-45.bpo-45738.e0cgKd.rst @@ -0,0 +1,2 @@ +Fix computation of error location for invalid continuation characters in the +parser. Patch by Pablo Galindo. diff --git a/Parser/pegen/pegen.c b/Parser/pegen/pegen.c index 98de05c5cdb69..efcf9ac1ebd74 100644 --- a/Parser/pegen/pegen.c +++ b/Parser/pegen/pegen.c @@ -348,14 +348,7 @@ tokenizer_error(Parser *p) msg = "too many levels of indentation"; break; case E_LINECONT: { - char* loc = strrchr(p->tok->buf, '\n'); - const char* last_char = p->tok->cur - 1; - if (loc != NULL && loc != last_char) { - col_offset = p->tok->cur - loc - 1; - p->tok->buf = loc; - } else { - col_offset = last_char - p->tok->buf - 1; - } + col_offset = p->tok->cur - p->tok->buf - 1; msg = "unexpected character after line continuation character"; break; } @@ -363,7 +356,8 @@ tokenizer_error(Parser *p) msg = "unknown parsing error"; } - RAISE_ERROR_KNOWN_LOCATION(p, errtype, p->tok->lineno, col_offset, msg); + RAISE_ERROR_KNOWN_LOCATION(p, errtype, p->tok->lineno, + col_offset >= 0 ? col_offset : 0, msg); return -1; } diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index 1a57db97c4ecd..41bfdb853c7a6 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -1752,7 +1752,6 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end) c = tok_nextc(tok); if (c != '\n') { tok->done = E_LINECONT; - tok->cur = tok->inp; return ERRORTOKEN; } c = tok_nextc(tok); From webhook-mailer at python.org Sun Nov 14 04:02:41 2021 From: webhook-mailer at python.org (tiran) Date: Sun, 14 Nov 2021 09:02:41 -0000 Subject: [Python-checkins] bpo-45800: Move pyexpat build setup into configure (GH-29547) Message-ID: https://github.com/python/cpython/commit/464e6616be86129e33af6d9e43540c260d6804d5 commit: 464e6616be86129e33af6d9e43540c260d6804d5 branch: main author: Christian Heimes committer: tiran date: 2021-11-14T10:02:24+01:00 summary: bpo-45800: Move pyexpat build setup into configure (GH-29547) Settings for :mod:`pyexpat` C extension are now detected by ``configure``. The bundled ``expat`` library is built in ``Makefile``. Signed-off-by: Christian Heimes files: A Misc/NEWS.d/next/Build/2021-11-13-16-40-05.bpo-45800.5Hz6nr.rst M Makefile.pre.in M Modules/Setup M configure M configure.ac M setup.py diff --git a/Makefile.pre.in b/Makefile.pre.in index a17054b6f65de..b6e4c2316bccc 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -537,6 +537,33 @@ LIBMPDEC_HEADERS= \ LIBMPDEC_A= Modules/_decimal/libmpdec/libmpdec.a +########################################################################## +# pyexpat's expat library + +LIBEXPAT_OBJS= \ + Modules/expat/xmlparse.o \ + Modules/expat/xmlrole.o \ + Modules/expat/xmltok.o + +LIBEXPAT_HEADERS= \ + Modules/expat/ascii.h \ + Modules/expat/asciitab.h \ + Modules/expat/expat.h \ + Modules/expat/expat_config.h \ + Modules/expat/expat_external.h \ + Modules/expat/iasciitab.h \ + Modules/expat/internal.h \ + Modules/expat/latin1tab.h \ + Modules/expat/nametab.h \ + Modules/expat/pyexpatns.h \ + Modules/expat/siphash.h \ + Modules/expat/utf8tab.h \ + Modules/expat/xmlrole.h \ + Modules/expat/xmltok.h \ + Modules/expat/xmltok_impl.h + +LIBEXPAT_A= Modules/expat/libexpat.a + ######################################################################### # Rules @@ -688,7 +715,7 @@ $(srcdir)/Modules/_blake2/blake2s_impl.c: $(srcdir)/Modules/_blake2/blake2b_impl # -s, --silent or --quiet is always the first char. # Under BSD make, MAKEFLAGS might be " -s -v x=y". # Ignore macros passed by GNU make, passed after -- -sharedmods: $(BUILDPYTHON) pybuilddir.txt @LIBMPDEC_INTERNAL@ +sharedmods: $(BUILDPYTHON) pybuilddir.txt @LIBMPDEC_INTERNAL@ @LIBEXPAT_INTERNAL@ @case "`echo X $$MAKEFLAGS | sed 's/^X //;s/ -- .*//'`" in \ *\ -s*|s*) quiet="-q";; \ *) quiet="";; \ @@ -828,6 +855,27 @@ $(LIBMPDEC_A): $(LIBMPDEC_OBJS) -rm -f $@ $(AR) $(ARFLAGS) $@ $(LIBMPDEC_OBJS) +########################################################################## +# Build static libexpat.a +LIBEXPAT_CFLAGS=$(PY_STDMODULE_CFLAGS) $(CCSHARED) @LIBEXPAT_CFLAGS@ + +# for setup.py +EXPAT_CFLAGS=@LIBEXPAT_CFLAGS@ +EXPAT_LDFLAGS=@LIBEXPAT_LDFLAGS@ + +Modules/expat/xmlparse.o: $(srcdir)/Modules/expat/xmlparse.c $(LIBEXPAT_HEADERS) $(PYTHON_HEADERS) + $(CC) -c $(LIBEXPAT_CFLAGS) -o $@ $(srcdir)/Modules/expat/xmlparse.c + +Modules/expat/xmlrole.o: $(srcdir)/Modules/expat/xmlrole.c $(LIBEXPAT_HEADERS) $(PYTHON_HEADERS) + $(CC) -c $(LIBEXPAT_CFLAGS) -o $@ $(srcdir)/Modules/expat/xmlrole.c + +Modules/expat/xmltok.o: $(srcdir)/Modules/expat/xmltok.c $(LIBEXPAT_HEADERS) $(PYTHON_HEADERS) + $(CC) -c $(LIBEXPAT_CFLAGS) -o $@ $(srcdir)/Modules/expat/xmltok.c + +$(LIBEXPAT_A): $(LIBEXPAT_OBJS) + -rm -f $@ + $(AR) $(ARFLAGS) $@ $(LIBEXPAT_OBJS) + # create relative links from build/lib.platform/egg.so to Modules/egg.so # pybuilddir.txt is created too late. We cannot use it in Makefile # targets. ln --relative is not portable. @@ -2407,12 +2455,12 @@ Python/thread.o: @THREADHEADERS@ $(srcdir)/Python/condvar.h MODULE_CMATH_DEPS=$(srcdir)/Modules/_math.h MODULE_MATH_DEPS=$(srcdir)/Modules/_math.h -MODULE_PYEXPAT_DEPS=$(srcdir)/Modules/expat/ascii.h $(srcdir)/Modules/expat/asciitab.h $(srcdir)/Modules/expat/expat.h $(srcdir)/Modules/expat/expat_config.h $(srcdir)/Modules/expat/expat_external.h $(srcdir)/Modules/expat/internal.h $(srcdir)/Modules/expat/latin1tab.h $(srcdir)/Modules/expat/utf8tab.h $(srcdir)/Modules/expat/xmlrole.h $(srcdir)/Modules/expat/xmltok.h $(srcdir)/Modules/expat/xmltok_impl.h +MODULE_PYEXPAT_DEPS=$(LIBEXPAT_HEADERS) @LIBEXPAT_INTERNAL@ MODULE_UNICODEDATA_DEPS=$(srcdir)/Modules/unicodedata_db.h $(srcdir)/Modules/unicodename_db.h MODULE__BLAKE2_DEPS=$(srcdir)/Modules/_blake2/impl/blake2-config.h $(srcdir)/Modules/_blake2/impl/blake2-dispatch.c $(srcdir)/Modules/_blake2/impl/blake2-impl.h $(srcdir)/Modules/_blake2/impl/blake2-kat.h $(srcdir)/Modules/_blake2/impl/blake2.h $(srcdir)/Modules/_blake2/impl/blake2b-load-sse2.h $(srcdir)/Modules/_blake2/impl/blake2b-load-sse41.h $(srcdir)/Modules/_blake2/impl/blake2b-ref.c $(srcdir)/Modules/_blake2/impl/blake2b-round.h $(srcdir)/Modules/_blake2/impl/blake2b-test.c $(srcdir)/Modules/_blake2/impl/blake2b.c $(srcdir)/Modules/_blake2/impl/blake2bp-test.c $(srcdir)/Modules/_blake2/impl/blake2bp.c $(srcdir)/Modules/_blake2/impl/blake2s-load-sse2.h $(srcdir)/Modules/_blake2/impl/blake2s-load-sse41.h $(srcdir)/Modules/_blake2/impl/blake2s-load-xop.h $(srcdir)/Modules/_blake2/impl/blake2s-ref.c $(srcdir)/Modules/_blake2/impl/blake2s-round.h $(srcdir)/Modules/_blake2/impl/blake2s-test.c $(srcdir)/Modules/_blake2/impl/blake2s.c $(srcdir)/Modules/_blake2/impl/blake2sp-test.c $(srcdir)/Modules/_blake2/impl/blake2sp.c $(srcdir)/Modules/hashlib.h MODULE__CTYPES_DEPS=$(srcdir)/Modules/_ctypes/ctypes.h MODULE__DECIMAL_DEPS=$(srcdir)/Modules/_decimal/docstrings.h $(LIBMPDEC_HEADERS) @LIBMPDEC_INTERNAL@ -MODULE__ELEMENTTREE_DEPS=$(srcdir)/Modules/expat/ascii.h $(srcdir)/Modules/expat/asciitab.h $(srcdir)/Modules/expat/expat.h $(srcdir)/Modules/expat/expat_config.h $(srcdir)/Modules/expat/expat_external.h $(srcdir)/Modules/expat/internal.h $(srcdir)/Modules/expat/latin1tab.h $(srcdir)/Modules/expat/utf8tab.h $(srcdir)/Modules/expat/xmlparse.c $(srcdir)/Modules/expat/xmlrole.c $(srcdir)/Modules/expat/xmlrole.h $(srcdir)/Modules/expat/xmltok.c $(srcdir)/Modules/expat/xmltok.h $(srcdir)/Modules/expat/xmltok_impl.h $(srcdir)/Modules/pyexpat.c +MODULE__ELEMENTTREE_DEPS=$(LIBEXPAT_HEADERS) @LIBEXPAT_INTERNAL@ MODULE__HASHLIB_DEPS=$(srcdir)/Modules/hashlib.h MODULE__IO_DEPS=$(srcdir)/Modules/_io/_iomodule.h MODULE__MD5_DEPS=$(srcdir)/Modules/hashlib.h diff --git a/Misc/NEWS.d/next/Build/2021-11-13-16-40-05.bpo-45800.5Hz6nr.rst b/Misc/NEWS.d/next/Build/2021-11-13-16-40-05.bpo-45800.5Hz6nr.rst new file mode 100644 index 0000000000000..8da3fcaebd06c --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-13-16-40-05.bpo-45800.5Hz6nr.rst @@ -0,0 +1,2 @@ +Settings for :mod:`pyexpat` C extension are now detected by ``configure``. +The bundled ``expat`` library is built in ``Makefile``. diff --git a/Modules/Setup b/Modules/Setup index 39dc39d534494..608866d9cedd5 100644 --- a/Modules/Setup +++ b/Modules/Setup @@ -172,8 +172,8 @@ time timemodule.c #select selectmodule.c # XML -#_elementtree -I$(srcdir)/Modules/expat _elementtree.c -#pyexpat -I$(srcdir)/Modules/expat expat/xmlparse.c expat/xmlrole.c expat/xmltok.c pyexpat.c +#_elementtree _elementtree.c $(EXPAT_CFLAGS) +#pyexpat pyexpat.c $(EXPAT_CFLAGS) $(EXPAT_LDFLAGS) # hashing builtins #_blake2 _blake2/blake2module.c _blake2/blake2b_impl.c _blake2/blake2s_impl.c diff --git a/configure b/configure index 43516a4f79736..53dc4a23f8063 100755 --- a/configure +++ b/configure @@ -664,6 +664,9 @@ LIBMPDEC_INTERNAL LIBMPDEC_LDFLAGS LIBMPDEC_CFLAGS LIBFFI_INCLUDEDIR +LIBEXPAT_INTERNAL +LIBEXPAT_LDFLAGS +LIBEXPAT_CFLAGS TZPATH SHLIBS CFLAGSFORSHARED @@ -10715,6 +10718,24 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_system_expat" >&5 $as_echo "$with_system_expat" >&6; } +if test "x$with_system_expat" = xyes; then : + + LIBEXPAT_CFLAGS="" + LIBEXPAT_LDFLAGS="-lexpat" + LIBEXPAT_INTERNAL= + +else + + LIBEXPAT_CFLAGS="-I\$(srcdir)/Modules/expat" + LIBEXPAT_LDFLAGS="-lm \$(LIBEXPAT_A)" + LIBEXPAT_INTERNAL="\$(LIBEXPAT_A)" + +fi + + + + + # Check for use of the system libffi library { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-system-ffi" >&5 $as_echo_n "checking for --with-system-ffi... " >&6; } diff --git a/configure.ac b/configure.ac index c3b52e3910d51..f43030e481068 100644 --- a/configure.ac +++ b/configure.ac @@ -3017,6 +3017,20 @@ AC_ARG_WITH(system_expat, AC_MSG_RESULT($with_system_expat) +AS_VAR_IF([with_system_expat], [yes], [ + LIBEXPAT_CFLAGS="" + LIBEXPAT_LDFLAGS="-lexpat" + LIBEXPAT_INTERNAL= +], [ + LIBEXPAT_CFLAGS="-I\$(srcdir)/Modules/expat" + LIBEXPAT_LDFLAGS="-lm \$(LIBEXPAT_A)" + LIBEXPAT_INTERNAL="\$(LIBEXPAT_A)" +]) + +AC_SUBST([LIBEXPAT_CFLAGS]) +AC_SUBST([LIBEXPAT_LDFLAGS]) +AC_SUBST([LIBEXPAT_INTERNAL]) + # Check for use of the system libffi library AC_MSG_CHECKING(for --with-system-ffi) AC_ARG_WITH(system_ffi, diff --git a/setup.py b/setup.py index 86ce5d2d91f37..c62f0427fd378 100644 --- a/setup.py +++ b/setup.py @@ -364,6 +364,57 @@ def find_module_file(module, dirlist): return os.path.join(dirs[0], module) +def parse_cflags(flags): + """Parse a string with compiler flags (-I, -D, -U, extra) + + Distutils appends extra args to the compiler arguments. Some flags like + -I must appear earlier. Otherwise the pre-processor picks up files + from system inclue directories. + """ + include_dirs = [] + define_macros = [] + undef_macros = [] + extra_compile_args = [] + if flags is not None: + # shlex.split(None) reads from stdin + for token in shlex.split(flags): + switch = token[0:2] + value = token[2:] + if switch == '-I': + include_dirs.append(value) + elif switch == '-D': + key, _, val = value.partition("=") + if not val: + val = None + define_macros.append((key, val)) + elif switch == '-U': + undef_macros.append(value) + else: + extra_compile_args.append(token) + + return include_dirs, define_macros, undef_macros, extra_compile_args + + +def parse_ldflags(flags): + """Parse a string with linker flags (-L, -l, extra)""" + library_dirs = [] + libraries = [] + extra_link_args = [] + if flags is not None: + # shlex.split(None) reads from stdin + for token in shlex.split(flags): + switch = token[0:2] + value = token[2:] + if switch == '-L': + library_dirs.append(value) + elif switch == '-l': + libraries.append(value) + else: + extra_link_args.append(token) + + return library_dirs, libraries, extra_link_args + + class PyBuildExt(build_ext): def __init__(self, dist): @@ -1469,59 +1520,39 @@ def detect_expat_elementtree(self): # # More information on Expat can be found at www.libexpat.org. # - if '--with-system-expat' in sysconfig.get_config_var("CONFIG_ARGS"): - expat_inc = [] - extra_compile_args = [] - expat_lib = ['expat'] - expat_sources = [] - expat_depends = [] - else: - expat_inc = [os.path.join(self.srcdir, 'Modules', 'expat')] - extra_compile_args = [] - # bpo-44394: libexpat uses isnan() of math.h and needs linkage - # against the libm - expat_lib = ['m'] - expat_sources = ['expat/xmlparse.c', - 'expat/xmlrole.c', - 'expat/xmltok.c'] - expat_depends = ['expat/ascii.h', - 'expat/asciitab.h', - 'expat/expat.h', - 'expat/expat_config.h', - 'expat/expat_external.h', - 'expat/internal.h', - 'expat/latin1tab.h', - 'expat/utf8tab.h', - 'expat/xmlrole.h', - 'expat/xmltok.h', - 'expat/xmltok_impl.h' - ] - - cc = sysconfig.get_config_var('CC').split()[0] - ret = run_command( - '"%s" -Werror -Wno-unreachable-code -E -xc /dev/null >/dev/null 2>&1' % cc) - if ret == 0: - extra_compile_args.append('-Wno-unreachable-code') + cflags = parse_cflags(sysconfig.get_config_var("EXPAT_CFLAGS")) + include_dirs, define_macros, undef_macros, extra_compile_args = cflags + # ldflags includes either system libexpat or full path to + # our static libexpat.a. + ldflags = parse_ldflags(sysconfig.get_config_var("EXPAT_LDFLAGS")) + library_dirs, libraries, extra_link_args = ldflags + + expat_depends = [] + libexpat_a = sysconfig.get_config_var("LIBEXPAT_A") + if libexpat_a: + expat_depends.append(libexpat_a) self.add(Extension('pyexpat', + include_dirs=include_dirs, + define_macros=define_macros, + undef_macros=undef_macros, extra_compile_args=extra_compile_args, - include_dirs=expat_inc, - libraries=expat_lib, - sources=['pyexpat.c'] + expat_sources, + library_dirs=library_dirs, + libraries=libraries, + extra_link_args=extra_link_args, + sources=['pyexpat.c'], depends=expat_depends)) # Fredrik Lundh's cElementTree module. Note that this also # uses expat (via the CAPI hook in pyexpat). - - if os.path.isfile(os.path.join(self.srcdir, 'Modules', '_elementtree.c')): - self.add(Extension('_elementtree', - include_dirs=expat_inc, - libraries=expat_lib, - sources=['_elementtree.c'], - depends=['pyexpat.c', *expat_sources, - *expat_depends])) - else: - self.missing.append('_elementtree') + self.add(Extension('_elementtree', + include_dirs=include_dirs, + define_macros=define_macros, + undef_macros=undef_macros, + extra_compile_args=extra_compile_args, + # no EXPAT_LDFLAGS + sources=['_elementtree.c'], + depends=['pyexpat.c', *expat_depends])) def detect_multibytecodecs(self): # Hye-Shik Chang's CJKCodecs modules. @@ -2019,15 +2050,14 @@ def detect_decimal(self): # Stefan Krah's _decimal module sources = ['_decimal/_decimal.c'] depends = ['_decimal/docstrings.h'] - define_macros = [] - - cflags = sysconfig.get_config_var("DECIMAL_CFLAGS") - extra_compile_args = shlex.split(cflags) if cflags else None + + cflags = parse_cflags(sysconfig.get_config_var("DECIMAL_CFLAGS")) + include_dirs, define_macros, undef_macros, extra_compile_args = cflags # ldflags includes either system libmpdec or full path to # our static libmpdec.a. - ldflags = sysconfig.get_config_var("DECIMAL_LDFLAGS") - extra_link_args = shlex.split(ldflags) if ldflags else None - + ldflags = parse_ldflags(sysconfig.get_config_var("DECIMAL_LDFLAGS")) + library_dirs, libraries, extra_link_args = ldflags + libmpdec_a = sysconfig.get_config_var("LIBMPDEC_A") if libmpdec_a: depends.append(libmpdec_a) @@ -2035,8 +2065,12 @@ def detect_decimal(self): # Uncomment for extra functionality: #define_macros.append(('EXTRA_FUNCTIONALITY', 1)) self.add(Extension('_decimal', + include_dirs=include_dirs, define_macros=define_macros, + undef_macros=undef_macros, extra_compile_args=extra_compile_args, + library_dirs=library_dirs, + libraries=libraries, extra_link_args=extra_link_args, sources=sources, depends=depends)) From webhook-mailer at python.org Sun Nov 14 04:34:42 2021 From: webhook-mailer at python.org (asvetlov) Date: Sun, 14 Nov 2021 09:34:42 -0000 Subject: [Python-checkins] bpo-45752: Fix no-support examples in 'copy' docs (GH-29548) Message-ID: https://github.com/python/cpython/commit/b7360ae395e9e633d384d16064c5dc04a9841e19 commit: b7360ae395e9e633d384d16064c5dc04a9841e19 branch: main author: M. Mostafa Farzan committer: asvetlov date: 2021-11-14T11:34:37+02:00 summary: bpo-45752: Fix no-support examples in 'copy' docs (GH-29548) files: M Doc/library/copy.rst diff --git a/Doc/library/copy.rst b/Doc/library/copy.rst index 01ebf198d7c50..a8bc2fa55ea8c 100644 --- a/Doc/library/copy.rst +++ b/Doc/library/copy.rst @@ -60,7 +60,7 @@ The :func:`deepcopy` function avoids these problems by: components copied. This module does not copy types like module, method, stack trace, stack frame, -file, socket, window, array, or any similar types. It does "copy" functions and +file, socket, window, or any similar types. It does "copy" functions and classes (shallow and deeply), by returning the original object unchanged; this is compatible with the way these are treated by the :mod:`pickle` module. From webhook-mailer at python.org Sun Nov 14 04:58:06 2021 From: webhook-mailer at python.org (miss-islington) Date: Sun, 14 Nov 2021 09:58:06 -0000 Subject: [Python-checkins] bpo-45752: Fix no-support examples in 'copy' docs (GH-29548) Message-ID: https://github.com/python/cpython/commit/6073920fcdb5a36d20a6a7c6ee204f74f00e1cb4 commit: 6073920fcdb5a36d20a6a7c6ee204f74f00e1cb4 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-14T01:58:01-08:00 summary: bpo-45752: Fix no-support examples in 'copy' docs (GH-29548) (cherry picked from commit b7360ae395e9e633d384d16064c5dc04a9841e19) Co-authored-by: M. Mostafa Farzan files: M Doc/library/copy.rst diff --git a/Doc/library/copy.rst b/Doc/library/copy.rst index 0eb5a793ad953..ce50c331bec86 100644 --- a/Doc/library/copy.rst +++ b/Doc/library/copy.rst @@ -60,7 +60,7 @@ The :func:`deepcopy` function avoids these problems by: components copied. This module does not copy types like module, method, stack trace, stack frame, -file, socket, window, array, or any similar types. It does "copy" functions and +file, socket, window, or any similar types. It does "copy" functions and classes (shallow and deeply), by returning the original object unchanged; this is compatible with the way these are treated by the :mod:`pickle` module. From webhook-mailer at python.org Sun Nov 14 07:54:46 2021 From: webhook-mailer at python.org (miss-islington) Date: Sun, 14 Nov 2021 12:54:46 -0000 Subject: [Python-checkins] [3.10] bpo-45752: Fix no-support examples in 'copy' docs (GH-29548) (GH-29556) Message-ID: https://github.com/python/cpython/commit/2081f9fe75a3a990394fbccd0c1c91c229c6289e commit: 2081f9fe75a3a990394fbccd0c1c91c229c6289e branch: 3.10 author: M. Mostafa Farzan committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-14T04:54:42-08:00 summary: [3.10] bpo-45752: Fix no-support examples in 'copy' docs (GH-29548) (GH-29556) (cherry picked from commit b7360ae395e9e633d384d16064c5dc04a9841e19) Co-authored-by: M. Mostafa Farzan Automerge-Triggered-By: GH:asvetlov files: M Doc/library/copy.rst diff --git a/Doc/library/copy.rst b/Doc/library/copy.rst index 01ebf198d7c50..a8bc2fa55ea8c 100644 --- a/Doc/library/copy.rst +++ b/Doc/library/copy.rst @@ -60,7 +60,7 @@ The :func:`deepcopy` function avoids these problems by: components copied. This module does not copy types like module, method, stack trace, stack frame, -file, socket, window, array, or any similar types. It does "copy" functions and +file, socket, window, or any similar types. It does "copy" functions and classes (shallow and deeply), by returning the original object unchanged; this is compatible with the way these are treated by the :mod:`pickle` module. From webhook-mailer at python.org Sun Nov 14 07:56:05 2021 From: webhook-mailer at python.org (miss-islington) Date: Sun, 14 Nov 2021 12:56:05 -0000 Subject: [Python-checkins] bpo-45752: Remove "array" from list of things that cannot be copied in `copy` module docstring (GH-29555) Message-ID: https://github.com/python/cpython/commit/c2c4fdf5ea6e9cba4ef469d08a52abb9cfa756a5 commit: c2c4fdf5ea6e9cba4ef469d08a52abb9cfa756a5 branch: main author: Alex Waygood committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-14T04:56:01-08:00 summary: bpo-45752: Remove "array" from list of things that cannot be copied in `copy` module docstring (GH-29555) Automerge-Triggered-By: GH:asvetlov files: M Lib/copy.py diff --git a/Lib/copy.py b/Lib/copy.py index dd41c54dffe1d..69bac980be205 100644 --- a/Lib/copy.py +++ b/Lib/copy.py @@ -39,8 +39,8 @@ class instances). set of components copied This version does not copy types like module, class, function, method, -nor stack trace, stack frame, nor file, socket, window, nor array, nor -any similar types. +nor stack trace, stack frame, nor file, socket, window, nor any +similar types. Classes can use the same interfaces to control copying that they use to control pickling: they can define methods called __getinitargs__(), From webhook-mailer at python.org Sun Nov 14 08:18:36 2021 From: webhook-mailer at python.org (miss-islington) Date: Sun, 14 Nov 2021 13:18:36 -0000 Subject: [Python-checkins] bpo-45752: Remove "array" from list of things that cannot be copied in `copy` module docstring (GH-29555) Message-ID: https://github.com/python/cpython/commit/55d24edaadba4ee90f464d88b44075649788f128 commit: 55d24edaadba4ee90f464d88b44075649788f128 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-14T05:18:31-08:00 summary: bpo-45752: Remove "array" from list of things that cannot be copied in `copy` module docstring (GH-29555) Automerge-Triggered-By: GH:asvetlov (cherry picked from commit c2c4fdf5ea6e9cba4ef469d08a52abb9cfa756a5) Co-authored-by: Alex Waygood files: M Lib/copy.py diff --git a/Lib/copy.py b/Lib/copy.py index dd41c54dffe1d..69bac980be205 100644 --- a/Lib/copy.py +++ b/Lib/copy.py @@ -39,8 +39,8 @@ class instances). set of components copied This version does not copy types like module, class, function, method, -nor stack trace, stack frame, nor file, socket, window, nor array, nor -any similar types. +nor stack trace, stack frame, nor file, socket, window, nor any +similar types. Classes can use the same interfaces to control copying that they use to control pickling: they can define methods called __getinitargs__(), From webhook-mailer at python.org Sun Nov 14 08:21:37 2021 From: webhook-mailer at python.org (miss-islington) Date: Sun, 14 Nov 2021 13:21:37 -0000 Subject: [Python-checkins] bpo-45752: Remove "array" from list of things that cannot be copied in `copy` module docstring (GH-29555) Message-ID: https://github.com/python/cpython/commit/9f9a3028e3bb923e726789ab3ea5ce298b596bc6 commit: 9f9a3028e3bb923e726789ab3ea5ce298b596bc6 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-14T05:21:32-08:00 summary: bpo-45752: Remove "array" from list of things that cannot be copied in `copy` module docstring (GH-29555) Automerge-Triggered-By: GH:asvetlov (cherry picked from commit c2c4fdf5ea6e9cba4ef469d08a52abb9cfa756a5) Co-authored-by: Alex Waygood files: M Lib/copy.py diff --git a/Lib/copy.py b/Lib/copy.py index 41873f2c046ca..1081d43952e1e 100644 --- a/Lib/copy.py +++ b/Lib/copy.py @@ -39,8 +39,8 @@ class instances). set of components copied This version does not copy types like module, class, function, method, -nor stack trace, stack frame, nor file, socket, window, nor array, nor -any similar types. +nor stack trace, stack frame, nor file, socket, window, nor any +similar types. Classes can use the same interfaces to control copying that they use to control pickling: they can define methods called __getinitargs__(), From webhook-mailer at python.org Sun Nov 14 14:55:25 2021 From: webhook-mailer at python.org (tiran) Date: Sun, 14 Nov 2021 19:55:25 -0000 Subject: [Python-checkins] bpo-45573: Use Makefile's dependencies in setup.py (GH-29559) Message-ID: https://github.com/python/cpython/commit/c3997865f24d9491318b401ae8e46d27332aca25 commit: c3997865f24d9491318b401ae8e46d27332aca25 branch: main author: Christian Heimes committer: tiran date: 2021-11-14T20:55:15+01:00 summary: bpo-45573: Use Makefile's dependencies in setup.py (GH-29559) files: M Makefile.pre.in M setup.py diff --git a/Makefile.pre.in b/Makefile.pre.in index b6e4c2316bccc..1535cabdade9c 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -2460,7 +2460,7 @@ MODULE_UNICODEDATA_DEPS=$(srcdir)/Modules/unicodedata_db.h $(srcdir)/Modules/uni MODULE__BLAKE2_DEPS=$(srcdir)/Modules/_blake2/impl/blake2-config.h $(srcdir)/Modules/_blake2/impl/blake2-dispatch.c $(srcdir)/Modules/_blake2/impl/blake2-impl.h $(srcdir)/Modules/_blake2/impl/blake2-kat.h $(srcdir)/Modules/_blake2/impl/blake2.h $(srcdir)/Modules/_blake2/impl/blake2b-load-sse2.h $(srcdir)/Modules/_blake2/impl/blake2b-load-sse41.h $(srcdir)/Modules/_blake2/impl/blake2b-ref.c $(srcdir)/Modules/_blake2/impl/blake2b-round.h $(srcdir)/Modules/_blake2/impl/blake2b-test.c $(srcdir)/Modules/_blake2/impl/blake2b.c $(srcdir)/Modules/_blake2/impl/blake2bp-test.c $(srcdir)/Modules/_blake2/impl/blake2bp.c $(srcdir)/Modules/_blake2/impl/blake2s-load-sse2.h $(srcdir)/Modules/_blake2/impl/blake2s-load-sse41.h $(srcdir)/Modules/_blake2/impl/blake2s-load-xop.h $(srcdir)/Modules/_blake2/impl/blake2s-ref.c $(srcdir)/Modules/_blake2/impl/blake2s-round.h $(srcdir)/Modules/_blake2/impl/blake2s-test.c $(srcdir)/Modules/_blake2/impl/blake2s.c $(srcdir)/Modules/_blake2/impl/blake2sp-test.c $(srcdir)/Modules/_blake2/impl/blake2sp.c $(srcdir)/Modules/hashlib.h MODULE__CTYPES_DEPS=$(srcdir)/Modules/_ctypes/ctypes.h MODULE__DECIMAL_DEPS=$(srcdir)/Modules/_decimal/docstrings.h $(LIBMPDEC_HEADERS) @LIBMPDEC_INTERNAL@ -MODULE__ELEMENTTREE_DEPS=$(LIBEXPAT_HEADERS) @LIBEXPAT_INTERNAL@ +MODULE__ELEMENTTREE_DEPS=$(srcdir)/Modules/pyexpat.c $(LIBEXPAT_HEADERS) @LIBEXPAT_INTERNAL@ MODULE__HASHLIB_DEPS=$(srcdir)/Modules/hashlib.h MODULE__IO_DEPS=$(srcdir)/Modules/_io/_iomodule.h MODULE__MD5_DEPS=$(srcdir)/Modules/hashlib.h diff --git a/setup.py b/setup.py index c62f0427fd378..915169e68630d 100644 --- a/setup.py +++ b/setup.py @@ -361,7 +361,7 @@ def find_module_file(module, dirlist): return module if len(dirs) > 1: log.info(f"WARNING: multiple copies of {module} found") - return os.path.join(dirs[0], module) + return os.path.abspath(os.path.join(dirs[0], module)) def parse_cflags(flags): @@ -454,7 +454,13 @@ def remove_disabled(self): def update_sources_depends(self): # Fix up the autodetected modules, prefixing all the source files # with Modules/. - moddirlist = [os.path.join(self.srcdir, 'Modules')] + # Add dependencies from MODULE_{name}_DEPS variable + moddirlist = [ + # files in Modules/ directory + os.path.join(self.srcdir, 'Modules'), + # files relative to build base, e.g. libmpdec.a, libexpat.a + os.getcwd() + ] # Fix up the paths for scripts, too self.distribution.scripts = [os.path.join(self.srcdir, filename) @@ -470,11 +476,16 @@ def update_sources_depends(self): for ext in self.extensions: ext.sources = [ find_module_file(filename, moddirlist) for filename in ext.sources ] - if ext.depends is not None: - ext.depends = [find_module_file(filename, moddirlist) - for filename in ext.depends] - else: - ext.depends = [] + # Update dependencies from Makefile + makedeps = sysconfig.get_config_var(f"MODULE_{ext.name.upper()}_DEPS") + if makedeps: + # remove backslashes from line break continuations + ext.depends.extend( + dep for dep in makedeps.split() if dep != "\\" + ) + ext.depends = [ + find_module_file(filename, moddirlist) for filename in ext.depends + ] # re-compile extensions if a header file has been changed ext.depends.extend(headers) @@ -966,12 +977,10 @@ def detect_simple_extensions(self): # math library functions, e.g. sin() self.add(Extension('math', ['mathmodule.c'], - depends=['_math.h'], libraries=['m'])) # complex math library functions self.add(Extension('cmath', ['cmathmodule.c'], - depends=['_math.h'], libraries=['m'])) # time libraries: librt may be needed for clock_gettime() @@ -1003,8 +1012,7 @@ def detect_simple_extensions(self): # profiler (_lsprof is for cProfile.py) self.add(Extension('_lsprof', ['_lsprof.c', 'rotatingtree.c'])) # static Unicode character database - self.add(Extension('unicodedata', ['unicodedata.c'], - depends=['unicodedata_db.h', 'unicodename_db.h'])) + self.add(Extension('unicodedata', ['unicodedata.c'])) # _opcode module self.add(Extension('_opcode', ['_opcode.c'])) # asyncio speedups @@ -1081,8 +1089,7 @@ def detect_simple_extensions(self): def detect_test_extensions(self): # Python C API test module - self.add(Extension('_testcapi', ['_testcapimodule.c'], - depends=['testcapi_long.h'])) + self.add(Extension('_testcapi', ['_testcapimodule.c'])) # Python Internal C API test module self.add(Extension('_testinternalcapi', ['_testinternalcapi.c'])) @@ -1263,7 +1270,7 @@ def detect_crypt(self): self.add(Extension('_crypt', ['_cryptmodule.c'], libraries=libs)) def detect_socket(self): - self.add(Extension('_socket', ['socketmodule.c'], depends=['socketmodule.h'])) + self.add(Extension('_socket', ['socketmodule.c'])) def detect_dbm_gdbm(self): # Modules that provide persistent dictionary-like semantics. You will @@ -1527,11 +1534,6 @@ def detect_expat_elementtree(self): ldflags = parse_ldflags(sysconfig.get_config_var("EXPAT_LDFLAGS")) library_dirs, libraries, extra_link_args = ldflags - expat_depends = [] - libexpat_a = sysconfig.get_config_var("LIBEXPAT_A") - if libexpat_a: - expat_depends.append(libexpat_a) - self.add(Extension('pyexpat', include_dirs=include_dirs, define_macros=define_macros, @@ -1540,8 +1542,7 @@ def detect_expat_elementtree(self): library_dirs=library_dirs, libraries=libraries, extra_link_args=extra_link_args, - sources=['pyexpat.c'], - depends=expat_depends)) + sources=['pyexpat.c'])) # Fredrik Lundh's cElementTree module. Note that this also # uses expat (via the CAPI hook in pyexpat). @@ -1551,8 +1552,7 @@ def detect_expat_elementtree(self): undef_macros=undef_macros, extra_compile_args=extra_compile_args, # no EXPAT_LDFLAGS - sources=['_elementtree.c'], - depends=['pyexpat.c', *expat_depends])) + sources=['_elementtree.c'])) def detect_multibytecodecs(self): # Hye-Shik Chang's CJKCodecs modules. @@ -1961,7 +1961,6 @@ def detect_ctypes(self): '_ctypes/callproc.c', '_ctypes/stgdict.c', '_ctypes/cfield.c'] - depends = ['_ctypes/ctypes.h'] if MACOS: sources.append('_ctypes/malloc_closure.c') @@ -1988,8 +1987,7 @@ def detect_ctypes(self): extra_compile_args=extra_compile_args, extra_link_args=extra_link_args, libraries=[], - sources=sources, - depends=depends) + sources=sources) self.add(ext) if TEST_EXTENSIONS: # function my_sqrt() needs libm for sqrt() @@ -2049,7 +2047,6 @@ def detect_ctypes(self): def detect_decimal(self): # Stefan Krah's _decimal module sources = ['_decimal/_decimal.c'] - depends = ['_decimal/docstrings.h'] cflags = parse_cflags(sysconfig.get_config_var("DECIMAL_CFLAGS")) include_dirs, define_macros, undef_macros, extra_compile_args = cflags @@ -2058,10 +2055,6 @@ def detect_decimal(self): ldflags = parse_ldflags(sysconfig.get_config_var("DECIMAL_LDFLAGS")) library_dirs, libraries, extra_link_args = ldflags - libmpdec_a = sysconfig.get_config_var("LIBMPDEC_A") - if libmpdec_a: - depends.append(libmpdec_a) - # Uncomment for extra functionality: #define_macros.append(('EXTRA_FUNCTIONALITY', 1)) self.add(Extension('_decimal', @@ -2072,8 +2065,7 @@ def detect_decimal(self): library_dirs=library_dirs, libraries=libraries, extra_link_args=extra_link_args, - sources=sources, - depends=depends)) + sources=sources)) def detect_openssl_hashlib(self): # Detect SSL support for the socket module (via _ssl) @@ -2141,16 +2133,6 @@ def split_var(name, sep): Extension( '_ssl', ['_ssl.c'], - depends=[ - 'socketmodule.h', - '_ssl.h', - '_ssl_data_111.h', - '_ssl_data_300.h', - '_ssl_data.h', - '_ssl/debughelpers.c', - '_ssl/misc.c', - '_ssl/cert.c', - ], **openssl_extension_kwargs ) ) @@ -2158,7 +2140,6 @@ def split_var(name, sep): Extension( '_hashlib', ['_hashopenssl.c'], - depends=['hashlib.h'], **openssl_extension_kwargs, ) ) @@ -2182,52 +2163,38 @@ def detect_hash_builtins(self): if "sha256" in configured: self.add(Extension( - '_sha256', ['sha256module.c'], - depends=['hashlib.h'], + '_sha256', ['sha256module.c'] )) if "sha512" in configured: self.add(Extension( '_sha512', ['sha512module.c'], - depends=['hashlib.h'], )) if "md5" in configured: self.add(Extension( '_md5', ['md5module.c'], - depends=['hashlib.h'], )) if "sha1" in configured: self.add(Extension( '_sha1', ['sha1module.c'], - depends=['hashlib.h'], )) if "blake2" in configured: - blake2_deps = glob( - os.path.join(escape(self.srcdir), 'Modules/_blake2/impl/*') - ) - blake2_deps.append('hashlib.h') self.add(Extension( '_blake2', [ '_blake2/blake2module.c', '_blake2/blake2b_impl.c', '_blake2/blake2s_impl.c' - ], - depends=blake2_deps, + ] )) if "sha3" in configured: - sha3_deps = glob( - os.path.join(escape(self.srcdir), 'Modules/_sha3/kcp/*') - ) - sha3_deps.append('hashlib.h') self.add(Extension( '_sha3', ['_sha3/sha3module.c'], - depends=sha3_deps, )) def detect_nis(self): From webhook-mailer at python.org Mon Nov 15 02:51:18 2021 From: webhook-mailer at python.org (corona10) Date: Mon, 15 Nov 2021 07:51:18 -0000 Subject: [Python-checkins] bpo-45512: Simplify isolation_level handling in `sqlite3` (GH-29053) Message-ID: https://github.com/python/cpython/commit/b567b9d74bd9e476a3027335873bb0508d6e450f commit: b567b9d74bd9e476a3027335873bb0508d6e450f branch: main author: Erlend Egeberg Aasland committer: corona10 date: 2021-11-15T16:50:59+09:00 summary: bpo-45512: Simplify isolation_level handling in `sqlite3` (GH-29053) files: M Modules/_sqlite/clinic/connection.c.h M Modules/_sqlite/connection.c M Modules/_sqlite/connection.h diff --git a/Modules/_sqlite/clinic/connection.c.h b/Modules/_sqlite/clinic/connection.c.h index 4e5ee500ad18e..5bfc589aeb149 100644 --- a/Modules/_sqlite/clinic/connection.c.h +++ b/Modules/_sqlite/clinic/connection.c.h @@ -5,7 +5,7 @@ preserve static int pysqlite_connection_init_impl(pysqlite_Connection *self, const char *database, double timeout, - int detect_types, PyObject *isolation_level, + int detect_types, const char *isolation_level, int check_same_thread, PyObject *factory, int cached_statements, int uri); @@ -22,7 +22,7 @@ pysqlite_connection_init(PyObject *self, PyObject *args, PyObject *kwargs) const char *database = NULL; double timeout = 5.0; int detect_types = 0; - PyObject *isolation_level = NULL; + const char *isolation_level = ""; int check_same_thread = 1; PyObject *factory = (PyObject*)clinic_state()->ConnectionType; int cached_statements = 128; @@ -63,7 +63,24 @@ pysqlite_connection_init(PyObject *self, PyObject *args, PyObject *kwargs) } } if (fastargs[3]) { - isolation_level = fastargs[3]; + if (fastargs[3] == Py_None) { + isolation_level = NULL; + } + else if (PyUnicode_Check(fastargs[3])) { + Py_ssize_t isolation_level_length; + isolation_level = PyUnicode_AsUTF8AndSize(fastargs[3], &isolation_level_length); + if (isolation_level == NULL) { + goto exit; + } + if (strlen(isolation_level) != (size_t)isolation_level_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + } + else { + _PyArg_BadArgument("Connection", "argument 'isolation_level'", "str or None", fastargs[3]); + goto exit; + } if (!--noptargs) { goto skip_optional_pos; } @@ -834,4 +851,4 @@ getlimit(pysqlite_Connection *self, PyObject *arg) #ifndef PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF #define PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF #endif /* !defined(PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF) */ -/*[clinic end generated code: output=d71bf16bef67878f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=663b1e9e71128f19 input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 964673a6125f3..e4f0013ae604e 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -79,7 +79,6 @@ static const char * const begin_statements[] = { NULL }; -static int pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* isolation_level, void *Py_UNUSED(ignored)); static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self); static void free_callback_context(callback_context *ctx); static void set_callback_context(callback_context **ctx_pp, @@ -107,6 +106,30 @@ new_statement_cache(pysqlite_Connection *self, int maxsize) return res; } +static inline const char * +begin_stmt_to_isolation_level(const char *begin_stmt) +{ + assert(begin_stmt != NULL); + + // All begin statements start with "BEGIN "; add strlen("BEGIN ") to get + // the isolation level. + return begin_stmt + 6; +} + +static const char * +get_begin_statement(const char *level) +{ + assert(level != NULL); + for (int i = 0; begin_statements[i] != NULL; i++) { + const char *stmt = begin_statements[i]; + const char *candidate = begin_stmt_to_isolation_level(stmt); + if (sqlite3_stricmp(level, candidate) == 0) { + return begin_statements[i]; + } + } + return NULL; +} + /*[python input] class FSConverter_converter(CConverter): type = "const char *" @@ -124,7 +147,7 @@ _sqlite3.Connection.__init__ as pysqlite_connection_init database: FSConverter timeout: double = 5.0 detect_types: int = 0 - isolation_level: object = NULL + isolation_level: str(accept={str, NoneType}) = "" check_same_thread: bool(accept={int}) = True factory: object(c_default='(PyObject*)clinic_state()->ConnectionType') = ConnectionType cached_statements: int = 128 @@ -134,10 +157,10 @@ _sqlite3.Connection.__init__ as pysqlite_connection_init static int pysqlite_connection_init_impl(pysqlite_Connection *self, const char *database, double timeout, - int detect_types, PyObject *isolation_level, + int detect_types, const char *isolation_level, int check_same_thread, PyObject *factory, int cached_statements, int uri) -/*[clinic end generated code: output=bc39e55eb0b68783 input=f8d1f7efc0d84104]*/ +/*[clinic end generated code: output=d8c37afc46d318b0 input=adfb29ac461f9e61]*/ { int rc; @@ -148,8 +171,6 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, pysqlite_state *state = pysqlite_get_state_by_type(Py_TYPE(self)); self->state = state; - self->begin_statement = NULL; - Py_CLEAR(self->statement_cache); Py_CLEAR(self->cursors); @@ -174,20 +195,16 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, return -1; } - if (!isolation_level) { - isolation_level = PyUnicode_FromString(""); - if (!isolation_level) { + if (isolation_level) { + const char *stmt = get_begin_statement(isolation_level); + if (stmt == NULL) { return -1; } - } else { - Py_INCREF(isolation_level); + self->begin_statement = stmt; } - Py_CLEAR(self->isolation_level); - if (pysqlite_connection_set_isolation_level(self, isolation_level, NULL) != 0) { - Py_DECREF(isolation_level); - return -1; + else { + self->begin_statement = NULL; } - Py_DECREF(isolation_level); self->statement_cache = new_statement_cache(self, cached_statements); if (self->statement_cache == NULL) { @@ -268,7 +285,6 @@ static int connection_traverse(pysqlite_Connection *self, visitproc visit, void *arg) { Py_VISIT(Py_TYPE(self)); - Py_VISIT(self->isolation_level); Py_VISIT(self->statement_cache); Py_VISIT(self->cursors); Py_VISIT(self->row_factory); @@ -292,7 +308,6 @@ clear_callback_context(callback_context *ctx) static int connection_clear(pysqlite_Connection *self) { - Py_CLEAR(self->isolation_level); Py_CLEAR(self->statement_cache); Py_CLEAR(self->cursors); Py_CLEAR(self->row_factory); @@ -1317,7 +1332,12 @@ static PyObject* pysqlite_connection_get_isolation_level(pysqlite_Connection* se if (!pysqlite_check_connection(self)) { return NULL; } - return Py_NewRef(self->isolation_level); + if (self->begin_statement != NULL) { + const char *stmt = self->begin_statement; + const char *iso_level = begin_stmt_to_isolation_level(stmt); + return PyUnicode_FromString(iso_level); + } + Py_RETURN_NONE; } static PyObject* pysqlite_connection_get_total_changes(pysqlite_Connection* self, void* unused) @@ -1347,53 +1367,40 @@ pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* iso PyErr_SetString(PyExc_AttributeError, "cannot delete attribute"); return -1; } - if (isolation_level == Py_None) { - /* We might get called during connection init, so we cannot use - * pysqlite_connection_commit() here. */ - if (self->db && !sqlite3_get_autocommit(self->db)) { - int rc; - Py_BEGIN_ALLOW_THREADS - rc = sqlite3_exec(self->db, "COMMIT", NULL, NULL, NULL); - Py_END_ALLOW_THREADS - if (rc != SQLITE_OK) { - return _pysqlite_seterror(self->state, self->db); - } - } - + if (Py_IsNone(isolation_level)) { self->begin_statement = NULL; - } else { - const char * const *candidate; - PyObject *uppercase_level; - _Py_IDENTIFIER(upper); - - if (!PyUnicode_Check(isolation_level)) { - PyErr_Format(PyExc_TypeError, - "isolation_level must be a string or None, not %.100s", - Py_TYPE(isolation_level)->tp_name); + + // Execute a COMMIT to re-enable autocommit mode + PyObject *res = pysqlite_connection_commit_impl(self); + if (res == NULL) { return -1; } - - uppercase_level = _PyObject_CallMethodIdOneArg( - (PyObject *)&PyUnicode_Type, &PyId_upper, - isolation_level); - if (!uppercase_level) { + Py_DECREF(res); + } + else if (PyUnicode_Check(isolation_level)) { + Py_ssize_t len; + const char *cstr_level = PyUnicode_AsUTF8AndSize(isolation_level, &len); + if (cstr_level == NULL) { return -1; } - for (candidate = begin_statements; *candidate; candidate++) { - if (_PyUnicode_EqualToASCIIString(uppercase_level, *candidate + 6)) - break; + if (strlen(cstr_level) != (size_t)len) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + return -1; } - Py_DECREF(uppercase_level); - if (!*candidate) { + const char *stmt = get_begin_statement(cstr_level); + if (stmt == NULL) { PyErr_SetString(PyExc_ValueError, - "invalid value for isolation_level"); + "isolation_level string must be '', 'DEFERRED', " + "'IMMEDIATE', or 'EXCLUSIVE'"); return -1; } - self->begin_statement = *candidate; + self->begin_statement = stmt; + } + else { + PyErr_SetString(PyExc_TypeError, + "isolation_level must be str or None"); + return -1; } - - Py_INCREF(isolation_level); - Py_XSETREF(self->isolation_level, isolation_level); return 0; } diff --git a/Modules/_sqlite/connection.h b/Modules/_sqlite/connection.h index 6a2aa1c8e080e..7baf63fb756e7 100644 --- a/Modules/_sqlite/connection.h +++ b/Modules/_sqlite/connection.h @@ -49,9 +49,6 @@ typedef struct * bitwise combination thereof makes sense */ int detect_types; - /* None for autocommit, otherwise a PyUnicode with the isolation level */ - PyObject* isolation_level; - /* NULL for autocommit, otherwise a string with the BEGIN statement */ const char* begin_statement; From webhook-mailer at python.org Mon Nov 15 07:55:42 2021 From: webhook-mailer at python.org (corona10) Date: Mon, 15 Nov 2021 12:55:42 -0000 Subject: [Python-checkins] bpo-45512: Raise exception if sqlite3.Connection.__init__ is called with bad isolation level (#29561) Message-ID: https://github.com/python/cpython/commit/822c3dcce3996e411c1ff5c432c6ac7d2845cfd6 commit: 822c3dcce3996e411c1ff5c432c6ac7d2845cfd6 branch: main author: Erlend Egeberg Aasland committer: corona10 date: 2021-11-15T21:55:38+09:00 summary: bpo-45512: Raise exception if sqlite3.Connection.__init__ is called with bad isolation level (#29561) * bpo-45512: Raise sqlite3.Connection.__init__ is called with bad isolation level * Also explicitly test allowed isolation levels * Use subTest for better error messages if something goes wrong * Update Lib/test/test_sqlite3/test_dbapi.py Co-authored-by: Dong-hee Na Co-authored-by: Dong-hee Na files: M Lib/test/test_sqlite3/test_dbapi.py M Modules/_sqlite/connection.c diff --git a/Lib/test/test_sqlite3/test_dbapi.py b/Lib/test/test_sqlite3/test_dbapi.py index a5ec66fe22a2a7..802a6919371f9d 100644 --- a/Lib/test/test_sqlite3/test_dbapi.py +++ b/Lib/test/test_sqlite3/test_dbapi.py @@ -48,8 +48,8 @@ def managed_connect(*args, in_mem=False, **kwargs): # Helper for temporary memory databases -def memory_database(): - cx = sqlite.connect(":memory:") +def memory_database(*args, **kwargs): + cx = sqlite.connect(":memory:", *args, **kwargs) return contextlib.closing(cx) @@ -509,6 +509,20 @@ def test_connection_bad_limit_category(self): self.assertRaisesRegex(sqlite.ProgrammingError, msg, self.cx.setlimit, cat, 0) + def test_connection_init_bad_isolation_level(self): + msg = ( + "isolation_level string must be '', 'DEFERRED', 'IMMEDIATE', or " + "'EXCLUSIVE'" + ) + with self.assertRaisesRegex(ValueError, msg): + memory_database(isolation_level="BOGUS") + + def test_connection_init_good_isolation_levels(self): + for level in ("", "DEFERRED", "IMMEDIATE", "EXCLUSIVE", None): + with self.subTest(level=level): + with memory_database(isolation_level=level) as cx: + cx.execute("select 'ok'") + class UninitialisedConnectionTests(unittest.TestCase): def setUp(self): diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index e4f0013ae604e4..b902dc845c6188 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -127,6 +127,9 @@ get_begin_statement(const char *level) return begin_statements[i]; } } + PyErr_SetString(PyExc_ValueError, + "isolation_level string must be '', 'DEFERRED', " + "'IMMEDIATE', or 'EXCLUSIVE'"); return NULL; } @@ -1389,9 +1392,6 @@ pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* iso } const char *stmt = get_begin_statement(cstr_level); if (stmt == NULL) { - PyErr_SetString(PyExc_ValueError, - "isolation_level string must be '', 'DEFERRED', " - "'IMMEDIATE', or 'EXCLUSIVE'"); return -1; } self->begin_statement = stmt; From webhook-mailer at python.org Mon Nov 15 11:58:32 2021 From: webhook-mailer at python.org (brandtbucher) Date: Mon, 15 Nov 2021 16:58:32 -0000 Subject: [Python-checkins] bpo-45636: Remove the old %-formatting fast-path (GH-29532) Message-ID: https://github.com/python/cpython/commit/ec382fac0db6d9159c2d3496a70b7a605545957e commit: ec382fac0db6d9159c2d3496a70b7a605545957e branch: main author: Brandt Bucher committer: brandtbucher date: 2021-11-15T08:58:23-08:00 summary: bpo-45636: Remove the old %-formatting fast-path (GH-29532) files: A Misc/NEWS.d/next/Core and Builtins/2021-11-11-19-11-57.bpo-45636.2fyIVm.rst M Python/ceval.c M Python/specialize.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-11-19-11-57.bpo-45636.2fyIVm.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-11-19-11-57.bpo-45636.2fyIVm.rst new file mode 100644 index 0000000000000..f705b41fd8c2d --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-11-19-11-57.bpo-45636.2fyIVm.rst @@ -0,0 +1,2 @@ +Remove an existing "fast path" for old-style string formatting, since +it no longer appears to have any measurable impact. diff --git a/Python/ceval.c b/Python/ceval.c index 0b24cbdcc2cc4..e808aeed73a22 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4711,14 +4711,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr res = PyNumber_Multiply(lhs, rhs); break; case NB_REMAINDER: - if (PyUnicode_CheckExact(lhs) && - (!PyUnicode_Check(rhs) || PyUnicode_CheckExact(rhs))) - { - // bpo-28598: Fast path for string formatting (but not - // if the RHS is a str subclass). - res = PyUnicode_Format(lhs, rhs); - break; - } res = PyNumber_Remainder(lhs, rhs); break; case NB_OR: diff --git a/Python/specialize.c b/Python/specialize.c index 7e72013cd8359..cfc21bf70ad6b 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -1380,13 +1380,13 @@ _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache) { _PyAdaptiveEntry *adaptive = &cache->adaptive; - if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) { - SPECIALIZATION_FAIL(BINARY_OP, SPEC_FAIL_DIFFERENT_TYPES); - goto failure; - } switch (adaptive->original_oparg) { case NB_ADD: case NB_INPLACE_ADD: + if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) { + SPECIALIZATION_FAIL(BINARY_OP, SPEC_FAIL_DIFFERENT_TYPES); + goto failure; + } if (PyUnicode_CheckExact(lhs)) { if (_Py_OPCODE(instr[1]) == STORE_FAST && Py_REFCNT(lhs) == 2) { *instr = _Py_MAKECODEUNIT(BINARY_OP_INPLACE_ADD_UNICODE, @@ -1409,6 +1409,10 @@ _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, break; case NB_MULTIPLY: case NB_INPLACE_MULTIPLY: + if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) { + SPECIALIZATION_FAIL(BINARY_OP, SPEC_FAIL_DIFFERENT_TYPES); + goto failure; + } if (PyLong_CheckExact(lhs)) { *instr = _Py_MAKECODEUNIT(BINARY_OP_MULTIPLY_INT, _Py_OPARG(*instr)); From webhook-mailer at python.org Mon Nov 15 12:40:18 2021 From: webhook-mailer at python.org (zooba) Date: Mon, 15 Nov 2021 17:40:18 -0000 Subject: [Python-checkins] bpo-45220: Ensure RT_MANIFEST is defined when compiling Windows resource files (GH-29501) Message-ID: https://github.com/python/cpython/commit/32d14b262d6d914f63485f8d6e7859df58cd2089 commit: 32d14b262d6d914f63485f8d6e7859df58cd2089 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: zooba date: 2021-11-15T17:40:08Z summary: bpo-45220: Ensure RT_MANIFEST is defined when compiling Windows resource files (GH-29501) (cherry picked from commit a56fbad85ea655631bce68d4c0f47f1a8b500abd) Co-authored-by: Steve Dower files: M PC/pylauncher.rc M PC/pyshellext.rc M PC/python_exe.rc M PC/python_nt.rc M PC/pythonw_exe.rc M PC/sqlite3.rc diff --git a/PC/pylauncher.rc b/PC/pylauncher.rc index d21f9b6e9d2ab..ff7e71e0fdb4e 100644 --- a/PC/pylauncher.rc +++ b/PC/pylauncher.rc @@ -2,6 +2,11 @@ #include "python_ver_rc.h" +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif // Include the manifest file that indicates we support all // current versions of Windows. 1 RT_MANIFEST "python.manifest" diff --git a/PC/pyshellext.rc b/PC/pyshellext.rc index fc607e97840fb..af797ce95d507 100644 --- a/PC/pyshellext.rc +++ b/PC/pyshellext.rc @@ -2,6 +2,12 @@ #include "python_ver_rc.h" +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif + // Include the manifest file that indicates we support all // current versions of Windows. 1 RT_MANIFEST "python.manifest" diff --git a/PC/python_exe.rc b/PC/python_exe.rc index 5eba89962b475..c3d3bff019895 100644 --- a/PC/python_exe.rc +++ b/PC/python_exe.rc @@ -2,6 +2,12 @@ #include "python_ver_rc.h" +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif + // Include the manifest file that indicates we support all // current versions of Windows. 1 RT_MANIFEST "python.manifest" diff --git a/PC/python_nt.rc b/PC/python_nt.rc index 6fd872c1a03cc..ae64fbd217af7 100644 --- a/PC/python_nt.rc +++ b/PC/python_nt.rc @@ -2,6 +2,12 @@ #include "python_ver_rc.h" +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif + // Include the manifest file that indicates we support all // current versions of Windows. 2 RT_MANIFEST "python.manifest" diff --git a/PC/pythonw_exe.rc b/PC/pythonw_exe.rc index 562652be18471..38570b74fa3e0 100644 --- a/PC/pythonw_exe.rc +++ b/PC/pythonw_exe.rc @@ -2,6 +2,12 @@ #include "python_ver_rc.h" +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif + // Include the manifest file that indicates we support all // current versions of Windows. 1 RT_MANIFEST "python.manifest" diff --git a/PC/sqlite3.rc b/PC/sqlite3.rc index d2c18f8add8b2..9ae2aa0f6f2f2 100644 --- a/PC/sqlite3.rc +++ b/PC/sqlite3.rc @@ -2,6 +2,12 @@ #include +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif + // Include the manifest file that indicates we support all // current versions of Windows. 2 RT_MANIFEST "python.manifest" From webhook-mailer at python.org Mon Nov 15 16:41:27 2021 From: webhook-mailer at python.org (ambv) Date: Mon, 15 Nov 2021 21:41:27 -0000 Subject: [Python-checkins] Python 3.9.9 Message-ID: https://github.com/python/cpython/commit/ccb0e6a3452335a4c3e2433934c3c0c5622a34cd commit: ccb0e6a3452335a4c3e2433934c3c0c5622a34cd branch: 3.9 author: ?ukasz Langa committer: ambv date: 2021-11-15T18:43:00+01:00 summary: Python 3.9.9 files: A Misc/NEWS.d/3.9.9.rst D Misc/NEWS.d/next/Core and Builtins/2021-11-14-00-14-45.bpo-45738.e0cgKd.rst D Misc/NEWS.d/next/Documentation/2021-11-06-10-54-17.bpo-45392.JZnVOz.rst D Misc/NEWS.d/next/Documentation/2021-11-09-13-10-55.bpo-45772.EdrM3t.rst D Misc/NEWS.d/next/Library/2021-11-06-17-47-46.bpo-45644.ZMqHD_.rst D Misc/NEWS.d/next/Library/2021-11-09-09-04-19.bpo-45765.JVobxK.rst D Misc/NEWS.d/next/Library/2021-11-11-13-03-17.bpo-45235.8ZbkHa.rst D Misc/NEWS.d/next/Windows/2021-11-05-01-05-46.bpo-45720.47Nc5I.rst D Misc/NEWS.d/next/Windows/2021-11-08-21-53-11.bpo-45732.idl5kx.rst M .gitignore M Include/patchlevel.h M Lib/pydoc_data/topics.py M README.rst diff --git a/.gitignore b/.gitignore index d0b608892a87c..864152451dd9d 100644 --- a/.gitignore +++ b/.gitignore @@ -134,3 +134,7 @@ Tools/ssl/win32 # Ignore ./python binary on Unix but still look into ./Python/ directory. /python !/Python/ + +# Artifacts generated by 3.11 lying around when switching branches: +/Programs/_freeze_module +/Python/frozen_modules/ \ No newline at end of file diff --git a/Include/patchlevel.h b/Include/patchlevel.h index 59741719c2153..293e51a25d0f8 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -18,12 +18,12 @@ /*--start constants--*/ #define PY_MAJOR_VERSION 3 #define PY_MINOR_VERSION 9 -#define PY_MICRO_VERSION 8 +#define PY_MICRO_VERSION 9 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL #define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "3.9.8+" +#define PY_VERSION "3.9.9" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py index 8567e304a09ed..890a61668df1c 100644 --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Fri Nov 5 20:19:23 2021 +# Autogenerated by Sphinx on Mon Nov 15 18:21:10 2021 topics = {'assert': 'The "assert" statement\n' '**********************\n' '\n' diff --git a/Misc/NEWS.d/3.9.9.rst b/Misc/NEWS.d/3.9.9.rst new file mode 100644 index 0000000000000..86a11a73765ec --- /dev/null +++ b/Misc/NEWS.d/3.9.9.rst @@ -0,0 +1,78 @@ +.. bpo: 45738 +.. date: 2021-11-14-00-14-45 +.. nonce: e0cgKd +.. release date: 2021-11-15 +.. section: Core and Builtins + +Fix computation of error location for invalid continuation characters in the +parser. Patch by Pablo Galindo. + +.. + +.. bpo: 45235 +.. date: 2021-11-11-13-03-17 +.. nonce: 8ZbkHa +.. section: Library + +Reverted an argparse bugfix that caused regression in the handling of +default arguments for subparsers. This prevented leaf level arguments from +taking precedence over root level arguments. + +.. + +.. bpo: 45765 +.. date: 2021-11-09-09-04-19 +.. nonce: JVobxK +.. section: Library + +In importlib.metadata, fix distribution discovery for an empty path. + +.. + +.. bpo: 45644 +.. date: 2021-11-06-17-47-46 +.. nonce: ZMqHD_ +.. section: Library + +In-place JSON file formatting using ``python3 -m json.tool infile infile`` +now works correctly, previously it left the file empty. Patch by Chris +Wesseling. + +.. + +.. bpo: 45772 +.. date: 2021-11-09-13-10-55 +.. nonce: EdrM3t +.. section: Documentation + +``socket.socket`` documentation is corrected to a class from a function. + +.. + +.. bpo: 45392 +.. date: 2021-11-06-10-54-17 +.. nonce: JZnVOz +.. section: Documentation + +Update the docstring of the :class:`type` built-in to remove a redundant +line and to mention keyword arguments for the constructor. + +.. + +.. bpo: 45732 +.. date: 2021-11-08-21-53-11 +.. nonce: idl5kx +.. section: Windows + +Updates bundled Tcl/Tk to 8.6.12. + +.. + +.. bpo: 45720 +.. date: 2021-11-05-01-05-46 +.. nonce: 47Nc5I +.. section: Windows + +Internal reference to :file:`shlwapi.dll` was dropped to help improve +startup time. This DLL will no longer be loaded at the start of every Python +process. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-14-00-14-45.bpo-45738.e0cgKd.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-14-00-14-45.bpo-45738.e0cgKd.rst deleted file mode 100644 index b238034323c77..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-11-14-00-14-45.bpo-45738.e0cgKd.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix computation of error location for invalid continuation characters in the -parser. Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Documentation/2021-11-06-10-54-17.bpo-45392.JZnVOz.rst b/Misc/NEWS.d/next/Documentation/2021-11-06-10-54-17.bpo-45392.JZnVOz.rst deleted file mode 100644 index 09c16578ff478..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-11-06-10-54-17.bpo-45392.JZnVOz.rst +++ /dev/null @@ -1,2 +0,0 @@ -Update the docstring of the :class:`type` built-in to remove a redundant -line and to mention keyword arguments for the constructor. diff --git a/Misc/NEWS.d/next/Documentation/2021-11-09-13-10-55.bpo-45772.EdrM3t.rst b/Misc/NEWS.d/next/Documentation/2021-11-09-13-10-55.bpo-45772.EdrM3t.rst deleted file mode 100644 index 47679521df30b..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-11-09-13-10-55.bpo-45772.EdrM3t.rst +++ /dev/null @@ -1 +0,0 @@ -``socket.socket`` documentation is corrected to a class from a function. diff --git a/Misc/NEWS.d/next/Library/2021-11-06-17-47-46.bpo-45644.ZMqHD_.rst b/Misc/NEWS.d/next/Library/2021-11-06-17-47-46.bpo-45644.ZMqHD_.rst deleted file mode 100644 index 2cf4eae02c449..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-11-06-17-47-46.bpo-45644.ZMqHD_.rst +++ /dev/null @@ -1,3 +0,0 @@ -In-place JSON file formatting using ``python3 -m json.tool infile infile`` -now works correctly, previously it left the file empty. Patch by Chris -Wesseling. diff --git a/Misc/NEWS.d/next/Library/2021-11-09-09-04-19.bpo-45765.JVobxK.rst b/Misc/NEWS.d/next/Library/2021-11-09-09-04-19.bpo-45765.JVobxK.rst deleted file mode 100644 index a1f4a1f7aa91c..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-11-09-09-04-19.bpo-45765.JVobxK.rst +++ /dev/null @@ -1 +0,0 @@ -In importlib.metadata, fix distribution discovery for an empty path. diff --git a/Misc/NEWS.d/next/Library/2021-11-11-13-03-17.bpo-45235.8ZbkHa.rst b/Misc/NEWS.d/next/Library/2021-11-11-13-03-17.bpo-45235.8ZbkHa.rst deleted file mode 100644 index f73589ccc8872..0000000000000 --- a/Misc/NEWS.d/next/Library/2021-11-11-13-03-17.bpo-45235.8ZbkHa.rst +++ /dev/null @@ -1,3 +0,0 @@ -Reverted an argparse bugfix that caused regression in the handling of -default arguments for subparsers. This prevented leaf level arguments from -taking precedence over root level arguments. diff --git a/Misc/NEWS.d/next/Windows/2021-11-05-01-05-46.bpo-45720.47Nc5I.rst b/Misc/NEWS.d/next/Windows/2021-11-05-01-05-46.bpo-45720.47Nc5I.rst deleted file mode 100644 index 315759b07e147..0000000000000 --- a/Misc/NEWS.d/next/Windows/2021-11-05-01-05-46.bpo-45720.47Nc5I.rst +++ /dev/null @@ -1,3 +0,0 @@ -Internal reference to :file:`shlwapi.dll` was dropped to help improve -startup time. This DLL will no longer be loaded at the start of every Python -process. diff --git a/Misc/NEWS.d/next/Windows/2021-11-08-21-53-11.bpo-45732.idl5kx.rst b/Misc/NEWS.d/next/Windows/2021-11-08-21-53-11.bpo-45732.idl5kx.rst deleted file mode 100644 index 563bcd33a401a..0000000000000 --- a/Misc/NEWS.d/next/Windows/2021-11-08-21-53-11.bpo-45732.idl5kx.rst +++ /dev/null @@ -1 +0,0 @@ -Updates bundled Tcl/Tk to 8.6.12. diff --git a/README.rst b/README.rst index ef78796301dc0..b808463b71271 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -This is Python version 3.9.8 +This is Python version 3.9.9 ============================ .. image:: https://travis-ci.org/python/cpython.svg?branch=3.9 From webhook-mailer at python.org Mon Nov 15 17:22:51 2021 From: webhook-mailer at python.org (willingc) Date: Mon, 15 Nov 2021 22:22:51 -0000 Subject: [Python-checkins] bpo-45677: Reword first section of `sqlite3` docs (#29326) Message-ID: https://github.com/python/cpython/commit/6c5a312fb6d92e879bf4c570b94e18bb9ffe5970 commit: 6c5a312fb6d92e879bf4c570b94e18bb9ffe5970 branch: main author: Erlend Egeberg Aasland committer: willingc date: 2021-11-15T14:22:42-08:00 summary: bpo-45677: Reword first section of `sqlite3` docs (#29326) * bpo-45677: Avoid addressing the reader as 'you' in sqlite3 docs * Adjust wording * Adjust wording again * Typo * Update Doc/library/sqlite3.rst Co-authored-by: Jacob Walls * Address review: adjust wording * Update Doc/library/sqlite3.rst Co-authored-by: Alex Waygood * Update Lib/sqlite3/__init__.py Co-authored-by: Alex Waygood * Update Doc/library/sqlite3.rst Co-authored-by: Alex Waygood * Update Doc/library/sqlite3.rst Co-authored-by: Alex Waygood * Update Lib/sqlite3/__init__.py Co-authored-by: Alex Waygood * Update Doc/library/sqlite3.rst Co-authored-by: Alex Waygood * Apply Alex' suggestion, and apply 80 char limit to PR * Minor adjustment Co-authored-by: Jacob Walls Co-authored-by: Alex Waygood files: M Doc/library/sqlite3.rst M Lib/sqlite3/__init__.py diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index 91bf7b0e7c879..9fffe4da901a8 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -21,16 +21,17 @@ The sqlite3 module was written by Gerhard H?ring. It provides a SQL interface compliant with the DB-API 2.0 specification described by :pep:`249`, and requires SQLite 3.7.15 or newer. -To use the module, you must first create a :class:`Connection` object that +To use the module, start by creating a :class:`Connection` object that represents the database. Here the data will be stored in the :file:`example.db` file:: import sqlite3 con = sqlite3.connect('example.db') -You can also supply the special name ``:memory:`` to create a database in RAM. +The special path name ``:memory:`` can be provided to create a temporary +database in RAM. -Once you have a :class:`Connection`, you can create a :class:`Cursor` object +Once a :class:`Connection` has been established, create a :class:`Cursor` object and call its :meth:`~Cursor.execute` method to perform SQL commands:: cur = con.cursor() @@ -49,16 +50,17 @@ and call its :meth:`~Cursor.execute` method to perform SQL commands:: # Just be sure any changes have been committed or they will be lost. con.close() -The data you've saved is persistent and is available in subsequent sessions:: +The saved data is persistent: it can be reloaded in a subsequent session even +after restarting the Python interpreter:: import sqlite3 con = sqlite3.connect('example.db') cur = con.cursor() -To retrieve data after executing a SELECT statement, you can either treat the -cursor as an :term:`iterator`, call the cursor's :meth:`~Cursor.fetchone` method to -retrieve a single matching row, or call :meth:`~Cursor.fetchall` to get a list of the -matching rows. +To retrieve data after executing a SELECT statement, either treat the cursor as +an :term:`iterator`, call the cursor's :meth:`~Cursor.fetchone` method to +retrieve a single matching row, or call :meth:`~Cursor.fetchall` to get a list +of the matching rows. This example uses the iterator form:: @@ -73,27 +75,27 @@ This example uses the iterator form:: .. _sqlite3-placeholders: -Usually your SQL operations will need to use values from Python variables. You -shouldn't assemble your query using Python's string operations because doing so -is insecure; it makes your program vulnerable to an SQL injection attack -(see the `xkcd webcomic `_ for a humorous example of -what can go wrong):: +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):: # Never do this -- insecure! symbol = 'RHAT' cur.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol) -Instead, use the DB-API's parameter substitution. Put a placeholder wherever -you want to use a value, and then provide a tuple of values as the second -argument to the cursor's :meth:`~Cursor.execute` method. An SQL statement may +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: +keys for all named parameters. Any extra items are ignored. Here's an example of +both styles: .. literalinclude:: ../includes/sqlite3/execute_1.py diff --git a/Lib/sqlite3/__init__.py b/Lib/sqlite3/__init__.py index edc58f15b25ce..0dedf186b1a1e 100644 --- a/Lib/sqlite3/__init__.py +++ b/Lib/sqlite3/__init__.py @@ -24,18 +24,18 @@ The sqlite3 extension module provides a DB-API 2.0 (PEP 249) compilant interface to the SQLite library, and requires SQLite 3.7.15 or newer. -To use the module, you must first create a database Connection object: +To use the module, start by creating a database Connection object: import sqlite3 cx = sqlite3.connect("test.db") # test.db will be created or opened -You can also use the special database name ":memory:" to connect to a transient +The special path name ":memory:" can be provided to connect to a transient in-memory database: cx = sqlite3.connect(":memory:") # connect to a database in RAM -Once you have a Connection object, you can create a Cursor object and call its -execute() method to perform SQL queries: +Once a connection has been established, create a Cursor object and call +its execute() method to perform SQL queries: cu = cx.cursor() From webhook-mailer at python.org Mon Nov 15 17:30:36 2021 From: webhook-mailer at python.org (willingc) Date: Mon, 15 Nov 2021 22:30:36 -0000 Subject: [Python-checkins] Save a reference for ensure_future and create_task (GH-29163) Message-ID: https://github.com/python/cpython/commit/c750adbe6990ee8239b27d5f4591283a06bfe862 commit: c750adbe6990ee8239b27d5f4591283a06bfe862 branch: main author: Joannah Nanjekye <33177550+nanjekyejoannah at users.noreply.github.com> committer: willingc date: 2021-11-15T14:30:28-08:00 summary: Save a reference for ensure_future and create_task (GH-29163) Co-authored-by: Joannah Nanjekye files: M Doc/library/asyncio-future.rst M Doc/library/asyncio-task.rst diff --git a/Doc/library/asyncio-future.rst b/Doc/library/asyncio-future.rst index ef496a23f5cd4..3496387c178af 100644 --- a/Doc/library/asyncio-future.rst +++ b/Doc/library/asyncio-future.rst @@ -54,6 +54,9 @@ Future Functions See also the :func:`create_task` function which is the preferred way for creating new Tasks. + Save a reference to the result of this function, to avoid + a task disappearing mid execution. + .. versionchanged:: 3.5.1 The function accepts any :term:`awaitable` object. diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 07354e028b12a..36e13f9295652 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -271,6 +271,11 @@ Creating Tasks task = asyncio.ensure_future(coro()) ... + .. important:: + + Save a reference to the result of this function, to avoid + a task disappearing mid execution. + .. versionadded:: 3.7 .. versionchanged:: 3.8 From webhook-mailer at python.org Mon Nov 15 17:39:01 2021 From: webhook-mailer at python.org (willingc) Date: Mon, 15 Nov 2021 22:39:01 -0000 Subject: [Python-checkins] bpo-25381: Update explanation of exceptions in C. (GH-26838) Message-ID: https://github.com/python/cpython/commit/ad43dc0b54994e7e7d06e3d4896ade188b36ee12 commit: ad43dc0b54994e7e7d06e3d4896ade188b36ee12 branch: main author: Terry Jan Reedy committer: willingc date: 2021-11-15T14:38:53-08:00 summary: bpo-25381: Update explanation of exceptions in C. (GH-26838) * bpo-25381: Update explanation of exception globals This paragraph in extending/extending.rst was unchanged (except for NULL markup) since committed in 2007 Aug 15 for 2.6 alpha. * Respond to reviews and remove duplication. * Update Doc/extending/extending.rst Co-authored-by: Serhiy Storchaka Co-authored-by: Serhiy Storchaka files: A Misc/NEWS.d/next/Documentation/2021-06-21-17-51-51.bpo-25381.7Kn-_H.rst M Doc/extending/extending.rst diff --git a/Doc/extending/extending.rst b/Doc/extending/extending.rst index 561d1c616cc10..2e3362b834e6f 100644 --- a/Doc/extending/extending.rst +++ b/Doc/extending/extending.rst @@ -127,13 +127,11 @@ Intermezzo: Errors and Exceptions An important convention throughout the Python interpreter is the following: when a function fails, it should set an exception condition and return an error value -(usually a ``NULL`` pointer). Exceptions are stored in a static global variable -inside the interpreter; if this variable is ``NULL`` no exception has occurred. A -second global variable stores the "associated value" of the exception (the -second argument to :keyword:`raise`). A third variable contains the stack -traceback in case the error originated in Python code. These three variables -are the C equivalents of the result in Python of :meth:`sys.exc_info` (see the -section on module :mod:`sys` in the Python Library Reference). It is important +(usually ``-1`` or a ``NULL`` pointer). Exception information is stored in +three members of the interpreter's thread state. These are ``NULL`` if +there is no exception. Otherwise they are the C equivalents of the members +of the Python tuple returned by :meth:`sys.exc_info`. These are the +exception type, exception instance, and a traceback object. It is important to know about them to understand how errors are passed around. The Python API defines a number of functions to set various types of exceptions. diff --git a/Misc/NEWS.d/next/Documentation/2021-06-21-17-51-51.bpo-25381.7Kn-_H.rst b/Misc/NEWS.d/next/Documentation/2021-06-21-17-51-51.bpo-25381.7Kn-_H.rst new file mode 100644 index 0000000000000..f009f880e917d --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-06-21-17-51-51.bpo-25381.7Kn-_H.rst @@ -0,0 +1,2 @@ +In the extending chapter of the extending doc, update a paragraph about the +global variables containing exception information. From webhook-mailer at python.org Mon Nov 15 17:44:38 2021 From: webhook-mailer at python.org (willingc) Date: Mon, 15 Nov 2021 22:44:38 -0000 Subject: [Python-checkins] bpo-43225: [DOC] Add missing value returned by methods on cookiejar (GH-24522) Message-ID: https://github.com/python/cpython/commit/3352834f59531dfa42dbef00ada4fb95ded2ae3a commit: 3352834f59531dfa42dbef00ada4fb95ded2ae3a branch: main author: Emmanuel Arias committer: willingc date: 2021-11-15T14:44:32-08:00 summary: bpo-43225: [DOC] Add missing value returned by methods on cookiejar (GH-24522) * Add missing value returned by methods on cookiejar Documentation say that return something but don't specific with what value is return, and that can be confuse. This patch add that information. * Update Doc/library/http.cookiejar.rst Co-authored-by: andrei kulakov * Update Doc/library/http.cookiejar.rst Co-authored-by: andrei kulakov Co-authored-by: andrei kulakov files: M Doc/library/http.cookiejar.rst diff --git a/Doc/library/http.cookiejar.rst b/Doc/library/http.cookiejar.rst index 3d59665be4f25..51a8c53152b01 100644 --- a/Doc/library/http.cookiejar.rst +++ b/Doc/library/http.cookiejar.rst @@ -494,7 +494,8 @@ and ``".168.1.2"``, 192.168.1.2 is blocked, but 193.168.1.2 is not. .. method:: DefaultCookiePolicy.is_blocked(domain) - Return whether *domain* is on the blocklist for setting or receiving cookies. + Return ``True`` if *domain* is on the blocklist for setting or receiving + cookies. .. method:: DefaultCookiePolicy.allowed_domains() @@ -509,7 +510,7 @@ and ``".168.1.2"``, 192.168.1.2 is blocked, but 193.168.1.2 is not. .. method:: DefaultCookiePolicy.is_not_allowed(domain) - Return whether *domain* is not on the allowlist for setting or receiving + Return ``True`` if *domain* is not on the allowlist for setting or receiving cookies. :class:`DefaultCookiePolicy` instances have the following attributes, which are @@ -766,4 +767,3 @@ returned:: cj = CookieJar(policy) opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj)) r = opener.open("http://example.com/") - From webhook-mailer at python.org Mon Nov 15 18:06:50 2021 From: webhook-mailer at python.org (terryjreedy) Date: Mon, 15 Nov 2021 23:06:50 -0000 Subject: [Python-checkins] bpo-25381: Update explanation of exceptions in C. (GH-26838) (GH-29568) Message-ID: https://github.com/python/cpython/commit/0320cf1a250b025f2ef25637851384bf8b61d207 commit: 0320cf1a250b025f2ef25637851384bf8b61d207 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: terryjreedy date: 2021-11-15T18:06:45-05:00 summary: bpo-25381: Update explanation of exceptions in C. (GH-26838) (GH-29568) Co-authored-by: Terry Jan Reedy Co-authored-by: Serhiy Storchaka (cherry picked from commit ad43dc0b54994e7e7d06e3d4896ade188b36ee12) files: A Misc/NEWS.d/next/Documentation/2021-06-21-17-51-51.bpo-25381.7Kn-_H.rst M Doc/extending/extending.rst diff --git a/Doc/extending/extending.rst b/Doc/extending/extending.rst index 561d1c616cc10..2e3362b834e6f 100644 --- a/Doc/extending/extending.rst +++ b/Doc/extending/extending.rst @@ -127,13 +127,11 @@ Intermezzo: Errors and Exceptions An important convention throughout the Python interpreter is the following: when a function fails, it should set an exception condition and return an error value -(usually a ``NULL`` pointer). Exceptions are stored in a static global variable -inside the interpreter; if this variable is ``NULL`` no exception has occurred. A -second global variable stores the "associated value" of the exception (the -second argument to :keyword:`raise`). A third variable contains the stack -traceback in case the error originated in Python code. These three variables -are the C equivalents of the result in Python of :meth:`sys.exc_info` (see the -section on module :mod:`sys` in the Python Library Reference). It is important +(usually ``-1`` or a ``NULL`` pointer). Exception information is stored in +three members of the interpreter's thread state. These are ``NULL`` if +there is no exception. Otherwise they are the C equivalents of the members +of the Python tuple returned by :meth:`sys.exc_info`. These are the +exception type, exception instance, and a traceback object. It is important to know about them to understand how errors are passed around. The Python API defines a number of functions to set various types of exceptions. diff --git a/Misc/NEWS.d/next/Documentation/2021-06-21-17-51-51.bpo-25381.7Kn-_H.rst b/Misc/NEWS.d/next/Documentation/2021-06-21-17-51-51.bpo-25381.7Kn-_H.rst new file mode 100644 index 0000000000000..f009f880e917d --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-06-21-17-51-51.bpo-25381.7Kn-_H.rst @@ -0,0 +1,2 @@ +In the extending chapter of the extending doc, update a paragraph about the +global variables containing exception information. From webhook-mailer at python.org Mon Nov 15 18:08:02 2021 From: webhook-mailer at python.org (terryjreedy) Date: Mon, 15 Nov 2021 23:08:02 -0000 Subject: [Python-checkins] bpo-25381: Update explanation of exceptions in C. (GH-26838) (GH-29569) Message-ID: https://github.com/python/cpython/commit/b0bdc093c2c15c352c5bede060117790705f5db0 commit: b0bdc093c2c15c352c5bede060117790705f5db0 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: terryjreedy date: 2021-11-15T18:07:58-05:00 summary: bpo-25381: Update explanation of exceptions in C. (GH-26838) (GH-29569) Co-authored-by: Terry Jan Reedy Co-authored-by: Serhiy Storchaka (cherry picked from commit ad43dc0b54994e7e7d06e3d4896ade188b36ee12) files: A Misc/NEWS.d/next/Documentation/2021-06-21-17-51-51.bpo-25381.7Kn-_H.rst M Doc/extending/extending.rst diff --git a/Doc/extending/extending.rst b/Doc/extending/extending.rst index bc85a05ff2f850..a7676708c8c8e8 100644 --- a/Doc/extending/extending.rst +++ b/Doc/extending/extending.rst @@ -127,13 +127,11 @@ Intermezzo: Errors and Exceptions An important convention throughout the Python interpreter is the following: when a function fails, it should set an exception condition and return an error value -(usually a ``NULL`` pointer). Exceptions are stored in a static global variable -inside the interpreter; if this variable is ``NULL`` no exception has occurred. A -second global variable stores the "associated value" of the exception (the -second argument to :keyword:`raise`). A third variable contains the stack -traceback in case the error originated in Python code. These three variables -are the C equivalents of the result in Python of :meth:`sys.exc_info` (see the -section on module :mod:`sys` in the Python Library Reference). It is important +(usually ``-1`` or a ``NULL`` pointer). Exception information is stored in +three members of the interpreter's thread state. These are ``NULL`` if +there is no exception. Otherwise they are the C equivalents of the members +of the Python tuple returned by :meth:`sys.exc_info`. These are the +exception type, exception instance, and a traceback object. It is important to know about them to understand how errors are passed around. The Python API defines a number of functions to set various types of exceptions. diff --git a/Misc/NEWS.d/next/Documentation/2021-06-21-17-51-51.bpo-25381.7Kn-_H.rst b/Misc/NEWS.d/next/Documentation/2021-06-21-17-51-51.bpo-25381.7Kn-_H.rst new file mode 100644 index 00000000000000..f009f880e917d5 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-06-21-17-51-51.bpo-25381.7Kn-_H.rst @@ -0,0 +1,2 @@ +In the extending chapter of the extending doc, update a paragraph about the +global variables containing exception information. From webhook-mailer at python.org Mon Nov 15 18:29:26 2021 From: webhook-mailer at python.org (vstinner) Date: Mon, 15 Nov 2021 23:29:26 -0000 Subject: [Python-checkins] bpo-28533: Remove asyncore, asynchat, smtpd modules (GH-29521) Message-ID: https://github.com/python/cpython/commit/9bf2cbc4c498812e14f20d86acb61c53928a5a57 commit: 9bf2cbc4c498812e14f20d86acb61c53928a5a57 branch: main author: Victor Stinner committer: vstinner date: 2021-11-16T00:29:17+01:00 summary: bpo-28533: Remove asyncore, asynchat, smtpd modules (GH-29521) Remove the asyncore and asynchat modules, deprecated in Python 3.6: use the asyncio module instead. Remove the smtpd module, deprecated in Python 3.6: the aiosmtpd module can be used instead, it is based on asyncio. * Remove asyncore, asynchat and smtpd documentation * Remove test_asyncore, test_asynchat and test_smtpd * Rename Lib/asynchat.py to Lib/test/support/_asynchat.py * Rename Lib/asyncore.py to Lib/test/support/_asyncore.py * Rename Lib/smtpd.py to Lib/test/support/_smtpd.py * Remove DeprecationWarning from private _asyncore, _asynchat and _smtpd modules * _smtpd: remove deprecated properties files: A Lib/test/support/_asynchat.py A Lib/test/support/_asyncore.py A Lib/test/support/_smtpd.py A Misc/NEWS.d/next/Library/2021-11-11-12-59-10.bpo-28533.68mMZa.rst A Misc/NEWS.d/next/Library/2021-11-11-12-59-49.bpo-28533.LvIFCQ.rst D Doc/library/asynchat.rst D Doc/library/asyncore.rst D Doc/library/smtpd.rst D Lib/asynchat.py D Lib/asyncore.py D Lib/smtpd.py D Lib/test/test_asynchat.py D Lib/test/test_asyncore.py D Lib/test/test_smtpd.py M .github/CODEOWNERS M Doc/library/email.rst M Doc/library/internet.rst M Doc/library/ipc.rst M Doc/library/socketserver.rst M Doc/license.rst M Doc/whatsnew/3.11.rst M Lib/test/libregrtest/save_env.py M Lib/test/mock_socket.py M Lib/test/test_ftplib.py M Lib/test/test_logging.py M Lib/test/test_os.py M Lib/test/test_poplib.py M Lib/test/test_smtplib.py M Lib/test/test_ssl.py M PCbuild/lib.pyproj M Python/stdlib_module_names.h diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index ce5121e7ac8f8..82f81e3452995 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -130,8 +130,6 @@ Lib/ast.py @isidentical **/*typing* @gvanrossum @Fidget-Spinner -**/*asyncore @giampaolo -**/*asynchat @giampaolo **/*ftplib @giampaolo **/*shutil @giampaolo diff --git a/Doc/library/asynchat.rst b/Doc/library/asynchat.rst deleted file mode 100644 index 9e51416b83a57..0000000000000 --- a/Doc/library/asynchat.rst +++ /dev/null @@ -1,213 +0,0 @@ -:mod:`asynchat` --- Asynchronous socket command/response handler -================================================================ - -.. module:: asynchat - :synopsis: Support for asynchronous command/response protocols. - -.. moduleauthor:: Sam Rushing -.. sectionauthor:: Steve Holden - -**Source code:** :source:`Lib/asynchat.py` - -.. deprecated:: 3.6 - Please use :mod:`asyncio` instead. - --------------- - -.. note:: - - This module exists for backwards compatibility only. For new code we - recommend using :mod:`asyncio`. - -This module builds on the :mod:`asyncore` infrastructure, simplifying -asynchronous clients and servers and making it easier to handle protocols -whose elements are terminated by arbitrary strings, or are of variable length. -:mod:`asynchat` defines the abstract class :class:`async_chat` that you -subclass, providing implementations of the :meth:`collect_incoming_data` and -:meth:`found_terminator` methods. It uses the same asynchronous loop as -:mod:`asyncore`, and the two types of channel, :class:`asyncore.dispatcher` -and :class:`asynchat.async_chat`, can freely be mixed in the channel map. -Typically an :class:`asyncore.dispatcher` server channel generates new -:class:`asynchat.async_chat` channel objects as it receives incoming -connection requests. - - -.. class:: async_chat() - - This class is an abstract subclass of :class:`asyncore.dispatcher`. To make - practical use of the code you must subclass :class:`async_chat`, providing - meaningful :meth:`collect_incoming_data` and :meth:`found_terminator` - methods. - The :class:`asyncore.dispatcher` methods can be used, although not all make - sense in a message/response context. - - Like :class:`asyncore.dispatcher`, :class:`async_chat` defines a set of - events that are generated by an analysis of socket conditions after a - :c:func:`select` call. Once the polling loop has been started the - :class:`async_chat` object's methods are called by the event-processing - framework with no action on the part of the programmer. - - Two class attributes can be modified, to improve performance, or possibly - even to conserve memory. - - - .. data:: ac_in_buffer_size - - The asynchronous input buffer size (default ``4096``). - - - .. data:: ac_out_buffer_size - - The asynchronous output buffer size (default ``4096``). - - Unlike :class:`asyncore.dispatcher`, :class:`async_chat` allows you to - define a :abbr:`FIFO (first-in, first-out)` queue of *producers*. A producer need - have only one method, :meth:`more`, which should return data to be - transmitted on the channel. - The producer indicates exhaustion (*i.e.* that it contains no more data) by - having its :meth:`more` method return the empty bytes object. At this point - the :class:`async_chat` object removes the producer from the queue and starts - using the next producer, if any. When the producer queue is empty the - :meth:`handle_write` method does nothing. You use the channel object's - :meth:`set_terminator` method to describe how to recognize the end of, or - an important breakpoint in, an incoming transmission from the remote - endpoint. - - To build a functioning :class:`async_chat` subclass your input methods - :meth:`collect_incoming_data` and :meth:`found_terminator` must handle the - data that the channel receives asynchronously. The methods are described - below. - - -.. method:: async_chat.close_when_done() - - Pushes a ``None`` on to the producer queue. When this producer is popped off - the queue it causes the channel to be closed. - - -.. method:: async_chat.collect_incoming_data(data) - - Called with *data* holding an arbitrary amount of received data. The - default method, which must be overridden, raises a - :exc:`NotImplementedError` exception. - - -.. method:: async_chat.discard_buffers() - - In emergencies this method will discard any data held in the input and/or - output buffers and the producer queue. - - -.. method:: async_chat.found_terminator() - - Called when the incoming data stream matches the termination condition set - by :meth:`set_terminator`. The default method, which must be overridden, - raises a :exc:`NotImplementedError` exception. The buffered input data - should be available via an instance attribute. - - -.. method:: async_chat.get_terminator() - - Returns the current terminator for the channel. - - -.. method:: async_chat.push(data) - - Pushes data on to the channel's queue to ensure its transmission. - This is all you need to do to have the channel write the data out to the - network, although it is possible to use your own producers in more complex - schemes to implement encryption and chunking, for example. - - -.. method:: async_chat.push_with_producer(producer) - - Takes a producer object and adds it to the producer queue associated with - the channel. When all currently-pushed producers have been exhausted the - channel will consume this producer's data by calling its :meth:`more` - method and send the data to the remote endpoint. - - -.. method:: async_chat.set_terminator(term) - - Sets the terminating condition to be recognized on the channel. ``term`` - may be any of three types of value, corresponding to three different ways - to handle incoming protocol data. - - +-----------+---------------------------------------------+ - | term | Description | - +===========+=============================================+ - | *string* | Will call :meth:`found_terminator` when the | - | | string is found in the input stream | - +-----------+---------------------------------------------+ - | *integer* | Will call :meth:`found_terminator` when the | - | | indicated number of characters have been | - | | received | - +-----------+---------------------------------------------+ - | ``None`` | The channel continues to collect data | - | | forever | - +-----------+---------------------------------------------+ - - Note that any data following the terminator will be available for reading - by the channel after :meth:`found_terminator` is called. - - -.. _asynchat-example: - -asynchat Example ----------------- - -The following partial example shows how HTTP requests can be read with -:class:`async_chat`. A web server might create an -:class:`http_request_handler` object for each incoming client connection. -Notice that initially the channel terminator is set to match the blank line at -the end of the HTTP headers, and a flag indicates that the headers are being -read. - -Once the headers have been read, if the request is of type POST (indicating -that further data are present in the input stream) then the -``Content-Length:`` header is used to set a numeric terminator to read the -right amount of data from the channel. - -The :meth:`handle_request` method is called once all relevant input has been -marshalled, after setting the channel terminator to ``None`` to ensure that -any extraneous data sent by the web client are ignored. :: - - - import asynchat - - class http_request_handler(asynchat.async_chat): - - def __init__(self, sock, addr, sessions, log): - asynchat.async_chat.__init__(self, sock=sock) - self.addr = addr - self.sessions = sessions - self.ibuffer = [] - self.obuffer = b"" - self.set_terminator(b"\r\n\r\n") - self.reading_headers = True - self.handling = False - self.cgi_data = None - self.log = log - - def collect_incoming_data(self, data): - """Buffer the data""" - self.ibuffer.append(data) - - def found_terminator(self): - if self.reading_headers: - self.reading_headers = False - self.parse_headers(b"".join(self.ibuffer)) - self.ibuffer = [] - if self.op.upper() == b"POST": - clen = self.headers.getheader("content-length") - self.set_terminator(int(clen)) - else: - self.handling = True - self.set_terminator(None) - self.handle_request() - elif not self.handling: - self.set_terminator(None) # browsers sometimes over-send - self.cgi_data = parse(self.headers, b"".join(self.ibuffer)) - self.handling = True - self.ibuffer = [] - self.handle_request() diff --git a/Doc/library/asyncore.rst b/Doc/library/asyncore.rst deleted file mode 100644 index a86518ebff277..0000000000000 --- a/Doc/library/asyncore.rst +++ /dev/null @@ -1,360 +0,0 @@ -:mod:`asyncore` --- Asynchronous socket handler -=============================================== - -.. module:: asyncore - :synopsis: A base class for developing asynchronous socket handling - services. - -.. moduleauthor:: Sam Rushing -.. sectionauthor:: Christopher Petrilli -.. sectionauthor:: Steve Holden -.. heavily adapted from original documentation by Sam Rushing - -**Source code:** :source:`Lib/asyncore.py` - -.. deprecated:: 3.6 - Please use :mod:`asyncio` instead. - --------------- - -.. note:: - - This module exists for backwards compatibility only. For new code we - recommend using :mod:`asyncio`. - -This module provides the basic infrastructure for writing asynchronous socket -service clients and servers. - -There are only two ways to have a program on a single processor do "more than -one thing at a time." Multi-threaded programming is the simplest and most -popular way to do it, but there is another very different technique, that lets -you have nearly all the advantages of multi-threading, without actually using -multiple threads. It's really only practical if your program is largely I/O -bound. If your program is processor bound, then pre-emptive scheduled threads -are probably what you really need. Network servers are rarely processor -bound, however. - -If your operating system supports the :c:func:`select` system call in its I/O -library (and nearly all do), then you can use it to juggle multiple -communication channels at once; doing other work while your I/O is taking -place in the "background." Although this strategy can seem strange and -complex, especially at first, it is in many ways easier to understand and -control than multi-threaded programming. The :mod:`asyncore` module solves -many of the difficult problems for you, making the task of building -sophisticated high-performance network servers and clients a snap. For -"conversational" applications and protocols the companion :mod:`asynchat` -module is invaluable. - -The basic idea behind both modules is to create one or more network -*channels*, instances of class :class:`asyncore.dispatcher` and -:class:`asynchat.async_chat`. Creating the channels adds them to a global -map, used by the :func:`loop` function if you do not provide it with your own -*map*. - -Once the initial channel(s) is(are) created, calling the :func:`loop` function -activates channel service, which continues until the last channel (including -any that have been added to the map during asynchronous service) is closed. - - -.. function:: loop([timeout[, use_poll[, map[,count]]]]) - - Enter a polling loop that terminates after count passes or all open - channels have been closed. All arguments are optional. The *count* - parameter defaults to ``None``, resulting in the loop terminating only when all - channels have been closed. The *timeout* argument sets the timeout - parameter for the appropriate :func:`~select.select` or :func:`~select.poll` - call, measured in seconds; the default is 30 seconds. The *use_poll* - parameter, if true, indicates that :func:`~select.poll` should be used in - preference to :func:`~select.select` (the default is ``False``). - - The *map* parameter is a dictionary whose items are the channels to watch. - As channels are closed they are deleted from their map. If *map* is - omitted, a global map is used. Channels (instances of - :class:`asyncore.dispatcher`, :class:`asynchat.async_chat` and subclasses - thereof) can freely be mixed in the map. - - -.. class:: dispatcher() - - The :class:`dispatcher` class is a thin wrapper around a low-level socket - object. To make it more useful, it has a few methods for event-handling - which are called from the asynchronous loop. Otherwise, it can be treated - as a normal non-blocking socket object. - - The firing of low-level events at certain times or in certain connection - states tells the asynchronous loop that certain higher-level events have - taken place. For example, if we have asked for a socket to connect to - another host, we know that the connection has been made when the socket - becomes writable for the first time (at this point you know that you may - write to it with the expectation of success). The implied higher-level - events are: - - +----------------------+----------------------------------------+ - | Event | Description | - +======================+========================================+ - | ``handle_connect()`` | Implied by the first read or write | - | | event | - +----------------------+----------------------------------------+ - | ``handle_close()`` | Implied by a read event with no data | - | | available | - +----------------------+----------------------------------------+ - | ``handle_accepted()``| Implied by a read event on a listening | - | | socket | - +----------------------+----------------------------------------+ - - During asynchronous processing, each mapped channel's :meth:`readable` and - :meth:`writable` methods are used to determine whether the channel's socket - should be added to the list of channels :c:func:`select`\ ed or - :c:func:`poll`\ ed for read and write events. - - Thus, the set of channel events is larger than the basic socket events. The - full set of methods that can be overridden in your subclass follows: - - - .. method:: handle_read() - - Called when the asynchronous loop detects that a :meth:`read` call on the - channel's socket will succeed. - - - .. method:: handle_write() - - Called when the asynchronous loop detects that a writable socket can be - written. Often this method will implement the necessary buffering for - performance. For example:: - - def handle_write(self): - sent = self.send(self.buffer) - self.buffer = self.buffer[sent:] - - - .. method:: handle_expt() - - Called when there is out of band (OOB) data for a socket connection. This - will almost never happen, as OOB is tenuously supported and rarely used. - - - .. method:: handle_connect() - - Called when the active opener's socket actually makes a connection. Might - send a "welcome" banner, or initiate a protocol negotiation with the - remote endpoint, for example. - - - .. method:: handle_close() - - Called when the socket is closed. - - - .. method:: handle_error() - - Called when an exception is raised and not otherwise handled. The default - version prints a condensed traceback. - - - .. method:: handle_accept() - - Called on listening channels (passive openers) when a connection can be - established with a new remote endpoint that has issued a :meth:`connect` - call for the local endpoint. Deprecated in version 3.2; use - :meth:`handle_accepted` instead. - - .. deprecated:: 3.2 - - - .. method:: handle_accepted(sock, addr) - - Called on listening channels (passive openers) when a connection has been - established with a new remote endpoint that has issued a :meth:`connect` - call for the local endpoint. *sock* is a *new* socket object usable to - send and receive data on the connection, and *addr* is the address - bound to the socket on the other end of the connection. - - .. versionadded:: 3.2 - - - .. method:: readable() - - Called each time around the asynchronous loop to determine whether a - channel's socket should be added to the list on which read events can - occur. The default method simply returns ``True``, indicating that by - default, all channels will be interested in read events. - - - .. method:: writable() - - Called each time around the asynchronous loop to determine whether a - channel's socket should be added to the list on which write events can - occur. The default method simply returns ``True``, indicating that by - default, all channels will be interested in write events. - - - In addition, each channel delegates or extends many of the socket methods. - Most of these are nearly identical to their socket partners. - - - .. method:: create_socket(family=socket.AF_INET, type=socket.SOCK_STREAM) - - This is identical to the creation of a normal socket, and will use the - same options for creation. Refer to the :mod:`socket` documentation for - information on creating sockets. - - .. versionchanged:: 3.3 - *family* and *type* arguments can be omitted. - - - .. method:: connect(address) - - As with the normal socket object, *address* is a tuple with the first - element the host to connect to, and the second the port number. - - - .. method:: send(data) - - Send *data* to the remote end-point of the socket. - - - .. method:: recv(buffer_size) - - Read at most *buffer_size* bytes from the socket's remote end-point. An - empty bytes object implies that the channel has been closed from the - other end. - - Note that :meth:`recv` may raise :exc:`BlockingIOError` , even though - :func:`select.select` or :func:`select.poll` has reported the socket - ready for reading. - - - .. method:: listen(backlog) - - Listen for connections made to the socket. The *backlog* argument - specifies the maximum number of queued connections and should be at least - 1; the maximum value is system-dependent (usually 5). - - - .. method:: bind(address) - - Bind the socket to *address*. The socket must not already be bound. (The - format of *address* depends on the address family --- refer to the - :mod:`socket` documentation for more information.) To mark - the socket as re-usable (setting the :const:`SO_REUSEADDR` option), call - the :class:`dispatcher` object's :meth:`set_reuse_addr` method. - - - .. method:: accept() - - Accept a connection. The socket must be bound to an address and listening - for connections. The return value can be either ``None`` or a pair - ``(conn, address)`` where *conn* is a *new* socket object usable to send - and receive data on the connection, and *address* is the address bound to - the socket on the other end of the connection. - When ``None`` is returned it means the connection didn't take place, in - which case the server should just ignore this event and keep listening - for further incoming connections. - - - .. method:: close() - - Close the socket. All future operations on the socket object will fail. - The remote end-point will receive no more data (after queued data is - flushed). Sockets are automatically closed when they are - garbage-collected. - - -.. class:: dispatcher_with_send() - - A :class:`dispatcher` subclass which adds simple buffered output capability, - useful for simple clients. For more sophisticated usage use - :class:`asynchat.async_chat`. - -.. class:: file_dispatcher() - - A file_dispatcher takes a file descriptor or :term:`file object` along - with an optional map argument and wraps it for use with the :c:func:`poll` - or :c:func:`loop` functions. If provided a file object or anything with a - :c:func:`fileno` method, that method will be called and passed to the - :class:`file_wrapper` constructor. - - .. availability:: Unix. - -.. class:: file_wrapper() - - A file_wrapper takes an integer file descriptor and calls :func:`os.dup` to - duplicate the handle so that the original handle may be closed independently - of the file_wrapper. This class implements sufficient methods to emulate a - socket for use by the :class:`file_dispatcher` class. - - .. availability:: Unix. - - -.. _asyncore-example-1: - -asyncore Example basic HTTP client ----------------------------------- - -Here is a very basic HTTP client that uses the :class:`dispatcher` class to -implement its socket handling:: - - import asyncore - - class HTTPClient(asyncore.dispatcher): - - def __init__(self, host, path): - asyncore.dispatcher.__init__(self) - self.create_socket() - self.connect( (host, 80) ) - self.buffer = bytes('GET %s HTTP/1.0\r\nHost: %s\r\n\r\n' % - (path, host), 'ascii') - - def handle_connect(self): - pass - - def handle_close(self): - self.close() - - def handle_read(self): - print(self.recv(8192)) - - def writable(self): - return (len(self.buffer) > 0) - - def handle_write(self): - sent = self.send(self.buffer) - self.buffer = self.buffer[sent:] - - - client = HTTPClient('www.python.org', '/') - asyncore.loop() - -.. _asyncore-example-2: - -asyncore Example basic echo server ----------------------------------- - -Here is a basic echo server that uses the :class:`dispatcher` class to accept -connections and dispatches the incoming connections to a handler:: - - import asyncore - - class EchoHandler(asyncore.dispatcher_with_send): - - def handle_read(self): - data = self.recv(8192) - if data: - self.send(data) - - class EchoServer(asyncore.dispatcher): - - def __init__(self, host, port): - asyncore.dispatcher.__init__(self) - self.create_socket() - self.set_reuse_addr() - self.bind((host, port)) - self.listen(5) - - def handle_accepted(self, sock, addr): - print('Incoming connection from %s' % repr(addr)) - handler = EchoHandler(sock) - - server = EchoServer('localhost', 8080) - asyncore.loop() diff --git a/Doc/library/email.rst b/Doc/library/email.rst index 5eebcd9e896d9..816fae991d24c 100644 --- a/Doc/library/email.rst +++ b/Doc/library/email.rst @@ -147,6 +147,3 @@ Legacy API: Module :mod:`mailbox` Tools for creating, reading, and managing collections of messages on disk using a variety standard formats. - - Module :mod:`smtpd` - SMTP server framework (primarily useful for testing) diff --git a/Doc/library/internet.rst b/Doc/library/internet.rst index e745dd1243512..65693c9b3b200 100644 --- a/Doc/library/internet.rst +++ b/Doc/library/internet.rst @@ -35,7 +35,6 @@ is currently supported on most popular platforms. Here is an overview: imaplib.rst nntplib.rst smtplib.rst - smtpd.rst telnetlib.rst uuid.rst socketserver.rst diff --git a/Doc/library/ipc.rst b/Doc/library/ipc.rst index b88a174eb97f1..4849c82f317d9 100644 --- a/Doc/library/ipc.rst +++ b/Doc/library/ipc.rst @@ -22,7 +22,5 @@ The list of modules described in this chapter is: ssl.rst select.rst selectors.rst - asyncore.rst - asynchat.rst signal.rst mmap.rst diff --git a/Doc/library/smtpd.rst b/Doc/library/smtpd.rst deleted file mode 100644 index 611411ddd295b..0000000000000 --- a/Doc/library/smtpd.rst +++ /dev/null @@ -1,264 +0,0 @@ -:mod:`smtpd` --- SMTP Server -============================ - -.. module:: smtpd - :synopsis: A SMTP server implementation in Python. - -.. moduleauthor:: Barry Warsaw -.. sectionauthor:: Moshe Zadka - -**Source code:** :source:`Lib/smtpd.py` - --------------- - -This module offers several classes to implement SMTP (email) servers. - -.. deprecated:: 3.6 - The `aiosmtpd `_ package is a recommended - replacement for this module. It is based on :mod:`asyncio` and provides a - more straightforward API. - -Several server implementations are present; one is a generic -do-nothing implementation, which can be overridden, while the other two offer -specific mail-sending strategies. - -Additionally the SMTPChannel may be extended to implement very specific -interaction behaviour with SMTP clients. - -The code supports :RFC:`5321`, plus the :rfc:`1870` SIZE and :rfc:`6531` -SMTPUTF8 extensions. - - -SMTPServer Objects ------------------- - - -.. class:: SMTPServer(localaddr, remoteaddr, data_size_limit=33554432,\ - map=None, enable_SMTPUTF8=False, decode_data=False) - - Create a new :class:`SMTPServer` object, which binds to local address - *localaddr*. It will treat *remoteaddr* as an upstream SMTP relayer. Both - *localaddr* and *remoteaddr* should be a :ref:`(host, port) ` - tuple. The object inherits from :class:`asyncore.dispatcher`, and so will - insert itself into :mod:`asyncore`'s event loop on instantiation. - - *data_size_limit* specifies the maximum number of bytes that will be - accepted in a ``DATA`` command. A value of ``None`` or ``0`` means no - limit. - - *map* is the socket map to use for connections (an initially empty - dictionary is a suitable value). If not specified the :mod:`asyncore` - global socket map is used. - - *enable_SMTPUTF8* determines whether the ``SMTPUTF8`` extension (as defined - in :RFC:`6531`) should be enabled. The default is ``False``. - When ``True``, ``SMTPUTF8`` is accepted as a parameter to the ``MAIL`` - command and when present is passed to :meth:`process_message` in the - ``kwargs['mail_options']`` list. *decode_data* and *enable_SMTPUTF8* - cannot be set to ``True`` at the same time. - - *decode_data* specifies whether the data portion of the SMTP transaction - should be decoded using UTF-8. When *decode_data* is ``False`` (the - default), the server advertises the ``8BITMIME`` - extension (:rfc:`6152`), accepts the ``BODY=8BITMIME`` parameter to - the ``MAIL`` command, and when present passes it to :meth:`process_message` - in the ``kwargs['mail_options']`` list. *decode_data* and *enable_SMTPUTF8* - cannot be set to ``True`` at the same time. - - .. method:: process_message(peer, mailfrom, rcpttos, data, **kwargs) - - Raise a :exc:`NotImplementedError` exception. Override this in subclasses to - do something useful with this message. Whatever was passed in the - constructor as *remoteaddr* will be available as the :attr:`_remoteaddr` - attribute. *peer* is the remote host's address, *mailfrom* is the envelope - originator, *rcpttos* are the envelope recipients and *data* is a string - containing the contents of the e-mail (which should be in :rfc:`5321` - format). - - If the *decode_data* constructor keyword is set to ``True``, the *data* - argument will be a unicode string. If it is set to ``False``, it - will be a bytes object. - - *kwargs* is a dictionary containing additional information. It is empty - if ``decode_data=True`` was given as an init argument, otherwise - it contains the following keys: - - *mail_options*: - a list of all received parameters to the ``MAIL`` - command (the elements are uppercase strings; example: - ``['BODY=8BITMIME', 'SMTPUTF8']``). - - *rcpt_options*: - same as *mail_options* but for the ``RCPT`` command. - Currently no ``RCPT TO`` options are supported, so for now - this will always be an empty list. - - Implementations of ``process_message`` should use the ``**kwargs`` - signature to accept arbitrary keyword arguments, since future feature - enhancements may add keys to the kwargs dictionary. - - Return ``None`` to request a normal ``250 Ok`` response; otherwise - return the desired response string in :RFC:`5321` format. - - .. attribute:: channel_class - - Override this in subclasses to use a custom :class:`SMTPChannel` for - managing SMTP clients. - - .. versionadded:: 3.4 - The *map* constructor argument. - - .. versionchanged:: 3.5 - *localaddr* and *remoteaddr* may now contain IPv6 addresses. - - .. versionadded:: 3.5 - The *decode_data* and *enable_SMTPUTF8* constructor parameters, and the - *kwargs* parameter to :meth:`process_message` when *decode_data* is - ``False``. - - .. versionchanged:: 3.6 - *decode_data* is now ``False`` by default. - - -DebuggingServer Objects ------------------------ - - -.. class:: DebuggingServer(localaddr, remoteaddr) - - Create a new debugging server. Arguments are as per :class:`SMTPServer`. - Messages will be discarded, and printed on stdout. - - -PureProxy Objects ------------------ - - -.. class:: PureProxy(localaddr, remoteaddr) - - Create a new pure proxy server. Arguments are as per :class:`SMTPServer`. - Everything will be relayed to *remoteaddr*. Note that running this has a good - chance to make you into an open relay, so please be careful. - - -SMTPChannel Objects -------------------- - -.. class:: SMTPChannel(server, conn, addr, data_size_limit=33554432,\ - map=None, enable_SMTPUTF8=False, decode_data=False) - - Create a new :class:`SMTPChannel` object which manages the communication - between the server and a single SMTP client. - - *conn* and *addr* are as per the instance variables described below. - - *data_size_limit* specifies the maximum number of bytes that will be - accepted in a ``DATA`` command. A value of ``None`` or ``0`` means no - limit. - - *enable_SMTPUTF8* determines whether the ``SMTPUTF8`` extension (as defined - in :RFC:`6531`) should be enabled. The default is ``False``. - *decode_data* and *enable_SMTPUTF8* cannot be set to ``True`` at the same - time. - - A dictionary can be specified in *map* to avoid using a global socket map. - - *decode_data* specifies whether the data portion of the SMTP transaction - should be decoded using UTF-8. The default is ``False``. - *decode_data* and *enable_SMTPUTF8* cannot be set to ``True`` at the same - time. - - To use a custom SMTPChannel implementation you need to override the - :attr:`SMTPServer.channel_class` of your :class:`SMTPServer`. - - .. versionchanged:: 3.5 - The *decode_data* and *enable_SMTPUTF8* parameters were added. - - .. versionchanged:: 3.6 - *decode_data* is now ``False`` by default. - - The :class:`SMTPChannel` has the following instance variables: - - .. attribute:: smtp_server - - Holds the :class:`SMTPServer` that spawned this channel. - - .. attribute:: conn - - Holds the socket object connecting to the client. - - .. attribute:: addr - - Holds the address of the client, the second value returned by - :func:`socket.accept ` - - .. attribute:: received_lines - - Holds a list of the line strings (decoded using UTF-8) received from - the client. The lines have their ``"\r\n"`` line ending translated to - ``"\n"``. - - .. attribute:: smtp_state - - Holds the current state of the channel. This will be either - :attr:`COMMAND` initially and then :attr:`DATA` after the client sends - a "DATA" line. - - .. attribute:: seen_greeting - - Holds a string containing the greeting sent by the client in its "HELO". - - .. attribute:: mailfrom - - Holds a string containing the address identified in the "MAIL FROM:" line - from the client. - - .. attribute:: rcpttos - - Holds a list of strings containing the addresses identified in the - "RCPT TO:" lines from the client. - - .. attribute:: received_data - - Holds a string containing all of the data sent by the client during the - DATA state, up to but not including the terminating ``"\r\n.\r\n"``. - - .. attribute:: fqdn - - Holds the fully-qualified domain name of the server as returned by - :func:`socket.getfqdn`. - - .. attribute:: peer - - Holds the name of the client peer as returned by ``conn.getpeername()`` - where ``conn`` is :attr:`conn`. - - The :class:`SMTPChannel` operates by invoking methods named ``smtp_`` - upon reception of a command line from the client. Built into the base - :class:`SMTPChannel` class are methods for handling the following commands - (and responding to them appropriately): - - ======== =================================================================== - Command Action taken - ======== =================================================================== - HELO Accepts the greeting from the client and stores it in - :attr:`seen_greeting`. Sets server to base command mode. - EHLO Accepts the greeting from the client and stores it in - :attr:`seen_greeting`. Sets server to extended command mode. - NOOP Takes no action. - QUIT Closes the connection cleanly. - MAIL Accepts the "MAIL FROM:" syntax and stores the supplied address as - :attr:`mailfrom`. In extended command mode, accepts the - :rfc:`1870` SIZE attribute and responds appropriately based on the - value of *data_size_limit*. - RCPT Accepts the "RCPT TO:" syntax and stores the supplied addresses in - the :attr:`rcpttos` list. - RSET Resets the :attr:`mailfrom`, :attr:`rcpttos`, and - :attr:`received_data`, but not the greeting. - DATA Sets the internal state to :attr:`DATA` and stores remaining lines - from the client in :attr:`received_data` until the terminator - ``"\r\n.\r\n"`` is received. - HELP Returns minimal information on command syntax - VRFY Returns code 252 (the server doesn't know if the address is valid) - EXPN Reports that the command is not implemented. - ======== =================================================================== diff --git a/Doc/library/socketserver.rst b/Doc/library/socketserver.rst index b65a3e8fb2b97..8aa72bd7332ef 100644 --- a/Doc/library/socketserver.rst +++ b/Doc/library/socketserver.rst @@ -176,7 +176,7 @@ partially finished requests and to use :mod:`selectors` to decide which request to work on next (or whether to handle a new incoming request). This is particularly important for stream services where each client can potentially be connected for a long time (if threads or subprocesses cannot be used). See -:mod:`asyncore` for another way to manage this. +:mod:`asyncio` for another way to manage this. .. XXX should data and methods be intermingled, or separate? how should the distinction between class and instance variables be drawn? diff --git a/Doc/license.rst b/Doc/license.rst index cd03411d6c94a..1d086b6fdd3fe 100644 --- a/Doc/license.rst +++ b/Doc/license.rst @@ -383,33 +383,6 @@ Project, http://www.wide.ad.jp/. :: SUCH DAMAGE. -Asynchronous socket services ----------------------------- - -The :mod:`asynchat` and :mod:`asyncore` modules contain the following notice:: - - Copyright 1996 by Sam Rushing - - All Rights Reserved - - Permission to use, copy, modify, and distribute this software and - its documentation for any purpose and without fee is hereby - granted, provided that the above copyright notice appear in all - copies and that both that copyright notice and this permission - notice appear in supporting documentation, and that the name of Sam - Rushing not be used in advertising or publicity pertaining to - distribution of the software without specific, written prior - permission. - - SAM RUSHING DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN - NO EVENT SHALL SAM RUSHING BE LIABLE FOR ANY SPECIAL, INDIRECT OR - CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - Cookie management ----------------- diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 0767a6a03ac2a..62516d207d0b1 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -468,6 +468,15 @@ Removed (Contributed by Hugo van Kemenade in :issue:`45320`.) +* Remove the ``asyncore`` and ``asynchat`` modules, deprecated in Python 3.6: + use the :mod:`asyncio` module instead. + (Contributed by Victor Stinner in :issue:`28533`.) + +* Remove the ``smtpd`` module, deprecated in Python 3.6: the `aiosmtpd + `__ module can be used instead, it is based + on asyncio. + (Contributed by Victor Stinner in :issue:`28533`.) + Porting to Python 3.11 ====================== diff --git a/Lib/test/libregrtest/save_env.py b/Lib/test/libregrtest/save_env.py index 60c9be24617a6..17dda99b64582 100644 --- a/Lib/test/libregrtest/save_env.py +++ b/Lib/test/libregrtest/save_env.py @@ -52,7 +52,7 @@ def __init__(self, testname, verbose=0, quiet=False, *, pgo=False): resources = ('sys.argv', 'cwd', 'sys.stdin', 'sys.stdout', 'sys.stderr', 'os.environ', 'sys.path', 'sys.path_hooks', '__import__', - 'warnings.filters', 'asyncore.socket_map', + 'warnings.filters', 'logging._handlers', 'logging._handlerList', 'sys.gettrace', 'sys.warnoptions', # multiprocessing.process._cleanup() may release ref @@ -160,16 +160,6 @@ def restore_warnings_filters(self, saved_filters): warnings.filters = saved_filters[1] warnings.filters[:] = saved_filters[2] - def get_asyncore_socket_map(self): - asyncore = sys.modules.get('asyncore') - # XXX Making a copy keeps objects alive until __exit__ gets called. - return asyncore and asyncore.socket_map.copy() or {} - def restore_asyncore_socket_map(self, saved_map): - asyncore = sys.modules.get('asyncore') - if asyncore is not None: - asyncore.close_all(ignore_all=True) - asyncore.socket_map.update(saved_map) - def get_shutil_archive_formats(self): shutil = self.try_get_module('shutil') # we could call get_archives_formats() but that only returns the diff --git a/Lib/test/mock_socket.py b/Lib/test/mock_socket.py index c7abddcf5fafd..9788d58b4c765 100644 --- a/Lib/test/mock_socket.py +++ b/Lib/test/mock_socket.py @@ -1,4 +1,4 @@ -"""Mock socket module used by the smtpd and smtplib tests. +"""Mock socket module used by the smtplib tests. """ # imported for _GLOBAL_DEFAULT_TIMEOUT @@ -33,7 +33,7 @@ def close(self): class MockSocket: - """Mock socket object used by smtpd and smtplib tests. + """Mock socket object used by smtplib tests. """ def __init__(self, family=None): global _reply_data diff --git a/Lib/asynchat.py b/Lib/test/support/_asynchat.py similarity index 98% rename from Lib/asynchat.py rename to Lib/test/support/_asynchat.py index de26ffa648ffe..941cc1d22e6b0 100644 --- a/Lib/asynchat.py +++ b/Lib/test/support/_asynchat.py @@ -45,17 +45,9 @@ method) up to the terminator, and then control will be returned to you - by calling your self.found_terminator() method. """ -import asyncore +from test.support import _asyncore as asyncore from collections import deque -from warnings import warn -warn( - 'The asynchat module is deprecated. ' - 'The recommended replacement is asyncio', - DeprecationWarning, - stacklevel=2) - - class async_chat(asyncore.dispatcher): """This is an abstract class. You must derive from this class, and add diff --git a/Lib/asyncore.py b/Lib/test/support/_asyncore.py similarity index 99% rename from Lib/asyncore.py rename to Lib/test/support/_asyncore.py index b1eea4bf65211..7863efaea66c8 100644 --- a/Lib/asyncore.py +++ b/Lib/test/support/_asyncore.py @@ -57,12 +57,6 @@ ENOTCONN, ESHUTDOWN, EISCONN, EBADF, ECONNABORTED, EPIPE, EAGAIN, \ errorcode -warnings.warn( - 'The asyncore module is deprecated. ' - 'The recommended replacement is asyncio', - DeprecationWarning, - stacklevel=2) - _DISCONNECTED = frozenset({ECONNRESET, ENOTCONN, ESHUTDOWN, ECONNABORTED, EPIPE, EBADF}) diff --git a/Lib/smtpd.py b/Lib/test/support/_smtpd.py similarity index 83% rename from Lib/smtpd.py rename to Lib/test/support/_smtpd.py index 1cd004fbc6fe5..0e37d08f2be34 100755 --- a/Lib/smtpd.py +++ b/Lib/test/support/_smtpd.py @@ -80,22 +80,13 @@ from warnings import warn from email._header_value_parser import get_addr_spec, get_angle_addr +from test.support import _asyncore as asyncore +from test.support import _asynchat as asynchat + __all__ = [ "SMTPChannel", "SMTPServer", "DebuggingServer", "PureProxy", ] -warn( - 'The smtpd module is deprecated and unmaintained. Please see aiosmtpd ' - '(https://aiosmtpd.readthedocs.io/) for the recommended replacement.', - DeprecationWarning, - stacklevel=2) - - -# These are imported after the above warning so that users get the correct -# deprecation warning. -import asyncore -import asynchat - program = sys.argv[0] __version__ = 'Python SMTP proxy version 0.3' @@ -188,128 +179,6 @@ def _set_rset_state(self): self.received_lines = [] - # properties for backwards-compatibility - @property - def __server(self): - warn("Access to __server attribute on SMTPChannel is deprecated, " - "use 'smtp_server' instead", DeprecationWarning, 2) - return self.smtp_server - @__server.setter - def __server(self, value): - warn("Setting __server attribute on SMTPChannel is deprecated, " - "set 'smtp_server' instead", DeprecationWarning, 2) - self.smtp_server = value - - @property - def __line(self): - warn("Access to __line attribute on SMTPChannel is deprecated, " - "use 'received_lines' instead", DeprecationWarning, 2) - return self.received_lines - @__line.setter - def __line(self, value): - warn("Setting __line attribute on SMTPChannel is deprecated, " - "set 'received_lines' instead", DeprecationWarning, 2) - self.received_lines = value - - @property - def __state(self): - warn("Access to __state attribute on SMTPChannel is deprecated, " - "use 'smtp_state' instead", DeprecationWarning, 2) - return self.smtp_state - @__state.setter - def __state(self, value): - warn("Setting __state attribute on SMTPChannel is deprecated, " - "set 'smtp_state' instead", DeprecationWarning, 2) - self.smtp_state = value - - @property - def __greeting(self): - warn("Access to __greeting attribute on SMTPChannel is deprecated, " - "use 'seen_greeting' instead", DeprecationWarning, 2) - return self.seen_greeting - @__greeting.setter - def __greeting(self, value): - warn("Setting __greeting attribute on SMTPChannel is deprecated, " - "set 'seen_greeting' instead", DeprecationWarning, 2) - self.seen_greeting = value - - @property - def __mailfrom(self): - warn("Access to __mailfrom attribute on SMTPChannel is deprecated, " - "use 'mailfrom' instead", DeprecationWarning, 2) - return self.mailfrom - @__mailfrom.setter - def __mailfrom(self, value): - warn("Setting __mailfrom attribute on SMTPChannel is deprecated, " - "set 'mailfrom' instead", DeprecationWarning, 2) - self.mailfrom = value - - @property - def __rcpttos(self): - warn("Access to __rcpttos attribute on SMTPChannel is deprecated, " - "use 'rcpttos' instead", DeprecationWarning, 2) - return self.rcpttos - @__rcpttos.setter - def __rcpttos(self, value): - warn("Setting __rcpttos attribute on SMTPChannel is deprecated, " - "set 'rcpttos' instead", DeprecationWarning, 2) - self.rcpttos = value - - @property - def __data(self): - warn("Access to __data attribute on SMTPChannel is deprecated, " - "use 'received_data' instead", DeprecationWarning, 2) - return self.received_data - @__data.setter - def __data(self, value): - warn("Setting __data attribute on SMTPChannel is deprecated, " - "set 'received_data' instead", DeprecationWarning, 2) - self.received_data = value - - @property - def __fqdn(self): - warn("Access to __fqdn attribute on SMTPChannel is deprecated, " - "use 'fqdn' instead", DeprecationWarning, 2) - return self.fqdn - @__fqdn.setter - def __fqdn(self, value): - warn("Setting __fqdn attribute on SMTPChannel is deprecated, " - "set 'fqdn' instead", DeprecationWarning, 2) - self.fqdn = value - - @property - def __peer(self): - warn("Access to __peer attribute on SMTPChannel is deprecated, " - "use 'peer' instead", DeprecationWarning, 2) - return self.peer - @__peer.setter - def __peer(self, value): - warn("Setting __peer attribute on SMTPChannel is deprecated, " - "set 'peer' instead", DeprecationWarning, 2) - self.peer = value - - @property - def __conn(self): - warn("Access to __conn attribute on SMTPChannel is deprecated, " - "use 'conn' instead", DeprecationWarning, 2) - return self.conn - @__conn.setter - def __conn(self, value): - warn("Setting __conn attribute on SMTPChannel is deprecated, " - "set 'conn' instead", DeprecationWarning, 2) - self.conn = value - - @property - def __addr(self): - warn("Access to __addr attribute on SMTPChannel is deprecated, " - "use 'addr' instead", DeprecationWarning, 2) - return self.addr - @__addr.setter - def __addr(self, value): - warn("Setting __addr attribute on SMTPChannel is deprecated, " - "set 'addr' instead", DeprecationWarning, 2) - self.addr = value - # Overrides base class for convenience. def push(self, msg): asynchat.async_chat.push(self, bytes( diff --git a/Lib/test/test_asynchat.py b/Lib/test/test_asynchat.py deleted file mode 100644 index 973ac1f7d97c9..0000000000000 --- a/Lib/test/test_asynchat.py +++ /dev/null @@ -1,292 +0,0 @@ -# test asynchat - -from test import support -from test.support import socket_helper -from test.support import threading_helper - -import errno -import socket -import sys -import threading -import time -import unittest -import unittest.mock - -import warnings -with warnings.catch_warnings(): - warnings.simplefilter('ignore', DeprecationWarning) - import asynchat - import asyncore - -HOST = socket_helper.HOST -SERVER_QUIT = b'QUIT\n' - - -class echo_server(threading.Thread): - # parameter to determine the number of bytes passed back to the - # client each send - chunk_size = 1 - - def __init__(self, event): - threading.Thread.__init__(self) - self.event = event - self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.port = socket_helper.bind_port(self.sock) - # This will be set if the client wants us to wait before echoing - # data back. - self.start_resend_event = None - - def run(self): - self.sock.listen() - self.event.set() - conn, client = self.sock.accept() - self.buffer = b"" - # collect data until quit message is seen - while SERVER_QUIT not in self.buffer: - data = conn.recv(1) - if not data: - break - self.buffer = self.buffer + data - - # remove the SERVER_QUIT message - self.buffer = self.buffer.replace(SERVER_QUIT, b'') - - if self.start_resend_event: - self.start_resend_event.wait() - - # re-send entire set of collected data - try: - # this may fail on some tests, such as test_close_when_done, - # since the client closes the channel when it's done sending - while self.buffer: - n = conn.send(self.buffer[:self.chunk_size]) - time.sleep(0.001) - self.buffer = self.buffer[n:] - except: - pass - - conn.close() - self.sock.close() - -class echo_client(asynchat.async_chat): - - def __init__(self, terminator, server_port): - asynchat.async_chat.__init__(self) - self.contents = [] - self.create_socket(socket.AF_INET, socket.SOCK_STREAM) - self.connect((HOST, server_port)) - self.set_terminator(terminator) - self.buffer = b"" - - def handle_connect(self): - pass - - if sys.platform == 'darwin': - # select.poll returns a select.POLLHUP at the end of the tests - # on darwin, so just ignore it - def handle_expt(self): - pass - - def collect_incoming_data(self, data): - self.buffer += data - - def found_terminator(self): - self.contents.append(self.buffer) - self.buffer = b"" - -def start_echo_server(): - event = threading.Event() - s = echo_server(event) - s.start() - event.wait() - event.clear() - time.sleep(0.01) # Give server time to start accepting. - return s, event - - -class TestAsynchat(unittest.TestCase): - usepoll = False - - def setUp(self): - self._threads = threading_helper.threading_setup() - - def tearDown(self): - threading_helper.threading_cleanup(*self._threads) - - def line_terminator_check(self, term, server_chunk): - event = threading.Event() - s = echo_server(event) - s.chunk_size = server_chunk - s.start() - event.wait() - event.clear() - time.sleep(0.01) # Give server time to start accepting. - c = echo_client(term, s.port) - c.push(b"hello ") - c.push(b"world" + term) - c.push(b"I'm not dead yet!" + term) - c.push(SERVER_QUIT) - asyncore.loop(use_poll=self.usepoll, count=300, timeout=.01) - threading_helper.join_thread(s) - - self.assertEqual(c.contents, [b"hello world", b"I'm not dead yet!"]) - - # the line terminator tests below check receiving variously-sized - # chunks back from the server in order to exercise all branches of - # async_chat.handle_read - - def test_line_terminator1(self): - # test one-character terminator - for l in (1, 2, 3): - self.line_terminator_check(b'\n', l) - - def test_line_terminator2(self): - # test two-character terminator - for l in (1, 2, 3): - self.line_terminator_check(b'\r\n', l) - - def test_line_terminator3(self): - # test three-character terminator - for l in (1, 2, 3): - self.line_terminator_check(b'qqq', l) - - def numeric_terminator_check(self, termlen): - # Try reading a fixed number of bytes - s, event = start_echo_server() - c = echo_client(termlen, s.port) - data = b"hello world, I'm not dead yet!\n" - c.push(data) - c.push(SERVER_QUIT) - asyncore.loop(use_poll=self.usepoll, count=300, timeout=.01) - threading_helper.join_thread(s) - - self.assertEqual(c.contents, [data[:termlen]]) - - def test_numeric_terminator1(self): - # check that ints & longs both work (since type is - # explicitly checked in async_chat.handle_read) - self.numeric_terminator_check(1) - - def test_numeric_terminator2(self): - self.numeric_terminator_check(6) - - def test_none_terminator(self): - # Try reading a fixed number of bytes - s, event = start_echo_server() - c = echo_client(None, s.port) - data = b"hello world, I'm not dead yet!\n" - c.push(data) - c.push(SERVER_QUIT) - asyncore.loop(use_poll=self.usepoll, count=300, timeout=.01) - threading_helper.join_thread(s) - - self.assertEqual(c.contents, []) - self.assertEqual(c.buffer, data) - - def test_simple_producer(self): - s, event = start_echo_server() - c = echo_client(b'\n', s.port) - data = b"hello world\nI'm not dead yet!\n" - p = asynchat.simple_producer(data+SERVER_QUIT, buffer_size=8) - c.push_with_producer(p) - asyncore.loop(use_poll=self.usepoll, count=300, timeout=.01) - threading_helper.join_thread(s) - - self.assertEqual(c.contents, [b"hello world", b"I'm not dead yet!"]) - - def test_string_producer(self): - s, event = start_echo_server() - c = echo_client(b'\n', s.port) - data = b"hello world\nI'm not dead yet!\n" - c.push_with_producer(data+SERVER_QUIT) - asyncore.loop(use_poll=self.usepoll, count=300, timeout=.01) - threading_helper.join_thread(s) - - self.assertEqual(c.contents, [b"hello world", b"I'm not dead yet!"]) - - def test_empty_line(self): - # checks that empty lines are handled correctly - s, event = start_echo_server() - c = echo_client(b'\n', s.port) - c.push(b"hello world\n\nI'm not dead yet!\n") - c.push(SERVER_QUIT) - asyncore.loop(use_poll=self.usepoll, count=300, timeout=.01) - threading_helper.join_thread(s) - - self.assertEqual(c.contents, - [b"hello world", b"", b"I'm not dead yet!"]) - - def test_close_when_done(self): - s, event = start_echo_server() - s.start_resend_event = threading.Event() - c = echo_client(b'\n', s.port) - c.push(b"hello world\nI'm not dead yet!\n") - c.push(SERVER_QUIT) - c.close_when_done() - asyncore.loop(use_poll=self.usepoll, count=300, timeout=.01) - - # Only allow the server to start echoing data back to the client after - # the client has closed its connection. This prevents a race condition - # where the server echoes all of its data before we can check that it - # got any down below. - s.start_resend_event.set() - threading_helper.join_thread(s) - - self.assertEqual(c.contents, []) - # the server might have been able to send a byte or two back, but this - # at least checks that it received something and didn't just fail - # (which could still result in the client not having received anything) - self.assertGreater(len(s.buffer), 0) - - def test_push(self): - # Issue #12523: push() should raise a TypeError if it doesn't get - # a bytes string - s, event = start_echo_server() - c = echo_client(b'\n', s.port) - data = b'bytes\n' - c.push(data) - c.push(bytearray(data)) - c.push(memoryview(data)) - self.assertRaises(TypeError, c.push, 10) - self.assertRaises(TypeError, c.push, 'unicode') - c.push(SERVER_QUIT) - asyncore.loop(use_poll=self.usepoll, count=300, timeout=.01) - threading_helper.join_thread(s) - self.assertEqual(c.contents, [b'bytes', b'bytes', b'bytes']) - - -class TestAsynchat_WithPoll(TestAsynchat): - usepoll = True - - -class TestAsynchatMocked(unittest.TestCase): - def test_blockingioerror(self): - # Issue #16133: handle_read() must ignore BlockingIOError - sock = unittest.mock.Mock() - sock.recv.side_effect = BlockingIOError(errno.EAGAIN) - - dispatcher = asynchat.async_chat() - dispatcher.set_socket(sock) - self.addCleanup(dispatcher.del_channel) - - with unittest.mock.patch.object(dispatcher, 'handle_error') as error: - dispatcher.handle_read() - self.assertFalse(error.called) - - -class TestHelperFunctions(unittest.TestCase): - def test_find_prefix_at_end(self): - self.assertEqual(asynchat.find_prefix_at_end("qwerty\r", "\r\n"), 1) - self.assertEqual(asynchat.find_prefix_at_end("qwertydkjf", "\r\n"), 0) - - -class TestNotConnected(unittest.TestCase): - def test_disallow_negative_terminator(self): - # Issue #11259 - client = asynchat.async_chat() - self.assertRaises(ValueError, client.set_terminator, -1) - - - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/test/test_asyncore.py b/Lib/test/test_asyncore.py deleted file mode 100644 index ecd1e120ecb51..0000000000000 --- a/Lib/test/test_asyncore.py +++ /dev/null @@ -1,841 +0,0 @@ -import unittest -import select -import os -import socket -import sys -import time -import errno -import struct -import threading - -from test import support -from test.support import os_helper -from test.support import socket_helper -from test.support import threading_helper -from test.support import warnings_helper -from io import BytesIO - -if support.PGO: - raise unittest.SkipTest("test is not helpful for PGO") - -import warnings -with warnings.catch_warnings(): - warnings.simplefilter('ignore', DeprecationWarning) - import asyncore - - -HAS_UNIX_SOCKETS = hasattr(socket, 'AF_UNIX') - -class dummysocket: - def __init__(self): - self.closed = False - - def close(self): - self.closed = True - - def fileno(self): - return 42 - -class dummychannel: - def __init__(self): - self.socket = dummysocket() - - def close(self): - self.socket.close() - -class exitingdummy: - def __init__(self): - pass - - def handle_read_event(self): - raise asyncore.ExitNow() - - handle_write_event = handle_read_event - handle_close = handle_read_event - handle_expt_event = handle_read_event - -class crashingdummy: - def __init__(self): - self.error_handled = False - - def handle_read_event(self): - raise Exception() - - handle_write_event = handle_read_event - handle_close = handle_read_event - handle_expt_event = handle_read_event - - def handle_error(self): - self.error_handled = True - -# used when testing senders; just collects what it gets until newline is sent -def capture_server(evt, buf, serv): - try: - serv.listen() - conn, addr = serv.accept() - except TimeoutError: - pass - else: - n = 200 - start = time.monotonic() - while n > 0 and time.monotonic() - start < 3.0: - r, w, e = select.select([conn], [], [], 0.1) - if r: - n -= 1 - data = conn.recv(10) - # keep everything except for the newline terminator - buf.write(data.replace(b'\n', b'')) - if b'\n' in data: - break - time.sleep(0.01) - - conn.close() - finally: - serv.close() - evt.set() - -def bind_af_aware(sock, addr): - """Helper function to bind a socket according to its family.""" - if HAS_UNIX_SOCKETS and sock.family == socket.AF_UNIX: - # Make sure the path doesn't exist. - os_helper.unlink(addr) - socket_helper.bind_unix_socket(sock, addr) - else: - sock.bind(addr) - - -class HelperFunctionTests(unittest.TestCase): - def test_readwriteexc(self): - # Check exception handling behavior of read, write and _exception - - # check that ExitNow exceptions in the object handler method - # bubbles all the way up through asyncore read/write/_exception calls - tr1 = exitingdummy() - self.assertRaises(asyncore.ExitNow, asyncore.read, tr1) - self.assertRaises(asyncore.ExitNow, asyncore.write, tr1) - self.assertRaises(asyncore.ExitNow, asyncore._exception, tr1) - - # check that an exception other than ExitNow in the object handler - # method causes the handle_error method to get called - tr2 = crashingdummy() - asyncore.read(tr2) - self.assertEqual(tr2.error_handled, True) - - tr2 = crashingdummy() - asyncore.write(tr2) - self.assertEqual(tr2.error_handled, True) - - tr2 = crashingdummy() - asyncore._exception(tr2) - self.assertEqual(tr2.error_handled, True) - - # asyncore.readwrite uses constants in the select module that - # are not present in Windows systems (see this thread: - # http://mail.python.org/pipermail/python-list/2001-October/109973.html) - # These constants should be present as long as poll is available - - @unittest.skipUnless(hasattr(select, 'poll'), 'select.poll required') - def test_readwrite(self): - # Check that correct methods are called by readwrite() - - attributes = ('read', 'expt', 'write', 'closed', 'error_handled') - - expected = ( - (select.POLLIN, 'read'), - (select.POLLPRI, 'expt'), - (select.POLLOUT, 'write'), - (select.POLLERR, 'closed'), - (select.POLLHUP, 'closed'), - (select.POLLNVAL, 'closed'), - ) - - class testobj: - def __init__(self): - self.read = False - self.write = False - self.closed = False - self.expt = False - self.error_handled = False - - def handle_read_event(self): - self.read = True - - def handle_write_event(self): - self.write = True - - def handle_close(self): - self.closed = True - - def handle_expt_event(self): - self.expt = True - - def handle_error(self): - self.error_handled = True - - for flag, expectedattr in expected: - tobj = testobj() - self.assertEqual(getattr(tobj, expectedattr), False) - asyncore.readwrite(tobj, flag) - - # Only the attribute modified by the routine we expect to be - # called should be True. - for attr in attributes: - self.assertEqual(getattr(tobj, attr), attr==expectedattr) - - # check that ExitNow exceptions in the object handler method - # bubbles all the way up through asyncore readwrite call - tr1 = exitingdummy() - self.assertRaises(asyncore.ExitNow, asyncore.readwrite, tr1, flag) - - # check that an exception other than ExitNow in the object handler - # method causes the handle_error method to get called - tr2 = crashingdummy() - self.assertEqual(tr2.error_handled, False) - asyncore.readwrite(tr2, flag) - self.assertEqual(tr2.error_handled, True) - - def test_closeall(self): - self.closeall_check(False) - - def test_closeall_default(self): - self.closeall_check(True) - - def closeall_check(self, usedefault): - # Check that close_all() closes everything in a given map - - l = [] - testmap = {} - for i in range(10): - c = dummychannel() - l.append(c) - self.assertEqual(c.socket.closed, False) - testmap[i] = c - - if usedefault: - socketmap = asyncore.socket_map - try: - asyncore.socket_map = testmap - asyncore.close_all() - finally: - testmap, asyncore.socket_map = asyncore.socket_map, socketmap - else: - asyncore.close_all(testmap) - - self.assertEqual(len(testmap), 0) - - for c in l: - self.assertEqual(c.socket.closed, True) - - def test_compact_traceback(self): - try: - raise Exception("I don't like spam!") - except: - real_t, real_v, real_tb = sys.exc_info() - r = asyncore.compact_traceback() - else: - self.fail("Expected exception") - - (f, function, line), t, v, info = r - self.assertEqual(os.path.split(f)[-1], 'test_asyncore.py') - self.assertEqual(function, 'test_compact_traceback') - self.assertEqual(t, real_t) - self.assertEqual(v, real_v) - self.assertEqual(info, '[%s|%s|%s]' % (f, function, line)) - - -class DispatcherTests(unittest.TestCase): - def setUp(self): - pass - - def tearDown(self): - asyncore.close_all() - - def test_basic(self): - d = asyncore.dispatcher() - self.assertEqual(d.readable(), True) - self.assertEqual(d.writable(), True) - - def test_repr(self): - d = asyncore.dispatcher() - self.assertEqual(repr(d), '' % id(d)) - - def test_log(self): - d = asyncore.dispatcher() - - # capture output of dispatcher.log() (to stderr) - l1 = "Lovely spam! Wonderful spam!" - l2 = "I don't like spam!" - with support.captured_stderr() as stderr: - d.log(l1) - d.log(l2) - - lines = stderr.getvalue().splitlines() - self.assertEqual(lines, ['log: %s' % l1, 'log: %s' % l2]) - - def test_log_info(self): - d = asyncore.dispatcher() - - # capture output of dispatcher.log_info() (to stdout via print) - l1 = "Have you got anything without spam?" - l2 = "Why can't she have egg bacon spam and sausage?" - l3 = "THAT'S got spam in it!" - with support.captured_stdout() as stdout: - d.log_info(l1, 'EGGS') - d.log_info(l2) - d.log_info(l3, 'SPAM') - - lines = stdout.getvalue().splitlines() - expected = ['EGGS: %s' % l1, 'info: %s' % l2, 'SPAM: %s' % l3] - self.assertEqual(lines, expected) - - def test_unhandled(self): - d = asyncore.dispatcher() - d.ignore_log_types = () - - # capture output of dispatcher.log_info() (to stdout via print) - with support.captured_stdout() as stdout: - d.handle_expt() - d.handle_read() - d.handle_write() - d.handle_connect() - - lines = stdout.getvalue().splitlines() - expected = ['warning: unhandled incoming priority event', - 'warning: unhandled read event', - 'warning: unhandled write event', - 'warning: unhandled connect event'] - self.assertEqual(lines, expected) - - def test_strerror(self): - # refers to bug #8573 - err = asyncore._strerror(errno.EPERM) - if hasattr(os, 'strerror'): - self.assertEqual(err, os.strerror(errno.EPERM)) - err = asyncore._strerror(-1) - self.assertTrue(err != "") - - -class dispatcherwithsend_noread(asyncore.dispatcher_with_send): - def readable(self): - return False - - def handle_connect(self): - pass - - -class DispatcherWithSendTests(unittest.TestCase): - def setUp(self): - pass - - def tearDown(self): - asyncore.close_all() - - @threading_helper.reap_threads - def test_send(self): - evt = threading.Event() - sock = socket.socket() - sock.settimeout(3) - port = socket_helper.bind_port(sock) - - cap = BytesIO() - args = (evt, cap, sock) - t = threading.Thread(target=capture_server, args=args) - t.start() - try: - # wait a little longer for the server to initialize (it sometimes - # refuses connections on slow machines without this wait) - time.sleep(0.2) - - data = b"Suppose there isn't a 16-ton weight?" - d = dispatcherwithsend_noread() - d.create_socket() - d.connect((socket_helper.HOST, port)) - - # give time for socket to connect - time.sleep(0.1) - - d.send(data) - d.send(data) - d.send(b'\n') - - n = 1000 - while d.out_buffer and n > 0: - asyncore.poll() - n -= 1 - - evt.wait() - - self.assertEqual(cap.getvalue(), data*2) - finally: - threading_helper.join_thread(t) - - - at unittest.skipUnless(hasattr(asyncore, 'file_wrapper'), - 'asyncore.file_wrapper required') -class FileWrapperTest(unittest.TestCase): - def setUp(self): - self.d = b"It's not dead, it's sleeping!" - with open(os_helper.TESTFN, 'wb') as file: - file.write(self.d) - - def tearDown(self): - os_helper.unlink(os_helper.TESTFN) - - def test_recv(self): - fd = os.open(os_helper.TESTFN, os.O_RDONLY) - w = asyncore.file_wrapper(fd) - os.close(fd) - - self.assertNotEqual(w.fd, fd) - self.assertNotEqual(w.fileno(), fd) - self.assertEqual(w.recv(13), b"It's not dead") - self.assertEqual(w.read(6), b", it's") - w.close() - self.assertRaises(OSError, w.read, 1) - - def test_send(self): - d1 = b"Come again?" - d2 = b"I want to buy some cheese." - fd = os.open(os_helper.TESTFN, os.O_WRONLY | os.O_APPEND) - w = asyncore.file_wrapper(fd) - os.close(fd) - - w.write(d1) - w.send(d2) - w.close() - with open(os_helper.TESTFN, 'rb') as file: - self.assertEqual(file.read(), self.d + d1 + d2) - - @unittest.skipUnless(hasattr(asyncore, 'file_dispatcher'), - 'asyncore.file_dispatcher required') - def test_dispatcher(self): - fd = os.open(os_helper.TESTFN, os.O_RDONLY) - data = [] - class FileDispatcher(asyncore.file_dispatcher): - def handle_read(self): - data.append(self.recv(29)) - s = FileDispatcher(fd) - os.close(fd) - asyncore.loop(timeout=0.01, use_poll=True, count=2) - self.assertEqual(b"".join(data), self.d) - - def test_resource_warning(self): - # Issue #11453 - fd = os.open(os_helper.TESTFN, os.O_RDONLY) - f = asyncore.file_wrapper(fd) - - os.close(fd) - with warnings_helper.check_warnings(('', ResourceWarning)): - f = None - support.gc_collect() - - def test_close_twice(self): - fd = os.open(os_helper.TESTFN, os.O_RDONLY) - f = asyncore.file_wrapper(fd) - os.close(fd) - - os.close(f.fd) # file_wrapper dupped fd - with self.assertRaises(OSError): - f.close() - - self.assertEqual(f.fd, -1) - # calling close twice should not fail - f.close() - - -class BaseTestHandler(asyncore.dispatcher): - - def __init__(self, sock=None): - asyncore.dispatcher.__init__(self, sock) - self.flag = False - - def handle_accept(self): - raise Exception("handle_accept not supposed to be called") - - def handle_accepted(self): - raise Exception("handle_accepted not supposed to be called") - - def handle_connect(self): - raise Exception("handle_connect not supposed to be called") - - def handle_expt(self): - raise Exception("handle_expt not supposed to be called") - - def handle_close(self): - raise Exception("handle_close not supposed to be called") - - def handle_error(self): - raise - - -class BaseServer(asyncore.dispatcher): - """A server which listens on an address and dispatches the - connection to a handler. - """ - - def __init__(self, family, addr, handler=BaseTestHandler): - asyncore.dispatcher.__init__(self) - self.create_socket(family) - self.set_reuse_addr() - bind_af_aware(self.socket, addr) - self.listen(5) - self.handler = handler - - @property - def address(self): - return self.socket.getsockname() - - def handle_accepted(self, sock, addr): - self.handler(sock) - - def handle_error(self): - raise - - -class BaseClient(BaseTestHandler): - - def __init__(self, family, address): - BaseTestHandler.__init__(self) - self.create_socket(family) - self.connect(address) - - def handle_connect(self): - pass - - -class BaseTestAPI: - - def tearDown(self): - asyncore.close_all(ignore_all=True) - - def loop_waiting_for_flag(self, instance, timeout=5): - timeout = float(timeout) / 100 - count = 100 - while asyncore.socket_map and count > 0: - asyncore.loop(timeout=0.01, count=1, use_poll=self.use_poll) - if instance.flag: - return - count -= 1 - time.sleep(timeout) - self.fail("flag not set") - - def test_handle_connect(self): - # make sure handle_connect is called on connect() - - class TestClient(BaseClient): - def handle_connect(self): - self.flag = True - - server = BaseServer(self.family, self.addr) - client = TestClient(self.family, server.address) - self.loop_waiting_for_flag(client) - - def test_handle_accept(self): - # make sure handle_accept() is called when a client connects - - class TestListener(BaseTestHandler): - - def __init__(self, family, addr): - BaseTestHandler.__init__(self) - self.create_socket(family) - bind_af_aware(self.socket, addr) - self.listen(5) - self.address = self.socket.getsockname() - - def handle_accept(self): - self.flag = True - - server = TestListener(self.family, self.addr) - client = BaseClient(self.family, server.address) - self.loop_waiting_for_flag(server) - - def test_handle_accepted(self): - # make sure handle_accepted() is called when a client connects - - class TestListener(BaseTestHandler): - - def __init__(self, family, addr): - BaseTestHandler.__init__(self) - self.create_socket(family) - bind_af_aware(self.socket, addr) - self.listen(5) - self.address = self.socket.getsockname() - - def handle_accept(self): - asyncore.dispatcher.handle_accept(self) - - def handle_accepted(self, sock, addr): - sock.close() - self.flag = True - - server = TestListener(self.family, self.addr) - client = BaseClient(self.family, server.address) - self.loop_waiting_for_flag(server) - - - def test_handle_read(self): - # make sure handle_read is called on data received - - class TestClient(BaseClient): - def handle_read(self): - self.flag = True - - class TestHandler(BaseTestHandler): - def __init__(self, conn): - BaseTestHandler.__init__(self, conn) - self.send(b'x' * 1024) - - server = BaseServer(self.family, self.addr, TestHandler) - client = TestClient(self.family, server.address) - self.loop_waiting_for_flag(client) - - def test_handle_write(self): - # make sure handle_write is called - - class TestClient(BaseClient): - def handle_write(self): - self.flag = True - - server = BaseServer(self.family, self.addr) - client = TestClient(self.family, server.address) - self.loop_waiting_for_flag(client) - - def test_handle_close(self): - # make sure handle_close is called when the other end closes - # the connection - - class TestClient(BaseClient): - - def handle_read(self): - # in order to make handle_close be called we are supposed - # to make at least one recv() call - self.recv(1024) - - def handle_close(self): - self.flag = True - self.close() - - class TestHandler(BaseTestHandler): - def __init__(self, conn): - BaseTestHandler.__init__(self, conn) - self.close() - - server = BaseServer(self.family, self.addr, TestHandler) - client = TestClient(self.family, server.address) - self.loop_waiting_for_flag(client) - - def test_handle_close_after_conn_broken(self): - # Check that ECONNRESET/EPIPE is correctly handled (issues #5661 and - # #11265). - - data = b'\0' * 128 - - class TestClient(BaseClient): - - def handle_write(self): - self.send(data) - - def handle_close(self): - self.flag = True - self.close() - - def handle_expt(self): - self.flag = True - self.close() - - class TestHandler(BaseTestHandler): - - def handle_read(self): - self.recv(len(data)) - self.close() - - def writable(self): - return False - - server = BaseServer(self.family, self.addr, TestHandler) - client = TestClient(self.family, server.address) - self.loop_waiting_for_flag(client) - - @unittest.skipIf(sys.platform.startswith("sunos"), - "OOB support is broken on Solaris") - def test_handle_expt(self): - # Make sure handle_expt is called on OOB data received. - # Note: this might fail on some platforms as OOB data is - # tenuously supported and rarely used. - if HAS_UNIX_SOCKETS and self.family == socket.AF_UNIX: - self.skipTest("Not applicable to AF_UNIX sockets.") - - if sys.platform == "darwin" and self.use_poll: - self.skipTest("poll may fail on macOS; see issue #28087") - - class TestClient(BaseClient): - def handle_expt(self): - self.socket.recv(1024, socket.MSG_OOB) - self.flag = True - - class TestHandler(BaseTestHandler): - def __init__(self, conn): - BaseTestHandler.__init__(self, conn) - self.socket.send(bytes(chr(244), 'latin-1'), socket.MSG_OOB) - - server = BaseServer(self.family, self.addr, TestHandler) - client = TestClient(self.family, server.address) - self.loop_waiting_for_flag(client) - - def test_handle_error(self): - - class TestClient(BaseClient): - def handle_write(self): - 1.0 / 0 - def handle_error(self): - self.flag = True - try: - raise - except ZeroDivisionError: - pass - else: - raise Exception("exception not raised") - - server = BaseServer(self.family, self.addr) - client = TestClient(self.family, server.address) - self.loop_waiting_for_flag(client) - - def test_connection_attributes(self): - server = BaseServer(self.family, self.addr) - client = BaseClient(self.family, server.address) - - # we start disconnected - self.assertFalse(server.connected) - self.assertTrue(server.accepting) - # this can't be taken for granted across all platforms - #self.assertFalse(client.connected) - self.assertFalse(client.accepting) - - # execute some loops so that client connects to server - asyncore.loop(timeout=0.01, use_poll=self.use_poll, count=100) - self.assertFalse(server.connected) - self.assertTrue(server.accepting) - self.assertTrue(client.connected) - self.assertFalse(client.accepting) - - # disconnect the client - client.close() - self.assertFalse(server.connected) - self.assertTrue(server.accepting) - self.assertFalse(client.connected) - self.assertFalse(client.accepting) - - # stop serving - server.close() - self.assertFalse(server.connected) - self.assertFalse(server.accepting) - - def test_create_socket(self): - s = asyncore.dispatcher() - s.create_socket(self.family) - self.assertEqual(s.socket.type, socket.SOCK_STREAM) - self.assertEqual(s.socket.family, self.family) - self.assertEqual(s.socket.gettimeout(), 0) - self.assertFalse(s.socket.get_inheritable()) - - def test_bind(self): - if HAS_UNIX_SOCKETS and self.family == socket.AF_UNIX: - self.skipTest("Not applicable to AF_UNIX sockets.") - s1 = asyncore.dispatcher() - s1.create_socket(self.family) - s1.bind(self.addr) - s1.listen(5) - port = s1.socket.getsockname()[1] - - s2 = asyncore.dispatcher() - s2.create_socket(self.family) - # EADDRINUSE indicates the socket was correctly bound - self.assertRaises(OSError, s2.bind, (self.addr[0], port)) - - def test_set_reuse_addr(self): - if HAS_UNIX_SOCKETS and self.family == socket.AF_UNIX: - self.skipTest("Not applicable to AF_UNIX sockets.") - - with socket.socket(self.family) as sock: - try: - sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - except OSError: - unittest.skip("SO_REUSEADDR not supported on this platform") - else: - # if SO_REUSEADDR succeeded for sock we expect asyncore - # to do the same - s = asyncore.dispatcher(socket.socket(self.family)) - self.assertFalse(s.socket.getsockopt(socket.SOL_SOCKET, - socket.SO_REUSEADDR)) - s.socket.close() - s.create_socket(self.family) - s.set_reuse_addr() - self.assertTrue(s.socket.getsockopt(socket.SOL_SOCKET, - socket.SO_REUSEADDR)) - - @threading_helper.reap_threads - def test_quick_connect(self): - # see: http://bugs.python.org/issue10340 - if self.family not in (socket.AF_INET, getattr(socket, "AF_INET6", object())): - self.skipTest("test specific to AF_INET and AF_INET6") - - server = BaseServer(self.family, self.addr) - # run the thread 500 ms: the socket should be connected in 200 ms - t = threading.Thread(target=lambda: asyncore.loop(timeout=0.1, - count=5)) - t.start() - try: - with socket.socket(self.family, socket.SOCK_STREAM) as s: - s.settimeout(.2) - s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, - struct.pack('ii', 1, 0)) - - try: - s.connect(server.address) - except OSError: - pass - finally: - threading_helper.join_thread(t) - -class TestAPI_UseIPv4Sockets(BaseTestAPI): - family = socket.AF_INET - addr = (socket_helper.HOST, 0) - - at unittest.skipUnless(socket_helper.IPV6_ENABLED, 'IPv6 support required') -class TestAPI_UseIPv6Sockets(BaseTestAPI): - family = socket.AF_INET6 - addr = (socket_helper.HOSTv6, 0) - - at unittest.skipUnless(HAS_UNIX_SOCKETS, 'Unix sockets required') -class TestAPI_UseUnixSockets(BaseTestAPI): - if HAS_UNIX_SOCKETS: - family = socket.AF_UNIX - addr = os_helper.TESTFN - - def tearDown(self): - os_helper.unlink(self.addr) - BaseTestAPI.tearDown(self) - -class TestAPI_UseIPv4Select(TestAPI_UseIPv4Sockets, unittest.TestCase): - use_poll = False - - at unittest.skipUnless(hasattr(select, 'poll'), 'select.poll required') -class TestAPI_UseIPv4Poll(TestAPI_UseIPv4Sockets, unittest.TestCase): - use_poll = True - -class TestAPI_UseIPv6Select(TestAPI_UseIPv6Sockets, unittest.TestCase): - use_poll = False - - at unittest.skipUnless(hasattr(select, 'poll'), 'select.poll required') -class TestAPI_UseIPv6Poll(TestAPI_UseIPv6Sockets, unittest.TestCase): - use_poll = True - -class TestAPI_UseUnixSocketsSelect(TestAPI_UseUnixSockets, unittest.TestCase): - use_poll = False - - at unittest.skipUnless(hasattr(select, 'poll'), 'select.poll required') -class TestAPI_UseUnixSocketsPoll(TestAPI_UseUnixSockets, unittest.TestCase): - use_poll = True - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/test/test_ftplib.py b/Lib/test/test_ftplib.py index 56e3d8ab8528a..c9edfac96871a 100644 --- a/Lib/test/test_ftplib.py +++ b/Lib/test/test_ftplib.py @@ -18,17 +18,13 @@ from unittest import TestCase, skipUnless from test import support -from test.support import threading_helper +from test.support import _asynchat as asynchat +from test.support import _asyncore as asyncore from test.support import socket_helper +from test.support import threading_helper from test.support import warnings_helper from test.support.socket_helper import HOST, HOSTv6 -import warnings -with warnings.catch_warnings(): - warnings.simplefilter('ignore', DeprecationWarning) - import asyncore - import asynchat - TIMEOUT = support.LOOPBACK_TIMEOUT DEFAULT_ENCODING = 'utf-8' diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 85b6e5f392111..e709ea327fbd3 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -42,6 +42,8 @@ import tempfile from test.support.script_helper import assert_python_ok, assert_python_failure from test import support +from test.support import _asyncore as asyncore +from test.support import _smtpd as smtpd from test.support import os_helper from test.support import socket_helper from test.support import threading_helper @@ -59,11 +61,6 @@ from socketserver import (ThreadingUDPServer, DatagramRequestHandler, ThreadingTCPServer, StreamRequestHandler) -with warnings.catch_warnings(): - warnings.simplefilter('ignore', DeprecationWarning) - import asyncore - import smtpd - try: import win32evtlog, win32evtlogutil, pywintypes except ImportError: diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 00e738ecf9a1c..91611dfff0ebc 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -30,6 +30,8 @@ import uuid import warnings from test import support +from test.support import _asynchat as asynchat +from test.support import _asyncore as asyncore from test.support import import_helper from test.support import os_helper from test.support import socket_helper @@ -37,11 +39,6 @@ from test.support import warnings_helper from platform import win32_is_iot -with warnings.catch_warnings(): - warnings.simplefilter('ignore', DeprecationWarning) - import asynchat - import asyncore - try: import resource except ImportError: diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py index 44cf5231f9d23..23c6be3a801bf 100644 --- a/Lib/test/test_poplib.py +++ b/Lib/test/test_poplib.py @@ -12,16 +12,12 @@ import unittest from unittest import TestCase, skipUnless from test import support as test_support +from test.support import _asynchat as asynchat +from test.support import _asyncore as asyncore from test.support import hashlib_helper from test.support import socket_helper from test.support import threading_helper -import warnings -with warnings.catch_warnings(): - warnings.simplefilter('ignore', DeprecationWarning) - import asynchat - import asyncore - HOST = socket_helper.HOST PORT = 0 diff --git a/Lib/test/test_smtpd.py b/Lib/test/test_smtpd.py deleted file mode 100644 index d2e150d535ff6..0000000000000 --- a/Lib/test/test_smtpd.py +++ /dev/null @@ -1,1018 +0,0 @@ -import unittest -import textwrap -from test import support, mock_socket -from test.support import socket_helper -from test.support import warnings_helper -import socket -import io - -import warnings -with warnings.catch_warnings(): - warnings.simplefilter('ignore', DeprecationWarning) - import smtpd - import asyncore - - -class DummyServer(smtpd.SMTPServer): - def __init__(self, *args, **kwargs): - smtpd.SMTPServer.__init__(self, *args, **kwargs) - self.messages = [] - if self._decode_data: - self.return_status = 'return status' - else: - self.return_status = b'return status' - - def process_message(self, peer, mailfrom, rcpttos, data, **kw): - self.messages.append((peer, mailfrom, rcpttos, data)) - if data == self.return_status: - return '250 Okish' - if 'mail_options' in kw and 'SMTPUTF8' in kw['mail_options']: - return '250 SMTPUTF8 message okish' - - -class DummyDispatcherBroken(Exception): - pass - - -class BrokenDummyServer(DummyServer): - def listen(self, num): - raise DummyDispatcherBroken() - - -class SMTPDServerTest(unittest.TestCase): - def setUp(self): - smtpd.socket = asyncore.socket = mock_socket - - def test_process_message_unimplemented(self): - server = smtpd.SMTPServer((socket_helper.HOST, 0), ('b', 0), - decode_data=True) - conn, addr = server.accept() - channel = smtpd.SMTPChannel(server, conn, addr, decode_data=True) - - def write_line(line): - channel.socket.queue_recv(line) - channel.handle_read() - - write_line(b'HELO example') - write_line(b'MAIL From:eggs at example') - write_line(b'RCPT To:spam at example') - write_line(b'DATA') - self.assertRaises(NotImplementedError, write_line, b'spam\r\n.\r\n') - - def test_decode_data_and_enable_SMTPUTF8_raises(self): - self.assertRaises( - ValueError, - smtpd.SMTPServer, - (socket_helper.HOST, 0), - ('b', 0), - enable_SMTPUTF8=True, - decode_data=True) - - def tearDown(self): - asyncore.close_all() - asyncore.socket = smtpd.socket = socket - - -class DebuggingServerTest(unittest.TestCase): - - def setUp(self): - smtpd.socket = asyncore.socket = mock_socket - - def send_data(self, channel, data, enable_SMTPUTF8=False): - def write_line(line): - channel.socket.queue_recv(line) - channel.handle_read() - write_line(b'EHLO example') - if enable_SMTPUTF8: - write_line(b'MAIL From:eggs at example BODY=8BITMIME SMTPUTF8') - else: - write_line(b'MAIL From:eggs at example') - write_line(b'RCPT To:spam at example') - write_line(b'DATA') - write_line(data) - write_line(b'.') - - def test_process_message_with_decode_data_true(self): - server = smtpd.DebuggingServer((socket_helper.HOST, 0), ('b', 0), - decode_data=True) - conn, addr = server.accept() - channel = smtpd.SMTPChannel(server, conn, addr, decode_data=True) - with support.captured_stdout() as s: - self.send_data(channel, b'From: test\n\nhello\n') - stdout = s.getvalue() - self.assertEqual(stdout, textwrap.dedent("""\ - ---------- MESSAGE FOLLOWS ---------- - From: test - X-Peer: peer-address - - hello - ------------ END MESSAGE ------------ - """)) - - def test_process_message_with_decode_data_false(self): - server = smtpd.DebuggingServer((socket_helper.HOST, 0), ('b', 0)) - conn, addr = server.accept() - channel = smtpd.SMTPChannel(server, conn, addr) - with support.captured_stdout() as s: - self.send_data(channel, b'From: test\n\nh\xc3\xa9llo\xff\n') - stdout = s.getvalue() - self.assertEqual(stdout, textwrap.dedent("""\ - ---------- MESSAGE FOLLOWS ---------- - b'From: test' - b'X-Peer: peer-address' - b'' - b'h\\xc3\\xa9llo\\xff' - ------------ END MESSAGE ------------ - """)) - - def test_process_message_with_enable_SMTPUTF8_true(self): - server = smtpd.DebuggingServer((socket_helper.HOST, 0), ('b', 0), - enable_SMTPUTF8=True) - conn, addr = server.accept() - channel = smtpd.SMTPChannel(server, conn, addr, enable_SMTPUTF8=True) - with support.captured_stdout() as s: - self.send_data(channel, b'From: test\n\nh\xc3\xa9llo\xff\n') - stdout = s.getvalue() - self.assertEqual(stdout, textwrap.dedent("""\ - ---------- MESSAGE FOLLOWS ---------- - b'From: test' - b'X-Peer: peer-address' - b'' - b'h\\xc3\\xa9llo\\xff' - ------------ END MESSAGE ------------ - """)) - - def test_process_SMTPUTF8_message_with_enable_SMTPUTF8_true(self): - server = smtpd.DebuggingServer((socket_helper.HOST, 0), ('b', 0), - enable_SMTPUTF8=True) - conn, addr = server.accept() - channel = smtpd.SMTPChannel(server, conn, addr, enable_SMTPUTF8=True) - with support.captured_stdout() as s: - self.send_data(channel, b'From: test\n\nh\xc3\xa9llo\xff\n', - enable_SMTPUTF8=True) - stdout = s.getvalue() - self.assertEqual(stdout, textwrap.dedent("""\ - ---------- MESSAGE FOLLOWS ---------- - mail options: ['BODY=8BITMIME', 'SMTPUTF8'] - b'From: test' - b'X-Peer: peer-address' - b'' - b'h\\xc3\\xa9llo\\xff' - ------------ END MESSAGE ------------ - """)) - - def tearDown(self): - asyncore.close_all() - asyncore.socket = smtpd.socket = socket - - -class TestFamilyDetection(unittest.TestCase): - def setUp(self): - smtpd.socket = asyncore.socket = mock_socket - - def tearDown(self): - asyncore.close_all() - asyncore.socket = smtpd.socket = socket - - @unittest.skipUnless(socket_helper.IPV6_ENABLED, "IPv6 not enabled") - def test_socket_uses_IPv6(self): - server = smtpd.SMTPServer((socket_helper.HOSTv6, 0), (socket_helper.HOSTv4, 0)) - self.assertEqual(server.socket.family, socket.AF_INET6) - - def test_socket_uses_IPv4(self): - server = smtpd.SMTPServer((socket_helper.HOSTv4, 0), (socket_helper.HOSTv6, 0)) - self.assertEqual(server.socket.family, socket.AF_INET) - - -class TestRcptOptionParsing(unittest.TestCase): - error_response = (b'555 RCPT TO parameters not recognized or not ' - b'implemented\r\n') - - def setUp(self): - smtpd.socket = asyncore.socket = mock_socket - self.old_debugstream = smtpd.DEBUGSTREAM - self.debug = smtpd.DEBUGSTREAM = io.StringIO() - - def tearDown(self): - asyncore.close_all() - asyncore.socket = smtpd.socket = socket - smtpd.DEBUGSTREAM = self.old_debugstream - - def write_line(self, channel, line): - channel.socket.queue_recv(line) - channel.handle_read() - - def test_params_rejected(self): - server = DummyServer((socket_helper.HOST, 0), ('b', 0)) - conn, addr = server.accept() - channel = smtpd.SMTPChannel(server, conn, addr) - self.write_line(channel, b'EHLO example') - self.write_line(channel, b'MAIL from: size=20') - self.write_line(channel, b'RCPT to: foo=bar') - self.assertEqual(channel.socket.last, self.error_response) - - def test_nothing_accepted(self): - server = DummyServer((socket_helper.HOST, 0), ('b', 0)) - conn, addr = server.accept() - channel = smtpd.SMTPChannel(server, conn, addr) - self.write_line(channel, b'EHLO example') - self.write_line(channel, b'MAIL from: size=20') - self.write_line(channel, b'RCPT to: ') - self.assertEqual(channel.socket.last, b'250 OK\r\n') - - -class TestMailOptionParsing(unittest.TestCase): - error_response = (b'555 MAIL FROM parameters not recognized or not ' - b'implemented\r\n') - - def setUp(self): - smtpd.socket = asyncore.socket = mock_socket - self.old_debugstream = smtpd.DEBUGSTREAM - self.debug = smtpd.DEBUGSTREAM = io.StringIO() - - def tearDown(self): - asyncore.close_all() - asyncore.socket = smtpd.socket = socket - smtpd.DEBUGSTREAM = self.old_debugstream - - def write_line(self, channel, line): - channel.socket.queue_recv(line) - channel.handle_read() - - def test_with_decode_data_true(self): - server = DummyServer((socket_helper.HOST, 0), ('b', 0), decode_data=True) - conn, addr = server.accept() - channel = smtpd.SMTPChannel(server, conn, addr, decode_data=True) - self.write_line(channel, b'EHLO example') - for line in [ - b'MAIL from: size=20 SMTPUTF8', - b'MAIL from: size=20 SMTPUTF8 BODY=8BITMIME', - b'MAIL from: size=20 BODY=UNKNOWN', - b'MAIL from: size=20 body=8bitmime', - ]: - self.write_line(channel, line) - self.assertEqual(channel.socket.last, self.error_response) - self.write_line(channel, b'MAIL from: size=20') - self.assertEqual(channel.socket.last, b'250 OK\r\n') - - def test_with_decode_data_false(self): - server = DummyServer((socket_helper.HOST, 0), ('b', 0)) - conn, addr = server.accept() - channel = smtpd.SMTPChannel(server, conn, addr) - self.write_line(channel, b'EHLO example') - for line in [ - b'MAIL from: size=20 SMTPUTF8', - b'MAIL from: size=20 SMTPUTF8 BODY=8BITMIME', - ]: - self.write_line(channel, line) - self.assertEqual(channel.socket.last, self.error_response) - self.write_line( - channel, - b'MAIL from: size=20 SMTPUTF8 BODY=UNKNOWN') - self.assertEqual( - channel.socket.last, - b'501 Error: BODY can only be one of 7BIT, 8BITMIME\r\n') - self.write_line( - channel, b'MAIL from: size=20 body=8bitmime') - self.assertEqual(channel.socket.last, b'250 OK\r\n') - - def test_with_enable_smtputf8_true(self): - server = DummyServer((socket_helper.HOST, 0), ('b', 0), enable_SMTPUTF8=True) - conn, addr = server.accept() - channel = smtpd.SMTPChannel(server, conn, addr, enable_SMTPUTF8=True) - self.write_line(channel, b'EHLO example') - self.write_line( - channel, - b'MAIL from: size=20 body=8bitmime smtputf8') - self.assertEqual(channel.socket.last, b'250 OK\r\n') - - -class SMTPDChannelTest(unittest.TestCase): - def setUp(self): - smtpd.socket = asyncore.socket = mock_socket - self.old_debugstream = smtpd.DEBUGSTREAM - self.debug = smtpd.DEBUGSTREAM = io.StringIO() - self.server = DummyServer((socket_helper.HOST, 0), ('b', 0), - decode_data=True) - conn, addr = self.server.accept() - self.channel = smtpd.SMTPChannel(self.server, conn, addr, - decode_data=True) - - def tearDown(self): - asyncore.close_all() - asyncore.socket = smtpd.socket = socket - smtpd.DEBUGSTREAM = self.old_debugstream - - def write_line(self, line): - self.channel.socket.queue_recv(line) - self.channel.handle_read() - - def test_broken_connect(self): - self.assertRaises( - DummyDispatcherBroken, BrokenDummyServer, - (socket_helper.HOST, 0), ('b', 0), decode_data=True) - - def test_decode_data_and_enable_SMTPUTF8_raises(self): - self.assertRaises( - ValueError, smtpd.SMTPChannel, - self.server, self.channel.conn, self.channel.addr, - enable_SMTPUTF8=True, decode_data=True) - - def test_server_accept(self): - self.server.handle_accept() - - def test_missing_data(self): - self.write_line(b'') - self.assertEqual(self.channel.socket.last, - b'500 Error: bad syntax\r\n') - - def test_EHLO(self): - self.write_line(b'EHLO example') - self.assertEqual(self.channel.socket.last, b'250 HELP\r\n') - - def test_EHLO_bad_syntax(self): - self.write_line(b'EHLO') - self.assertEqual(self.channel.socket.last, - b'501 Syntax: EHLO hostname\r\n') - - def test_EHLO_duplicate(self): - self.write_line(b'EHLO example') - self.write_line(b'EHLO example') - self.assertEqual(self.channel.socket.last, - b'503 Duplicate HELO/EHLO\r\n') - - def test_EHLO_HELO_duplicate(self): - self.write_line(b'EHLO example') - self.write_line(b'HELO example') - self.assertEqual(self.channel.socket.last, - b'503 Duplicate HELO/EHLO\r\n') - - def test_HELO(self): - name = smtpd.socket.getfqdn() - self.write_line(b'HELO example') - self.assertEqual(self.channel.socket.last, - '250 {}\r\n'.format(name).encode('ascii')) - - def test_HELO_EHLO_duplicate(self): - self.write_line(b'HELO example') - self.write_line(b'EHLO example') - self.assertEqual(self.channel.socket.last, - b'503 Duplicate HELO/EHLO\r\n') - - def test_HELP(self): - self.write_line(b'HELP') - self.assertEqual(self.channel.socket.last, - b'250 Supported commands: EHLO HELO MAIL RCPT ' + \ - b'DATA RSET NOOP QUIT VRFY\r\n') - - def test_HELP_command(self): - self.write_line(b'HELP MAIL') - self.assertEqual(self.channel.socket.last, - b'250 Syntax: MAIL FROM:
\r\n') - - def test_HELP_command_unknown(self): - self.write_line(b'HELP SPAM') - self.assertEqual(self.channel.socket.last, - b'501 Supported commands: EHLO HELO MAIL RCPT ' + \ - b'DATA RSET NOOP QUIT VRFY\r\n') - - def test_HELO_bad_syntax(self): - self.write_line(b'HELO') - self.assertEqual(self.channel.socket.last, - b'501 Syntax: HELO hostname\r\n') - - def test_HELO_duplicate(self): - self.write_line(b'HELO example') - self.write_line(b'HELO example') - self.assertEqual(self.channel.socket.last, - b'503 Duplicate HELO/EHLO\r\n') - - def test_HELO_parameter_rejected_when_extensions_not_enabled(self): - self.extended_smtp = False - self.write_line(b'HELO example') - self.write_line(b'MAIL from: SIZE=1234') - self.assertEqual(self.channel.socket.last, - b'501 Syntax: MAIL FROM:
\r\n') - - def test_MAIL_allows_space_after_colon(self): - self.write_line(b'HELO example') - self.write_line(b'MAIL from: ') - self.assertEqual(self.channel.socket.last, - b'250 OK\r\n') - - def test_extended_MAIL_allows_space_after_colon(self): - self.write_line(b'EHLO example') - self.write_line(b'MAIL from: size=20') - self.assertEqual(self.channel.socket.last, - b'250 OK\r\n') - - def test_NOOP(self): - self.write_line(b'NOOP') - self.assertEqual(self.channel.socket.last, b'250 OK\r\n') - - def test_HELO_NOOP(self): - self.write_line(b'HELO example') - self.write_line(b'NOOP') - self.assertEqual(self.channel.socket.last, b'250 OK\r\n') - - def test_NOOP_bad_syntax(self): - self.write_line(b'NOOP hi') - self.assertEqual(self.channel.socket.last, - b'501 Syntax: NOOP\r\n') - - def test_QUIT(self): - self.write_line(b'QUIT') - self.assertEqual(self.channel.socket.last, b'221 Bye\r\n') - - def test_HELO_QUIT(self): - self.write_line(b'HELO example') - self.write_line(b'QUIT') - self.assertEqual(self.channel.socket.last, b'221 Bye\r\n') - - def test_QUIT_arg_ignored(self): - self.write_line(b'QUIT bye bye') - self.assertEqual(self.channel.socket.last, b'221 Bye\r\n') - - def test_bad_state(self): - self.channel.smtp_state = 'BAD STATE' - self.write_line(b'HELO example') - self.assertEqual(self.channel.socket.last, - b'451 Internal confusion\r\n') - - def test_command_too_long(self): - self.write_line(b'HELO example') - self.write_line(b'MAIL from: ' + - b'a' * self.channel.command_size_limit + - b'@example') - self.assertEqual(self.channel.socket.last, - b'500 Error: line too long\r\n') - - def test_MAIL_command_limit_extended_with_SIZE(self): - self.write_line(b'EHLO example') - fill_len = self.channel.command_size_limit - len('MAIL from:<@example>') - self.write_line(b'MAIL from:<' + - b'a' * fill_len + - b'@example> SIZE=1234') - self.assertEqual(self.channel.socket.last, b'250 OK\r\n') - - self.write_line(b'MAIL from:<' + - b'a' * (fill_len + 26) + - b'@example> SIZE=1234') - self.assertEqual(self.channel.socket.last, - b'500 Error: line too long\r\n') - - def test_MAIL_command_rejects_SMTPUTF8_by_default(self): - self.write_line(b'EHLO example') - self.write_line( - b'MAIL from: BODY=8BITMIME SMTPUTF8') - self.assertEqual(self.channel.socket.last[0:1], b'5') - - def test_data_longer_than_default_data_size_limit(self): - # Hack the default so we don't have to generate so much data. - self.channel.data_size_limit = 1048 - self.write_line(b'HELO example') - self.write_line(b'MAIL From:eggs at example') - self.write_line(b'RCPT To:spam at example') - self.write_line(b'DATA') - self.write_line(b'A' * self.channel.data_size_limit + - b'A\r\n.') - self.assertEqual(self.channel.socket.last, - b'552 Error: Too much mail data\r\n') - - def test_MAIL_size_parameter(self): - self.write_line(b'EHLO example') - self.write_line(b'MAIL FROM: SIZE=512') - self.assertEqual(self.channel.socket.last, - b'250 OK\r\n') - - def test_MAIL_invalid_size_parameter(self): - self.write_line(b'EHLO example') - self.write_line(b'MAIL FROM: SIZE=invalid') - self.assertEqual(self.channel.socket.last, - b'501 Syntax: MAIL FROM:
[SP ]\r\n') - - def test_MAIL_RCPT_unknown_parameters(self): - self.write_line(b'EHLO example') - self.write_line(b'MAIL FROM: ham=green') - self.assertEqual(self.channel.socket.last, - b'555 MAIL FROM parameters not recognized or not implemented\r\n') - - self.write_line(b'MAIL FROM:') - self.write_line(b'RCPT TO: ham=green') - self.assertEqual(self.channel.socket.last, - b'555 RCPT TO parameters not recognized or not implemented\r\n') - - def test_MAIL_size_parameter_larger_than_default_data_size_limit(self): - self.channel.data_size_limit = 1048 - self.write_line(b'EHLO example') - self.write_line(b'MAIL FROM: SIZE=2096') - self.assertEqual(self.channel.socket.last, - b'552 Error: message size exceeds fixed maximum message size\r\n') - - def test_need_MAIL(self): - self.write_line(b'HELO example') - self.write_line(b'RCPT to:spam at example') - self.assertEqual(self.channel.socket.last, - b'503 Error: need MAIL command\r\n') - - def test_MAIL_syntax_HELO(self): - self.write_line(b'HELO example') - self.write_line(b'MAIL from eggs at example') - self.assertEqual(self.channel.socket.last, - b'501 Syntax: MAIL FROM:
\r\n') - - def test_MAIL_syntax_EHLO(self): - self.write_line(b'EHLO example') - self.write_line(b'MAIL from eggs at example') - self.assertEqual(self.channel.socket.last, - b'501 Syntax: MAIL FROM:
[SP ]\r\n') - - def test_MAIL_missing_address(self): - self.write_line(b'HELO example') - self.write_line(b'MAIL from:') - self.assertEqual(self.channel.socket.last, - b'501 Syntax: MAIL FROM:
\r\n') - - def test_MAIL_chevrons(self): - self.write_line(b'HELO example') - self.write_line(b'MAIL from:') - self.assertEqual(self.channel.socket.last, b'250 OK\r\n') - - def test_MAIL_empty_chevrons(self): - self.write_line(b'EHLO example') - self.write_line(b'MAIL from:<>') - self.assertEqual(self.channel.socket.last, b'250 OK\r\n') - - def test_MAIL_quoted_localpart(self): - self.write_line(b'EHLO example') - self.write_line(b'MAIL from: <"Fred Blogs"@example.com>') - self.assertEqual(self.channel.socket.last, b'250 OK\r\n') - self.assertEqual(self.channel.mailfrom, '"Fred Blogs"@example.com') - - def test_MAIL_quoted_localpart_no_angles(self): - self.write_line(b'EHLO example') - self.write_line(b'MAIL from: "Fred Blogs"@example.com') - self.assertEqual(self.channel.socket.last, b'250 OK\r\n') - self.assertEqual(self.channel.mailfrom, '"Fred Blogs"@example.com') - - def test_MAIL_quoted_localpart_with_size(self): - self.write_line(b'EHLO example') - self.write_line(b'MAIL from: <"Fred Blogs"@example.com> SIZE=1000') - self.assertEqual(self.channel.socket.last, b'250 OK\r\n') - self.assertEqual(self.channel.mailfrom, '"Fred Blogs"@example.com') - - def test_MAIL_quoted_localpart_with_size_no_angles(self): - self.write_line(b'EHLO example') - self.write_line(b'MAIL from: "Fred Blogs"@example.com SIZE=1000') - self.assertEqual(self.channel.socket.last, b'250 OK\r\n') - self.assertEqual(self.channel.mailfrom, '"Fred Blogs"@example.com') - - def test_nested_MAIL(self): - self.write_line(b'HELO example') - self.write_line(b'MAIL from:eggs at example') - self.write_line(b'MAIL from:spam at example') - self.assertEqual(self.channel.socket.last, - b'503 Error: nested MAIL command\r\n') - - def test_VRFY(self): - self.write_line(b'VRFY eggs at example') - self.assertEqual(self.channel.socket.last, - b'252 Cannot VRFY user, but will accept message and attempt ' + \ - b'delivery\r\n') - - def test_VRFY_syntax(self): - self.write_line(b'VRFY') - self.assertEqual(self.channel.socket.last, - b'501 Syntax: VRFY
\r\n') - - def test_EXPN_not_implemented(self): - self.write_line(b'EXPN') - self.assertEqual(self.channel.socket.last, - b'502 EXPN not implemented\r\n') - - def test_no_HELO_MAIL(self): - self.write_line(b'MAIL from:') - self.assertEqual(self.channel.socket.last, - b'503 Error: send HELO first\r\n') - - def test_need_RCPT(self): - self.write_line(b'HELO example') - self.write_line(b'MAIL From:eggs at example') - self.write_line(b'DATA') - self.assertEqual(self.channel.socket.last, - b'503 Error: need RCPT command\r\n') - - def test_RCPT_syntax_HELO(self): - self.write_line(b'HELO example') - self.write_line(b'MAIL From: eggs at example') - self.write_line(b'RCPT to eggs at example') - self.assertEqual(self.channel.socket.last, - b'501 Syntax: RCPT TO:
\r\n') - - def test_RCPT_syntax_EHLO(self): - self.write_line(b'EHLO example') - self.write_line(b'MAIL From: eggs at example') - self.write_line(b'RCPT to eggs at example') - self.assertEqual(self.channel.socket.last, - b'501 Syntax: RCPT TO:
[SP ]\r\n') - - def test_RCPT_lowercase_to_OK(self): - self.write_line(b'HELO example') - self.write_line(b'MAIL From: eggs at example') - self.write_line(b'RCPT to: ') - self.assertEqual(self.channel.socket.last, b'250 OK\r\n') - - def test_no_HELO_RCPT(self): - self.write_line(b'RCPT to eggs at example') - self.assertEqual(self.channel.socket.last, - b'503 Error: send HELO first\r\n') - - def test_data_dialog(self): - self.write_line(b'HELO example') - self.write_line(b'MAIL From:eggs at example') - self.assertEqual(self.channel.socket.last, b'250 OK\r\n') - self.write_line(b'RCPT To:spam at example') - self.assertEqual(self.channel.socket.last, b'250 OK\r\n') - - self.write_line(b'DATA') - self.assertEqual(self.channel.socket.last, - b'354 End data with .\r\n') - self.write_line(b'data\r\nmore\r\n.') - self.assertEqual(self.channel.socket.last, b'250 OK\r\n') - self.assertEqual(self.server.messages, - [(('peer-address', 'peer-port'), - 'eggs at example', - ['spam at example'], - 'data\nmore')]) - - def test_DATA_syntax(self): - self.write_line(b'HELO example') - self.write_line(b'MAIL From:eggs at example') - self.write_line(b'RCPT To:spam at example') - self.write_line(b'DATA spam') - self.assertEqual(self.channel.socket.last, b'501 Syntax: DATA\r\n') - - def test_no_HELO_DATA(self): - self.write_line(b'DATA spam') - self.assertEqual(self.channel.socket.last, - b'503 Error: send HELO first\r\n') - - def test_data_transparency_section_4_5_2(self): - self.write_line(b'HELO example') - self.write_line(b'MAIL From:eggs at example') - self.write_line(b'RCPT To:spam at example') - self.write_line(b'DATA') - self.write_line(b'..\r\n.\r\n') - self.assertEqual(self.channel.received_data, '.') - - def test_multiple_RCPT(self): - self.write_line(b'HELO example') - self.write_line(b'MAIL From:eggs at example') - self.write_line(b'RCPT To:spam at example') - self.write_line(b'RCPT To:ham at example') - self.write_line(b'DATA') - self.write_line(b'data\r\n.') - self.assertEqual(self.server.messages, - [(('peer-address', 'peer-port'), - 'eggs at example', - ['spam at example','ham at example'], - 'data')]) - - def test_manual_status(self): - # checks that the Channel is able to return a custom status message - self.write_line(b'HELO example') - self.write_line(b'MAIL From:eggs at example') - self.write_line(b'RCPT To:spam at example') - self.write_line(b'DATA') - self.write_line(b'return status\r\n.') - self.assertEqual(self.channel.socket.last, b'250 Okish\r\n') - - def test_RSET(self): - self.write_line(b'HELO example') - self.write_line(b'MAIL From:eggs at example') - self.write_line(b'RCPT To:spam at example') - self.write_line(b'RSET') - self.assertEqual(self.channel.socket.last, b'250 OK\r\n') - self.write_line(b'MAIL From:foo at example') - self.write_line(b'RCPT To:eggs at example') - self.write_line(b'DATA') - self.write_line(b'data\r\n.') - self.assertEqual(self.server.messages, - [(('peer-address', 'peer-port'), - 'foo at example', - ['eggs at example'], - 'data')]) - - def test_HELO_RSET(self): - self.write_line(b'HELO example') - self.write_line(b'RSET') - self.assertEqual(self.channel.socket.last, b'250 OK\r\n') - - def test_RSET_syntax(self): - self.write_line(b'RSET hi') - self.assertEqual(self.channel.socket.last, b'501 Syntax: RSET\r\n') - - def test_unknown_command(self): - self.write_line(b'UNKNOWN_CMD') - self.assertEqual(self.channel.socket.last, - b'500 Error: command "UNKNOWN_CMD" not ' + \ - b'recognized\r\n') - - def test_attribute_deprecations(self): - with warnings_helper.check_warnings(('', DeprecationWarning)): - spam = self.channel._SMTPChannel__server - with warnings_helper.check_warnings(('', DeprecationWarning)): - self.channel._SMTPChannel__server = 'spam' - with warnings_helper.check_warnings(('', DeprecationWarning)): - spam = self.channel._SMTPChannel__line - with warnings_helper.check_warnings(('', DeprecationWarning)): - self.channel._SMTPChannel__line = 'spam' - with warnings_helper.check_warnings(('', DeprecationWarning)): - spam = self.channel._SMTPChannel__state - with warnings_helper.check_warnings(('', DeprecationWarning)): - self.channel._SMTPChannel__state = 'spam' - with warnings_helper.check_warnings(('', DeprecationWarning)): - spam = self.channel._SMTPChannel__greeting - with warnings_helper.check_warnings(('', DeprecationWarning)): - self.channel._SMTPChannel__greeting = 'spam' - with warnings_helper.check_warnings(('', DeprecationWarning)): - spam = self.channel._SMTPChannel__mailfrom - with warnings_helper.check_warnings(('', DeprecationWarning)): - self.channel._SMTPChannel__mailfrom = 'spam' - with warnings_helper.check_warnings(('', DeprecationWarning)): - spam = self.channel._SMTPChannel__rcpttos - with warnings_helper.check_warnings(('', DeprecationWarning)): - self.channel._SMTPChannel__rcpttos = 'spam' - with warnings_helper.check_warnings(('', DeprecationWarning)): - spam = self.channel._SMTPChannel__data - with warnings_helper.check_warnings(('', DeprecationWarning)): - self.channel._SMTPChannel__data = 'spam' - with warnings_helper.check_warnings(('', DeprecationWarning)): - spam = self.channel._SMTPChannel__fqdn - with warnings_helper.check_warnings(('', DeprecationWarning)): - self.channel._SMTPChannel__fqdn = 'spam' - with warnings_helper.check_warnings(('', DeprecationWarning)): - spam = self.channel._SMTPChannel__peer - with warnings_helper.check_warnings(('', DeprecationWarning)): - self.channel._SMTPChannel__peer = 'spam' - with warnings_helper.check_warnings(('', DeprecationWarning)): - spam = self.channel._SMTPChannel__conn - with warnings_helper.check_warnings(('', DeprecationWarning)): - self.channel._SMTPChannel__conn = 'spam' - with warnings_helper.check_warnings(('', DeprecationWarning)): - spam = self.channel._SMTPChannel__addr - with warnings_helper.check_warnings(('', DeprecationWarning)): - self.channel._SMTPChannel__addr = 'spam' - - at unittest.skipUnless(socket_helper.IPV6_ENABLED, "IPv6 not enabled") -class SMTPDChannelIPv6Test(SMTPDChannelTest): - def setUp(self): - smtpd.socket = asyncore.socket = mock_socket - self.old_debugstream = smtpd.DEBUGSTREAM - self.debug = smtpd.DEBUGSTREAM = io.StringIO() - self.server = DummyServer((socket_helper.HOSTv6, 0), ('b', 0), - decode_data=True) - conn, addr = self.server.accept() - self.channel = smtpd.SMTPChannel(self.server, conn, addr, - decode_data=True) - -class SMTPDChannelWithDataSizeLimitTest(unittest.TestCase): - - def setUp(self): - smtpd.socket = asyncore.socket = mock_socket - self.old_debugstream = smtpd.DEBUGSTREAM - self.debug = smtpd.DEBUGSTREAM = io.StringIO() - self.server = DummyServer((socket_helper.HOST, 0), ('b', 0), - decode_data=True) - conn, addr = self.server.accept() - # Set DATA size limit to 32 bytes for easy testing - self.channel = smtpd.SMTPChannel(self.server, conn, addr, 32, - decode_data=True) - - def tearDown(self): - asyncore.close_all() - asyncore.socket = smtpd.socket = socket - smtpd.DEBUGSTREAM = self.old_debugstream - - def write_line(self, line): - self.channel.socket.queue_recv(line) - self.channel.handle_read() - - def test_data_limit_dialog(self): - self.write_line(b'HELO example') - self.write_line(b'MAIL From:eggs at example') - self.assertEqual(self.channel.socket.last, b'250 OK\r\n') - self.write_line(b'RCPT To:spam at example') - self.assertEqual(self.channel.socket.last, b'250 OK\r\n') - - self.write_line(b'DATA') - self.assertEqual(self.channel.socket.last, - b'354 End data with .\r\n') - self.write_line(b'data\r\nmore\r\n.') - self.assertEqual(self.channel.socket.last, b'250 OK\r\n') - self.assertEqual(self.server.messages, - [(('peer-address', 'peer-port'), - 'eggs at example', - ['spam at example'], - 'data\nmore')]) - - def test_data_limit_dialog_too_much_data(self): - self.write_line(b'HELO example') - self.write_line(b'MAIL From:eggs at example') - self.assertEqual(self.channel.socket.last, b'250 OK\r\n') - self.write_line(b'RCPT To:spam at example') - self.assertEqual(self.channel.socket.last, b'250 OK\r\n') - - self.write_line(b'DATA') - self.assertEqual(self.channel.socket.last, - b'354 End data with .\r\n') - self.write_line(b'This message is longer than 32 bytes\r\n.') - self.assertEqual(self.channel.socket.last, - b'552 Error: Too much mail data\r\n') - - -class SMTPDChannelWithDecodeDataFalse(unittest.TestCase): - - def setUp(self): - smtpd.socket = asyncore.socket = mock_socket - self.old_debugstream = smtpd.DEBUGSTREAM - self.debug = smtpd.DEBUGSTREAM = io.StringIO() - self.server = DummyServer((socket_helper.HOST, 0), ('b', 0)) - conn, addr = self.server.accept() - self.channel = smtpd.SMTPChannel(self.server, conn, addr) - - def tearDown(self): - asyncore.close_all() - asyncore.socket = smtpd.socket = socket - smtpd.DEBUGSTREAM = self.old_debugstream - - def write_line(self, line): - self.channel.socket.queue_recv(line) - self.channel.handle_read() - - def test_ascii_data(self): - self.write_line(b'HELO example') - self.write_line(b'MAIL From:eggs at example') - self.write_line(b'RCPT To:spam at example') - self.write_line(b'DATA') - self.write_line(b'plain ascii text') - self.write_line(b'.') - self.assertEqual(self.channel.received_data, b'plain ascii text') - - def test_utf8_data(self): - self.write_line(b'HELO example') - self.write_line(b'MAIL From:eggs at example') - self.write_line(b'RCPT To:spam at example') - self.write_line(b'DATA') - self.write_line(b'utf8 enriched text: \xc5\xbc\xc5\xba\xc4\x87') - self.write_line(b'and some plain ascii') - self.write_line(b'.') - self.assertEqual( - self.channel.received_data, - b'utf8 enriched text: \xc5\xbc\xc5\xba\xc4\x87\n' - b'and some plain ascii') - - -class SMTPDChannelWithDecodeDataTrue(unittest.TestCase): - - def setUp(self): - smtpd.socket = asyncore.socket = mock_socket - self.old_debugstream = smtpd.DEBUGSTREAM - self.debug = smtpd.DEBUGSTREAM = io.StringIO() - self.server = DummyServer((socket_helper.HOST, 0), ('b', 0), - decode_data=True) - conn, addr = self.server.accept() - # Set decode_data to True - self.channel = smtpd.SMTPChannel(self.server, conn, addr, - decode_data=True) - - def tearDown(self): - asyncore.close_all() - asyncore.socket = smtpd.socket = socket - smtpd.DEBUGSTREAM = self.old_debugstream - - def write_line(self, line): - self.channel.socket.queue_recv(line) - self.channel.handle_read() - - def test_ascii_data(self): - self.write_line(b'HELO example') - self.write_line(b'MAIL From:eggs at example') - self.write_line(b'RCPT To:spam at example') - self.write_line(b'DATA') - self.write_line(b'plain ascii text') - self.write_line(b'.') - self.assertEqual(self.channel.received_data, 'plain ascii text') - - def test_utf8_data(self): - self.write_line(b'HELO example') - self.write_line(b'MAIL From:eggs at example') - self.write_line(b'RCPT To:spam at example') - self.write_line(b'DATA') - self.write_line(b'utf8 enriched text: \xc5\xbc\xc5\xba\xc4\x87') - self.write_line(b'and some plain ascii') - self.write_line(b'.') - self.assertEqual( - self.channel.received_data, - 'utf8 enriched text: ???\nand some plain ascii') - - -class SMTPDChannelTestWithEnableSMTPUTF8True(unittest.TestCase): - def setUp(self): - smtpd.socket = asyncore.socket = mock_socket - self.old_debugstream = smtpd.DEBUGSTREAM - self.debug = smtpd.DEBUGSTREAM = io.StringIO() - self.server = DummyServer((socket_helper.HOST, 0), ('b', 0), - enable_SMTPUTF8=True) - conn, addr = self.server.accept() - self.channel = smtpd.SMTPChannel(self.server, conn, addr, - enable_SMTPUTF8=True) - - def tearDown(self): - asyncore.close_all() - asyncore.socket = smtpd.socket = socket - smtpd.DEBUGSTREAM = self.old_debugstream - - def write_line(self, line): - self.channel.socket.queue_recv(line) - self.channel.handle_read() - - def test_MAIL_command_accepts_SMTPUTF8_when_announced(self): - self.write_line(b'EHLO example') - self.write_line( - 'MAIL from: BODY=8BITMIME SMTPUTF8'.encode( - 'utf-8') - ) - self.assertEqual(self.channel.socket.last, b'250 OK\r\n') - - def test_process_smtputf8_message(self): - self.write_line(b'EHLO example') - for mail_parameters in [b'', b'BODY=8BITMIME SMTPUTF8']: - self.write_line(b'MAIL from: ' + mail_parameters) - self.assertEqual(self.channel.socket.last[0:3], b'250') - self.write_line(b'rcpt to:') - self.assertEqual(self.channel.socket.last[0:3], b'250') - self.write_line(b'data') - self.assertEqual(self.channel.socket.last[0:3], b'354') - self.write_line(b'c\r\n.') - if mail_parameters == b'': - self.assertEqual(self.channel.socket.last, b'250 OK\r\n') - else: - self.assertEqual(self.channel.socket.last, - b'250 SMTPUTF8 message okish\r\n') - - def test_utf8_data(self): - self.write_line(b'EHLO example') - self.write_line( - 'MAIL From: nai?ve at exampl? BODY=8BITMIME SMTPUTF8'.encode('utf-8')) - self.assertEqual(self.channel.socket.last[0:3], b'250') - self.write_line('RCPT To:sp?m at exampl?'.encode('utf-8')) - self.assertEqual(self.channel.socket.last[0:3], b'250') - self.write_line(b'DATA') - self.assertEqual(self.channel.socket.last[0:3], b'354') - self.write_line(b'utf8 enriched text: \xc5\xbc\xc5\xba\xc4\x87') - self.write_line(b'.') - self.assertEqual( - self.channel.received_data, - b'utf8 enriched text: \xc5\xbc\xc5\xba\xc4\x87') - - def test_MAIL_command_limit_extended_with_SIZE_and_SMTPUTF8(self): - self.write_line(b'ehlo example') - fill_len = (512 + 26 + 10) - len('mail from:<@example>') - self.write_line(b'MAIL from:<' + - b'a' * (fill_len + 1) + - b'@example>') - self.assertEqual(self.channel.socket.last, - b'500 Error: line too long\r\n') - self.write_line(b'MAIL from:<' + - b'a' * fill_len + - b'@example>') - self.assertEqual(self.channel.socket.last, b'250 OK\r\n') - - def test_multiple_emails_with_extended_command_length(self): - self.write_line(b'ehlo example') - fill_len = (512 + 26 + 10) - len('mail from:<@example>') - for char in [b'a', b'b', b'c']: - self.write_line(b'MAIL from:<' + char * fill_len + b'a at example>') - self.assertEqual(self.channel.socket.last[0:3], b'500') - self.write_line(b'MAIL from:<' + char * fill_len + b'@example>') - self.assertEqual(self.channel.socket.last[0:3], b'250') - self.write_line(b'rcpt to:') - self.assertEqual(self.channel.socket.last[0:3], b'250') - self.write_line(b'data') - self.assertEqual(self.channel.socket.last[0:3], b'354') - self.write_line(b'test\r\n.') - self.assertEqual(self.channel.socket.last[0:3], b'250') - - -class MiscTestCase(unittest.TestCase): - def test__all__(self): - not_exported = { - "program", "Devnull", "DEBUGSTREAM", "NEWLINE", "COMMASPACE", - "DATA_SIZE_DEFAULT", "usage", "Options", "parseargs", - } - support.check__all__(self, smtpd, not_exported=not_exported) - - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py index 9761a37251731..bdce3e37095e4 100644 --- a/Lib/test/test_smtplib.py +++ b/Lib/test/test_smtplib.py @@ -18,17 +18,13 @@ import unittest from test import support, mock_socket +from test.support import _asyncore as asyncore +from test.support import _smtpd as smtpd from test.support import hashlib_helper from test.support import socket_helper from test.support import threading_helper from unittest.mock import Mock -import warnings -with warnings.catch_warnings(): - warnings.simplefilter('ignore', DeprecationWarning) - import asyncore - import smtpd - HOST = socket_helper.HOST if sys.platform == 'darwin': diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 981e2fe82ee46..88eeb07afa036 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -4,6 +4,7 @@ import unittest import unittest.mock from test import support +from test.support import _asyncore as asyncore from test.support import import_helper from test.support import os_helper from test.support import socket_helper @@ -30,10 +31,6 @@ except ImportError: ctypes = None -import warnings -with warnings.catch_warnings(): - warnings.simplefilter('ignore', DeprecationWarning) - import asyncore ssl = import_helper.import_module("ssl") import _ssl diff --git a/Misc/NEWS.d/next/Library/2021-11-11-12-59-10.bpo-28533.68mMZa.rst b/Misc/NEWS.d/next/Library/2021-11-11-12-59-10.bpo-28533.68mMZa.rst new file mode 100644 index 0000000000000..49243815e31f2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-11-12-59-10.bpo-28533.68mMZa.rst @@ -0,0 +1,2 @@ +Remove the ``asyncore`` and ``asynchat`` modules, deprecated in Python 3.6: +use the :mod:`asyncio` module instead. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2021-11-11-12-59-49.bpo-28533.LvIFCQ.rst b/Misc/NEWS.d/next/Library/2021-11-11-12-59-49.bpo-28533.LvIFCQ.rst new file mode 100644 index 0000000000000..67fb3686b1d86 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-11-12-59-49.bpo-28533.LvIFCQ.rst @@ -0,0 +1,3 @@ +Remove the ``smtpd`` module, deprecated in Python 3.6: the `aiosmtpd +`__ module can be used instead, it is based +on asyncio. Patch by Victor Stinner. diff --git a/PCbuild/lib.pyproj b/PCbuild/lib.pyproj index 43c570f1dab37..7dd40ad64a7e3 100644 --- a/PCbuild/lib.pyproj +++ b/PCbuild/lib.pyproj @@ -24,7 +24,6 @@ - @@ -50,7 +49,6 @@ - @@ -722,7 +720,6 @@ - @@ -860,7 +857,6 @@ - @@ -882,7 +878,6 @@ - @@ -1263,7 +1258,6 @@ - diff --git a/Python/stdlib_module_names.h b/Python/stdlib_module_names.h index 754fa94e35eba..7d421081b2ab8 100644 --- a/Python/stdlib_module_names.h +++ b/Python/stdlib_module_names.h @@ -96,9 +96,7 @@ static const char* _Py_stdlib_module_names[] = { "argparse", "array", "ast", -"asynchat", "asyncio", -"asyncore", "atexit", "audioop", "base64", @@ -242,7 +240,6 @@ static const char* _Py_stdlib_module_names[] = { "shutil", "signal", "site", -"smtpd", "smtplib", "sndhdr", "socket", From webhook-mailer at python.org Mon Nov 15 18:31:43 2021 From: webhook-mailer at python.org (willingc) Date: Mon, 15 Nov 2021 23:31:43 -0000 Subject: [Python-checkins] bpo-45677: Reword first section of `sqlite3` docs (GH-29326) (GH-29566) Message-ID: https://github.com/python/cpython/commit/94dad5e41e5863e03972f3f3646087fb591f73f9 commit: 94dad5e41e5863e03972f3f3646087fb591f73f9 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: willingc date: 2021-11-15T15:31:38-08:00 summary: bpo-45677: Reword first section of `sqlite3` docs (GH-29326) (GH-29566) * bpo-45677: Avoid addressing the reader as 'you' in sqlite3 docs * Adjust wording * Adjust wording again * Typo * Update Doc/library/sqlite3.rst Co-authored-by: Jacob Walls * Address review: adjust wording * Update Doc/library/sqlite3.rst Co-authored-by: Alex Waygood * Update Lib/sqlite3/__init__.py Co-authored-by: Alex Waygood * Update Doc/library/sqlite3.rst Co-authored-by: Alex Waygood * Update Doc/library/sqlite3.rst Co-authored-by: Alex Waygood * Update Lib/sqlite3/__init__.py Co-authored-by: Alex Waygood * Update Doc/library/sqlite3.rst Co-authored-by: Alex Waygood * Apply Alex' suggestion, and apply 80 char limit to PR * Minor adjustment Co-authored-by: Jacob Walls Co-authored-by: Alex Waygood (cherry picked from commit 6c5a312fb6d92e879bf4c570b94e18bb9ffe5970) Co-authored-by: Erlend Egeberg Aasland Co-authored-by: Erlend Egeberg Aasland files: M Doc/library/sqlite3.rst M Lib/sqlite3/__init__.py diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index 16d2c2e85f42b..f3964b9aa23ae 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -21,16 +21,17 @@ The sqlite3 module was written by Gerhard H?ring. It provides a SQL interface compliant with the DB-API 2.0 specification described by :pep:`249`, and requires SQLite 3.7.15 or newer. -To use the module, you must first create a :class:`Connection` object that +To use the module, start by creating a :class:`Connection` object that represents the database. Here the data will be stored in the :file:`example.db` file:: import sqlite3 con = sqlite3.connect('example.db') -You can also supply the special name ``:memory:`` to create a database in RAM. +The special path name ``:memory:`` can be provided to create a temporary +database in RAM. -Once you have a :class:`Connection`, you can create a :class:`Cursor` object +Once a :class:`Connection` has been established, create a :class:`Cursor` object and call its :meth:`~Cursor.execute` method to perform SQL commands:: cur = con.cursor() @@ -49,16 +50,17 @@ and call its :meth:`~Cursor.execute` method to perform SQL commands:: # Just be sure any changes have been committed or they will be lost. con.close() -The data you've saved is persistent and is available in subsequent sessions:: +The saved data is persistent: it can be reloaded in a subsequent session even +after restarting the Python interpreter:: import sqlite3 con = sqlite3.connect('example.db') cur = con.cursor() -To retrieve data after executing a SELECT statement, you can either treat the -cursor as an :term:`iterator`, call the cursor's :meth:`~Cursor.fetchone` method to -retrieve a single matching row, or call :meth:`~Cursor.fetchall` to get a list of the -matching rows. +To retrieve data after executing a SELECT statement, either treat the cursor as +an :term:`iterator`, call the cursor's :meth:`~Cursor.fetchone` method to +retrieve a single matching row, or call :meth:`~Cursor.fetchall` to get a list +of the matching rows. This example uses the iterator form:: @@ -73,27 +75,27 @@ This example uses the iterator form:: .. _sqlite3-placeholders: -Usually your SQL operations will need to use values from Python variables. You -shouldn't assemble your query using Python's string operations because doing so -is insecure; it makes your program vulnerable to an SQL injection attack -(see the `xkcd webcomic `_ for a humorous example of -what can go wrong):: +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):: # Never do this -- insecure! symbol = 'RHAT' cur.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol) -Instead, use the DB-API's parameter substitution. Put a placeholder wherever -you want to use a value, and then provide a tuple of values as the second -argument to the cursor's :meth:`~Cursor.execute` method. An SQL statement may +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: +keys for all named parameters. Any extra items are ignored. Here's an example of +both styles: .. literalinclude:: ../includes/sqlite3/execute_1.py diff --git a/Lib/sqlite3/__init__.py b/Lib/sqlite3/__init__.py index edc58f15b25ce..0dedf186b1a1e 100644 --- a/Lib/sqlite3/__init__.py +++ b/Lib/sqlite3/__init__.py @@ -24,18 +24,18 @@ The sqlite3 extension module provides a DB-API 2.0 (PEP 249) compilant interface to the SQLite library, and requires SQLite 3.7.15 or newer. -To use the module, you must first create a database Connection object: +To use the module, start by creating a database Connection object: import sqlite3 cx = sqlite3.connect("test.db") # test.db will be created or opened -You can also use the special database name ":memory:" to connect to a transient +The special path name ":memory:" can be provided to connect to a transient in-memory database: cx = sqlite3.connect(":memory:") # connect to a database in RAM -Once you have a Connection object, you can create a Cursor object and call its -execute() method to perform SQL queries: +Once a connection has been established, create a Cursor object and call +its execute() method to perform SQL queries: cu = cx.cursor() From webhook-mailer at python.org Mon Nov 15 18:32:36 2021 From: webhook-mailer at python.org (willingc) Date: Mon, 15 Nov 2021 23:32:36 -0000 Subject: [Python-checkins] bpo-45677: Reword first section of `sqlite3` docs (GH-29326) (GH-29567) Message-ID: https://github.com/python/cpython/commit/a40d066e8ef548b52eca2b0e27c219ddd7e11592 commit: a40d066e8ef548b52eca2b0e27c219ddd7e11592 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: willingc date: 2021-11-15T15:32:31-08:00 summary: bpo-45677: Reword first section of `sqlite3` docs (GH-29326) (GH-29567) * bpo-45677: Avoid addressing the reader as 'you' in sqlite3 docs * Adjust wording * Adjust wording again * Typo * Update Doc/library/sqlite3.rst Co-authored-by: Jacob Walls * Address review: adjust wording * Update Doc/library/sqlite3.rst Co-authored-by: Alex Waygood * Update Lib/sqlite3/__init__.py Co-authored-by: Alex Waygood * Update Doc/library/sqlite3.rst Co-authored-by: Alex Waygood * Update Doc/library/sqlite3.rst Co-authored-by: Alex Waygood * Update Lib/sqlite3/__init__.py Co-authored-by: Alex Waygood * Update Doc/library/sqlite3.rst Co-authored-by: Alex Waygood * Apply Alex' suggestion, and apply 80 char limit to PR * Minor adjustment Co-authored-by: Jacob Walls Co-authored-by: Alex Waygood (cherry picked from commit 6c5a312fb6d92e879bf4c570b94e18bb9ffe5970) Co-authored-by: Erlend Egeberg Aasland Co-authored-by: Erlend Egeberg Aasland files: M Doc/library/sqlite3.rst M Lib/sqlite3/__init__.py diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index b24a2f0985489..3f4f8536c1c6b 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -20,16 +20,17 @@ PostgreSQL or Oracle. The sqlite3 module was written by Gerhard H?ring. It provides a SQL interface compliant with the DB-API 2.0 specification described by :pep:`249`. -To use the module, you must first create a :class:`Connection` object that +To use the module, start by creating a :class:`Connection` object that represents the database. Here the data will be stored in the :file:`example.db` file:: import sqlite3 con = sqlite3.connect('example.db') -You can also supply the special name ``:memory:`` to create a database in RAM. +The special path name ``:memory:`` can be provided to create a temporary +database in RAM. -Once you have a :class:`Connection`, you can create a :class:`Cursor` object +Once a :class:`Connection` has been established, create a :class:`Cursor` object and call its :meth:`~Cursor.execute` method to perform SQL commands:: cur = con.cursor() @@ -48,16 +49,17 @@ and call its :meth:`~Cursor.execute` method to perform SQL commands:: # Just be sure any changes have been committed or they will be lost. con.close() -The data you've saved is persistent and is available in subsequent sessions:: +The saved data is persistent: it can be reloaded in a subsequent session even +after restarting the Python interpreter:: import sqlite3 con = sqlite3.connect('example.db') cur = con.cursor() -To retrieve data after executing a SELECT statement, you can either treat the -cursor as an :term:`iterator`, call the cursor's :meth:`~Cursor.fetchone` method to -retrieve a single matching row, or call :meth:`~Cursor.fetchall` to get a list of the -matching rows. +To retrieve data after executing a SELECT statement, either treat the cursor as +an :term:`iterator`, call the cursor's :meth:`~Cursor.fetchone` method to +retrieve a single matching row, or call :meth:`~Cursor.fetchall` to get a list +of the matching rows. This example uses the iterator form:: @@ -72,27 +74,27 @@ This example uses the iterator form:: .. _sqlite3-placeholders: -Usually your SQL operations will need to use values from Python variables. You -shouldn't assemble your query using Python's string operations because doing so -is insecure; it makes your program vulnerable to an SQL injection attack -(see the `xkcd webcomic `_ for a humorous example of -what can go wrong):: +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):: # Never do this -- insecure! symbol = 'RHAT' cur.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol) -Instead, use the DB-API's parameter substitution. Put a placeholder wherever -you want to use a value, and then provide a tuple of values as the second -argument to the cursor's :meth:`~Cursor.execute` method. An SQL statement may +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: +keys for all named parameters. Any extra items are ignored. Here's an example of +both styles: .. literalinclude:: ../includes/sqlite3/execute_1.py diff --git a/Lib/sqlite3/__init__.py b/Lib/sqlite3/__init__.py index efdb7f2ba20f1..1e717450c29bf 100644 --- a/Lib/sqlite3/__init__.py +++ b/Lib/sqlite3/__init__.py @@ -24,18 +24,18 @@ The sqlite3 extension module provides a DB-API 2.0 (PEP 249) compilant interface to the SQLite library, and requires SQLite 3.7.15 or newer. -To use the module, you must first create a database Connection object: +To use the module, start by creating a database Connection object: import sqlite3 cx = sqlite3.connect("test.db") # test.db will be created or opened -You can also use the special database name ":memory:" to connect to a transient +The special path name ":memory:" can be provided to connect to a transient in-memory database: cx = sqlite3.connect(":memory:") # connect to a database in RAM -Once you have a Connection object, you can create a Cursor object and call its -execute() method to perform SQL queries: +Once a connection has been established, create a Cursor object and call +its execute() method to perform SQL queries: cu = cx.cursor() From webhook-mailer at python.org Mon Nov 15 22:11:19 2021 From: webhook-mailer at python.org (rhettinger) Date: Tue, 16 Nov 2021 03:11:19 -0000 Subject: [Python-checkins] ensure deprecation warning from assertDictContainsSubset points at actual test code (#26497) Message-ID: https://github.com/python/cpython/commit/7c99e434a9b3830698d52a62fe8641d480856ca9 commit: 7c99e434a9b3830698d52a62fe8641d480856ca9 branch: 3.10 author: Anthony Sottile committer: rhettinger date: 2021-11-15T21:11:02-06:00 summary: ensure deprecation warning from assertDictContainsSubset points at actual test code (#26497) files: A Misc/NEWS.d/next/Library/2021-06-02-16-39-42.bpo-44295.erg01m.rst M Lib/unittest/case.py M Lib/unittest/test/test_case.py diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py index 607c7aecc7003..61003d0c6ead9 100644 --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -1146,7 +1146,8 @@ def assertDictEqual(self, d1, d2, msg=None): def assertDictContainsSubset(self, subset, dictionary, msg=None): """Checks whether dictionary is a superset of subset.""" warnings.warn('assertDictContainsSubset is deprecated', - DeprecationWarning) + DeprecationWarning, + stacklevel=2) missing = [] mismatched = [] for key, value in subset.items(): diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py index 35334851304d8..442651e1e4884 100644 --- a/Lib/unittest/test/test_case.py +++ b/Lib/unittest/test/test_case.py @@ -706,6 +706,10 @@ def testAssertDictContainsSubset(self): with self.assertRaises(self.failureException): self.assertDictContainsSubset({'foo': one}, {'foo': '\uFFFD'}) + with self.assertWarns(DeprecationWarning) as warninfo: + self.assertDictContainsSubset({}, {}) + self.assertEqual(warninfo.warnings[0].filename, __file__) + def testAssertEqual(self): equal_pairs = [ ((), ()), diff --git a/Misc/NEWS.d/next/Library/2021-06-02-16-39-42.bpo-44295.erg01m.rst b/Misc/NEWS.d/next/Library/2021-06-02-16-39-42.bpo-44295.erg01m.rst new file mode 100644 index 0000000000000..86501c15d86f4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-06-02-16-39-42.bpo-44295.erg01m.rst @@ -0,0 +1,2 @@ +Ensure deprecation warning from :func:`assertDictContainsSubset` points at +calling code - by Anthony Sottile. From webhook-mailer at python.org Tue Nov 16 04:57:22 2021 From: webhook-mailer at python.org (ambv) Date: Tue, 16 Nov 2021 09:57:22 -0000 Subject: [Python-checkins] bpo-45792: Fix contextvar.Token's intersphinx FQN (GH-29533) (GH-29537) Message-ID: https://github.com/python/cpython/commit/c37a0d9c0ae4aa0d9135fac9a58afc7b34ff71d6 commit: c37a0d9c0ae4aa0d9135fac9a58afc7b34ff71d6 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-16T10:56:56+01:00 summary: bpo-45792: Fix contextvar.Token's intersphinx FQN (GH-29533) (GH-29537) Since `.. module:: contextvars` sets the module using `.. class:: contextvars.Token`, intersphinx records it as `contextvars.contextvars.Token`. (cherry picked from commit e501d70b347c5093018d12482c30a7a98aab86d0) Co-authored-by: Hynek Schlawack files: M Doc/library/contextvars.rst diff --git a/Doc/library/contextvars.rst b/Doc/library/contextvars.rst index 14ac47f4c9eb1..be1dd0c9eb57e 100644 --- a/Doc/library/contextvars.rst +++ b/Doc/library/contextvars.rst @@ -94,7 +94,7 @@ Context Variables # var.get() would raise a LookupError. -.. class:: contextvars.Token +.. class:: Token *Token* objects are returned by the :meth:`ContextVar.set` method. They can be passed to the :meth:`ContextVar.reset` method to revert From webhook-mailer at python.org Tue Nov 16 06:02:06 2021 From: webhook-mailer at python.org (markshannon) Date: Tue, 16 Nov 2021 11:02:06 -0000 Subject: [Python-checkins] bpo-45753: Make recursion checks more efficient. (GH-29524) Message-ID: https://github.com/python/cpython/commit/b9310773756f40f77e075f221a90dd41e6964efc commit: b9310773756f40f77e075f221a90dd41e6964efc branch: main author: Mark Shannon committer: markshannon date: 2021-11-16T11:01:57Z summary: bpo-45753: Make recursion checks more efficient. (GH-29524) * Uses recursion remaining, instead of recursion depth to speed up check against recursion limit. files: A Misc/NEWS.d/next/Core and Builtins/2021-11-11-17-14-21.bpo-45753.nEBFcC.rst M Include/cpython/pystate.h M Include/internal/pycore_ceval.h M Modules/_testinternalcapi.c M Python/ast.c M Python/ast_opt.c M Python/ceval.c M Python/pystate.c M Python/symtable.c M Python/sysmodule.c diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index cf69c72028a3a..9ac0a298baab4 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -79,9 +79,9 @@ struct _ts { struct _ts *next; PyInterpreterState *interp; - int recursion_depth; + int recursion_remaining; + int recursion_limit; int recursion_headroom; /* Allow 50 more calls to handle any errors. */ - int stackcheck_counter; /* 'tracing' keeps track of the execution depth when tracing/profiling. This is to prevent the actual trace/profile code from being recorded in diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index 53580b99d33ac..c2251b04be65d 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -75,12 +75,12 @@ extern void _PyEval_DeactivateOpCache(void); /* With USE_STACKCHECK macro defined, trigger stack checks in _Py_CheckRecursiveCall() on every 64th call to Py_EnterRecursiveCall. */ static inline int _Py_MakeRecCheck(PyThreadState *tstate) { - return (++tstate->recursion_depth > tstate->interp->ceval.recursion_limit - || ++tstate->stackcheck_counter > 64); + return (tstate->recursion_remaining-- <= 0 + || (tstate->recursion_remaining & 63) == 0); } #else static inline int _Py_MakeRecCheck(PyThreadState *tstate) { - return (++tstate->recursion_depth > tstate->interp->ceval.recursion_limit); + return tstate->recursion_remaining-- <= 0; } #endif @@ -101,7 +101,7 @@ static inline int _Py_EnterRecursiveCall_inline(const char *where) { #define Py_EnterRecursiveCall(where) _Py_EnterRecursiveCall_inline(where) static inline void _Py_LeaveRecursiveCall(PyThreadState *tstate) { - tstate->recursion_depth--; + tstate->recursion_remaining++; } static inline void _Py_LeaveRecursiveCall_inline(void) { diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-11-17-14-21.bpo-45753.nEBFcC.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-11-17-14-21.bpo-45753.nEBFcC.rst new file mode 100644 index 0000000000000..327f00d68911b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-11-17-14-21.bpo-45753.nEBFcC.rst @@ -0,0 +1,2 @@ +Make recursion checks a bit more efficient by tracking amount of calls left +before overflow. diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index 1f205b873beaf..c230ba28d6111 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -37,7 +37,8 @@ get_recursion_depth(PyObject *self, PyObject *Py_UNUSED(args)) PyThreadState *tstate = _PyThreadState_GET(); /* subtract one to ignore the frame of the get_recursion_depth() call */ - return PyLong_FromLong(tstate->recursion_depth - 1); + + return PyLong_FromLong(tstate->recursion_limit - tstate->recursion_remaining - 1); } diff --git a/Python/ast.c b/Python/ast.c index 2113124dbd51c..0c3121d3ee7b6 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -933,8 +933,9 @@ _PyAST_Validate(mod_ty mod) return 0; } /* Be careful here to prevent overflow. */ - starting_recursion_depth = (tstate->recursion_depth < INT_MAX / COMPILER_STACK_FRAME_SCALE) ? - tstate->recursion_depth * COMPILER_STACK_FRAME_SCALE : tstate->recursion_depth; + int recursion_depth = tstate->recursion_limit - tstate->recursion_remaining; + starting_recursion_depth = (recursion_depth< INT_MAX / COMPILER_STACK_FRAME_SCALE) ? + recursion_depth * COMPILER_STACK_FRAME_SCALE : recursion_depth; state.recursion_depth = starting_recursion_depth; state.recursion_limit = (recursion_limit < INT_MAX / COMPILER_STACK_FRAME_SCALE) ? recursion_limit * COMPILER_STACK_FRAME_SCALE : recursion_limit; diff --git a/Python/ast_opt.c b/Python/ast_opt.c index f6506cef035cd..356f60e2d5399 100644 --- a/Python/ast_opt.c +++ b/Python/ast_opt.c @@ -1098,8 +1098,9 @@ _PyAST_Optimize(mod_ty mod, PyArena *arena, _PyASTOptimizeState *state) return 0; } /* Be careful here to prevent overflow. */ - starting_recursion_depth = (tstate->recursion_depth < INT_MAX / COMPILER_STACK_FRAME_SCALE) ? - tstate->recursion_depth * COMPILER_STACK_FRAME_SCALE : tstate->recursion_depth; + int recursion_depth = tstate->recursion_limit - tstate->recursion_remaining; + starting_recursion_depth = (recursion_depth < INT_MAX / COMPILER_STACK_FRAME_SCALE) ? + recursion_depth * COMPILER_STACK_FRAME_SCALE : recursion_depth; state->recursion_depth = starting_recursion_depth; state->recursion_limit = (recursion_limit < INT_MAX / COMPILER_STACK_FRAME_SCALE) ? recursion_limit * COMPILER_STACK_FRAME_SCALE : recursion_limit; diff --git a/Python/ceval.c b/Python/ceval.c index e808aeed73a22..bf4e22dc6fec4 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -785,42 +785,49 @@ Py_GetRecursionLimit(void) void Py_SetRecursionLimit(int new_limit) { - PyThreadState *tstate = _PyThreadState_GET(); - tstate->interp->ceval.recursion_limit = new_limit; + PyInterpreterState *interp = _PyInterpreterState_GET(); + interp->ceval.recursion_limit = new_limit; + for (PyThreadState *p = interp->tstate_head; p != NULL; p = p->next) { + int depth = p->recursion_limit - p->recursion_remaining; + p->recursion_limit = new_limit; + p->recursion_remaining = new_limit - depth; + } } /* The function _Py_EnterRecursiveCall() only calls _Py_CheckRecursiveCall() - if the recursion_depth reaches recursion_limit. - If USE_STACKCHECK, the macro decrements recursion_limit - to guarantee that _Py_CheckRecursiveCall() is regularly called. - Without USE_STACKCHECK, there is no need for this. */ + if the recursion_depth reaches recursion_limit. */ int _Py_CheckRecursiveCall(PyThreadState *tstate, const char *where) { - int recursion_limit = tstate->interp->ceval.recursion_limit; - + /* Check against global limit first. */ + int depth = tstate->recursion_limit - tstate->recursion_remaining; + if (depth < tstate->interp->ceval.recursion_limit) { + tstate->recursion_limit = tstate->interp->ceval.recursion_limit; + tstate->recursion_remaining = tstate->recursion_limit - depth; + assert(tstate->recursion_remaining > 0); + return 0; + } #ifdef USE_STACKCHECK - tstate->stackcheck_counter = 0; if (PyOS_CheckStack()) { - --tstate->recursion_depth; + ++tstate->recursion_remaining; _PyErr_SetString(tstate, PyExc_MemoryError, "Stack overflow"); return -1; } #endif if (tstate->recursion_headroom) { - if (tstate->recursion_depth > recursion_limit + 50) { + if (tstate->recursion_remaining < -50) { /* Overflowing while handling an overflow. Give up. */ Py_FatalError("Cannot recover from stack overflow."); } } else { - if (tstate->recursion_depth > recursion_limit) { + if (tstate->recursion_remaining <= 0) { tstate->recursion_headroom++; _PyErr_Format(tstate, PyExc_RecursionError, "maximum recursion depth exceeded%s", where); tstate->recursion_headroom--; - --tstate->recursion_depth; + ++tstate->recursion_remaining; return -1; } } @@ -1582,7 +1589,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr start_frame: if (_Py_EnterRecursiveCall(tstate, "")) { - tstate->recursion_depth++; + tstate->recursion_remaining--; goto exit_eval_frame; } @@ -5688,13 +5695,13 @@ _PyEvalFramePushAndInit(PyThreadState *tstate, PyFrameConstructor *con, static int _PyEvalFrameClearAndPop(PyThreadState *tstate, InterpreterFrame * frame) { - ++tstate->recursion_depth; + --tstate->recursion_remaining; assert(frame->frame_obj == NULL || frame->frame_obj->f_own_locals_memory == 0); if (_PyFrame_Clear(frame, 0)) { - --tstate->recursion_depth; + ++tstate->recursion_remaining; return -1; } - --tstate->recursion_depth; + ++tstate->recursion_remaining; _PyThreadState_PopFrame(tstate, frame); return 0; } diff --git a/Python/pystate.c b/Python/pystate.c index a9ed08a7e34be..8df28078f2a4e 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -636,9 +636,9 @@ new_threadstate(PyInterpreterState *interp, int init) tstate->interp = interp; - tstate->recursion_depth = 0; + tstate->recursion_limit = interp->ceval.recursion_limit; + tstate->recursion_remaining = interp->ceval.recursion_limit; tstate->recursion_headroom = 0; - tstate->stackcheck_counter = 0; tstate->tracing = 0; tstate->root_cframe.use_tracing = 0; tstate->root_cframe.current_frame = NULL; diff --git a/Python/symtable.c b/Python/symtable.c index 64c1635fba760..dc5426cf3b426 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -298,8 +298,9 @@ _PySymtable_Build(mod_ty mod, PyObject *filename, PyFutureFeatures *future) return NULL; } /* Be careful here to prevent overflow. */ - starting_recursion_depth = (tstate->recursion_depth < INT_MAX / COMPILER_STACK_FRAME_SCALE) ? - tstate->recursion_depth * COMPILER_STACK_FRAME_SCALE : tstate->recursion_depth; + int recursion_depth = tstate->recursion_limit - tstate->recursion_remaining; + starting_recursion_depth = (recursion_depth < INT_MAX / COMPILER_STACK_FRAME_SCALE) ? + recursion_depth * COMPILER_STACK_FRAME_SCALE : recursion_depth; st->recursion_depth = starting_recursion_depth; st->recursion_limit = (recursion_limit < INT_MAX / COMPILER_STACK_FRAME_SCALE) ? recursion_limit * COMPILER_STACK_FRAME_SCALE : recursion_limit; diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 27937a03e8968..3e2091e70ab8a 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1187,20 +1187,14 @@ sys_setrecursionlimit_impl(PyObject *module, int new_limit) return NULL; } - /* Issue #25274: When the recursion depth hits the recursion limit in - _Py_CheckRecursiveCall(), the overflowed flag of the thread state is - set to 1 and a RecursionError is raised. The overflowed flag is reset - to 0 when the recursion depth goes below the low-water mark: see - Py_LeaveRecursiveCall(). - - Reject too low new limit if the current recursion depth is higher than - the new low-water mark. Otherwise it may not be possible anymore to - reset the overflowed flag to 0. */ - if (tstate->recursion_depth >= new_limit) { + /* Reject too low new limit if the current recursion depth is higher than + the new low-water mark. */ + int depth = tstate->recursion_limit - tstate->recursion_remaining; + if (depth >= new_limit) { _PyErr_Format(tstate, PyExc_RecursionError, "cannot set the recursion limit to %i at " "the recursion depth %i: the limit is too low", - new_limit, tstate->recursion_depth); + new_limit, depth); return NULL; } From webhook-mailer at python.org Tue Nov 16 06:47:07 2021 From: webhook-mailer at python.org (miss-islington) Date: Tue, 16 Nov 2021 11:47:07 -0000 Subject: [Python-checkins] [3.9] Save a reference for ensure_future and create_task (GH-29163) (GH-29573) Message-ID: https://github.com/python/cpython/commit/fd206b680705de3e0408fd29c7943317563e61e1 commit: fd206b680705de3e0408fd29c7943317563e61e1 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-16T03:47:02-08:00 summary: [3.9] Save a reference for ensure_future and create_task (GH-29163) (GH-29573) Co-authored-by: Joannah Nanjekye (cherry picked from commit c750adbe6990ee8239b27d5f4591283a06bfe862) Co-authored-by: Joannah Nanjekye <33177550+nanjekyejoannah at users.noreply.github.com> Automerge-Triggered-By: GH:asvetlov files: M Doc/library/asyncio-future.rst M Doc/library/asyncio-task.rst diff --git a/Doc/library/asyncio-future.rst b/Doc/library/asyncio-future.rst index 939d4c1a84523..63c369263fd99 100644 --- a/Doc/library/asyncio-future.rst +++ b/Doc/library/asyncio-future.rst @@ -54,6 +54,9 @@ Future Functions See also the :func:`create_task` function which is the preferred way for creating new Tasks. + Save a reference to the result of this function, to avoid + a task disappearing mid execution. + .. versionchanged:: 3.5.1 The function accepts any :term:`awaitable` object. diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index ca6e525e93597..e8bee20bc76bc 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -274,6 +274,11 @@ Creating Tasks task = asyncio.ensure_future(coro()) ... + .. important:: + + Save a reference to the result of this function, to avoid + a task disappearing mid execution. + .. versionadded:: 3.7 .. versionchanged:: 3.8 From webhook-mailer at python.org Tue Nov 16 06:51:24 2021 From: webhook-mailer at python.org (miss-islington) Date: Tue, 16 Nov 2021 11:51:24 -0000 Subject: [Python-checkins] Save a reference for ensure_future and create_task (GH-29163) Message-ID: https://github.com/python/cpython/commit/7bac59881969f6054fee12d4e3343b7fa1c43136 commit: 7bac59881969f6054fee12d4e3343b7fa1c43136 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-16T03:51:19-08:00 summary: Save a reference for ensure_future and create_task (GH-29163) Co-authored-by: Joannah Nanjekye (cherry picked from commit c750adbe6990ee8239b27d5f4591283a06bfe862) Co-authored-by: Joannah Nanjekye <33177550+nanjekyejoannah at users.noreply.github.com> files: M Doc/library/asyncio-future.rst M Doc/library/asyncio-task.rst diff --git a/Doc/library/asyncio-future.rst b/Doc/library/asyncio-future.rst index ef496a23f5cd4..3496387c178af 100644 --- a/Doc/library/asyncio-future.rst +++ b/Doc/library/asyncio-future.rst @@ -54,6 +54,9 @@ Future Functions See also the :func:`create_task` function which is the preferred way for creating new Tasks. + Save a reference to the result of this function, to avoid + a task disappearing mid execution. + .. versionchanged:: 3.5.1 The function accepts any :term:`awaitable` object. diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index fb86892547b5f..f18b0e347b631 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -274,6 +274,11 @@ Creating Tasks task = asyncio.ensure_future(coro()) ... + .. important:: + + Save a reference to the result of this function, to avoid + a task disappearing mid execution. + .. versionadded:: 3.7 .. versionchanged:: 3.8 From webhook-mailer at python.org Tue Nov 16 06:58:32 2021 From: webhook-mailer at python.org (tirkarthi) Date: Tue, 16 Nov 2021 11:58:32 -0000 Subject: [Python-checkins] bpo-45292: Use raw strings for regex in tests (GH-29545) Message-ID: https://github.com/python/cpython/commit/8b06d01507fd708468570eaa43a349828784489a commit: 8b06d01507fd708468570eaa43a349828784489a branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: tirkarthi date: 2021-11-16T17:28:21+05:30 summary: bpo-45292: Use raw strings for regex in tests (GH-29545) files: M Lib/test/test_exception_group.py diff --git a/Lib/test/test_exception_group.py b/Lib/test/test_exception_group.py index 5bb6094cde742..62ec1ee248de5 100644 --- a/Lib/test/test_exception_group.py +++ b/Lib/test/test_exception_group.py @@ -38,18 +38,18 @@ def test_bad_EG_construction__bad_message(self): ExceptionGroup(None, [ValueError(12)]) def test_bad_EG_construction__bad_excs_sequence(self): - MSG = 'second argument \(exceptions\) must be a sequence' + MSG = r'second argument \(exceptions\) must be a sequence' with self.assertRaisesRegex(TypeError, MSG): ExceptionGroup('errors not sequence', {ValueError(42)}) with self.assertRaisesRegex(TypeError, MSG): ExceptionGroup("eg", None) - MSG = 'second argument \(exceptions\) must be a non-empty sequence' + MSG = r'second argument \(exceptions\) must be a non-empty sequence' with self.assertRaisesRegex(ValueError, MSG): ExceptionGroup("eg", []) def test_bad_EG_construction__nested_non_exceptions(self): - MSG = ('Item [0-9]+ of second argument \(exceptions\)' + MSG = (r'Item [0-9]+ of second argument \(exceptions\)' ' is not an exception') with self.assertRaisesRegex(ValueError, MSG): ExceptionGroup('expect instance, not type', [OSError]); From webhook-mailer at python.org Tue Nov 16 08:41:29 2021 From: webhook-mailer at python.org (corona10) Date: Tue, 16 Nov 2021 13:41:29 -0000 Subject: [Python-checkins] bpo-45429: Support CREATE_WAITABLE_TIMER_HIGH_RESOLUTION if possible (GH-29203) Message-ID: https://github.com/python/cpython/commit/55868f1a335cd3853938082a5b25cfba66563135 commit: 55868f1a335cd3853938082a5b25cfba66563135 branch: main author: Dong-hee Na committer: corona10 date: 2021-11-16T22:41:20+09:00 summary: bpo-45429: Support CREATE_WAITABLE_TIMER_HIGH_RESOLUTION if possible (GH-29203) files: A Misc/NEWS.d/next/Library/2021-10-25-01-22-49.bpo-45429.VaEyN9.rst M Doc/whatsnew/3.11.rst M Modules/timemodule.c diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 62516d207d0b1..0c7c74e7c3242 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -283,6 +283,10 @@ time a resolution of 1 millisecond (10\ :sup:`-3` seconds). (Contributed by Benjamin Sz?ke and Victor Stinner in :issue:`21302`.) +* On Windows, :func:`time.sleep` now uses a waitable timer which supports high-resolution timers. + In Python 3.10, the best resolution was 1 ms, from Python 3.11 it's now smaller than 1 ms. + (Contributed by Dong-hee Na and Eryk Sun in :issue:`45429`.) + unicodedata ----------- diff --git a/Misc/NEWS.d/next/Library/2021-10-25-01-22-49.bpo-45429.VaEyN9.rst b/Misc/NEWS.d/next/Library/2021-10-25-01-22-49.bpo-45429.VaEyN9.rst new file mode 100644 index 0000000000000..0a274f1ef8ab7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-10-25-01-22-49.bpo-45429.VaEyN9.rst @@ -0,0 +1,2 @@ +On Windows, :func:`time.sleep` now uses a waitable timer which supports +high-resolution timers. Patch by Dong-hee Na and Eryk Sun. diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 0ef3b2ffaa898..bb713908eb1e4 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -408,6 +408,13 @@ static PyStructSequence_Desc struct_time_type_desc = { static int initialized; static PyTypeObject StructTimeType; +#if defined(MS_WINDOWS) +#ifndef CREATE_WAITABLE_TIMER_HIGH_RESOLUTION + #define CREATE_WAITABLE_TIMER_HIGH_RESOLUTION 0x00000002 +#endif + +static DWORD timer_flags = (DWORD)-1; +#endif static PyObject * tmtotuple(struct tm *p @@ -2017,6 +2024,23 @@ time_exec(PyObject *module) utc_string = tm.tm_zone; #endif +#if defined(MS_WINDOWS) + if (timer_flags == (DWORD)-1) { + DWORD test_flags = CREATE_WAITABLE_TIMER_HIGH_RESOLUTION; + HANDLE timer = CreateWaitableTimerExW(NULL, NULL, test_flags, + TIMER_ALL_ACCESS); + if (timer == NULL) { + // CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is not supported. + timer_flags = 0; + } + else { + // CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is supported. + timer_flags = CREATE_WAITABLE_TIMER_HIGH_RESOLUTION; + CloseHandle(timer); + } + } +#endif + return 0; } @@ -2150,20 +2174,18 @@ pysleep(_PyTime_t timeout) // SetWaitableTimer(): a negative due time indicates relative time relative_timeout.QuadPart = -timeout_100ns; - HANDLE timer = CreateWaitableTimerW(NULL, FALSE, NULL); + HANDLE timer = CreateWaitableTimerExW(NULL, NULL, timer_flags, + TIMER_ALL_ACCESS); if (timer == NULL) { PyErr_SetFromWindowsErr(0); return -1; } - if (!SetWaitableTimer(timer, &relative_timeout, - // period: the timer is signaled once - 0, - // no completion routine - NULL, NULL, - // Don't restore a system in suspended power - // conservation mode when the timer is signaled. - FALSE)) + if (!SetWaitableTimerEx(timer, &relative_timeout, + 0, // no period; the timer is signaled once + NULL, NULL, // no completion routine + NULL, // no wake context; do not resume from suspend + 0)) // no tolerable delay for timer coalescing { PyErr_SetFromWindowsErr(0); goto error; From webhook-mailer at python.org Tue Nov 16 08:54:06 2021 From: webhook-mailer at python.org (brandtbucher) Date: Tue, 16 Nov 2021 13:54:06 -0000 Subject: [Python-checkins] bpo-45636: Simplify BINARY_OP (GH-29565) Message-ID: https://github.com/python/cpython/commit/6a84d61c55f2e543cf5fa84522d8781a795bba33 commit: 6a84d61c55f2e543cf5fa84522d8781a795bba33 branch: main author: Brandt Bucher committer: brandtbucher date: 2021-11-16T05:53:57-08:00 summary: bpo-45636: Simplify BINARY_OP (GH-29565) files: A Misc/NEWS.d/next/Core and Builtins/2021-11-15-13-32-54.bpo-45636.RDlTdL.rst M Include/internal/pycore_abstract.h M Objects/abstract.c M Python/ceval.c diff --git a/Include/internal/pycore_abstract.h b/Include/internal/pycore_abstract.h index b791bf2432199..b1afb2dc7be65 100644 --- a/Include/internal/pycore_abstract.h +++ b/Include/internal/pycore_abstract.h @@ -16,6 +16,9 @@ _PyIndex_Check(PyObject *obj) return (tp_as_number != NULL && tp_as_number->nb_index != NULL); } +PyObject *_PyNumber_PowerNoMod(PyObject *lhs, PyObject *rhs); +PyObject *_PyNumber_InPlacePowerNoMod(PyObject *lhs, PyObject *rhs); + #ifdef __cplusplus } #endif diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-15-13-32-54.bpo-45636.RDlTdL.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-15-13-32-54.bpo-45636.RDlTdL.rst new file mode 100644 index 0000000000000..92b1b272f0215 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-15-13-32-54.bpo-45636.RDlTdL.rst @@ -0,0 +1,2 @@ +Simplify the implementation of :opcode:`BINARY_OP` by indexing into an array +of function pointers (rather than switching on the oparg). diff --git a/Objects/abstract.c b/Objects/abstract.c index 6227ad5a18bb9..82599dd6eca23 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -1152,6 +1152,12 @@ PyNumber_Power(PyObject *v, PyObject *w, PyObject *z) return ternary_op(v, w, z, NB_SLOT(nb_power), "** or pow()"); } +PyObject * +_PyNumber_PowerNoMod(PyObject *lhs, PyObject *rhs) +{ + return PyNumber_Power(lhs, rhs, Py_None); +} + /* Binary in-place operators */ /* The in-place operators are defined to fall back to the 'normal', @@ -1331,6 +1337,12 @@ PyNumber_InPlacePower(PyObject *v, PyObject *w, PyObject *z) NB_SLOT(nb_power), "**="); } +PyObject * +_PyNumber_InPlacePowerNoMod(PyObject *lhs, PyObject *rhs) +{ + return PyNumber_InPlacePower(lhs, rhs, Py_None); +} + /* Unary operators and functions */ diff --git a/Python/ceval.c b/Python/ceval.c index bf4e22dc6fec4..c02e3517d44f4 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -835,6 +835,36 @@ _Py_CheckRecursiveCall(PyThreadState *tstate, const char *where) } +static const binaryfunc binary_ops[] = { + [NB_ADD] = PyNumber_Add, + [NB_AND] = PyNumber_And, + [NB_FLOOR_DIVIDE] = PyNumber_FloorDivide, + [NB_LSHIFT] = PyNumber_Lshift, + [NB_MATRIX_MULTIPLY] = PyNumber_MatrixMultiply, + [NB_MULTIPLY] = PyNumber_Multiply, + [NB_REMAINDER] = PyNumber_Remainder, + [NB_OR] = PyNumber_Or, + [NB_POWER] = _PyNumber_PowerNoMod, + [NB_RSHIFT] = PyNumber_Rshift, + [NB_SUBTRACT] = PyNumber_Subtract, + [NB_TRUE_DIVIDE] = PyNumber_TrueDivide, + [NB_XOR] = PyNumber_Xor, + [NB_INPLACE_ADD] = PyNumber_InPlaceAdd, + [NB_INPLACE_AND] = PyNumber_InPlaceAnd, + [NB_INPLACE_FLOOR_DIVIDE] = PyNumber_InPlaceFloorDivide, + [NB_INPLACE_LSHIFT] = PyNumber_InPlaceLshift, + [NB_INPLACE_MATRIX_MULTIPLY] = PyNumber_InPlaceMatrixMultiply, + [NB_INPLACE_MULTIPLY] = PyNumber_InPlaceMultiply, + [NB_INPLACE_REMAINDER] = PyNumber_InPlaceRemainder, + [NB_INPLACE_OR] = PyNumber_InPlaceOr, + [NB_INPLACE_POWER] = _PyNumber_InPlacePowerNoMod, + [NB_INPLACE_RSHIFT] = PyNumber_InPlaceRshift, + [NB_INPLACE_SUBTRACT] = PyNumber_InPlaceSubtract, + [NB_INPLACE_TRUE_DIVIDE] = PyNumber_InPlaceTrueDivide, + [NB_INPLACE_XOR] = PyNumber_InPlaceXor, +}; + + // PEP 634: Structural Pattern Matching @@ -4697,89 +4727,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr STAT_INC(BINARY_OP, unquickened); PyObject *rhs = POP(); PyObject *lhs = TOP(); - PyObject *res; - switch (oparg) { - case NB_ADD: - res = PyNumber_Add(lhs, rhs); - break; - case NB_AND: - res = PyNumber_And(lhs, rhs); - break; - case NB_FLOOR_DIVIDE: - res = PyNumber_FloorDivide(lhs, rhs); - break; - case NB_LSHIFT: - res = PyNumber_Lshift(lhs, rhs); - break; - case NB_MATRIX_MULTIPLY: - res = PyNumber_MatrixMultiply(lhs, rhs); - break; - case NB_MULTIPLY: - res = PyNumber_Multiply(lhs, rhs); - break; - case NB_REMAINDER: - res = PyNumber_Remainder(lhs, rhs); - break; - case NB_OR: - res = PyNumber_Or(lhs, rhs); - break; - case NB_POWER: - res = PyNumber_Power(lhs, rhs, Py_None); - break; - case NB_RSHIFT: - res = PyNumber_Rshift(lhs, rhs); - break; - case NB_SUBTRACT: - res = PyNumber_Subtract(lhs, rhs); - break; - case NB_TRUE_DIVIDE: - res = PyNumber_TrueDivide(lhs, rhs); - break; - case NB_XOR: - res = PyNumber_Xor(lhs, rhs); - break; - case NB_INPLACE_ADD: - res = PyNumber_InPlaceAdd(lhs, rhs); - break; - case NB_INPLACE_AND: - res = PyNumber_InPlaceAnd(lhs, rhs); - break; - case NB_INPLACE_FLOOR_DIVIDE: - res = PyNumber_InPlaceFloorDivide(lhs, rhs); - break; - case NB_INPLACE_LSHIFT: - res = PyNumber_InPlaceLshift(lhs, rhs); - break; - case NB_INPLACE_MATRIX_MULTIPLY: - res = PyNumber_InPlaceMatrixMultiply(lhs, rhs); - break; - case NB_INPLACE_MULTIPLY: - res = PyNumber_InPlaceMultiply(lhs, rhs); - break; - case NB_INPLACE_REMAINDER: - res = PyNumber_InPlaceRemainder(lhs, rhs); - break; - case NB_INPLACE_OR: - res = PyNumber_InPlaceOr(lhs, rhs); - break; - case NB_INPLACE_POWER: - res = PyNumber_InPlacePower(lhs, rhs, Py_None); - break; - case NB_INPLACE_RSHIFT: - res = PyNumber_InPlaceRshift(lhs, rhs); - break; - case NB_INPLACE_SUBTRACT: - res = PyNumber_InPlaceSubtract(lhs, rhs); - break; - case NB_INPLACE_TRUE_DIVIDE: - res = PyNumber_InPlaceTrueDivide(lhs, rhs); - break; - case NB_INPLACE_XOR: - res = PyNumber_InPlaceXor(lhs, rhs); - break; - default: - Py_UNREACHABLE(); - } + assert(0 <= oparg); + assert((unsigned)oparg < Py_ARRAY_LENGTH(binary_ops)); + assert(binary_ops[oparg]); + PyObject *res = binary_ops[oparg](lhs, rhs); Py_DECREF(lhs); Py_DECREF(rhs); SET_TOP(res); From webhook-mailer at python.org Tue Nov 16 09:53:44 2021 From: webhook-mailer at python.org (encukou) Date: Tue, 16 Nov 2021 14:53:44 -0000 Subject: [Python-checkins] bpo-45126: Harden `sqlite3` connection initialisation (GH-28227) Message-ID: https://github.com/python/cpython/commit/9d6215a54c177a5e359c37ecd1c50b594b194f41 commit: 9d6215a54c177a5e359c37ecd1c50b594b194f41 branch: main author: Erlend Egeberg Aasland committer: encukou date: 2021-11-16T15:53:35+01:00 summary: bpo-45126: Harden `sqlite3` connection initialisation (GH-28227) files: M Lib/test/test_sqlite3/test_dbapi.py M Modules/_sqlite/clinic/connection.c.h M Modules/_sqlite/connection.c diff --git a/Lib/test/test_sqlite3/test_dbapi.py b/Lib/test/test_sqlite3/test_dbapi.py index 802a6919371f9..18359e1a5e2ab 100644 --- a/Lib/test/test_sqlite3/test_dbapi.py +++ b/Lib/test/test_sqlite3/test_dbapi.py @@ -523,6 +523,44 @@ def test_connection_init_good_isolation_levels(self): with memory_database(isolation_level=level) as cx: cx.execute("select 'ok'") + def test_connection_reinit(self): + db = ":memory:" + cx = sqlite.connect(db) + cx.text_factory = bytes + cx.row_factory = sqlite.Row + cu = cx.cursor() + cu.execute("create table foo (bar)") + cu.executemany("insert into foo (bar) values (?)", + ((str(v),) for v in range(4))) + cu.execute("select bar from foo") + + rows = [r for r in cu.fetchmany(2)] + self.assertTrue(all(isinstance(r, sqlite.Row) for r in rows)) + self.assertEqual([r[0] for r in rows], [b"0", b"1"]) + + cx.__init__(db) + cx.execute("create table foo (bar)") + cx.executemany("insert into foo (bar) values (?)", + ((v,) for v in ("a", "b", "c", "d"))) + + # This uses the old database, old row factory, but new text factory + rows = [r for r in cu.fetchall()] + self.assertTrue(all(isinstance(r, sqlite.Row) for r in rows)) + self.assertEqual([r[0] for r in rows], ["2", "3"]) + + def test_connection_bad_reinit(self): + cx = sqlite.connect(":memory:") + with cx: + cx.execute("create table t(t)") + with temp_dir() as db: + self.assertRaisesRegex(sqlite.OperationalError, + "unable to open database file", + cx.__init__, db) + self.assertRaisesRegex(sqlite.ProgrammingError, + "Base Connection.__init__ not called", + cx.executemany, "insert into t values(?)", + ((v,) for v in range(3))) + class UninitialisedConnectionTests(unittest.TestCase): def setUp(self): diff --git a/Modules/_sqlite/clinic/connection.c.h b/Modules/_sqlite/clinic/connection.c.h index 5bfc589aeb149..3a3ae04e8a193 100644 --- a/Modules/_sqlite/clinic/connection.c.h +++ b/Modules/_sqlite/clinic/connection.c.h @@ -7,7 +7,7 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, const char *database, double timeout, int detect_types, const char *isolation_level, int check_same_thread, PyObject *factory, - int cached_statements, int uri); + int cache_size, int uri); static int pysqlite_connection_init(PyObject *self, PyObject *args, PyObject *kwargs) @@ -25,7 +25,7 @@ pysqlite_connection_init(PyObject *self, PyObject *args, PyObject *kwargs) const char *isolation_level = ""; int check_same_thread = 1; PyObject *factory = (PyObject*)clinic_state()->ConnectionType; - int cached_statements = 128; + int cache_size = 128; int uri = 0; fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 8, 0, argsbuf); @@ -101,8 +101,8 @@ pysqlite_connection_init(PyObject *self, PyObject *args, PyObject *kwargs) } } if (fastargs[6]) { - cached_statements = _PyLong_AsInt(fastargs[6]); - if (cached_statements == -1 && PyErr_Occurred()) { + cache_size = _PyLong_AsInt(fastargs[6]); + if (cache_size == -1 && PyErr_Occurred()) { goto exit; } if (!--noptargs) { @@ -114,7 +114,7 @@ pysqlite_connection_init(PyObject *self, PyObject *args, PyObject *kwargs) goto exit; } skip_optional_pos: - return_value = pysqlite_connection_init_impl((pysqlite_Connection *)self, database, timeout, detect_types, isolation_level, check_same_thread, factory, cached_statements, uri); + return_value = pysqlite_connection_init_impl((pysqlite_Connection *)self, database, timeout, detect_types, isolation_level, check_same_thread, factory, cache_size, uri); exit: /* Cleanup for database */ @@ -851,4 +851,4 @@ getlimit(pysqlite_Connection *self, PyObject *arg) #ifndef PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF #define PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF #endif /* !defined(PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF) */ -/*[clinic end generated code: output=663b1e9e71128f19 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=6f267f20e77f92d0 input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index b902dc845c618..e7947671db354 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -83,15 +83,17 @@ static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self); static void free_callback_context(callback_context *ctx); static void set_callback_context(callback_context **ctx_pp, callback_context *ctx); +static void connection_close(pysqlite_Connection *self); static PyObject * -new_statement_cache(pysqlite_Connection *self, int maxsize) +new_statement_cache(pysqlite_Connection *self, pysqlite_state *state, + int maxsize) { PyObject *args[] = { NULL, PyLong_FromLong(maxsize), }; if (args[1] == NULL) { return NULL; } - PyObject *lru_cache = self->state->lru_cache; + PyObject *lru_cache = state->lru_cache; size_t nargsf = 1 | PY_VECTORCALL_ARGUMENTS_OFFSET; PyObject *inner = PyObject_Vectorcall(lru_cache, args + 1, nargsf, NULL); Py_DECREF(args[1]); @@ -153,7 +155,7 @@ _sqlite3.Connection.__init__ as pysqlite_connection_init isolation_level: str(accept={str, NoneType}) = "" check_same_thread: bool(accept={int}) = True factory: object(c_default='(PyObject*)clinic_state()->ConnectionType') = ConnectionType - cached_statements: int = 128 + cached_statements as cache_size: int = 128 uri: bool = False [clinic start generated code]*/ @@ -162,78 +164,82 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, const char *database, double timeout, int detect_types, const char *isolation_level, int check_same_thread, PyObject *factory, - int cached_statements, int uri) -/*[clinic end generated code: output=d8c37afc46d318b0 input=adfb29ac461f9e61]*/ + int cache_size, int uri) +/*[clinic end generated code: output=7d640ae1d83abfd4 input=35e316f66d9f70fd]*/ { - int rc; - if (PySys_Audit("sqlite3.connect", "s", database) < 0) { return -1; } - pysqlite_state *state = pysqlite_get_state_by_type(Py_TYPE(self)); - self->state = state; - - Py_CLEAR(self->statement_cache); - Py_CLEAR(self->cursors); - - Py_INCREF(Py_None); - Py_XSETREF(self->row_factory, Py_None); - - Py_INCREF(&PyUnicode_Type); - Py_XSETREF(self->text_factory, (PyObject*)&PyUnicode_Type); + if (self->initialized) { + PyTypeObject *tp = Py_TYPE(self); + tp->tp_clear((PyObject *)self); + connection_close(self); + self->initialized = 0; + } + // Create and configure SQLite database object. + sqlite3 *db; + int rc; Py_BEGIN_ALLOW_THREADS - rc = sqlite3_open_v2(database, &self->db, + rc = sqlite3_open_v2(database, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | (uri ? SQLITE_OPEN_URI : 0), NULL); + if (rc == SQLITE_OK) { + (void)sqlite3_busy_timeout(db, (int)(timeout*1000)); + } Py_END_ALLOW_THREADS - if (self->db == NULL && rc == SQLITE_NOMEM) { + if (db == NULL && rc == SQLITE_NOMEM) { PyErr_NoMemory(); return -1; } + + pysqlite_state *state = pysqlite_get_state_by_type(Py_TYPE(self)); if (rc != SQLITE_OK) { - _pysqlite_seterror(state, self->db); + _pysqlite_seterror(state, db); return -1; } - if (isolation_level) { - const char *stmt = get_begin_statement(isolation_level); - if (stmt == NULL) { + // Convert isolation level to begin statement. + const char *begin_statement = NULL; + if (isolation_level != NULL) { + begin_statement = get_begin_statement(isolation_level); + if (begin_statement == NULL) { return -1; } - self->begin_statement = stmt; - } - else { - self->begin_statement = NULL; } - self->statement_cache = new_statement_cache(self, cached_statements); - if (self->statement_cache == NULL) { - return -1; - } - if (PyErr_Occurred()) { + // Create LRU statement cache; returns a new reference. + PyObject *statement_cache = new_statement_cache(self, state, cache_size); + if (statement_cache == NULL) { return -1; } - self->created_cursors = 0; - - /* Create list of weak references to cursors */ - self->cursors = PyList_New(0); - if (self->cursors == NULL) { + // Create list of weak references to cursors. + PyObject *cursors = PyList_New(0); + if (cursors == NULL) { + Py_DECREF(statement_cache); return -1; } + // Init connection state members. + self->db = db; + self->state = state; self->detect_types = detect_types; - (void)sqlite3_busy_timeout(self->db, (int)(timeout*1000)); - self->thread_ident = PyThread_get_thread_ident(); + self->begin_statement = begin_statement; self->check_same_thread = check_same_thread; + self->thread_ident = PyThread_get_thread_ident(); + self->statement_cache = statement_cache; + self->cursors = cursors; + self->created_cursors = 0; + self->row_factory = Py_NewRef(Py_None); + self->text_factory = Py_NewRef(&PyUnicode_Type); + self->trace_ctx = NULL; + self->progress_ctx = NULL; + self->authorizer_ctx = NULL; - set_callback_context(&self->trace_ctx, NULL); - set_callback_context(&self->progress_ctx, NULL); - set_callback_context(&self->authorizer_ctx, NULL); - + // Borrowed refs self->Warning = state->Warning; self->Error = state->Error; self->InterfaceError = state->InterfaceError; @@ -250,7 +256,6 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, } self->initialized = 1; - return 0; } @@ -321,16 +326,6 @@ connection_clear(pysqlite_Connection *self) return 0; } -static void -connection_close(pysqlite_Connection *self) -{ - if (self->db) { - int rc = sqlite3_close_v2(self->db); - assert(rc == SQLITE_OK), (void)rc; - self->db = NULL; - } -} - static void free_callback_contexts(pysqlite_Connection *self) { @@ -339,6 +334,22 @@ free_callback_contexts(pysqlite_Connection *self) set_callback_context(&self->authorizer_ctx, NULL); } +static void +connection_close(pysqlite_Connection *self) +{ + if (self->db) { + free_callback_contexts(self); + + sqlite3 *db = self->db; + self->db = NULL; + + Py_BEGIN_ALLOW_THREADS + int rc = sqlite3_close_v2(db); + assert(rc == SQLITE_OK), (void)rc; + Py_END_ALLOW_THREADS + } +} + static void connection_dealloc(pysqlite_Connection *self) { @@ -348,7 +359,6 @@ connection_dealloc(pysqlite_Connection *self) /* Clean up if user has not called .close() explicitly. */ connection_close(self); - free_callback_contexts(self); tp->tp_free(self); Py_DECREF(tp); From webhook-mailer at python.org Tue Nov 16 14:52:02 2021 From: webhook-mailer at python.org (pablogsal) Date: Tue, 16 Nov 2021 19:52:02 -0000 Subject: [Python-checkins] bpo-45820: Fix a segfault when the parser fails without reading any input (GH-29580) Message-ID: https://github.com/python/cpython/commit/df4ae55e66e34ea8de6a34f0b104871ddaf35d53 commit: df4ae55e66e34ea8de6a34f0b104871ddaf35d53 branch: main author: Pablo Galindo Salgado committer: pablogsal date: 2021-11-16T19:51:52Z summary: bpo-45820: Fix a segfault when the parser fails without reading any input (GH-29580) files: A Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-00-27.bpo-45820.2X6Psr.rst M Parser/pegen.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-00-27.bpo-45820.2X6Psr.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-00-27.bpo-45820.2X6Psr.rst new file mode 100644 index 0000000000000..c2ec3d690cd4b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-00-27.bpo-45820.2X6Psr.rst @@ -0,0 +1,2 @@ +Fix a segfault when the parser fails without reading any input. Patch by +Pablo Galindo diff --git a/Parser/pegen.c b/Parser/pegen.c index 8a3f740c359c0..2931a40560867 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -368,6 +368,14 @@ tokenizer_error(Parser *p) void * _PyPegen_raise_error(Parser *p, PyObject *errtype, const char *errmsg, ...) { + if (p->fill == 0) { + va_list va; + va_start(va, errmsg); + _PyPegen_raise_error_known_location(p, errtype, 0, 0, 0, -1, errmsg, va); + va_end(va); + return NULL; + } + Token *t = p->known_err_token != NULL ? p->known_err_token : p->tokens[p->fill - 1]; Py_ssize_t col_offset; Py_ssize_t end_col_offset = -1; From webhook-mailer at python.org Tue Nov 16 14:59:54 2021 From: webhook-mailer at python.org (miss-islington) Date: Tue, 16 Nov 2021 19:59:54 -0000 Subject: [Python-checkins] bpo-37800: Clean up importlib documentation for some module attributes (GH-10016) Message-ID: https://github.com/python/cpython/commit/d7e210070f915d8df5fa863ecba8628304ee1ded commit: d7e210070f915d8df5fa863ecba8628304ee1ded branch: main author: G?ry Ogam committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-16T11:59:45-08:00 summary: bpo-37800: Clean up importlib documentation for some module attributes (GH-10016) Automerge-Triggered-By: GH:brettcannon files: M Doc/library/importlib.rst diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index 5b4fba381ce5b..6b71e64bcbfa7 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -383,11 +383,11 @@ ABC hierarchy:: See :pep:`302` for the exact definition for a loader. Loaders that wish to support resource reading should implement a - ``get_resource_reader(fullname)`` method as specified by + :meth:`get_resource_reader` method as specified by :class:`importlib.abc.ResourceReader`. .. versionchanged:: 3.7 - Introduced the optional ``get_resource_reader()`` method. + Introduced the optional :meth:`get_resource_reader` method. .. method:: create_module(spec) @@ -405,17 +405,17 @@ ABC hierarchy:: An abstract method that executes the module in its own namespace when a module is imported or reloaded. The module should already - be initialized when ``exec_module()`` is called. When this method exists, - :meth:`~importlib.abc.Loader.create_module` must be defined. + be initialized when :meth:`exec_module` is called. When this method exists, + :meth:`create_module` must be defined. .. versionadded:: 3.4 .. versionchanged:: 3.6 - :meth:`~importlib.abc.Loader.create_module` must also be defined. + :meth:`create_module` must also be defined. .. method:: load_module(fullname) - A legacy method for loading a module. If the module cannot be + A legacy method for loading a module. If the module cannot be loaded, :exc:`ImportError` is raised, otherwise the loaded module is returned. @@ -423,62 +423,64 @@ ABC hierarchy:: module should be used and reloaded. Otherwise the loader should create a new module and insert it into :data:`sys.modules` before any loading begins, to prevent recursion - from the import. If the loader inserted a module and the load fails, it + from the import. If the loader inserted a module and the load fails, it must be removed by the loader from :data:`sys.modules`; modules already in :data:`sys.modules` before the loader began execution should be left alone (see :func:`importlib.util.module_for_loader`). - The loader should set several attributes on the module. - (Note that some of these attributes can change when a module is + The loader should set several attributes on the module + (note that some of these attributes can change when a module is reloaded): - :attr:`__name__` - The name of the module. + The module's fully-qualified name. + It is ``'__main__'`` for an executed module. - :attr:`__file__` - The path to where the module data is stored (not set for built-in - modules). + The location the :term:`loader` used to load the module. + For example, for modules loaded from a .py file this is the filename. + It is not set on all modules (e.g. built-in modules). - :attr:`__cached__` - The path to where a compiled version of the module is/should be - stored (not set when the attribute would be inappropriate). + The filename of a compiled version of the module's code. + It is not set on all modules (e.g. built-in modules). - :attr:`__path__` - A list of strings specifying the search path within a - package. This attribute is not set on modules. + The list of locations where the package's submodules will be found. + Most of the time this is a single directory. + The import system passes this attribute to ``__import__()`` and to finders + in the same way as :attr:`sys.path` but just for the package. + It is not set on non-package modules so it can be used + as an indicator that the module is a package. - :attr:`__package__` - The fully-qualified name of the package under which the module was - loaded as a submodule (or the empty string for top-level modules). - For packages, it is the same as :attr:`__name__`. The - :func:`importlib.util.module_for_loader` decorator can handle the - details for :attr:`__package__`. + The fully-qualified name of the package the module is in (or the + empty string for a top-level module). + If the module is a package then this is the same as :attr:`__name__`. - :attr:`__loader__` - The loader used to load the module. The - :func:`importlib.util.module_for_loader` decorator can handle the - details for :attr:`__package__`. + The :term:`loader` used to load the module. When :meth:`exec_module` is available then backwards-compatible functionality is provided. .. versionchanged:: 3.4 Raise :exc:`ImportError` when called instead of - :exc:`NotImplementedError`. Functionality provided when + :exc:`NotImplementedError`. Functionality provided when :meth:`exec_module` is available. .. deprecated:: 3.4 The recommended API for loading a module is :meth:`exec_module` - (and :meth:`create_module`). Loaders should implement - it instead of load_module(). The import machinery takes care of - all the other responsibilities of load_module() when exec_module() - is implemented. + (and :meth:`create_module`). Loaders should implement it instead of + :meth:`load_module`. The import machinery takes care of all the + other responsibilities of :meth:`load_module` when + :meth:`exec_module` is implemented. .. method:: module_repr(module) - A legacy method which when implemented calculates and returns the - given module's repr, as a string. The module type's default repr() will - use the result of this method as appropriate. + A legacy method which when implemented calculates and returns the given + module's representation, as a string. The module type's default + :meth:`__repr__` will use the result of this method as appropriate. .. versionadded:: 3.3 @@ -1420,69 +1422,80 @@ find and load modules. .. class:: ModuleSpec(name, loader, *, origin=None, loader_state=None, is_package=None) A specification for a module's import-system-related state. This is - typically exposed as the module's ``__spec__`` attribute. In the + typically exposed as the module's :attr:`__spec__` attribute. In the descriptions below, the names in parentheses give the corresponding - attribute available directly on the module object. - E.g. ``module.__spec__.origin == module.__file__``. Note however that + attribute available directly on the module object, + e.g. ``module.__spec__.origin == module.__file__``. Note, however, that while the *values* are usually equivalent, they can differ since there is - no synchronization between the two objects. Thus it is possible to update - the module's ``__path__`` at runtime, and this will not be automatically - reflected in ``__spec__.submodule_search_locations``. + no synchronization between the two objects. For example, it is possible to update + the module's :attr:`__file__` at runtime and this will not be automatically + reflected in the module's :attr:`__spec__.origin`, and vice versa. .. versionadded:: 3.4 .. attribute:: name - (``__name__``) + (:attr:`__name__`) - A string for the fully-qualified name of the module. + The module's fully-qualified name. + The :term:`finder` should always set this attribute to a non-empty string. .. attribute:: loader - (``__loader__``) + (:attr:`__loader__`) - The :term:`Loader ` that should be used when loading - the module. :term:`Finders ` should always set this. + The :term:`loader` used to load the module. + The :term:`finder` should always set this attribute. .. attribute:: origin - (``__file__``) + (:attr:`__file__`) - Name of the place from which the module is loaded, e.g. "builtin" for - built-in modules and the filename for modules loaded from source. - Normally "origin" should be set, but it may be ``None`` (the default) - which indicates it is unspecified (e.g. for namespace packages). + The location the :term:`loader` should use to load the module. + For example, for modules loaded from a .py file this is the filename. + The :term:`finder` should always set this attribute to a meaningful value + for the :term:`loader` to use. In the uncommon case that there is not one + (like for namespace packages), it should be set to ``None``. .. attribute:: submodule_search_locations - (``__path__``) + (:attr:`__path__`) - List of strings for where to find submodules, if a package (``None`` - otherwise). + The list of locations where the package's submodules will be found. + Most of the time this is a single directory. + The :term:`finder` should set this attribute to a list, even an empty one, to indicate + to the import system that the module is a package. It should be set to ``None`` for + non-package modules. It is set automatically later to a special object for + namespace packages. .. attribute:: loader_state - Container of extra module-specific data for use during loading (or - ``None``). + The :term:`finder` may set this attribute to an object containing additional, + module-specific data to use when loading the module. Otherwise it should be + set to ``None``. .. attribute:: cached - (``__cached__``) + (:attr:`__cached__`) - String for where the compiled module should be stored (or ``None``). + The filename of a compiled version of the module's code. + The :term:`finder` should always set this attribute but it may be ``None`` + for modules that do not need compiled code stored. .. attribute:: parent - (``__package__``) + (:attr:`__package__`) - (Read-only) The fully-qualified name of the package under which the module - should be loaded as a submodule (or the empty string for top-level modules). - For packages, it is the same as :attr:`__name__`. + (Read-only) The fully-qualified name of the package the module is in (or the + empty string for a top-level module). + If the module is a package then this is the same as :attr:`name`. .. attribute:: has_location - Boolean indicating whether or not the module's "origin" - attribute refers to a loadable location. + ``True`` if the spec's :attr:`origin` refers to a loadable location, + ``False`` otherwise. This value impacts how :attr:`origin` is interpreted + and how the module's :attr:`__file__` is populated. + :mod:`importlib.util` -- Utility code for importers --------------------------------------------------- @@ -1574,8 +1587,9 @@ an :term:`importer`. :exc:`ImportError` is raised if **name** is a relative module name but **package** is a false value (e.g. ``None`` or the empty string). - :exc:`ImportError` is also raised a relative name would escape its containing - package (e.g. requesting ``..bacon`` from within the ``spam`` package). + :exc:`ImportError` is also raised if a relative name would escape its + containing package (e.g. requesting ``..bacon`` from within the ``spam`` + package). .. versionadded:: 3.3 From webhook-mailer at python.org Tue Nov 16 15:31:01 2021 From: webhook-mailer at python.org (miss-islington) Date: Tue, 16 Nov 2021 20:31:01 -0000 Subject: [Python-checkins] bpo-45822: Respect PEP 263's coding cookies in the parser even if flags are not provided (GH-29582) Message-ID: https://github.com/python/cpython/commit/da20d7401de97b425897d3069f71f77b039eb16f commit: da20d7401de97b425897d3069f71f77b039eb16f branch: main author: Pablo Galindo Salgado committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-16T12:30:47-08:00 summary: bpo-45822: Respect PEP 263's coding cookies in the parser even if flags are not provided (GH-29582) files: A Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-41-04.bpo-45822.OT6ueS.rst M Lib/test/test_capi.py M Modules/_testcapimodule.c M Parser/pegen.c diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index d954942286676..5e1619bf7dc9d 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -1017,6 +1017,14 @@ def test_state_access(self): with self.assertRaises(TypeError): increment_count(1, 2, 3) + 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) + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-41-04.bpo-45822.OT6ueS.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-41-04.bpo-45822.OT6ueS.rst new file mode 100644 index 0000000000000..1ac7a8becee40 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-41-04.bpo-45822.OT6ueS.rst @@ -0,0 +1,2 @@ +Fixed a bug in the parser that was causing it to not respect :pep:`263` +coding cookies when no flags are provided. Patch by Pablo Galindo diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 5e4c577962601..c9ba148973162 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -381,6 +381,19 @@ static PyTypeObject _HashInheritanceTester_Type = { PyType_GenericNew, /* tp_new */ }; +static PyObject* +pycompilestring(PyObject* self, PyObject *obj) { + if (PyBytes_CheckExact(obj) == 0) { + PyErr_SetString(PyExc_ValueError, "Argument must be a bytes object"); + return NULL; + } + const char *the_string = PyBytes_AsString(obj); + if (the_string == NULL) { + return NULL; + } + return Py_CompileString(the_string, "blech", Py_file_input); +} + static PyObject* test_lazy_hash_inheritance(PyObject* self, PyObject *Py_UNUSED(ignored)) { @@ -6070,6 +6083,7 @@ static PyMethodDef TestMethods[] = { {"return_null_without_error", return_null_without_error, METH_NOARGS}, {"return_result_with_error", return_result_with_error, METH_NOARGS}, {"getitem_with_error", getitem_with_error, METH_VARARGS}, + {"Py_CompileString", pycompilestring, METH_O}, {"PyTime_FromSeconds", test_pytime_fromseconds, METH_VARARGS}, {"PyTime_FromSecondsObject", test_pytime_fromsecondsobject, METH_VARARGS}, {"PyTime_AsSecondsDouble", test_pytime_assecondsdouble, METH_VARARGS}, diff --git a/Parser/pegen.c b/Parser/pegen.c index 2931a40560867..15879a64f279c 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -1463,7 +1463,7 @@ _PyPegen_run_parser_from_string(const char *str, int start_rule, PyObject *filen int exec_input = start_rule == Py_file_input; struct tok_state *tok; - if (flags == NULL || flags->cf_flags & PyCF_IGNORE_COOKIE) { + if (flags != NULL && flags->cf_flags & PyCF_IGNORE_COOKIE) { tok = _PyTokenizer_FromUTF8(str, exec_input); } else { tok = _PyTokenizer_FromString(str, exec_input); From webhook-mailer at python.org Tue Nov 16 17:31:50 2021 From: webhook-mailer at python.org (pablogsal) Date: Tue, 16 Nov 2021 22:31:50 -0000 Subject: [Python-checkins] [3.10] bpo-45716: Improve the error message when using True/False/None as keywords in a call (GH-29413). (GH-29428) Message-ID: https://github.com/python/cpython/commit/5618c81e139419b4665dc1f1e8a468738546f542 commit: 5618c81e139419b4665dc1f1e8a468738546f542 branch: 3.10 author: Pablo Galindo Salgado committer: pablogsal date: 2021-11-16T22:31:16Z summary: [3.10] bpo-45716: Improve the error message when using True/False/None as keywords in a call (GH-29413). (GH-29428) (cherry picked from commit e2d65630f36712dbdbf7711520c985c526a5cc25) Co-authored-by: Pablo Galindo Salgado files: A Misc/NEWS.d/next/Core and Builtins/2021-11-04-20-19-07.bpo-45716.5C0pA1.rst M Grammar/python.gram M Lib/test/test_syntax.py M Parser/parser.c diff --git a/Grammar/python.gram b/Grammar/python.gram index 24f5fb43f7870..7934ccdfcc5aa 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -838,6 +838,8 @@ invalid_arguments: RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, asdl_seq_GET(b, b->size-1)->target, "Generator expression must be parenthesized") } | a=args ',' args { _PyPegen_arguments_parsing_error(p, a) } invalid_kwarg: + | a[Token*]=('True'|'False'|'None') b='=' { + RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "cannot assign to %s", PyBytes_AS_STRING(a->bytes)) } | a=NAME b='=' expression for_if_clauses { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "invalid syntax. Maybe you meant '==' or ':=' instead of '='?")} | !(NAME '=') a=expression b='=' { diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 3b79b7a0b67b6..8f961c6bfdbba 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -524,9 +524,15 @@ >>> f((x)=2) Traceback (most recent call last): SyntaxError: expression cannot contain assignment, perhaps you meant "=="? ->>> f(True=2) +>>> f(True=1) Traceback (most recent call last): -SyntaxError: expression cannot contain assignment, perhaps you meant "=="? +SyntaxError: cannot assign to True +>>> f(False=1) +Traceback (most recent call last): +SyntaxError: cannot assign to False +>>> f(None=1) +Traceback (most recent call last): +SyntaxError: cannot assign to None >>> f(__debug__=1) Traceback (most recent call last): SyntaxError: cannot assign to __debug__ diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-04-20-19-07.bpo-45716.5C0pA1.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-04-20-19-07.bpo-45716.5C0pA1.rst new file mode 100644 index 0000000000000..682900c295416 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-04-20-19-07.bpo-45716.5C0pA1.rst @@ -0,0 +1,2 @@ +Improve the :exc:`SyntaxError` message when using ``True``, ``None`` or +``False`` as keywords in a function call. Patch by Pablo Galindo. diff --git a/Parser/parser.c b/Parser/parser.c index fc0347135ff3f..bda24a3de52ce 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -440,38 +440,38 @@ static char *soft_keywords[] = { #define _tmp_145_type 1366 #define _tmp_146_type 1367 #define _tmp_147_type 1368 -#define _loop0_148_type 1369 +#define _tmp_148_type 1369 #define _loop0_149_type 1370 #define _loop0_150_type 1371 -#define _tmp_151_type 1372 +#define _loop0_151_type 1372 #define _tmp_152_type 1373 #define _tmp_153_type 1374 #define _tmp_154_type 1375 -#define _loop0_155_type 1376 -#define _loop1_156_type 1377 -#define _loop0_157_type 1378 -#define _loop1_158_type 1379 -#define _tmp_159_type 1380 +#define _tmp_155_type 1376 +#define _loop0_156_type 1377 +#define _loop1_157_type 1378 +#define _loop0_158_type 1379 +#define _loop1_159_type 1380 #define _tmp_160_type 1381 #define _tmp_161_type 1382 -#define _loop0_163_type 1383 -#define _gather_162_type 1384 -#define _loop0_165_type 1385 -#define _gather_164_type 1386 -#define _loop0_167_type 1387 -#define _gather_166_type 1388 -#define _loop0_169_type 1389 -#define _gather_168_type 1390 -#define _tmp_170_type 1391 +#define _tmp_162_type 1383 +#define _loop0_164_type 1384 +#define _gather_163_type 1385 +#define _loop0_166_type 1386 +#define _gather_165_type 1387 +#define _loop0_168_type 1388 +#define _gather_167_type 1389 +#define _loop0_170_type 1390 +#define _gather_169_type 1391 #define _tmp_171_type 1392 #define _tmp_172_type 1393 #define _tmp_173_type 1394 #define _tmp_174_type 1395 #define _tmp_175_type 1396 #define _tmp_176_type 1397 -#define _loop0_178_type 1398 -#define _gather_177_type 1399 -#define _tmp_179_type 1400 +#define _tmp_177_type 1398 +#define _loop0_179_type 1399 +#define _gather_178_type 1400 #define _tmp_180_type 1401 #define _tmp_181_type 1402 #define _tmp_182_type 1403 @@ -498,6 +498,7 @@ static char *soft_keywords[] = { #define _tmp_203_type 1424 #define _tmp_204_type 1425 #define _tmp_205_type 1426 +#define _tmp_206_type 1427 static mod_ty file_rule(Parser *p); static mod_ty interactive_rule(Parser *p); @@ -868,38 +869,38 @@ static void *_tmp_144_rule(Parser *p); static void *_tmp_145_rule(Parser *p); static void *_tmp_146_rule(Parser *p); static void *_tmp_147_rule(Parser *p); -static asdl_seq *_loop0_148_rule(Parser *p); +static void *_tmp_148_rule(Parser *p); static asdl_seq *_loop0_149_rule(Parser *p); static asdl_seq *_loop0_150_rule(Parser *p); -static void *_tmp_151_rule(Parser *p); +static asdl_seq *_loop0_151_rule(Parser *p); static void *_tmp_152_rule(Parser *p); static void *_tmp_153_rule(Parser *p); static void *_tmp_154_rule(Parser *p); -static asdl_seq *_loop0_155_rule(Parser *p); -static asdl_seq *_loop1_156_rule(Parser *p); -static asdl_seq *_loop0_157_rule(Parser *p); -static asdl_seq *_loop1_158_rule(Parser *p); -static void *_tmp_159_rule(Parser *p); +static void *_tmp_155_rule(Parser *p); +static asdl_seq *_loop0_156_rule(Parser *p); +static asdl_seq *_loop1_157_rule(Parser *p); +static asdl_seq *_loop0_158_rule(Parser *p); +static asdl_seq *_loop1_159_rule(Parser *p); static void *_tmp_160_rule(Parser *p); static void *_tmp_161_rule(Parser *p); -static asdl_seq *_loop0_163_rule(Parser *p); -static asdl_seq *_gather_162_rule(Parser *p); -static asdl_seq *_loop0_165_rule(Parser *p); -static asdl_seq *_gather_164_rule(Parser *p); -static asdl_seq *_loop0_167_rule(Parser *p); -static asdl_seq *_gather_166_rule(Parser *p); -static asdl_seq *_loop0_169_rule(Parser *p); -static asdl_seq *_gather_168_rule(Parser *p); -static void *_tmp_170_rule(Parser *p); +static void *_tmp_162_rule(Parser *p); +static asdl_seq *_loop0_164_rule(Parser *p); +static asdl_seq *_gather_163_rule(Parser *p); +static asdl_seq *_loop0_166_rule(Parser *p); +static asdl_seq *_gather_165_rule(Parser *p); +static asdl_seq *_loop0_168_rule(Parser *p); +static asdl_seq *_gather_167_rule(Parser *p); +static asdl_seq *_loop0_170_rule(Parser *p); +static asdl_seq *_gather_169_rule(Parser *p); static void *_tmp_171_rule(Parser *p); static void *_tmp_172_rule(Parser *p); static void *_tmp_173_rule(Parser *p); static void *_tmp_174_rule(Parser *p); static void *_tmp_175_rule(Parser *p); static void *_tmp_176_rule(Parser *p); -static asdl_seq *_loop0_178_rule(Parser *p); -static asdl_seq *_gather_177_rule(Parser *p); -static void *_tmp_179_rule(Parser *p); +static void *_tmp_177_rule(Parser *p); +static asdl_seq *_loop0_179_rule(Parser *p); +static asdl_seq *_gather_178_rule(Parser *p); static void *_tmp_180_rule(Parser *p); static void *_tmp_181_rule(Parser *p); static void *_tmp_182_rule(Parser *p); @@ -926,6 +927,7 @@ static void *_tmp_202_rule(Parser *p); static void *_tmp_203_rule(Parser *p); static void *_tmp_204_rule(Parser *p); static void *_tmp_205_rule(Parser *p); +static void *_tmp_206_rule(Parser *p); // file: statements? $ @@ -17991,7 +17993,10 @@ invalid_arguments_rule(Parser *p) return _res; } -// invalid_kwarg: NAME '=' expression for_if_clauses | !(NAME '=') expression '=' +// invalid_kwarg: +// | ('True' | 'False' | 'None') '=' +// | NAME '=' expression for_if_clauses +// | !(NAME '=') expression '=' static void * invalid_kwarg_rule(Parser *p) { @@ -18002,6 +18007,33 @@ invalid_kwarg_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; + { // ('True' | 'False' | 'None') '=' + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> invalid_kwarg[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('True' | 'False' | 'None') '='")); + Token* a; + Token * b; + if ( + (a = (Token*)_tmp_142_rule(p)) // 'True' | 'False' | 'None' + && + (b = _PyPegen_expect_token(p, 22)) // token='=' + ) + { + D(fprintf(stderr, "%*c+ invalid_kwarg[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "('True' | 'False' | 'None') '='")); + _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot assign to %s" , PyBytes_AS_STRING ( a -> bytes ) ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + D(p->level--); + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s invalid_kwarg[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('True' | 'False' | 'None') '='")); + } { // NAME '=' expression for_if_clauses if (p->error_indicator) { D(p->level--); @@ -18044,7 +18076,7 @@ invalid_kwarg_rule(Parser *p) expr_ty a; Token * b; if ( - _PyPegen_lookahead(0, _tmp_142_rule, p) + _PyPegen_lookahead(0, _tmp_143_rule, p) && (a = expression_rule(p)) // expression && @@ -18270,7 +18302,7 @@ invalid_expression_rule(Parser *p) expr_ty a; expr_ty b; if ( - _PyPegen_lookahead(0, _tmp_143_rule, p) + _PyPegen_lookahead(0, _tmp_144_rule, p) && (a = disjunction_rule(p)) // disjunction && @@ -18306,7 +18338,7 @@ invalid_expression_rule(Parser *p) && (b = disjunction_rule(p)) // disjunction && - _PyPegen_lookahead(0, _tmp_144_rule, p) + _PyPegen_lookahead(0, _tmp_145_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction !('else' | ':')")); @@ -18388,7 +18420,7 @@ invalid_named_expression_rule(Parser *p) && (b = bitwise_or_rule(p)) // bitwise_or && - _PyPegen_lookahead(0, _tmp_145_rule, p) + _PyPegen_lookahead(0, _tmp_146_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' bitwise_or !('=' | ':=')")); @@ -18414,7 +18446,7 @@ invalid_named_expression_rule(Parser *p) Token * b; expr_ty bitwise_or_var; if ( - _PyPegen_lookahead(0, _tmp_146_rule, p) + _PyPegen_lookahead(0, _tmp_147_rule, p) && (a = bitwise_or_rule(p)) // bitwise_or && @@ -18422,7 +18454,7 @@ invalid_named_expression_rule(Parser *p) && (bitwise_or_var = bitwise_or_rule(p)) // bitwise_or && - _PyPegen_lookahead(0, _tmp_147_rule, p) + _PyPegen_lookahead(0, _tmp_148_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!(list | tuple | genexp | 'True' | 'None' | 'False') bitwise_or '=' bitwise_or !('=' | ':=')")); @@ -18499,7 +18531,7 @@ invalid_assignment_rule(Parser *p) D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions* ':' expression")); Token * _literal; Token * _literal_1; - asdl_seq * _loop0_148_var; + asdl_seq * _loop0_149_var; expr_ty a; expr_ty expression_var; if ( @@ -18507,7 +18539,7 @@ invalid_assignment_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_loop0_148_var = _loop0_148_rule(p)) // star_named_expressions* + (_loop0_149_var = _loop0_149_rule(p)) // star_named_expressions* && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -18564,10 +18596,10 @@ invalid_assignment_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* star_expressions '='")); Token * _literal; - asdl_seq * _loop0_149_var; + asdl_seq * _loop0_150_var; expr_ty a; if ( - (_loop0_149_var = _loop0_149_rule(p)) // ((star_targets '='))* + (_loop0_150_var = _loop0_150_rule(p)) // ((star_targets '='))* && (a = star_expressions_rule(p)) // star_expressions && @@ -18594,10 +18626,10 @@ invalid_assignment_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* yield_expr '='")); Token * _literal; - asdl_seq * _loop0_150_var; + asdl_seq * _loop0_151_var; expr_ty a; if ( - (_loop0_150_var = _loop0_150_rule(p)) // ((star_targets '='))* + (_loop0_151_var = _loop0_151_rule(p)) // ((star_targets '='))* && (a = yield_expr_rule(p)) // yield_expr && @@ -18623,7 +18655,7 @@ invalid_assignment_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions augassign (yield_expr | star_expressions)")); - void *_tmp_151_var; + void *_tmp_152_var; expr_ty a; AugOperator* augassign_var; if ( @@ -18631,7 +18663,7 @@ invalid_assignment_rule(Parser *p) && (augassign_var = augassign_rule(p)) // augassign && - (_tmp_151_var = _tmp_151_rule(p)) // yield_expr | star_expressions + (_tmp_152_var = _tmp_152_rule(p)) // yield_expr | star_expressions ) { D(fprintf(stderr, "%*c+ invalid_assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions augassign (yield_expr | star_expressions)")); @@ -18890,11 +18922,11 @@ invalid_comprehension_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '(' | '{') starred_expression for_if_clauses")); - void *_tmp_152_var; + void *_tmp_153_var; expr_ty a; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_152_var = _tmp_152_rule(p)) // '[' | '(' | '{' + (_tmp_153_var = _tmp_153_rule(p)) // '[' | '(' | '{' && (a = starred_expression_rule(p)) // starred_expression && @@ -18921,12 +18953,12 @@ invalid_comprehension_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '{') star_named_expression ',' star_named_expressions for_if_clauses")); Token * _literal; - void *_tmp_153_var; + void *_tmp_154_var; expr_ty a; asdl_expr_seq* b; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_153_var = _tmp_153_rule(p)) // '[' | '{' + (_tmp_154_var = _tmp_154_rule(p)) // '[' | '{' && (a = star_named_expression_rule(p)) // star_named_expression && @@ -18956,12 +18988,12 @@ invalid_comprehension_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '{') star_named_expression ',' for_if_clauses")); - void *_tmp_154_var; + void *_tmp_155_var; expr_ty a; Token * b; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_154_var = _tmp_154_rule(p)) // '[' | '{' + (_tmp_155_var = _tmp_155_rule(p)) // '[' | '{' && (a = star_named_expression_rule(p)) // star_named_expression && @@ -19059,11 +19091,11 @@ invalid_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* invalid_parameters_helper param_no_default")); - asdl_seq * _loop0_155_var; + asdl_seq * _loop0_156_var; arg_ty a; void *invalid_parameters_helper_var; if ( - (_loop0_155_var = _loop0_155_rule(p)) // param_no_default* + (_loop0_156_var = _loop0_156_rule(p)) // param_no_default* && (invalid_parameters_helper_var = invalid_parameters_helper_rule(p)) // invalid_parameters_helper && @@ -19130,13 +19162,13 @@ invalid_parameters_helper_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default+")); - asdl_seq * _loop1_156_var; + asdl_seq * _loop1_157_var; if ( - (_loop1_156_var = _loop1_156_rule(p)) // param_with_default+ + (_loop1_157_var = _loop1_157_rule(p)) // param_with_default+ ) { D(fprintf(stderr, "%*c+ invalid_parameters_helper[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_with_default+")); - _res = _loop1_156_var; + _res = _loop1_157_var; goto done; } p->mark = _mark; @@ -19167,11 +19199,11 @@ invalid_lambda_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* invalid_lambda_parameters_helper lambda_param_no_default")); - asdl_seq * _loop0_157_var; + asdl_seq * _loop0_158_var; arg_ty a; void *invalid_lambda_parameters_helper_var; if ( - (_loop0_157_var = _loop0_157_rule(p)) // lambda_param_no_default* + (_loop0_158_var = _loop0_158_rule(p)) // lambda_param_no_default* && (invalid_lambda_parameters_helper_var = invalid_lambda_parameters_helper_rule(p)) // invalid_lambda_parameters_helper && @@ -19240,13 +19272,13 @@ invalid_lambda_parameters_helper_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+")); - asdl_seq * _loop1_158_var; + asdl_seq * _loop1_159_var; if ( - (_loop1_158_var = _loop1_158_rule(p)) // lambda_param_with_default+ + (_loop1_159_var = _loop1_159_rule(p)) // lambda_param_with_default+ ) { D(fprintf(stderr, "%*c+ invalid_lambda_parameters_helper[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+")); - _res = _loop1_158_var; + _res = _loop1_159_var; goto done; } p->mark = _mark; @@ -19276,12 +19308,12 @@ invalid_star_etc_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))")); - void *_tmp_159_var; + void *_tmp_160_var; Token * a; if ( (a = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_159_var = _tmp_159_rule(p)) // ')' | ',' (')' | '**') + (_tmp_160_var = _tmp_160_rule(p)) // ')' | ',' (')' | '**') ) { D(fprintf(stderr, "%*c+ invalid_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))")); @@ -19351,11 +19383,11 @@ invalid_lambda_star_etc_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))")); Token * _literal; - void *_tmp_160_var; + void *_tmp_161_var; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_160_var = _tmp_160_rule(p)) // ':' | ',' (':' | '**') + (_tmp_161_var = _tmp_161_rule(p)) // ':' | ',' (':' | '**') ) { D(fprintf(stderr, "%*c+ invalid_lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))")); @@ -19457,7 +19489,7 @@ invalid_with_item_rule(Parser *p) && (a = expression_rule(p)) // expression && - _PyPegen_lookahead(1, _tmp_161_rule, p) + _PyPegen_lookahead(1, _tmp_162_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_with_item[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression 'as' expression &(',' | ')' | ':')")); @@ -19673,7 +19705,7 @@ invalid_with_stmt_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' ','.(expression ['as' star_target])+ &&':'")); - asdl_seq * _gather_162_var; + asdl_seq * _gather_163_var; Token * _keyword; Token * _literal; void *_opt_var; @@ -19683,13 +19715,13 @@ invalid_with_stmt_rule(Parser *p) && (_keyword = _PyPegen_expect_token(p, 519)) // token='with' && - (_gather_162_var = _gather_162_rule(p)) // ','.(expression ['as' star_target])+ + (_gather_163_var = _gather_163_rule(p)) // ','.(expression ['as' star_target])+ && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' ) { D(fprintf(stderr, "%*c+ invalid_with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' ','.(expression ['as' star_target])+ &&':'")); - _res = _PyPegen_dummy_name(p, _opt_var, _keyword, _gather_162_var, _literal); + _res = _PyPegen_dummy_name(p, _opt_var, _keyword, _gather_163_var, _literal); goto done; } p->mark = _mark; @@ -19702,7 +19734,7 @@ invalid_with_stmt_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' &&':'")); - asdl_seq * _gather_164_var; + asdl_seq * _gather_165_var; Token * _keyword; Token * _literal; Token * _literal_1; @@ -19718,7 +19750,7 @@ invalid_with_stmt_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_164_var = _gather_164_rule(p)) // ','.(expressions ['as' star_target])+ + (_gather_165_var = _gather_165_rule(p)) // ','.(expressions ['as' star_target])+ && (_opt_var_1 = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -19728,7 +19760,7 @@ invalid_with_stmt_rule(Parser *p) ) { D(fprintf(stderr, "%*c+ invalid_with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' &&':'")); - _res = _PyPegen_dummy_name(p, _opt_var, _keyword, _literal, _gather_164_var, _opt_var_1, _literal_1, _literal_2); + _res = _PyPegen_dummy_name(p, _opt_var, _keyword, _literal, _gather_165_var, _opt_var_1, _literal_1, _literal_2); goto done; } p->mark = _mark; @@ -19760,7 +19792,7 @@ invalid_with_stmt_indent_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' ','.(expression ['as' star_target])+ ':' NEWLINE !INDENT")); - asdl_seq * _gather_166_var; + asdl_seq * _gather_167_var; Token * _literal; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings @@ -19771,7 +19803,7 @@ invalid_with_stmt_indent_rule(Parser *p) && (a = _PyPegen_expect_token(p, 519)) // token='with' && - (_gather_166_var = _gather_166_rule(p)) // ','.(expression ['as' star_target])+ + (_gather_167_var = _gather_167_rule(p)) // ','.(expression ['as' star_target])+ && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -19799,7 +19831,7 @@ invalid_with_stmt_indent_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' ':' NEWLINE !INDENT")); - asdl_seq * _gather_168_var; + asdl_seq * _gather_169_var; Token * _literal; Token * _literal_1; Token * _literal_2; @@ -19816,7 +19848,7 @@ invalid_with_stmt_indent_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_168_var = _gather_168_rule(p)) // ','.(expressions ['as' star_target])+ + (_gather_169_var = _gather_169_rule(p)) // ','.(expressions ['as' star_target])+ && (_opt_var_1 = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -19907,7 +19939,7 @@ invalid_try_stmt_rule(Parser *p) && (block_var = block_rule(p)) // block && - _PyPegen_lookahead(0, _tmp_170_rule, p) + _PyPegen_lookahead(0, _tmp_171_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' ':' block !('except' | 'finally')")); @@ -19965,7 +19997,7 @@ invalid_except_stmt_rule(Parser *p) && (expressions_var = expressions_rule(p)) // expressions && - (_opt_var = _tmp_171_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_172_rule(p), !p->error_indicator) // ['as' NAME] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' ) @@ -19999,7 +20031,7 @@ invalid_except_stmt_rule(Parser *p) && (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_172_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_173_rule(p), !p->error_indicator) // ['as' NAME] && (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) @@ -20129,7 +20161,7 @@ invalid_except_stmt_indent_rule(Parser *p) && (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_173_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_174_rule(p), !p->error_indicator) // ['as' NAME] && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -20513,7 +20545,7 @@ invalid_class_argument_pattern_rule(Parser *p) asdl_pattern_seq* a; asdl_seq* keyword_patterns_var; if ( - (_opt_var = _tmp_174_rule(p), !p->error_indicator) // [positional_patterns ','] + (_opt_var = _tmp_175_rule(p), !p->error_indicator) // [positional_patterns ','] && (keyword_patterns_var = keyword_patterns_rule(p)) // keyword_patterns && @@ -20947,7 +20979,7 @@ invalid_def_raw_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' && - (_opt_var_2 = _tmp_175_rule(p), !p->error_indicator) // ['->' expression] + (_opt_var_2 = _tmp_176_rule(p), !p->error_indicator) // ['->' expression] && (_literal_2 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -21003,7 +21035,7 @@ invalid_class_def_raw_rule(Parser *p) && (name_var = _PyPegen_name_token(p)) // NAME && - (_opt_var = _tmp_176_rule(p), !p->error_indicator) // ['(' arguments? ')'] + (_opt_var = _tmp_177_rule(p), !p->error_indicator) // ['(' arguments? ')'] && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -21051,11 +21083,11 @@ invalid_double_starred_kvpairs_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_double_starred_kvpairs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ',' invalid_kvpair")); - asdl_seq * _gather_177_var; + asdl_seq * _gather_178_var; Token * _literal; void *invalid_kvpair_var; if ( - (_gather_177_var = _gather_177_rule(p)) // ','.double_starred_kvpair+ + (_gather_178_var = _gather_178_rule(p)) // ','.double_starred_kvpair+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && @@ -21063,7 +21095,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) ) { D(fprintf(stderr, "%*c+ invalid_double_starred_kvpairs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ',' invalid_kvpair")); - _res = _PyPegen_dummy_name(p, _gather_177_var, _literal, invalid_kvpair_var); + _res = _PyPegen_dummy_name(p, _gather_178_var, _literal, invalid_kvpair_var); goto done; } p->mark = _mark; @@ -21116,7 +21148,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) && (a = _PyPegen_expect_token(p, 11)) // token=':' && - _PyPegen_lookahead(1, _tmp_179_rule, p) + _PyPegen_lookahead(1, _tmp_180_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_double_starred_kvpairs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' &('}' | ',')")); @@ -22489,12 +22521,12 @@ _loop1_22_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_22[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_180_var; + void *_tmp_181_var; while ( - (_tmp_180_var = _tmp_180_rule(p)) // star_targets '=' + (_tmp_181_var = _tmp_181_rule(p)) // star_targets '=' ) { - _res = _tmp_180_var; + _res = _tmp_181_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -22997,12 +23029,12 @@ _loop0_31_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_31[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); - void *_tmp_181_var; + void *_tmp_182_var; while ( - (_tmp_181_var = _tmp_181_rule(p)) // '.' | '...' + (_tmp_182_var = _tmp_182_rule(p)) // '.' | '...' ) { - _res = _tmp_181_var; + _res = _tmp_182_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -23063,12 +23095,12 @@ _loop1_32_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_32[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); - void *_tmp_182_var; + void *_tmp_183_var; while ( - (_tmp_182_var = _tmp_182_rule(p)) // '.' | '...' + (_tmp_183_var = _tmp_183_rule(p)) // '.' | '...' ) { - _res = _tmp_182_var; + _res = _tmp_183_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -26179,12 +26211,12 @@ _loop1_84_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_84[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('@' named_expression NEWLINE)")); - void *_tmp_183_var; + void *_tmp_184_var; while ( - (_tmp_183_var = _tmp_183_rule(p)) // '@' named_expression NEWLINE + (_tmp_184_var = _tmp_184_rule(p)) // '@' named_expression NEWLINE ) { - _res = _tmp_183_var; + _res = _tmp_184_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -26297,12 +26329,12 @@ _loop1_86_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_86[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_expression)")); - void *_tmp_184_var; + void *_tmp_185_var; while ( - (_tmp_184_var = _tmp_184_rule(p)) // ',' star_expression + (_tmp_185_var = _tmp_185_rule(p)) // ',' star_expression ) { - _res = _tmp_184_var; + _res = _tmp_185_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -26482,12 +26514,12 @@ _loop1_89_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_89[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' expression)")); - void *_tmp_185_var; + void *_tmp_186_var; while ( - (_tmp_185_var = _tmp_185_rule(p)) // ',' expression + (_tmp_186_var = _tmp_186_rule(p)) // ',' expression ) { - _res = _tmp_185_var; + _res = _tmp_186_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -27512,12 +27544,12 @@ _loop1_104_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_104[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('or' conjunction)")); - void *_tmp_186_var; + void *_tmp_187_var; while ( - (_tmp_186_var = _tmp_186_rule(p)) // 'or' conjunction + (_tmp_187_var = _tmp_187_rule(p)) // 'or' conjunction ) { - _res = _tmp_186_var; + _res = _tmp_187_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -27583,12 +27615,12 @@ _loop1_105_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_105[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('and' inversion)")); - void *_tmp_187_var; + void *_tmp_188_var; while ( - (_tmp_187_var = _tmp_187_rule(p)) // 'and' inversion + (_tmp_188_var = _tmp_188_rule(p)) // 'and' inversion ) { - _res = _tmp_187_var; + _res = _tmp_188_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -28561,12 +28593,12 @@ _loop0_121_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); - void *_tmp_188_var; + void *_tmp_189_var; while ( - (_tmp_188_var = _tmp_188_rule(p)) // 'if' disjunction + (_tmp_189_var = _tmp_189_rule(p)) // 'if' disjunction ) { - _res = _tmp_188_var; + _res = _tmp_189_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -28627,12 +28659,12 @@ _loop0_122_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); - void *_tmp_189_var; + void *_tmp_190_var; while ( - (_tmp_189_var = _tmp_189_rule(p)) // 'if' disjunction + (_tmp_190_var = _tmp_190_rule(p)) // 'if' disjunction ) { - _res = _tmp_189_var; + _res = _tmp_190_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -28698,7 +28730,7 @@ _loop0_124_rule(Parser *p) while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_190_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' + (elem = _tmp_191_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' ) { _res = elem; @@ -28762,7 +28794,7 @@ _gather_123_rule(Parser *p) void *elem; asdl_seq * seq; if ( - (elem = _tmp_190_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' + (elem = _tmp_191_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' && (seq = _loop0_124_rule(p)) // _loop0_124 ) @@ -29308,12 +29340,12 @@ _loop0_134_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); - void *_tmp_191_var; + void *_tmp_192_var; while ( - (_tmp_191_var = _tmp_191_rule(p)) // ',' star_target + (_tmp_192_var = _tmp_192_rule(p)) // ',' star_target ) { - _res = _tmp_191_var; + _res = _tmp_192_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -29488,12 +29520,12 @@ _loop1_137_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); - void *_tmp_192_var; + void *_tmp_193_var; while ( - (_tmp_192_var = _tmp_192_rule(p)) // ',' star_target + (_tmp_193_var = _tmp_193_rule(p)) // ',' star_target ) { - _res = _tmp_192_var; + _res = _tmp_193_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -29742,9 +29774,83 @@ _tmp_141_rule(Parser *p) return _res; } -// _tmp_142: NAME '=' +// _tmp_142: 'True' | 'False' | 'None' static void * _tmp_142_rule(Parser *p) +{ + D(p->level++); + if (p->error_indicator) { + D(p->level--); + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // 'True' + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); + Token * _keyword; + if ( + (_keyword = _PyPegen_expect_token(p, 524)) // token='True' + ) + { + D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); + _res = _keyword; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'True'")); + } + { // 'False' + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); + Token * _keyword; + if ( + (_keyword = _PyPegen_expect_token(p, 525)) // token='False' + ) + { + D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); + _res = _keyword; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'False'")); + } + { // 'None' + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); + Token * _keyword; + if ( + (_keyword = _PyPegen_expect_token(p, 523)) // token='None' + ) + { + D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); + _res = _keyword; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'None'")); + } + _res = NULL; + done: + D(p->level--); + return _res; +} + +// _tmp_143: NAME '=' +static void * +_tmp_143_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29758,7 +29864,7 @@ _tmp_142_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '='")); + D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '='")); Token * _literal; expr_ty name_var; if ( @@ -29767,12 +29873,12 @@ _tmp_142_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '='")); + D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '='")); _res = _PyPegen_dummy_name(p, name_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_143[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME '='")); } _res = NULL; @@ -29781,9 +29887,9 @@ _tmp_142_rule(Parser *p) return _res; } -// _tmp_143: NAME STRING | SOFT_KEYWORD +// _tmp_144: NAME STRING | SOFT_KEYWORD static void * -_tmp_143_rule(Parser *p) +_tmp_144_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29797,7 +29903,7 @@ _tmp_143_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME STRING")); + D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME STRING")); expr_ty name_var; expr_ty string_var; if ( @@ -29806,12 +29912,12 @@ _tmp_143_rule(Parser *p) (string_var = _PyPegen_string_token(p)) // STRING ) { - D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME STRING")); + D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME STRING")); _res = _PyPegen_dummy_name(p, name_var, string_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_143[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME STRING")); } { // SOFT_KEYWORD @@ -29819,18 +29925,18 @@ _tmp_143_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); + D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); expr_ty soft_keyword_var; if ( (soft_keyword_var = _PyPegen_soft_keyword_token(p)) // SOFT_KEYWORD ) { - D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); + D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); _res = soft_keyword_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_143[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "SOFT_KEYWORD")); } _res = NULL; @@ -29839,9 +29945,9 @@ _tmp_143_rule(Parser *p) return _res; } -// _tmp_144: 'else' | ':' +// _tmp_145: 'else' | ':' static void * -_tmp_144_rule(Parser *p) +_tmp_145_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29855,18 +29961,18 @@ _tmp_144_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else'")); + D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 516)) // token='else' ) { - D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else'")); + D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'else'")); } { // ':' @@ -29874,18 +29980,18 @@ _tmp_144_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } _res = NULL; @@ -29894,9 +30000,9 @@ _tmp_144_rule(Parser *p) return _res; } -// _tmp_145: '=' | ':=' +// _tmp_146: '=' | ':=' static void * -_tmp_145_rule(Parser *p) +_tmp_146_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29910,18 +30016,18 @@ _tmp_145_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); } { // ':=' @@ -29929,18 +30035,18 @@ _tmp_145_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 53)) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':='")); } _res = NULL; @@ -29949,9 +30055,9 @@ _tmp_145_rule(Parser *p) return _res; } -// _tmp_146: list | tuple | genexp | 'True' | 'None' | 'False' +// _tmp_147: list | tuple | genexp | 'True' | 'None' | 'False' static void * -_tmp_146_rule(Parser *p) +_tmp_147_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -29965,18 +30071,18 @@ _tmp_146_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); + D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); expr_ty list_var; if ( (list_var = list_rule(p)) // list ) { - D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "list")); + D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "list")); _res = list_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "list")); } { // tuple @@ -29984,18 +30090,18 @@ _tmp_146_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); + D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); expr_ty tuple_var; if ( (tuple_var = tuple_rule(p)) // tuple ) { - D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tuple")); + D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tuple")); _res = tuple_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "tuple")); } { // genexp @@ -30003,18 +30109,18 @@ _tmp_146_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); + D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); expr_ty genexp_var; if ( (genexp_var = genexp_rule(p)) // genexp ) { - D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "genexp")); + D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "genexp")); _res = genexp_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "genexp")); } { // 'True' @@ -30022,18 +30128,18 @@ _tmp_146_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); + D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 524)) // token='True' ) { - D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); + D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'True'")); } { // 'None' @@ -30041,18 +30147,18 @@ _tmp_146_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); + D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 523)) // token='None' ) { - D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); + D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'None'")); } { // 'False' @@ -30060,18 +30166,18 @@ _tmp_146_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); + D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 525)) // token='False' ) { - D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); + D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'False'")); } _res = NULL; @@ -30080,9 +30186,9 @@ _tmp_146_rule(Parser *p) return _res; } -// _tmp_147: '=' | ':=' +// _tmp_148: '=' | ':=' static void * -_tmp_147_rule(Parser *p) +_tmp_148_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30096,18 +30202,18 @@ _tmp_147_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); } { // ':=' @@ -30115,18 +30221,18 @@ _tmp_147_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 53)) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':='")); } _res = NULL; @@ -30135,9 +30241,9 @@ _tmp_147_rule(Parser *p) return _res; } -// _loop0_148: star_named_expressions +// _loop0_149: star_named_expressions static asdl_seq * -_loop0_148_rule(Parser *p) +_loop0_149_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30161,7 +30267,7 @@ _loop0_148_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expressions")); + D(fprintf(stderr, "%*c> _loop0_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expressions")); asdl_expr_seq* star_named_expressions_var; while ( (star_named_expressions_var = star_named_expressions_rule(p)) // star_named_expressions @@ -30183,7 +30289,7 @@ _loop0_148_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_148[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_149[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expressions")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30196,14 +30302,14 @@ _loop0_148_rule(Parser *p) } 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_148_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_149_type, _seq); D(p->level--); return _seq; } -// _loop0_149: (star_targets '=') +// _loop0_150: (star_targets '=') static asdl_seq * -_loop0_149_rule(Parser *p) +_loop0_150_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30227,13 +30333,13 @@ _loop0_149_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_193_var; + D(fprintf(stderr, "%*c> _loop0_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); + void *_tmp_194_var; while ( - (_tmp_193_var = _tmp_193_rule(p)) // star_targets '=' + (_tmp_194_var = _tmp_194_rule(p)) // star_targets '=' ) { - _res = _tmp_193_var; + _res = _tmp_194_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30249,7 +30355,7 @@ _loop0_149_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_149[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_150[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(star_targets '=')")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30262,14 +30368,14 @@ _loop0_149_rule(Parser *p) } 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); + _PyPegen_insert_memo(p, _start_mark, _loop0_150_type, _seq); D(p->level--); return _seq; } -// _loop0_150: (star_targets '=') +// _loop0_151: (star_targets '=') static asdl_seq * -_loop0_150_rule(Parser *p) +_loop0_151_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30293,13 +30399,13 @@ _loop0_150_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_194_var; + D(fprintf(stderr, "%*c> _loop0_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); + void *_tmp_195_var; while ( - (_tmp_194_var = _tmp_194_rule(p)) // star_targets '=' + (_tmp_195_var = _tmp_195_rule(p)) // star_targets '=' ) { - _res = _tmp_194_var; + _res = _tmp_195_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30315,7 +30421,7 @@ _loop0_150_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_150[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_151[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(star_targets '=')")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30328,14 +30434,14 @@ _loop0_150_rule(Parser *p) } 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); + _PyPegen_insert_memo(p, _start_mark, _loop0_151_type, _seq); D(p->level--); return _seq; } -// _tmp_151: yield_expr | star_expressions +// _tmp_152: yield_expr | star_expressions static void * -_tmp_151_rule(Parser *p) +_tmp_152_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30349,18 +30455,18 @@ _tmp_151_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_151[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // star_expressions @@ -30368,18 +30474,18 @@ _tmp_151_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); expr_ty star_expressions_var; if ( (star_expressions_var = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); _res = star_expressions_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_151[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); } _res = NULL; @@ -30388,9 +30494,9 @@ _tmp_151_rule(Parser *p) return _res; } -// _tmp_152: '[' | '(' | '{' +// _tmp_153: '[' | '(' | '{' static void * -_tmp_152_rule(Parser *p) +_tmp_153_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30404,18 +30510,18 @@ _tmp_152_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' ) { - D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); } { // '(' @@ -30423,18 +30529,18 @@ _tmp_152_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' ) { - D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'('")); } { // '{' @@ -30442,18 +30548,18 @@ _tmp_152_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' ) { - D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); } _res = NULL; @@ -30462,9 +30568,9 @@ _tmp_152_rule(Parser *p) return _res; } -// _tmp_153: '[' | '{' +// _tmp_154: '[' | '{' static void * -_tmp_153_rule(Parser *p) +_tmp_154_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30478,18 +30584,18 @@ _tmp_153_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' ) { - D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); } { // '{' @@ -30497,18 +30603,18 @@ _tmp_153_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' ) { - D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); } _res = NULL; @@ -30517,9 +30623,9 @@ _tmp_153_rule(Parser *p) return _res; } -// _tmp_154: '[' | '{' +// _tmp_155: '[' | '{' static void * -_tmp_154_rule(Parser *p) +_tmp_155_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30533,18 +30639,18 @@ _tmp_154_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' ) { - D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); } { // '{' @@ -30552,18 +30658,18 @@ _tmp_154_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' ) { - D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); } _res = NULL; @@ -30572,9 +30678,9 @@ _tmp_154_rule(Parser *p) return _res; } -// _loop0_155: param_no_default +// _loop0_156: param_no_default static asdl_seq * -_loop0_155_rule(Parser *p) +_loop0_156_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30598,7 +30704,7 @@ _loop0_155_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _loop0_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; while ( (param_no_default_var = param_no_default_rule(p)) // param_no_default @@ -30620,7 +30726,7 @@ _loop0_155_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_155[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_156[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30633,14 +30739,14 @@ _loop0_155_rule(Parser *p) } 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_155_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_156_type, _seq); D(p->level--); return _seq; } -// _loop1_156: param_with_default +// _loop1_157: param_with_default static asdl_seq * -_loop1_156_rule(Parser *p) +_loop1_157_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30664,7 +30770,7 @@ _loop1_156_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); + D(fprintf(stderr, "%*c> _loop1_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); NameDefaultPair* param_with_default_var; while ( (param_with_default_var = param_with_default_rule(p)) // param_with_default @@ -30686,7 +30792,7 @@ _loop1_156_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_156[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_157[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -30704,14 +30810,14 @@ _loop1_156_rule(Parser *p) } 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_156_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_157_type, _seq); D(p->level--); return _seq; } -// _loop0_157: lambda_param_no_default +// _loop0_158: lambda_param_no_default static asdl_seq * -_loop0_157_rule(Parser *p) +_loop0_158_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30735,7 +30841,7 @@ _loop0_157_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop0_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -30757,7 +30863,7 @@ _loop0_157_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_157[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_158[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30770,14 +30876,14 @@ _loop0_157_rule(Parser *p) } 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_157_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_158_type, _seq); D(p->level--); return _seq; } -// _loop1_158: lambda_param_with_default +// _loop1_159: lambda_param_with_default static asdl_seq * -_loop1_158_rule(Parser *p) +_loop1_159_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30801,7 +30907,7 @@ _loop1_158_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop1_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -30823,7 +30929,7 @@ _loop1_158_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_158[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_159[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -30841,14 +30947,14 @@ _loop1_158_rule(Parser *p) } 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_158_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_159_type, _seq); D(p->level--); return _seq; } -// _tmp_159: ')' | ',' (')' | '**') +// _tmp_160: ')' | ',' (')' | '**') static void * -_tmp_159_rule(Parser *p) +_tmp_160_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30862,18 +30968,18 @@ _tmp_159_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_159[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // ',' (')' | '**') @@ -30881,21 +30987,21 @@ _tmp_159_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); + D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); Token * _literal; - void *_tmp_195_var; + void *_tmp_196_var; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_tmp_195_var = _tmp_195_rule(p)) // ')' | '**' + (_tmp_196_var = _tmp_196_rule(p)) // ')' | '**' ) { - D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); - _res = _PyPegen_dummy_name(p, _literal, _tmp_195_var); + D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); + _res = _PyPegen_dummy_name(p, _literal, _tmp_196_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_159[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (')' | '**')")); } _res = NULL; @@ -30904,9 +31010,9 @@ _tmp_159_rule(Parser *p) return _res; } -// _tmp_160: ':' | ',' (':' | '**') +// _tmp_161: ':' | ',' (':' | '**') static void * -_tmp_160_rule(Parser *p) +_tmp_161_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30920,18 +31026,18 @@ _tmp_160_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // ',' (':' | '**') @@ -30939,21 +31045,21 @@ _tmp_160_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); + D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); Token * _literal; - void *_tmp_196_var; + void *_tmp_197_var; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_tmp_196_var = _tmp_196_rule(p)) // ':' | '**' + (_tmp_197_var = _tmp_197_rule(p)) // ':' | '**' ) { - D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); - _res = _PyPegen_dummy_name(p, _literal, _tmp_196_var); + D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); + _res = _PyPegen_dummy_name(p, _literal, _tmp_197_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (':' | '**')")); } _res = NULL; @@ -30962,9 +31068,9 @@ _tmp_160_rule(Parser *p) return _res; } -// _tmp_161: ',' | ')' | ':' +// _tmp_162: ',' | ')' | ':' static void * -_tmp_161_rule(Parser *p) +_tmp_162_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30978,18 +31084,18 @@ _tmp_161_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_162[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } { // ')' @@ -30997,18 +31103,18 @@ _tmp_161_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_162[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // ':' @@ -31016,18 +31122,18 @@ _tmp_161_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_162[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } _res = NULL; @@ -31036,9 +31142,9 @@ _tmp_161_rule(Parser *p) return _res; } -// _loop0_163: ',' (expression ['as' star_target]) +// _loop0_164: ',' (expression ['as' star_target]) static asdl_seq * -_loop0_163_rule(Parser *p) +_loop0_164_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31062,13 +31168,13 @@ _loop0_163_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_163[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_164[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_197_rule(p)) // expression ['as' star_target] + (elem = _tmp_198_rule(p)) // expression ['as' star_target] ) { _res = elem; @@ -31093,7 +31199,7 @@ _loop0_163_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_163[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_164[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expression ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31106,14 +31212,14 @@ _loop0_163_rule(Parser *p) } 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_163_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_164_type, _seq); D(p->level--); return _seq; } -// _gather_162: (expression ['as' star_target]) _loop0_163 +// _gather_163: (expression ['as' star_target]) _loop0_164 static asdl_seq * -_gather_162_rule(Parser *p) +_gather_163_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31122,27 +31228,27 @@ _gather_162_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expression ['as' star_target]) _loop0_163 + { // (expression ['as' star_target]) _loop0_164 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_163")); + D(fprintf(stderr, "%*c> _gather_163[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_164")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_197_rule(p)) // expression ['as' star_target] + (elem = _tmp_198_rule(p)) // expression ['as' star_target] && - (seq = _loop0_163_rule(p)) // _loop0_163 + (seq = _loop0_164_rule(p)) // _loop0_164 ) { - D(fprintf(stderr, "%*c+ _gather_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_163")); + D(fprintf(stderr, "%*c+ _gather_163[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_164")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_162[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_163")); + D(fprintf(stderr, "%*c%s _gather_163[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_164")); } _res = NULL; done: @@ -31150,9 +31256,9 @@ _gather_162_rule(Parser *p) return _res; } -// _loop0_165: ',' (expressions ['as' star_target]) +// _loop0_166: ',' (expressions ['as' star_target]) static asdl_seq * -_loop0_165_rule(Parser *p) +_loop0_166_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31176,13 +31282,13 @@ _loop0_165_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_198_rule(p)) // expressions ['as' star_target] + (elem = _tmp_199_rule(p)) // expressions ['as' star_target] ) { _res = elem; @@ -31207,7 +31313,7 @@ _loop0_165_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_165[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_166[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expressions ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31220,14 +31326,14 @@ _loop0_165_rule(Parser *p) } 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_165_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_166_type, _seq); D(p->level--); return _seq; } -// _gather_164: (expressions ['as' star_target]) _loop0_165 +// _gather_165: (expressions ['as' star_target]) _loop0_166 static asdl_seq * -_gather_164_rule(Parser *p) +_gather_165_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31236,27 +31342,27 @@ _gather_164_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expressions ['as' star_target]) _loop0_165 + { // (expressions ['as' star_target]) _loop0_166 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_164[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_165")); + D(fprintf(stderr, "%*c> _gather_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_166")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_198_rule(p)) // expressions ['as' star_target] + (elem = _tmp_199_rule(p)) // expressions ['as' star_target] && - (seq = _loop0_165_rule(p)) // _loop0_165 + (seq = _loop0_166_rule(p)) // _loop0_166 ) { - D(fprintf(stderr, "%*c+ _gather_164[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_165")); + D(fprintf(stderr, "%*c+ _gather_165[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_166")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_164[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_165")); + D(fprintf(stderr, "%*c%s _gather_165[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_166")); } _res = NULL; done: @@ -31264,9 +31370,9 @@ _gather_164_rule(Parser *p) return _res; } -// _loop0_167: ',' (expression ['as' star_target]) +// _loop0_168: ',' (expression ['as' star_target]) static asdl_seq * -_loop0_167_rule(Parser *p) +_loop0_168_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31290,13 +31396,13 @@ _loop0_167_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_199_rule(p)) // expression ['as' star_target] + (elem = _tmp_200_rule(p)) // expression ['as' star_target] ) { _res = elem; @@ -31321,7 +31427,7 @@ _loop0_167_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_167[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_168[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expression ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31334,14 +31440,14 @@ _loop0_167_rule(Parser *p) } 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_167_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_168_type, _seq); D(p->level--); return _seq; } -// _gather_166: (expression ['as' star_target]) _loop0_167 +// _gather_167: (expression ['as' star_target]) _loop0_168 static asdl_seq * -_gather_166_rule(Parser *p) +_gather_167_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31350,27 +31456,27 @@ _gather_166_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expression ['as' star_target]) _loop0_167 + { // (expression ['as' star_target]) _loop0_168 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_167")); + D(fprintf(stderr, "%*c> _gather_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_168")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_199_rule(p)) // expression ['as' star_target] + (elem = _tmp_200_rule(p)) // expression ['as' star_target] && - (seq = _loop0_167_rule(p)) // _loop0_167 + (seq = _loop0_168_rule(p)) // _loop0_168 ) { - D(fprintf(stderr, "%*c+ _gather_166[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_167")); + D(fprintf(stderr, "%*c+ _gather_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_168")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_166[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_167")); + D(fprintf(stderr, "%*c%s _gather_167[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_168")); } _res = NULL; done: @@ -31378,9 +31484,9 @@ _gather_166_rule(Parser *p) return _res; } -// _loop0_169: ',' (expressions ['as' star_target]) +// _loop0_170: ',' (expressions ['as' star_target]) static asdl_seq * -_loop0_169_rule(Parser *p) +_loop0_170_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31404,13 +31510,13 @@ _loop0_169_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_170[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_200_rule(p)) // expressions ['as' star_target] + (elem = _tmp_201_rule(p)) // expressions ['as' star_target] ) { _res = elem; @@ -31435,7 +31541,7 @@ _loop0_169_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_169[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_170[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expressions ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31448,14 +31554,14 @@ _loop0_169_rule(Parser *p) } 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_169_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_170_type, _seq); D(p->level--); return _seq; } -// _gather_168: (expressions ['as' star_target]) _loop0_169 +// _gather_169: (expressions ['as' star_target]) _loop0_170 static asdl_seq * -_gather_168_rule(Parser *p) +_gather_169_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31464,27 +31570,27 @@ _gather_168_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expressions ['as' star_target]) _loop0_169 + { // (expressions ['as' star_target]) _loop0_170 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_169")); + D(fprintf(stderr, "%*c> _gather_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_170")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_200_rule(p)) // expressions ['as' star_target] + (elem = _tmp_201_rule(p)) // expressions ['as' star_target] && - (seq = _loop0_169_rule(p)) // _loop0_169 + (seq = _loop0_170_rule(p)) // _loop0_170 ) { - D(fprintf(stderr, "%*c+ _gather_168[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_169")); + D(fprintf(stderr, "%*c+ _gather_169[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_170")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_168[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_169")); + D(fprintf(stderr, "%*c%s _gather_169[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_170")); } _res = NULL; done: @@ -31492,9 +31598,9 @@ _gather_168_rule(Parser *p) return _res; } -// _tmp_170: 'except' | 'finally' +// _tmp_171: 'except' | 'finally' static void * -_tmp_170_rule(Parser *p) +_tmp_171_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31508,18 +31614,18 @@ _tmp_170_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_170[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'")); + D(fprintf(stderr, "%*c> _tmp_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 521)) // token='except' ) { - D(fprintf(stderr, "%*c+ _tmp_170[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except'")); + D(fprintf(stderr, "%*c+ _tmp_171[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_170[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_171[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except'")); } { // 'finally' @@ -31527,18 +31633,18 @@ _tmp_170_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_170[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'")); + D(fprintf(stderr, "%*c> _tmp_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 522)) // token='finally' ) { - D(fprintf(stderr, "%*c+ _tmp_170[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally'")); + D(fprintf(stderr, "%*c+ _tmp_171[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_170[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_171[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'finally'")); } _res = NULL; @@ -31547,9 +31653,9 @@ _tmp_170_rule(Parser *p) return _res; } -// _tmp_171: 'as' NAME +// _tmp_172: 'as' NAME static void * -_tmp_171_rule(Parser *p) +_tmp_172_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31563,7 +31669,7 @@ _tmp_171_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_172[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( @@ -31572,12 +31678,12 @@ _tmp_171_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_171[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_172[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_171[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_172[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -31586,9 +31692,9 @@ _tmp_171_rule(Parser *p) return _res; } -// _tmp_172: 'as' NAME +// _tmp_173: 'as' NAME static void * -_tmp_172_rule(Parser *p) +_tmp_173_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31602,7 +31708,7 @@ _tmp_172_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_172[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_173[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( @@ -31611,12 +31717,12 @@ _tmp_172_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_172[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_173[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_172[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_173[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -31625,9 +31731,9 @@ _tmp_172_rule(Parser *p) return _res; } -// _tmp_173: 'as' NAME +// _tmp_174: 'as' NAME static void * -_tmp_173_rule(Parser *p) +_tmp_174_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31641,7 +31747,7 @@ _tmp_173_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_173[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_174[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( @@ -31650,12 +31756,12 @@ _tmp_173_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_173[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_174[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_173[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_174[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -31664,9 +31770,9 @@ _tmp_173_rule(Parser *p) return _res; } -// _tmp_174: positional_patterns ',' +// _tmp_175: positional_patterns ',' static void * -_tmp_174_rule(Parser *p) +_tmp_175_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31680,7 +31786,7 @@ _tmp_174_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_174[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); + D(fprintf(stderr, "%*c> _tmp_175[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); Token * _literal; asdl_pattern_seq* positional_patterns_var; if ( @@ -31689,12 +31795,12 @@ _tmp_174_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_174[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); + D(fprintf(stderr, "%*c+ _tmp_175[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); _res = _PyPegen_dummy_name(p, positional_patterns_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_174[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_175[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "positional_patterns ','")); } _res = NULL; @@ -31703,9 +31809,9 @@ _tmp_174_rule(Parser *p) return _res; } -// _tmp_175: '->' expression +// _tmp_176: '->' expression static void * -_tmp_175_rule(Parser *p) +_tmp_176_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31719,7 +31825,7 @@ _tmp_175_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_175[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); + D(fprintf(stderr, "%*c> _tmp_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); Token * _literal; expr_ty expression_var; if ( @@ -31728,12 +31834,12 @@ _tmp_175_rule(Parser *p) (expression_var = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ _tmp_175[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); + D(fprintf(stderr, "%*c+ _tmp_176[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); _res = _PyPegen_dummy_name(p, _literal, expression_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_175[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_176[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'->' expression")); } _res = NULL; @@ -31742,9 +31848,9 @@ _tmp_175_rule(Parser *p) return _res; } -// _tmp_176: '(' arguments? ')' +// _tmp_177: '(' arguments? ')' static void * -_tmp_176_rule(Parser *p) +_tmp_177_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31758,7 +31864,7 @@ _tmp_176_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c> _tmp_177[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); Token * _literal; Token * _literal_1; void *_opt_var; @@ -31771,12 +31877,12 @@ _tmp_176_rule(Parser *p) (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_176[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c+ _tmp_177[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); _res = _PyPegen_dummy_name(p, _literal, _opt_var, _literal_1); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_176[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_177[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' arguments? ')'")); } _res = NULL; @@ -31785,9 +31891,9 @@ _tmp_176_rule(Parser *p) return _res; } -// _loop0_178: ',' double_starred_kvpair +// _loop0_179: ',' double_starred_kvpair static asdl_seq * -_loop0_178_rule(Parser *p) +_loop0_179_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31811,7 +31917,7 @@ _loop0_178_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); + D(fprintf(stderr, "%*c> _loop0_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); Token * _literal; KeyValuePair* elem; while ( @@ -31842,7 +31948,7 @@ _loop0_178_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_178[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_179[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' double_starred_kvpair")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31855,14 +31961,14 @@ _loop0_178_rule(Parser *p) } 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_178_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_179_type, _seq); D(p->level--); return _seq; } -// _gather_177: double_starred_kvpair _loop0_178 +// _gather_178: double_starred_kvpair _loop0_179 static asdl_seq * -_gather_177_rule(Parser *p) +_gather_178_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31871,27 +31977,27 @@ _gather_177_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // double_starred_kvpair _loop0_178 + { // double_starred_kvpair _loop0_179 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_177[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_178")); + D(fprintf(stderr, "%*c> _gather_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_179")); KeyValuePair* elem; asdl_seq * seq; if ( (elem = double_starred_kvpair_rule(p)) // double_starred_kvpair && - (seq = _loop0_178_rule(p)) // _loop0_178 + (seq = _loop0_179_rule(p)) // _loop0_179 ) { - D(fprintf(stderr, "%*c+ _gather_177[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_178")); + D(fprintf(stderr, "%*c+ _gather_178[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_179")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_177[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_178")); + D(fprintf(stderr, "%*c%s _gather_178[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_179")); } _res = NULL; done: @@ -31899,9 +32005,9 @@ _gather_177_rule(Parser *p) return _res; } -// _tmp_179: '}' | ',' +// _tmp_180: '}' | ',' static void * -_tmp_179_rule(Parser *p) +_tmp_180_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31915,18 +32021,18 @@ _tmp_179_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_179[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_179[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } { // ',' @@ -31934,18 +32040,18 @@ _tmp_179_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_179[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_179[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -31954,9 +32060,9 @@ _tmp_179_rule(Parser *p) return _res; } -// _tmp_180: star_targets '=' +// _tmp_181: star_targets '=' static void * -_tmp_180_rule(Parser *p) +_tmp_181_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31970,7 +32076,7 @@ _tmp_180_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty z; if ( @@ -31979,7 +32085,7 @@ _tmp_180_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_181[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -31989,7 +32095,7 @@ _tmp_180_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_181[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; @@ -31998,9 +32104,9 @@ _tmp_180_rule(Parser *p) return _res; } -// _tmp_181: '.' | '...' +// _tmp_182: '.' | '...' static void * -_tmp_181_rule(Parser *p) +_tmp_182_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32014,18 +32120,18 @@ _tmp_181_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 23)) // token='.' ) { - D(fprintf(stderr, "%*c+ _tmp_181[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c+ _tmp_182[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_181[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_182[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); } { // '...' @@ -32033,18 +32139,18 @@ _tmp_181_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 52)) // token='...' ) { - D(fprintf(stderr, "%*c+ _tmp_181[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c+ _tmp_182[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_181[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_182[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'")); } _res = NULL; @@ -32053,9 +32159,9 @@ _tmp_181_rule(Parser *p) return _res; } -// _tmp_182: '.' | '...' +// _tmp_183: '.' | '...' static void * -_tmp_182_rule(Parser *p) +_tmp_183_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32069,18 +32175,18 @@ _tmp_182_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 23)) // token='.' ) { - D(fprintf(stderr, "%*c+ _tmp_182[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_182[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); } { // '...' @@ -32088,18 +32194,18 @@ _tmp_182_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 52)) // token='...' ) { - D(fprintf(stderr, "%*c+ _tmp_182[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_182[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'")); } _res = NULL; @@ -32108,9 +32214,9 @@ _tmp_182_rule(Parser *p) return _res; } -// _tmp_183: '@' named_expression NEWLINE +// _tmp_184: '@' named_expression NEWLINE static void * -_tmp_183_rule(Parser *p) +_tmp_184_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32124,7 +32230,7 @@ _tmp_183_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); + D(fprintf(stderr, "%*c> _tmp_184[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); Token * _literal; expr_ty f; Token * newline_var; @@ -32136,7 +32242,7 @@ _tmp_183_rule(Parser *p) (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) { - D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); + D(fprintf(stderr, "%*c+ _tmp_184[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); _res = f; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32146,7 +32252,7 @@ _tmp_183_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_184[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'@' named_expression NEWLINE")); } _res = NULL; @@ -32155,9 +32261,9 @@ _tmp_183_rule(Parser *p) return _res; } -// _tmp_184: ',' star_expression +// _tmp_185: ',' star_expression static void * -_tmp_184_rule(Parser *p) +_tmp_185_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32171,7 +32277,7 @@ _tmp_184_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_184[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression")); + D(fprintf(stderr, "%*c> _tmp_185[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression")); Token * _literal; expr_ty c; if ( @@ -32180,7 +32286,7 @@ _tmp_184_rule(Parser *p) (c = star_expression_rule(p)) // star_expression ) { - D(fprintf(stderr, "%*c+ _tmp_184[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression")); + D(fprintf(stderr, "%*c+ _tmp_185[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32190,7 +32296,7 @@ _tmp_184_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_184[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_185[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_expression")); } _res = NULL; @@ -32199,9 +32305,9 @@ _tmp_184_rule(Parser *p) return _res; } -// _tmp_185: ',' expression +// _tmp_186: ',' expression static void * -_tmp_185_rule(Parser *p) +_tmp_186_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32215,7 +32321,7 @@ _tmp_185_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_185[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _tmp_186[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty c; if ( @@ -32224,7 +32330,7 @@ _tmp_185_rule(Parser *p) (c = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ _tmp_185[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c+ _tmp_186[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32234,7 +32340,7 @@ _tmp_185_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_185[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_186[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } _res = NULL; @@ -32243,9 +32349,9 @@ _tmp_185_rule(Parser *p) return _res; } -// _tmp_186: 'or' conjunction +// _tmp_187: 'or' conjunction static void * -_tmp_186_rule(Parser *p) +_tmp_187_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32259,7 +32365,7 @@ _tmp_186_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_186[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); + D(fprintf(stderr, "%*c> _tmp_187[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); Token * _keyword; expr_ty c; if ( @@ -32268,7 +32374,7 @@ _tmp_186_rule(Parser *p) (c = conjunction_rule(p)) // conjunction ) { - D(fprintf(stderr, "%*c+ _tmp_186[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); + D(fprintf(stderr, "%*c+ _tmp_187[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32278,7 +32384,7 @@ _tmp_186_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_186[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_187[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'or' conjunction")); } _res = NULL; @@ -32287,9 +32393,9 @@ _tmp_186_rule(Parser *p) return _res; } -// _tmp_187: 'and' inversion +// _tmp_188: 'and' inversion static void * -_tmp_187_rule(Parser *p) +_tmp_188_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32303,7 +32409,7 @@ _tmp_187_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_187[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion")); + D(fprintf(stderr, "%*c> _tmp_188[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion")); Token * _keyword; expr_ty c; if ( @@ -32312,7 +32418,7 @@ _tmp_187_rule(Parser *p) (c = inversion_rule(p)) // inversion ) { - D(fprintf(stderr, "%*c+ _tmp_187[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion")); + D(fprintf(stderr, "%*c+ _tmp_188[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32322,7 +32428,7 @@ _tmp_187_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_187[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_188[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'and' inversion")); } _res = NULL; @@ -32331,9 +32437,9 @@ _tmp_187_rule(Parser *p) return _res; } -// _tmp_188: 'if' disjunction +// _tmp_189: 'if' disjunction static void * -_tmp_188_rule(Parser *p) +_tmp_189_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32347,7 +32453,7 @@ _tmp_188_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_188[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c> _tmp_189[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); Token * _keyword; expr_ty z; if ( @@ -32356,7 +32462,7 @@ _tmp_188_rule(Parser *p) (z = disjunction_rule(p)) // disjunction ) { - D(fprintf(stderr, "%*c+ _tmp_188[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c+ _tmp_189[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32366,7 +32472,7 @@ _tmp_188_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_188[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_189[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction")); } _res = NULL; @@ -32375,9 +32481,9 @@ _tmp_188_rule(Parser *p) return _res; } -// _tmp_189: 'if' disjunction +// _tmp_190: 'if' disjunction static void * -_tmp_189_rule(Parser *p) +_tmp_190_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32391,7 +32497,7 @@ _tmp_189_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_189[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c> _tmp_190[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); Token * _keyword; expr_ty z; if ( @@ -32400,7 +32506,7 @@ _tmp_189_rule(Parser *p) (z = disjunction_rule(p)) // disjunction ) { - D(fprintf(stderr, "%*c+ _tmp_189[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c+ _tmp_190[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32410,7 +32516,7 @@ _tmp_189_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_189[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_190[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction")); } _res = NULL; @@ -32419,9 +32525,9 @@ _tmp_189_rule(Parser *p) return _res; } -// _tmp_190: starred_expression | (assignment_expression | expression !':=') !'=' +// _tmp_191: starred_expression | (assignment_expression | expression !':=') !'=' static void * -_tmp_190_rule(Parser *p) +_tmp_191_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32435,18 +32541,18 @@ _tmp_190_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_190[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c> _tmp_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); expr_ty starred_expression_var; if ( (starred_expression_var = starred_expression_rule(p)) // starred_expression ) { - D(fprintf(stderr, "%*c+ _tmp_190[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c+ _tmp_191[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); _res = starred_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_190[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_191[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression")); } { // (assignment_expression | expression !':=') !'=' @@ -32454,20 +32560,20 @@ _tmp_190_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_190[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); - void *_tmp_201_var; + D(fprintf(stderr, "%*c> _tmp_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); + void *_tmp_202_var; if ( - (_tmp_201_var = _tmp_201_rule(p)) // assignment_expression | expression !':=' + (_tmp_202_var = _tmp_202_rule(p)) // assignment_expression | expression !':=' && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_190[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); - _res = _tmp_201_var; + D(fprintf(stderr, "%*c+ _tmp_191[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); + _res = _tmp_202_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_190[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_191[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(assignment_expression | expression !':=') !'='")); } _res = NULL; @@ -32476,9 +32582,9 @@ _tmp_190_rule(Parser *p) return _res; } -// _tmp_191: ',' star_target +// _tmp_192: ',' star_target static void * -_tmp_191_rule(Parser *p) +_tmp_192_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32492,7 +32598,7 @@ _tmp_191_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _tmp_192[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); Token * _literal; expr_ty c; if ( @@ -32501,7 +32607,7 @@ _tmp_191_rule(Parser *p) (c = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_191[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c+ _tmp_192[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32511,7 +32617,7 @@ _tmp_191_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_191[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_192[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } _res = NULL; @@ -32520,9 +32626,9 @@ _tmp_191_rule(Parser *p) return _res; } -// _tmp_192: ',' star_target +// _tmp_193: ',' star_target static void * -_tmp_192_rule(Parser *p) +_tmp_193_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32536,7 +32642,7 @@ _tmp_192_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_192[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _tmp_193[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); Token * _literal; expr_ty c; if ( @@ -32545,7 +32651,7 @@ _tmp_192_rule(Parser *p) (c = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_192[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c+ _tmp_193[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32555,7 +32661,7 @@ _tmp_192_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_192[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_193[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } _res = NULL; @@ -32564,9 +32670,9 @@ _tmp_192_rule(Parser *p) return _res; } -// _tmp_193: star_targets '=' +// _tmp_194: star_targets '=' static void * -_tmp_193_rule(Parser *p) +_tmp_194_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32580,7 +32686,7 @@ _tmp_193_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_193[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_194[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty star_targets_var; if ( @@ -32589,12 +32695,12 @@ _tmp_193_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_193[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_194[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = _PyPegen_dummy_name(p, star_targets_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_193[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_194[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; @@ -32603,9 +32709,9 @@ _tmp_193_rule(Parser *p) return _res; } -// _tmp_194: star_targets '=' +// _tmp_195: star_targets '=' static void * -_tmp_194_rule(Parser *p) +_tmp_195_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32619,7 +32725,7 @@ _tmp_194_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_194[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_195[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty star_targets_var; if ( @@ -32628,12 +32734,12 @@ _tmp_194_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_194[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_195[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = _PyPegen_dummy_name(p, star_targets_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_194[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_195[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; @@ -32642,9 +32748,9 @@ _tmp_194_rule(Parser *p) return _res; } -// _tmp_195: ')' | '**' +// _tmp_196: ')' | '**' static void * -_tmp_195_rule(Parser *p) +_tmp_196_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32658,18 +32764,18 @@ _tmp_195_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_195[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_195[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_196[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_195[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_196[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // '**' @@ -32677,18 +32783,18 @@ _tmp_195_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_195[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_195[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_196[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_195[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_196[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } _res = NULL; @@ -32697,9 +32803,9 @@ _tmp_195_rule(Parser *p) return _res; } -// _tmp_196: ':' | '**' +// _tmp_197: ':' | '**' static void * -_tmp_196_rule(Parser *p) +_tmp_197_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32713,18 +32819,18 @@ _tmp_196_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_196[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_197[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_196[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_197[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // '**' @@ -32732,18 +32838,18 @@ _tmp_196_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_196[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_197[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_196[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_197[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } _res = NULL; @@ -32752,9 +32858,9 @@ _tmp_196_rule(Parser *p) return _res; } -// _tmp_197: expression ['as' star_target] +// _tmp_198: expression ['as' star_target] static void * -_tmp_197_rule(Parser *p) +_tmp_198_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32768,22 +32874,22 @@ _tmp_197_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_198[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_202_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_203_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_197[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_198[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); _res = _PyPegen_dummy_name(p, expression_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_197[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_198[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' star_target]")); } _res = NULL; @@ -32792,9 +32898,9 @@ _tmp_197_rule(Parser *p) return _res; } -// _tmp_198: expressions ['as' star_target] +// _tmp_199: expressions ['as' star_target] static void * -_tmp_198_rule(Parser *p) +_tmp_199_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32808,22 +32914,22 @@ _tmp_198_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_198[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_199[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expressions_var; if ( (expressions_var = expressions_rule(p)) // expressions && - (_opt_var = _tmp_203_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_204_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_198[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_199[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); _res = _PyPegen_dummy_name(p, expressions_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_198[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_199[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expressions ['as' star_target]")); } _res = NULL; @@ -32832,9 +32938,9 @@ _tmp_198_rule(Parser *p) return _res; } -// _tmp_199: expression ['as' star_target] +// _tmp_200: expression ['as' star_target] static void * -_tmp_199_rule(Parser *p) +_tmp_200_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32848,22 +32954,22 @@ _tmp_199_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_199[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_200[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_204_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_205_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_199[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_200[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); _res = _PyPegen_dummy_name(p, expression_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_199[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_200[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' star_target]")); } _res = NULL; @@ -32872,9 +32978,9 @@ _tmp_199_rule(Parser *p) return _res; } -// _tmp_200: expressions ['as' star_target] +// _tmp_201: expressions ['as' star_target] static void * -_tmp_200_rule(Parser *p) +_tmp_201_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32888,22 +32994,22 @@ _tmp_200_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_200[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expressions_var; if ( (expressions_var = expressions_rule(p)) // expressions && - (_opt_var = _tmp_205_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_206_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_200[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); _res = _PyPegen_dummy_name(p, expressions_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_200[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expressions ['as' star_target]")); } _res = NULL; @@ -32912,9 +33018,9 @@ _tmp_200_rule(Parser *p) return _res; } -// _tmp_201: assignment_expression | expression !':=' +// _tmp_202: assignment_expression | expression !':=' static void * -_tmp_201_rule(Parser *p) +_tmp_202_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32928,18 +33034,18 @@ _tmp_201_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); expr_ty assignment_expression_var; if ( (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression ) { - D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); _res = assignment_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); } { // expression !':=' @@ -32947,7 +33053,7 @@ _tmp_201_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression @@ -32955,12 +33061,12 @@ _tmp_201_rule(Parser *p) _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 53) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); _res = expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression !':='")); } _res = NULL; @@ -32969,9 +33075,9 @@ _tmp_201_rule(Parser *p) return _res; } -// _tmp_202: 'as' star_target +// _tmp_203: 'as' star_target static void * -_tmp_202_rule(Parser *p) +_tmp_203_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32985,7 +33091,7 @@ _tmp_202_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( @@ -32994,12 +33100,12 @@ _tmp_202_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_203[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_203[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; @@ -33008,9 +33114,9 @@ _tmp_202_rule(Parser *p) return _res; } -// _tmp_203: 'as' star_target +// _tmp_204: 'as' star_target static void * -_tmp_203_rule(Parser *p) +_tmp_204_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -33024,7 +33130,7 @@ _tmp_203_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_204[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( @@ -33033,12 +33139,12 @@ _tmp_203_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_203[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_204[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_203[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_204[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; @@ -33047,9 +33153,9 @@ _tmp_203_rule(Parser *p) return _res; } -// _tmp_204: 'as' star_target +// _tmp_205: 'as' star_target static void * -_tmp_204_rule(Parser *p) +_tmp_205_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -33063,7 +33169,7 @@ _tmp_204_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_204[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_205[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( @@ -33072,12 +33178,12 @@ _tmp_204_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_204[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_205[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_204[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_205[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; @@ -33086,9 +33192,9 @@ _tmp_204_rule(Parser *p) return _res; } -// _tmp_205: 'as' star_target +// _tmp_206: 'as' star_target static void * -_tmp_205_rule(Parser *p) +_tmp_206_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -33102,7 +33208,7 @@ _tmp_205_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_205[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_206[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( @@ -33111,12 +33217,12 @@ _tmp_205_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_205[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_206[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_205[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_206[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; From webhook-mailer at python.org Wed Nov 17 04:08:40 2021 From: webhook-mailer at python.org (asvetlov) Date: Wed, 17 Nov 2021 09:08:40 -0000 Subject: [Python-checkins] bpo-28806: Continue work: improve the netrc library (GH-26330) Message-ID: https://github.com/python/cpython/commit/15409c720be0503131713e3d3abc1acd0da07378 commit: 15409c720be0503131713e3d3abc1acd0da07378 branch: main author: Emmanuel Arias committer: asvetlov date: 2021-11-17T11:07:54+02:00 summary: bpo-28806: Continue work: improve the netrc library (GH-26330) Continue with the improvement of the library netrc Original work and report Xiang Zhang * ?? Added by blurb_it. Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> files: A Misc/NEWS.d/next/Library/2021-05-24-13-48-34.bpo-28806.PkNw5D.rst M Doc/library/netrc.rst M Lib/netrc.py M Lib/test/test_netrc.py diff --git a/Doc/library/netrc.rst b/Doc/library/netrc.rst index 4bf7de67c1d03..88265d9b9e9e9 100644 --- a/Doc/library/netrc.rst +++ b/Doc/library/netrc.rst @@ -41,6 +41,10 @@ the Unix :program:`ftp` program and other FTP clients. .. versionchanged:: 3.10 :class:`netrc` try UTF-8 encoding before using locale specific encoding. + The entry in the netrc file no longer needs to contain all tokens. The missing + tokens' value default to an empty string. All the tokens and their values now + can contain arbitrary characters, like whitespace and non-ASCII characters. + If the login name is anonymous, it won't trigger the security check. .. exception:: NetrcParseError @@ -85,10 +89,3 @@ Instances of :class:`~netrc.netrc` have public instance variables: .. attribute:: netrc.macros Dictionary mapping macro names to string lists. - -.. note:: - - Passwords are limited to a subset of the ASCII character set. All ASCII - punctuation is allowed in passwords, however, note that whitespace and - non-printable characters are not allowed in passwords. This is a limitation - of the way the .netrc file is parsed and may be removed in the future. diff --git a/Lib/netrc.py b/Lib/netrc.py index 734d94c8a6285..c1358aac6ae02 100644 --- a/Lib/netrc.py +++ b/Lib/netrc.py @@ -19,6 +19,50 @@ def __str__(self): return "%s (%s, line %s)" % (self.msg, self.filename, self.lineno) +class _netrclex: + def __init__(self, fp): + self.lineno = 1 + self.instream = fp + self.whitespace = "\n\t\r " + self.pushback = [] + + def _read_char(self): + ch = self.instream.read(1) + if ch == "\n": + self.lineno += 1 + return ch + + def get_token(self): + if self.pushback: + return self.pushback.pop(0) + token = "" + fiter = iter(self._read_char, "") + for ch in fiter: + if ch in self.whitespace: + continue + if ch == '"': + for ch in fiter: + if ch == '"': + return token + elif ch == "\\": + ch = self._read_char() + token += ch + else: + if ch == "\\": + ch = self._read_char() + token += ch + for ch in fiter: + if ch in self.whitespace: + return token + elif ch == "\\": + ch = self._read_char() + token += ch + return token + + def push_token(self, token): + self.pushback.append(token) + + class netrc: def __init__(self, file=None): default_netrc = file is None @@ -34,9 +78,7 @@ def __init__(self, file=None): self._parse(file, fp, default_netrc) def _parse(self, file, fp, default_netrc): - lexer = shlex.shlex(fp) - lexer.wordchars += r"""!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~""" - lexer.commenters = lexer.commenters.replace('#', '') + lexer = _netrclex(fp) while 1: # Look for a machine, default, or macdef top-level keyword saved_lineno = lexer.lineno @@ -51,14 +93,19 @@ def _parse(self, file, fp, default_netrc): entryname = lexer.get_token() elif tt == 'default': entryname = 'default' - elif tt == 'macdef': # Just skip to end of macdefs + elif tt == 'macdef': entryname = lexer.get_token() self.macros[entryname] = [] - lexer.whitespace = ' \t' while 1: line = lexer.instream.readline() - if not line or line == '\012': - lexer.whitespace = ' \t\r\n' + if not line: + raise NetrcParseError( + "Macro definition missing null line terminator.", + file, lexer.lineno) + if line == '\n': + # a macro definition finished with consecutive new-line + # characters. The first \n is encountered by the + # readline() method and this is the second \n. break self.macros[entryname].append(line) continue @@ -66,53 +113,55 @@ def _parse(self, file, fp, default_netrc): raise NetrcParseError( "bad toplevel token %r" % tt, file, lexer.lineno) + if not entryname: + raise NetrcParseError("missing %r name" % tt, file, lexer.lineno) + # We're looking at start of an entry for a named machine or default. - login = '' - account = password = None + login = account = password = '' self.hosts[entryname] = {} while 1: + prev_lineno = lexer.lineno tt = lexer.get_token() - if (tt.startswith('#') or - tt in {'', 'machine', 'default', 'macdef'}): - if password: - self.hosts[entryname] = (login, account, password) - lexer.push_token(tt) - break - else: - raise NetrcParseError( - "malformed %s entry %s terminated by %s" - % (toplevel, entryname, repr(tt)), - file, lexer.lineno) + if tt.startswith('#'): + if lexer.lineno == prev_lineno: + lexer.instream.readline() + continue + if tt in {'', 'machine', 'default', 'macdef'}: + self.hosts[entryname] = (login, account, password) + lexer.push_token(tt) + break elif tt == 'login' or tt == 'user': login = lexer.get_token() elif tt == 'account': account = lexer.get_token() elif tt == 'password': - if os.name == 'posix' and default_netrc: - prop = os.fstat(fp.fileno()) - if prop.st_uid != os.getuid(): - import pwd - try: - fowner = pwd.getpwuid(prop.st_uid)[0] - except KeyError: - fowner = 'uid %s' % prop.st_uid - try: - user = pwd.getpwuid(os.getuid())[0] - except KeyError: - user = 'uid %s' % os.getuid() - raise NetrcParseError( - ("~/.netrc file owner (%s) does not match" - " current user (%s)") % (fowner, user), - file, lexer.lineno) - if (prop.st_mode & (stat.S_IRWXG | stat.S_IRWXO)): - raise NetrcParseError( - "~/.netrc access too permissive: access" - " permissions must restrict access to only" - " the owner", file, lexer.lineno) password = lexer.get_token() else: raise NetrcParseError("bad follower token %r" % tt, file, lexer.lineno) + self._security_check(fp, default_netrc, self.hosts[entryname][0]) + + def _security_check(self, fp, default_netrc, login): + if os.name == 'posix' and default_netrc and login != "anonymous": + prop = os.fstat(fp.fileno()) + if prop.st_uid != os.getuid(): + import pwd + try: + fowner = pwd.getpwuid(prop.st_uid)[0] + except KeyError: + fowner = 'uid %s' % prop.st_uid + try: + user = pwd.getpwuid(os.getuid())[0] + except KeyError: + user = 'uid %s' % os.getuid() + raise NetrcParseError( + (f"~/.netrc file owner ({fowner}, {user}) does not match" + " current user")) + if (prop.st_mode & (stat.S_IRWXG | stat.S_IRWXO)): + raise NetrcParseError( + "~/.netrc access too permissive: access" + " permissions must restrict access to only" + " the owner") def authenticators(self, host): """Return a (user, account, password) tuple for given host.""" diff --git a/Lib/test/test_netrc.py b/Lib/test/test_netrc.py index 90ef5cd363b3f..a6b4bc47a32c1 100644 --- a/Lib/test/test_netrc.py +++ b/Lib/test/test_netrc.py @@ -1,7 +1,7 @@ -import netrc, os, unittest, sys, tempfile, textwrap -from test import support -from test.support import os_helper +import netrc, os, unittest, sys, textwrap +from test.support import os_helper, run_unittest +temp_filename = os_helper.TESTFN class NetrcTestCase(unittest.TestCase): @@ -10,26 +10,32 @@ def make_nrc(self, test_data): mode = 'w' if sys.platform != 'cygwin': mode += 't' - temp_fd, temp_filename = tempfile.mkstemp() - with os.fdopen(temp_fd, mode=mode) as fp: + with open(temp_filename, mode) as fp: fp.write(test_data) - self.addCleanup(os.unlink, temp_filename) - return netrc.netrc(temp_filename) + try: + nrc = netrc.netrc(temp_filename) + finally: + os.unlink(temp_filename) + return nrc - def test_default(self): + def test_toplevel_non_ordered_tokens(self): nrc = self.make_nrc("""\ - machine host1.domain.com login log1 password pass1 account acct1 - default login log2 password pass2 + machine host.domain.com password pass1 login log1 account acct1 + default login log2 password pass2 account acct2 """) - self.assertEqual(nrc.hosts['host1.domain.com'], - ('log1', 'acct1', 'pass1')) - self.assertEqual(nrc.hosts['default'], ('log2', None, 'pass2')) + self.assertEqual(nrc.hosts['host.domain.com'], ('log1', 'acct1', 'pass1')) + self.assertEqual(nrc.hosts['default'], ('log2', 'acct2', 'pass2')) - nrc2 = self.make_nrc(nrc.__repr__()) - self.assertEqual(nrc.hosts, nrc2.hosts) + def test_toplevel_tokens(self): + nrc = self.make_nrc("""\ + machine host.domain.com login log1 password pass1 account acct1 + default login log2 password pass2 account acct2 + """) + self.assertEqual(nrc.hosts['host.domain.com'], ('log1', 'acct1', 'pass1')) + self.assertEqual(nrc.hosts['default'], ('log2', 'acct2', 'pass2')) def test_macros(self): - nrc = self.make_nrc("""\ + data = """\ macdef macro1 line1 line2 @@ -37,33 +43,151 @@ def test_macros(self): macdef macro2 line3 line4 - """) + + """ + nrc = self.make_nrc(data) self.assertEqual(nrc.macros, {'macro1': ['line1\n', 'line2\n'], 'macro2': ['line3\n', 'line4\n']}) + # strip the last \n + self.assertRaises(netrc.NetrcParseError, self.make_nrc, + data.rstrip(' ')[:-1]) + + def test_optional_tokens(self): + data = ( + "machine host.domain.com", + "machine host.domain.com login", + "machine host.domain.com account", + "machine host.domain.com password", + "machine host.domain.com login \"\" account", + "machine host.domain.com login \"\" password", + "machine host.domain.com account \"\" password" + ) + for item in data: + nrc = self.make_nrc(item) + self.assertEqual(nrc.hosts['host.domain.com'], ('', '', '')) + data = ( + "default", + "default login", + "default account", + "default password", + "default login \"\" account", + "default login \"\" password", + "default account \"\" password" + ) + for item in data: + nrc = self.make_nrc(item) + self.assertEqual(nrc.hosts['default'], ('', '', '')) - def _test_passwords(self, nrc, passwd): + def test_invalid_tokens(self): + data = ( + "invalid host.domain.com", + "machine host.domain.com invalid", + "machine host.domain.com login log password pass account acct invalid", + "default host.domain.com invalid", + "default host.domain.com login log password pass account acct invalid" + ) + for item in data: + self.assertRaises(netrc.NetrcParseError, self.make_nrc, item) + + def _test_token_x(self, nrc, token, value): nrc = self.make_nrc(nrc) - self.assertEqual(nrc.hosts['host.domain.com'], ('log', 'acct', passwd)) + if token == 'login': + self.assertEqual(nrc.hosts['host.domain.com'], (value, 'acct', 'pass')) + elif token == 'account': + self.assertEqual(nrc.hosts['host.domain.com'], ('log', value, 'pass')) + elif token == 'password': + self.assertEqual(nrc.hosts['host.domain.com'], ('log', 'acct', value)) + + def test_token_value_quotes(self): + self._test_token_x("""\ + machine host.domain.com login "log" password pass account acct + """, 'login', 'log') + self._test_token_x("""\ + machine host.domain.com login log password pass account "acct" + """, 'account', 'acct') + self._test_token_x("""\ + machine host.domain.com login log password "pass" account acct + """, 'password', 'pass') + + def test_token_value_escape(self): + self._test_token_x("""\ + machine host.domain.com login \\"log password pass account acct + """, 'login', '"log') + self._test_token_x("""\ + machine host.domain.com login "\\"log" password pass account acct + """, 'login', '"log') + self._test_token_x("""\ + machine host.domain.com login log password pass account \\"acct + """, 'account', '"acct') + self._test_token_x("""\ + machine host.domain.com login log password pass account "\\"acct" + """, 'account', '"acct') + self._test_token_x("""\ + machine host.domain.com login log password \\"pass account acct + """, 'password', '"pass') + self._test_token_x("""\ + machine host.domain.com login log password "\\"pass" account acct + """, 'password', '"pass') - def test_password_with_leading_hash(self): - self._test_passwords("""\ + def test_token_value_whitespace(self): + self._test_token_x("""\ + machine host.domain.com login "lo g" password pass account acct + """, 'login', 'lo g') + self._test_token_x("""\ + machine host.domain.com login log password "pas s" account acct + """, 'password', 'pas s') + self._test_token_x("""\ + machine host.domain.com login log password pass account "acc t" + """, 'account', 'acc t') + + def test_token_value_non_ascii(self): + self._test_token_x("""\ + machine host.domain.com login \xa1\xa2 password pass account acct + """, 'login', '\xa1\xa2') + self._test_token_x("""\ + machine host.domain.com login log password pass account \xa1\xa2 + """, 'account', '\xa1\xa2') + self._test_token_x("""\ + machine host.domain.com login log password \xa1\xa2 account acct + """, 'password', '\xa1\xa2') + + def test_token_value_leading_hash(self): + self._test_token_x("""\ + machine host.domain.com login #log password pass account acct + """, 'login', '#log') + self._test_token_x("""\ + machine host.domain.com login log password pass account #acct + """, 'account', '#acct') + self._test_token_x("""\ machine host.domain.com login log password #pass account acct - """, '#pass') + """, 'password', '#pass') - def test_password_with_trailing_hash(self): - self._test_passwords("""\ + def test_token_value_trailing_hash(self): + self._test_token_x("""\ + machine host.domain.com login log# password pass account acct + """, 'login', 'log#') + self._test_token_x("""\ + machine host.domain.com login log password pass account acct# + """, 'account', 'acct#') + self._test_token_x("""\ machine host.domain.com login log password pass# account acct - """, 'pass#') + """, 'password', 'pass#') - def test_password_with_internal_hash(self): - self._test_passwords("""\ + def test_token_value_internal_hash(self): + self._test_token_x("""\ + machine host.domain.com login lo#g password pass account acct + """, 'login', 'lo#g') + self._test_token_x("""\ + machine host.domain.com login log password pass account ac#ct + """, 'account', 'ac#ct') + self._test_token_x("""\ machine host.domain.com login log password pa#ss account acct - """, 'pa#ss') + """, 'password', 'pa#ss') def _test_comment(self, nrc, passwd='pass'): nrc = self.make_nrc(nrc) - self.assertEqual(nrc.hosts['foo.domain.com'], ('bar', None, passwd)) - self.assertEqual(nrc.hosts['bar.domain.com'], ('foo', None, 'pass')) + self.assertEqual(nrc.hosts['foo.domain.com'], ('bar', '', passwd)) + self.assertEqual(nrc.hosts['bar.domain.com'], ('foo', '', 'pass')) def test_comment_before_machine_line(self): self._test_comment("""\ @@ -86,6 +210,42 @@ def test_comment_before_machine_line_hash_only(self): machine bar.domain.com login foo password pass """) + def test_comment_after_machine_line(self): + self._test_comment("""\ + machine foo.domain.com login bar password pass + # comment + machine bar.domain.com login foo password pass + """) + self._test_comment("""\ + machine foo.domain.com login bar password pass + machine bar.domain.com login foo password pass + # comment + """) + + def test_comment_after_machine_line_no_space(self): + self._test_comment("""\ + machine foo.domain.com login bar password pass + #comment + machine bar.domain.com login foo password pass + """) + self._test_comment("""\ + machine foo.domain.com login bar password pass + machine bar.domain.com login foo password pass + #comment + """) + + def test_comment_after_machine_line_hash_only(self): + self._test_comment("""\ + machine foo.domain.com login bar password pass + # + machine bar.domain.com login foo password pass + """) + self._test_comment("""\ + machine foo.domain.com login bar password pass + machine bar.domain.com login foo password pass + # + """) + def test_comment_at_end_of_machine_line(self): self._test_comment("""\ machine foo.domain.com login bar password pass # comment @@ -109,57 +269,40 @@ def test_comment_at_end_of_machine_line_pass_has_hash(self): def test_security(self): # This test is incomplete since we are normally not run as root and # therefore can't test the file ownership being wrong. - with os_helper.temp_cwd(None) as d: - fn = os.path.join(d, '.netrc') - with open(fn, 'wt') as f: - f.write("""\ - machine foo.domain.com login bar password pass - default login foo password pass - """) - with os_helper.EnvironmentVarGuard() as environ: - environ.set('HOME', d) - os.chmod(fn, 0o600) - nrc = netrc.netrc() - self.assertEqual(nrc.hosts['foo.domain.com'], - ('bar', None, 'pass')) - os.chmod(fn, 0o622) - self.assertRaises(netrc.NetrcParseError, netrc.netrc) - - def test_file_not_found_in_home(self): - with os_helper.temp_cwd(None) as d: - with os_helper.EnvironmentVarGuard() as environ: - environ.set('HOME', d) - self.assertRaises(FileNotFoundError, netrc.netrc) - - def test_file_not_found_explicit(self): - self.assertRaises(FileNotFoundError, netrc.netrc, - file='unlikely_netrc') - - def test_home_not_set(self): - with os_helper.temp_cwd(None) as fake_home: - fake_netrc_path = os.path.join(fake_home, '.netrc') - with open(fake_netrc_path, 'w') as f: - f.write('machine foo.domain.com login bar password pass') - os.chmod(fake_netrc_path, 0o600) - - orig_expanduser = os.path.expanduser - called = [] - - def fake_expanduser(s): - called.append(s) - with os_helper.EnvironmentVarGuard() as environ: - environ.set('HOME', fake_home) - environ.set('USERPROFILE', fake_home) - result = orig_expanduser(s) - return result - - with support.swap_attr(os.path, 'expanduser', fake_expanduser): - nrc = netrc.netrc() - login, account, password = nrc.authenticators('foo.domain.com') - self.assertEqual(login, 'bar') - - self.assertTrue(called) + d = os_helper.TESTFN + os.mkdir(d) + self.addCleanup(os_helper.rmtree, d) + fn = os.path.join(d, '.netrc') + with open(fn, 'wt') as f: + f.write("""\ + machine foo.domain.com login bar password pass + default login foo password pass + """) + with os_helper.EnvironmentVarGuard() as environ: + environ.set('HOME', d) + os.chmod(fn, 0o600) + nrc = netrc.netrc() + self.assertEqual(nrc.hosts['foo.domain.com'], + ('bar', '', 'pass')) + os.chmod(fn, 0o622) + self.assertRaises(netrc.NetrcParseError, netrc.netrc) + with open(fn, 'wt') as f: + f.write("""\ + machine foo.domain.com login anonymous password pass + default login foo password pass + """) + with os_helper.EnvironmentVarGuard() as environ: + environ.set('HOME', d) + os.chmod(fn, 0o600) + nrc = netrc.netrc() + self.assertEqual(nrc.hosts['foo.domain.com'], + ('anonymous', '', 'pass')) + os.chmod(fn, 0o622) + self.assertEqual(nrc.hosts['foo.domain.com'], + ('anonymous', '', 'pass')) +def test_main(): + run_unittest(NetrcTestCase) if __name__ == "__main__": - unittest.main() + test_main() diff --git a/Misc/NEWS.d/next/Library/2021-05-24-13-48-34.bpo-28806.PkNw5D.rst b/Misc/NEWS.d/next/Library/2021-05-24-13-48-34.bpo-28806.PkNw5D.rst new file mode 100644 index 0000000000000..7783845efbcc5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-05-24-13-48-34.bpo-28806.PkNw5D.rst @@ -0,0 +1 @@ +Improve netrc library. netrc file no longer needs to contain all tokens. And if the login name is anonymous, security check is no longer need. \ No newline at end of file From webhook-mailer at python.org Wed Nov 17 05:02:00 2021 From: webhook-mailer at python.org (corona10) Date: Wed, 17 Nov 2021 10:02:00 -0000 Subject: [Python-checkins] bpo-45512: Extend `sqlite3` test suite regarding isolation levels (GH-29576) Message-ID: https://github.com/python/cpython/commit/5f9247e36a0213b0dcfd43533db5cf6570895cfd commit: 5f9247e36a0213b0dcfd43533db5cf6570895cfd branch: main author: Erlend Egeberg Aasland committer: corona10 date: 2021-11-17T19:01:54+09:00 summary: bpo-45512: Extend `sqlite3` test suite regarding isolation levels (GH-29576) files: M Lib/test/test_sqlite3/test_dbapi.py M Lib/test/test_sqlite3/test_transactions.py diff --git a/Lib/test/test_sqlite3/test_dbapi.py b/Lib/test/test_sqlite3/test_dbapi.py index 18359e1a5e2ab..4eb4e180bf117 100644 --- a/Lib/test/test_sqlite3/test_dbapi.py +++ b/Lib/test/test_sqlite3/test_dbapi.py @@ -514,14 +514,35 @@ def test_connection_init_bad_isolation_level(self): "isolation_level string must be '', 'DEFERRED', 'IMMEDIATE', or " "'EXCLUSIVE'" ) - with self.assertRaisesRegex(ValueError, msg): - memory_database(isolation_level="BOGUS") + levels = ( + "BOGUS", + " ", + "DEFERRE", + "IMMEDIAT", + "EXCLUSIV", + "DEFERREDS", + "IMMEDIATES", + "EXCLUSIVES", + ) + for level in levels: + with self.subTest(level=level): + with self.assertRaisesRegex(ValueError, msg): + memory_database(isolation_level=level) + with memory_database() as cx: + with self.assertRaisesRegex(ValueError, msg): + cx.isolation_level = level + # Check that the default level is not changed + self.assertEqual(cx.isolation_level, "") def test_connection_init_good_isolation_levels(self): for level in ("", "DEFERRED", "IMMEDIATE", "EXCLUSIVE", None): with self.subTest(level=level): with memory_database(isolation_level=level) as cx: - cx.execute("select 'ok'") + self.assertEqual(cx.isolation_level, level) + with memory_database() as cx: + self.assertEqual(cx.isolation_level, "") + cx.isolation_level = level + self.assertEqual(cx.isolation_level, level) def test_connection_reinit(self): db = ":memory:" diff --git a/Lib/test/test_sqlite3/test_transactions.py b/Lib/test/test_sqlite3/test_transactions.py index 8ea352b9ef0f9..3efa2c1e604ff 100644 --- a/Lib/test/test_sqlite3/test_transactions.py +++ b/Lib/test/test_sqlite3/test_transactions.py @@ -23,6 +23,8 @@ import os, unittest import sqlite3 as sqlite +from .test_dbapi import memory_database + def get_db_path(): return "sqlite_testdb" @@ -143,6 +145,7 @@ def test_rollback_cursor_consistency(self): with self.assertRaises(sqlite.InterfaceError): cur.fetchall() + class SpecialCommandTests(unittest.TestCase): def setUp(self): self.con = sqlite.connect(":memory:") @@ -162,6 +165,7 @@ def tearDown(self): self.cur.close() self.con.close() + class TransactionalDDL(unittest.TestCase): def setUp(self): self.con = sqlite.connect(":memory:") @@ -196,5 +200,101 @@ def tearDown(self): self.con.close() +class IsolationLevelFromInit(unittest.TestCase): + CREATE = "create table t(t)" + INSERT = "insert into t values(1)" + + def setUp(self): + self.traced = [] + + def _run_test(self, cx): + cx.execute(self.CREATE) + cx.set_trace_callback(lambda stmt: self.traced.append(stmt)) + with cx: + cx.execute(self.INSERT) + + def test_isolation_level_default(self): + with memory_database() as cx: + self._run_test(cx) + self.assertEqual(self.traced, ["BEGIN ", self.INSERT, "COMMIT"]) + + def test_isolation_level_begin(self): + with memory_database(isolation_level="") as cx: + self._run_test(cx) + self.assertEqual(self.traced, ["BEGIN ", self.INSERT, "COMMIT"]) + + def test_isolation_level_deferred(self): + with memory_database(isolation_level="DEFERRED") as cx: + self._run_test(cx) + self.assertEqual(self.traced, ["BEGIN DEFERRED", self.INSERT, "COMMIT"]) + + def test_isolation_level_immediate(self): + with memory_database(isolation_level="IMMEDIATE") as cx: + self._run_test(cx) + self.assertEqual(self.traced, + ["BEGIN IMMEDIATE", self.INSERT, "COMMIT"]) + + def test_isolation_level_exclusive(self): + with memory_database(isolation_level="EXCLUSIVE") as cx: + self._run_test(cx) + self.assertEqual(self.traced, + ["BEGIN EXCLUSIVE", self.INSERT, "COMMIT"]) + + def test_isolation_level_none(self): + with memory_database(isolation_level=None) as cx: + self._run_test(cx) + self.assertEqual(self.traced, [self.INSERT]) + + +class IsolationLevelPostInit(unittest.TestCase): + QUERY = "insert into t values(1)" + + def setUp(self): + self.cx = sqlite.connect(":memory:") + self.cx.execute("create table t(t)") + self.traced = [] + self.cx.set_trace_callback(lambda stmt: self.traced.append(stmt)) + + def tearDown(self): + self.cx.close() + + def test_isolation_level_default(self): + with self.cx: + self.cx.execute(self.QUERY) + self.assertEqual(self.traced, ["BEGIN ", self.QUERY, "COMMIT"]) + + def test_isolation_level_begin(self): + self.cx.isolation_level = "" + with self.cx: + self.cx.execute(self.QUERY) + self.assertEqual(self.traced, ["BEGIN ", self.QUERY, "COMMIT"]) + + def test_isolation_level_deferrred(self): + self.cx.isolation_level = "DEFERRED" + with self.cx: + self.cx.execute(self.QUERY) + self.assertEqual(self.traced, ["BEGIN DEFERRED", self.QUERY, "COMMIT"]) + + def test_isolation_level_immediate(self): + self.cx.isolation_level = "IMMEDIATE" + with self.cx: + self.cx.execute(self.QUERY) + self.assertEqual(self.traced, + ["BEGIN IMMEDIATE", self.QUERY, "COMMIT"]) + + def test_isolation_level_exclusive(self): + self.cx.isolation_level = "EXCLUSIVE" + with self.cx: + self.cx.execute(self.QUERY) + self.assertEqual(self.traced, + ["BEGIN EXCLUSIVE", self.QUERY, "COMMIT"]) + + def test_isolation_level_none(self): + self.cx.isolation_level = None + with self.cx: + self.cx.execute(self.QUERY) + self.assertEqual(self.traced, [self.QUERY]) + + if __name__ == "__main__": unittest.main() From webhook-mailer at python.org Wed Nov 17 07:47:40 2021 From: webhook-mailer at python.org (corona10) Date: Wed, 17 Nov 2021 12:47:40 -0000 Subject: [Python-checkins] bpo-45512: Simplify manage isolation level (GH-29562) Message-ID: https://github.com/python/cpython/commit/e002bbc6cce637171fb2b1391ffeca8643a13843 commit: e002bbc6cce637171fb2b1391ffeca8643a13843 branch: main author: Dong-hee Na committer: corona10 date: 2021-11-17T21:47:02+09:00 summary: bpo-45512: Simplify manage isolation level (GH-29562) files: M Modules/_sqlite/connection.c M Modules/_sqlite/connection.h M Modules/_sqlite/cursor.c diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index e7947671db354..f632e3359cfb9 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -71,14 +71,6 @@ class _sqlite3.Connection "pysqlite_Connection *" "clinic_state()->ConnectionTyp _Py_IDENTIFIER(cursor); -static const char * const begin_statements[] = { - "BEGIN ", - "BEGIN DEFERRED", - "BEGIN IMMEDIATE", - "BEGIN EXCLUSIVE", - NULL -}; - static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self); static void free_callback_context(callback_context *ctx); static void set_callback_context(callback_context **ctx_pp, @@ -108,25 +100,21 @@ new_statement_cache(pysqlite_Connection *self, pysqlite_state *state, return res; } -static inline const char * -begin_stmt_to_isolation_level(const char *begin_stmt) -{ - assert(begin_stmt != NULL); - - // All begin statements start with "BEGIN "; add strlen("BEGIN ") to get - // the isolation level. - return begin_stmt + 6; -} - static const char * -get_begin_statement(const char *level) +get_isolation_level(const char *level) { assert(level != NULL); - for (int i = 0; begin_statements[i] != NULL; i++) { - const char *stmt = begin_statements[i]; - const char *candidate = begin_stmt_to_isolation_level(stmt); + static const char *const allowed_levels[] = { + "", + "DEFERRED", + "IMMEDIATE", + "EXCLUSIVE", + NULL + }; + for (int i = 0; allowed_levels[i] != NULL; i++) { + const char *candidate = allowed_levels[i]; if (sqlite3_stricmp(level, candidate) == 0) { - return begin_statements[i]; + return candidate; } } PyErr_SetString(PyExc_ValueError, @@ -202,10 +190,10 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, } // Convert isolation level to begin statement. - const char *begin_statement = NULL; + const char *level = NULL; if (isolation_level != NULL) { - begin_statement = get_begin_statement(isolation_level); - if (begin_statement == NULL) { + level = get_isolation_level(isolation_level); + if (level == NULL) { return -1; } } @@ -227,7 +215,7 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, self->db = db; self->state = state; self->detect_types = detect_types; - self->begin_statement = begin_statement; + self->isolation_level = level; self->check_same_thread = check_same_thread; self->thread_ident = PyThread_get_thread_ident(); self->statement_cache = statement_cache; @@ -1345,10 +1333,8 @@ static PyObject* pysqlite_connection_get_isolation_level(pysqlite_Connection* se if (!pysqlite_check_connection(self)) { return NULL; } - if (self->begin_statement != NULL) { - const char *stmt = self->begin_statement; - const char *iso_level = begin_stmt_to_isolation_level(stmt); - return PyUnicode_FromString(iso_level); + if (self->isolation_level != NULL) { + return PyUnicode_FromString(self->isolation_level); } Py_RETURN_NONE; } @@ -1381,7 +1367,7 @@ pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* iso return -1; } if (Py_IsNone(isolation_level)) { - self->begin_statement = NULL; + self->isolation_level = NULL; // Execute a COMMIT to re-enable autocommit mode PyObject *res = pysqlite_connection_commit_impl(self); @@ -1400,11 +1386,11 @@ pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* iso PyErr_SetString(PyExc_ValueError, "embedded null character"); return -1; } - const char *stmt = get_begin_statement(cstr_level); - if (stmt == NULL) { + const char *level = get_isolation_level(cstr_level); + if (level == NULL) { return -1; } - self->begin_statement = stmt; + self->isolation_level = level; } else { PyErr_SetString(PyExc_TypeError, diff --git a/Modules/_sqlite/connection.h b/Modules/_sqlite/connection.h index 7baf63fb756e7..84f1f095cb386 100644 --- a/Modules/_sqlite/connection.h +++ b/Modules/_sqlite/connection.h @@ -42,15 +42,15 @@ typedef struct _callback_context typedef struct { PyObject_HEAD - sqlite3* db; + sqlite3 *db; pysqlite_state *state; /* the type detection mode. Only 0, PARSE_DECLTYPES, PARSE_COLNAMES or a * bitwise combination thereof makes sense */ int detect_types; - /* NULL for autocommit, otherwise a string with the BEGIN statement */ - const char* begin_statement; + /* NULL for autocommit, otherwise a string with the isolation level */ + const char *isolation_level; /* 1 if a check should be performed for each API call if the connection is * used from the same thread it was created in */ diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index 3ee1c5da9d0b4..e475d933b5315 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -430,12 +430,18 @@ static int check_cursor(pysqlite_Cursor* cur) static int begin_transaction(pysqlite_Connection *self) { + assert(self->isolation_level != NULL); int rc; Py_BEGIN_ALLOW_THREADS sqlite3_stmt *statement; - rc = sqlite3_prepare_v2(self->db, self->begin_statement, -1, &statement, - NULL); + char begin_stmt[16] = "BEGIN "; +#ifdef Py_DEBUG + size_t len = strlen(self->isolation_level); + assert(len <= 9); +#endif + (void)strcat(begin_stmt, self->isolation_level); + rc = sqlite3_prepare_v2(self->db, begin_stmt, -1, &statement, NULL); if (rc == SQLITE_OK) { (void)sqlite3_step(statement); rc = sqlite3_finalize(statement); @@ -555,7 +561,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation /* We start a transaction implicitly before a DML statement. SELECT is the only exception. See #9924. */ - if (self->connection->begin_statement + if (self->connection->isolation_level && self->statement->is_dml && sqlite3_get_autocommit(self->connection->db)) { From webhook-mailer at python.org Wed Nov 17 15:12:27 2021 From: webhook-mailer at python.org (ambv) Date: Wed, 17 Nov 2021 20:12:27 -0000 Subject: [Python-checkins] bpo-45831: _Py_DumpASCII() uses a single write() call if possible (GH-29596) Message-ID: https://github.com/python/cpython/commit/b919d8105c4d77f00509b6d3ab2073f09db640de commit: b919d8105c4d77f00509b6d3ab2073f09db640de branch: main author: Victor Stinner committer: ambv date: 2021-11-17T21:12:20+01:00 summary: bpo-45831: _Py_DumpASCII() uses a single write() call if possible (GH-29596) If the string is ASCII only and doesn't need to escape characters, write the whole string with a single write() syscall. files: A Misc/NEWS.d/next/Library/2021-11-17-19-25-37.bpo-45831.9-TojK.rst M Python/traceback.c diff --git a/Misc/NEWS.d/next/Library/2021-11-17-19-25-37.bpo-45831.9-TojK.rst b/Misc/NEWS.d/next/Library/2021-11-17-19-25-37.bpo-45831.9-TojK.rst new file mode 100644 index 0000000000000..049449ff0a4a1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-17-19-25-37.bpo-45831.9-TojK.rst @@ -0,0 +1,5 @@ +:mod:`faulthandler` can now write ASCII-only strings (like filenames and +function names) with a single write() syscall when dumping a traceback. It +reduces the risk of getting an unreadable dump when two threads or two +processes dump a traceback to the same file (like stderr) at the same time. +Patch by Victor Stinner. diff --git a/Python/traceback.c b/Python/traceback.c index 67f995a759980..8aef3d810d316 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -1072,6 +1072,26 @@ _Py_DumpASCII(int fd, PyObject *text) truncated = 0; } + // Is an ASCII string? + if (ascii->state.ascii) { + assert(kind == PyUnicode_1BYTE_KIND); + char *str = data; + + int need_escape = 0; + for (i=0; i < size; i++) { + ch = str[i]; + if (!(' ' <= ch && ch <= 126)) { + need_escape = 1; + break; + } + } + if (!need_escape) { + // The string can be written with a single write() syscall + _Py_write_noraise(fd, str, size); + goto done; + } + } + for (i=0; i < size; i++) { if (kind != PyUnicode_WCHAR_KIND) ch = PyUnicode_READ(kind, data, i); @@ -1095,6 +1115,8 @@ _Py_DumpASCII(int fd, PyObject *text) _Py_DumpHexadecimal(fd, ch, 8); } } + +done: if (truncated) { PUTS(fd, "..."); } From webhook-mailer at python.org Wed Nov 17 15:51:46 2021 From: webhook-mailer at python.org (vstinner) Date: Wed, 17 Nov 2021 20:51:46 -0000 Subject: [Python-checkins] bpo-42540: reallocation of id_mutex should not force default allocator (GH-29564) Message-ID: https://github.com/python/cpython/commit/736684b1bb67369a2e95a9f621752deead44e7ef commit: 736684b1bb67369a2e95a9f621752deead44e7ef branch: main author: Sam Gross committer: vstinner date: 2021-11-17T21:51:03+01:00 summary: bpo-42540: reallocation of id_mutex should not force default allocator (GH-29564) Unlike the other locks reinitialized by _PyRuntimeState_ReInitThreads, the "interpreters.main->id_mutex" is not freed by _PyRuntimeState_Fini and should not force the default raw allocator. files: A Misc/NEWS.d/next/Core and Builtins/2021-11-15-12-08-27.bpo-42540.V2w107.rst M Lib/test/test_os.py M Python/pystate.c diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 91611dfff0ebc..5e15340515674 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -4500,6 +4500,22 @@ def test_times(self): self.assertEqual(times.elapsed, 0) + at requires_os_func('fork') +class ForkTests(unittest.TestCase): + def test_fork(self): + # bpo-42540: ensure os.fork() with non-default memory allocator does + # not crash on exit. + code = """if 1: + import os + from test import support + pid = os.fork() + if pid != 0: + support.wait_process(pid, exitcode=0) + """ + assert_python_ok("-c", code) + assert_python_ok("-c", code, PYTHONMALLOC="malloc_debug") + + # Only test if the C version is provided, otherwise TestPEP519 already tested # the pure Python implementation. if hasattr(os, "_fspath"): diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-15-12-08-27.bpo-42540.V2w107.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-15-12-08-27.bpo-42540.V2w107.rst new file mode 100644 index 0000000000000..91160598bd3f4 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-15-12-08-27.bpo-42540.V2w107.rst @@ -0,0 +1,2 @@ +Fix crash when :func:`os.fork` is called with an active non-default +memory allocator. diff --git a/Python/pystate.c b/Python/pystate.c index 8df28078f2a4e..273982b4bd2f5 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -148,12 +148,15 @@ _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime) _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); int reinit_interp = _PyThread_at_fork_reinit(&runtime->interpreters.mutex); - int reinit_main_id = _PyThread_at_fork_reinit(&runtime->interpreters.main->id_mutex); int reinit_xidregistry = _PyThread_at_fork_reinit(&runtime->xidregistry.mutex); int reinit_unicode_ids = _PyThread_at_fork_reinit(&runtime->unicode_ids.lock); PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + /* bpo-42540: id_mutex is freed by _PyInterpreterState_Delete, which does + * not force the default allocator. */ + int reinit_main_id = _PyThread_at_fork_reinit(&runtime->interpreters.main->id_mutex); + if (reinit_interp < 0 || reinit_main_id < 0 || reinit_xidregistry < 0 From webhook-mailer at python.org Wed Nov 17 16:16:11 2021 From: webhook-mailer at python.org (miss-islington) Date: Wed, 17 Nov 2021 21:16:11 -0000 Subject: [Python-checkins] bpo-42540: reallocation of id_mutex should not force default allocator (GH-29564) Message-ID: https://github.com/python/cpython/commit/1079b3e3cb3eba7062e174ecc6c0ab20c2d0722e commit: 1079b3e3cb3eba7062e174ecc6c0ab20c2d0722e branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-17T13:16:01-08:00 summary: bpo-42540: reallocation of id_mutex should not force default allocator (GH-29564) Unlike the other locks reinitialized by _PyRuntimeState_ReInitThreads, the "interpreters.main->id_mutex" is not freed by _PyRuntimeState_Fini and should not force the default raw allocator. (cherry picked from commit 736684b1bb67369a2e95a9f621752deead44e7ef) Co-authored-by: Sam Gross files: A Misc/NEWS.d/next/Core and Builtins/2021-11-15-12-08-27.bpo-42540.V2w107.rst M Lib/test/test_os.py M Python/pystate.c diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 684e308ad3a05..0ad13d59ded37 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -4501,6 +4501,22 @@ def test_times(self): self.assertEqual(times.elapsed, 0) + at requires_os_func('fork') +class ForkTests(unittest.TestCase): + def test_fork(self): + # bpo-42540: ensure os.fork() with non-default memory allocator does + # not crash on exit. + code = """if 1: + import os + from test import support + pid = os.fork() + if pid != 0: + support.wait_process(pid, exitcode=0) + """ + assert_python_ok("-c", code) + assert_python_ok("-c", code, PYTHONMALLOC="malloc_debug") + + # Only test if the C version is provided, otherwise TestPEP519 already tested # the pure Python implementation. if hasattr(os, "_fspath"): diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-15-12-08-27.bpo-42540.V2w107.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-15-12-08-27.bpo-42540.V2w107.rst new file mode 100644 index 0000000000000..91160598bd3f4 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-15-12-08-27.bpo-42540.V2w107.rst @@ -0,0 +1,2 @@ +Fix crash when :func:`os.fork` is called with an active non-default +memory allocator. diff --git a/Python/pystate.c b/Python/pystate.c index aeebd6f61c6d7..df98eb11bb0a4 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -147,12 +147,15 @@ _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime) _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); int reinit_interp = _PyThread_at_fork_reinit(&runtime->interpreters.mutex); - int reinit_main_id = _PyThread_at_fork_reinit(&runtime->interpreters.main->id_mutex); int reinit_xidregistry = _PyThread_at_fork_reinit(&runtime->xidregistry.mutex); int reinit_unicode_ids = _PyThread_at_fork_reinit(&runtime->unicode_ids.lock); PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + /* bpo-42540: id_mutex is freed by _PyInterpreterState_Delete, which does + * not force the default allocator. */ + int reinit_main_id = _PyThread_at_fork_reinit(&runtime->interpreters.main->id_mutex); + if (reinit_interp < 0 || reinit_main_id < 0 || reinit_xidregistry < 0 From webhook-mailer at python.org Wed Nov 17 17:00:02 2021 From: webhook-mailer at python.org (ambv) Date: Wed, 17 Nov 2021 22:00:02 -0000 Subject: [Python-checkins] bpo-45831: _Py_DumpASCII() uses a single write() call if possible (GH-29596) (GH-29598) Message-ID: https://github.com/python/cpython/commit/4ffde90dccd741b04a448f2e44f0b82a41b6fe96 commit: 4ffde90dccd741b04a448f2e44f0b82a41b6fe96 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-17T22:59:19+01:00 summary: bpo-45831: _Py_DumpASCII() uses a single write() call if possible (GH-29596) (GH-29598) If the string is ASCII only and doesn't need to escape characters, write the whole string with a single write() syscall. (cherry picked from commit b919d8105c4d77f00509b6d3ab2073f09db640de) Co-authored-by: Victor Stinner files: A Misc/NEWS.d/next/Library/2021-11-17-19-25-37.bpo-45831.9-TojK.rst M Python/traceback.c diff --git a/Misc/NEWS.d/next/Library/2021-11-17-19-25-37.bpo-45831.9-TojK.rst b/Misc/NEWS.d/next/Library/2021-11-17-19-25-37.bpo-45831.9-TojK.rst new file mode 100644 index 0000000000000..049449ff0a4a1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-17-19-25-37.bpo-45831.9-TojK.rst @@ -0,0 +1,5 @@ +:mod:`faulthandler` can now write ASCII-only strings (like filenames and +function names) with a single write() syscall when dumping a traceback. It +reduces the risk of getting an unreadable dump when two threads or two +processes dump a traceback to the same file (like stderr) at the same time. +Patch by Victor Stinner. diff --git a/Python/traceback.c b/Python/traceback.c index 284c18119daf0..7d6f7f435a6ba 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -717,6 +717,26 @@ _Py_DumpASCII(int fd, PyObject *text) truncated = 0; } + // Is an ASCII string? + if (ascii->state.ascii) { + assert(kind == PyUnicode_1BYTE_KIND); + char *str = data; + + int need_escape = 0; + for (i=0; i < size; i++) { + ch = str[i]; + if (!(' ' <= ch && ch <= 126)) { + need_escape = 1; + break; + } + } + if (!need_escape) { + // The string can be written with a single write() syscall + _Py_write_noraise(fd, str, size); + goto done; + } + } + for (i=0; i < size; i++) { if (kind != PyUnicode_WCHAR_KIND) ch = PyUnicode_READ(kind, data, i); @@ -740,6 +760,8 @@ _Py_DumpASCII(int fd, PyObject *text) _Py_DumpHexadecimal(fd, ch, 8); } } + +done: if (truncated) { PUTS(fd, "..."); } From webhook-mailer at python.org Wed Nov 17 17:00:03 2021 From: webhook-mailer at python.org (ambv) Date: Wed, 17 Nov 2021 22:00:03 -0000 Subject: [Python-checkins] bpo-45831: _Py_DumpASCII() uses a single write() call if possible (GH-29596) (GH-29597) Message-ID: https://github.com/python/cpython/commit/ac89f8cab79800195687dd141de472f90c626ec3 commit: ac89f8cab79800195687dd141de472f90c626ec3 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-17T22:59:42+01:00 summary: bpo-45831: _Py_DumpASCII() uses a single write() call if possible (GH-29596) (GH-29597) If the string is ASCII only and doesn't need to escape characters, write the whole string with a single write() syscall. (cherry picked from commit b919d8105c4d77f00509b6d3ab2073f09db640de) Co-authored-by: Victor Stinner files: A Misc/NEWS.d/next/Library/2021-11-17-19-25-37.bpo-45831.9-TojK.rst M Python/traceback.c diff --git a/Misc/NEWS.d/next/Library/2021-11-17-19-25-37.bpo-45831.9-TojK.rst b/Misc/NEWS.d/next/Library/2021-11-17-19-25-37.bpo-45831.9-TojK.rst new file mode 100644 index 0000000000000..049449ff0a4a1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-17-19-25-37.bpo-45831.9-TojK.rst @@ -0,0 +1,5 @@ +:mod:`faulthandler` can now write ASCII-only strings (like filenames and +function names) with a single write() syscall when dumping a traceback. It +reduces the risk of getting an unreadable dump when two threads or two +processes dump a traceback to the same file (like stderr) at the same time. +Patch by Victor Stinner. diff --git a/Python/traceback.c b/Python/traceback.c index 83f3074f43d05..23d0e38e7377c 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -719,6 +719,26 @@ _Py_DumpASCII(int fd, PyObject *text) truncated = 0; } + // Is an ASCII string? + if (ascii->state.ascii) { + assert(kind == PyUnicode_1BYTE_KIND); + char *str = data; + + int need_escape = 0; + for (i=0; i < size; i++) { + ch = str[i]; + if (!(' ' <= ch && ch <= 126)) { + need_escape = 1; + break; + } + } + if (!need_escape) { + // The string can be written with a single write() syscall + _Py_write_noraise(fd, str, size); + goto done; + } + } + for (i=0; i < size; i++) { if (kind != PyUnicode_WCHAR_KIND) ch = PyUnicode_READ(kind, data, i); @@ -742,6 +762,8 @@ _Py_DumpASCII(int fd, PyObject *text) _Py_DumpHexadecimal(fd, ch, 8); } } + +done: if (truncated) { PUTS(fd, "..."); } From webhook-mailer at python.org Wed Nov 17 17:54:14 2021 From: webhook-mailer at python.org (ambv) Date: Wed, 17 Nov 2021 22:54:14 -0000 Subject: [Python-checkins] [3.9] bpo-42540: reallocation of id_mutex should not force default allocator (GH-29564) (GH-29600) Message-ID: https://github.com/python/cpython/commit/87787c8774221c81602b31b0e0dc0678ad494e91 commit: 87787c8774221c81602b31b0e0dc0678ad494e91 branch: 3.9 author: Sam Gross committer: ambv date: 2021-11-17T23:53:33+01:00 summary: [3.9] bpo-42540: reallocation of id_mutex should not force default allocator (GH-29564) (GH-29600) Unlike the other locks reinitialized by _PyRuntimeState_ReInitThreads, the "interpreters.main->id_mutex" is not freed by _PyRuntimeState_Fini and should not force the default raw allocator.. (cherry picked from commit 736684b1bb67369a2e95a9f621752deead44e7ef) Co-authored-by: Sam Gross files: A Misc/NEWS.d/next/Core and Builtins/2021-11-15-12-08-27.bpo-42540.V2w107.rst M Lib/test/test_os.py M Python/pystate.c diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 35933e9c8c3a9..59ddf9e0b3c91 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -4273,6 +4273,22 @@ def test_times(self): self.assertEqual(times.elapsed, 0) + at requires_os_func('fork') +class ForkTests(unittest.TestCase): + def test_fork(self): + # bpo-42540: ensure os.fork() with non-default memory allocator does + # not crash on exit. + code = """if 1: + import os + from test import support + pid = os.fork() + if pid != 0: + support.wait_process(pid, exitcode=0) + """ + assert_python_ok("-c", code) + assert_python_ok("-c", code, PYTHONMALLOC="malloc_debug") + + # Only test if the C version is provided, otherwise TestPEP519 already tested # the pure Python implementation. if hasattr(os, "_fspath"): diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-15-12-08-27.bpo-42540.V2w107.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-15-12-08-27.bpo-42540.V2w107.rst new file mode 100644 index 0000000000000..91160598bd3f4 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-15-12-08-27.bpo-42540.V2w107.rst @@ -0,0 +1,2 @@ +Fix crash when :func:`os.fork` is called with an active non-default +memory allocator. diff --git a/Python/pystate.c b/Python/pystate.c index 9beefa8e20c44..c3520c336a794 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -139,11 +139,14 @@ _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime) _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); int interp_mutex = _PyThread_at_fork_reinit(&runtime->interpreters.mutex); - int main_interp_id_mutex = _PyThread_at_fork_reinit(&runtime->interpreters.main->id_mutex); int xidregistry_mutex = _PyThread_at_fork_reinit(&runtime->xidregistry.mutex); PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + /* bpo-42540: id_mutex is freed by _PyInterpreterState_Delete, which does + * not force the default allocator. */ + int main_interp_id_mutex = _PyThread_at_fork_reinit(&runtime->interpreters.main->id_mutex); + if (interp_mutex < 0) { Py_FatalError("Can't initialize lock for runtime interpreters"); } From webhook-mailer at python.org Wed Nov 17 18:04:27 2021 From: webhook-mailer at python.org (ambv) Date: Wed, 17 Nov 2021 23:04:27 -0000 Subject: [Python-checkins] bpo-45826: Fix a crash in suggestions.c by checking for `traceback is None` (GH-29590) Message-ID: https://github.com/python/cpython/commit/5d90c467c02ffefdb13c1abc83a171db1a99ffad commit: 5d90c467c02ffefdb13c1abc83a171db1a99ffad branch: main author: Dennis Sweeney <36520290+sweeneyde at users.noreply.github.com> committer: ambv date: 2021-11-18T00:03:52+01:00 summary: bpo-45826: Fix a crash in suggestions.c by checking for `traceback is None` (GH-29590) files: A Misc/NEWS.d/next/Core and Builtins/2021-11-17-08-05-27.bpo-45826.OERoTm.rst M Lib/test/test_exceptions.py M Python/suggestions.c diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 0f8a8f134b61f..098804fad5e2d 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -1885,6 +1885,37 @@ def foo(): self.assertNotIn("something", err.getvalue()) + def test_issue45826(self): + # regression test for bpo-45826 + def f(): + with self.assertRaisesRegex(NameError, 'aaa'): + aab + + try: + f() + except self.failureException: + with support.captured_stderr() as err: + sys.__excepthook__(*sys.exc_info()) + + self.assertIn("aab", err.getvalue()) + + def test_issue45826_focused(self): + def f(): + try: + nonsense + except BaseException as E: + E.with_traceback(None) + raise ZeroDivisionError() + + try: + f() + except ZeroDivisionError: + with support.captured_stderr() as err: + sys.__excepthook__(*sys.exc_info()) + + self.assertIn("nonsense", err.getvalue()) + self.assertIn("ZeroDivisionError", err.getvalue()) + class AttributeErrorTests(unittest.TestCase): def test_attributes(self): diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-17-08-05-27.bpo-45826.OERoTm.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-17-08-05-27.bpo-45826.OERoTm.rst new file mode 100644 index 0000000000000..f04373bf2fc59 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-17-08-05-27.bpo-45826.OERoTm.rst @@ -0,0 +1 @@ +Fixed a crash when calling ``.with_traceback(None)`` on ``NameError``. This occurs internally in ``unittest.TestCase.assertRaises()``. \ No newline at end of file diff --git a/Python/suggestions.c b/Python/suggestions.c index 81976ff4f2eb4..d9e69fa7e0db2 100644 --- a/Python/suggestions.c +++ b/Python/suggestions.c @@ -202,13 +202,21 @@ offer_suggestions_for_name_error(PyNameErrorObject *exc) PyTracebackObject *traceback = (PyTracebackObject *) exc->traceback; // borrowed reference // Abort if we don't have a variable name or we have an invalid one // or if we don't have a traceback to work with - if (name == NULL || traceback == NULL || !PyUnicode_CheckExact(name)) { + if (name == NULL || !PyUnicode_CheckExact(name) || + traceback == NULL || !Py_IS_TYPE(traceback, &PyTraceBack_Type) + ) { return NULL; } // Move to the traceback of the exception - while (traceback->tb_next != NULL) { - traceback = traceback->tb_next; + while (1) { + PyTracebackObject *next = traceback->tb_next; + if (next == NULL || !Py_IS_TYPE(next, &PyTraceBack_Type)) { + break; + } + else { + traceback = next; + } } PyFrameObject *frame = traceback->tb_frame; From webhook-mailer at python.org Wed Nov 17 18:17:22 2021 From: webhook-mailer at python.org (ambv) Date: Wed, 17 Nov 2021 23:17:22 -0000 Subject: [Python-checkins] [3.10] bpo-45822: Respect PEP 263's coding cookies in the parser even if flags are not provided (GH-29582) (GH-29586) Message-ID: https://github.com/python/cpython/commit/e3aa9fd77bf474bb3e8a7a1d1bd1ebf45147945a commit: e3aa9fd77bf474bb3e8a7a1d1bd1ebf45147945a branch: 3.10 author: Pablo Galindo Salgado committer: ambv date: 2021-11-18T00:17:18+01:00 summary: [3.10] bpo-45822: Respect PEP 263's coding cookies in the parser even if flags are not provided (GH-29582) (GH-29586) (cherry picked from commit da20d7401de97b425897d3069f71f77b039eb16f) Co-authored-by: Pablo Galindo Salgado files: A Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-41-04.bpo-45822.OT6ueS.rst M Lib/test/test_capi.py M Modules/_testcapimodule.c M Parser/pegen.c diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index 6ed5ecdeca5e2..974e3d03a6172 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -1013,6 +1013,14 @@ def test_state_access(self): with self.assertRaises(TypeError): increment_count(1, 2, 3) + 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) + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-41-04.bpo-45822.OT6ueS.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-41-04.bpo-45822.OT6ueS.rst new file mode 100644 index 0000000000000..1ac7a8becee40 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-41-04.bpo-45822.OT6ueS.rst @@ -0,0 +1,2 @@ +Fixed a bug in the parser that was causing it to not respect :pep:`263` +coding cookies when no flags are provided. Patch by Pablo Galindo diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 5e59549252115..9f25b64eb1671 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -390,6 +390,19 @@ static PyTypeObject _HashInheritanceTester_Type = { PyType_GenericNew, /* tp_new */ }; +static PyObject* +pycompilestring(PyObject* self, PyObject *obj) { + if (PyBytes_CheckExact(obj) == 0) { + PyErr_SetString(PyExc_ValueError, "Argument must be a bytes object"); + return NULL; + } + const char *the_string = PyBytes_AsString(obj); + if (the_string == NULL) { + return NULL; + } + return Py_CompileString(the_string, "blech", Py_file_input); +} + static PyObject* test_lazy_hash_inheritance(PyObject* self, PyObject *Py_UNUSED(ignored)) { @@ -5826,6 +5839,7 @@ static PyMethodDef TestMethods[] = { {"return_null_without_error", return_null_without_error, METH_NOARGS}, {"return_result_with_error", return_result_with_error, METH_NOARGS}, {"getitem_with_error", getitem_with_error, METH_VARARGS}, + {"Py_CompileString", pycompilestring, METH_O}, {"PyTime_FromSeconds", test_pytime_fromseconds, METH_VARARGS}, {"PyTime_FromSecondsObject", test_pytime_fromsecondsobject, METH_VARARGS}, {"PyTime_AsSecondsDouble", test_pytime_assecondsdouble, METH_VARARGS}, diff --git a/Parser/pegen.c b/Parser/pegen.c index cfb4b8e8fb157..170d28b94d4ee 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -1434,7 +1434,7 @@ _PyPegen_run_parser_from_string(const char *str, int start_rule, PyObject *filen int exec_input = start_rule == Py_file_input; struct tok_state *tok; - if (flags == NULL || flags->cf_flags & PyCF_IGNORE_COOKIE) { + if (flags != NULL && flags->cf_flags & PyCF_IGNORE_COOKIE) { tok = PyTokenizer_FromUTF8(str, exec_input); } else { tok = PyTokenizer_FromString(str, exec_input); From webhook-mailer at python.org Wed Nov 17 18:18:21 2021 From: webhook-mailer at python.org (ambv) Date: Wed, 17 Nov 2021 23:18:21 -0000 Subject: [Python-checkins] bpo-45822: Respect PEP 263's coding cookies in the parser even if flags are not provided (GH-29582) (GH-29585) Message-ID: https://github.com/python/cpython/commit/0ef308a2890571c850c624fb99ac00f8951363c6 commit: 0ef308a2890571c850c624fb99ac00f8951363c6 branch: 3.9 author: Pablo Galindo Salgado committer: ambv date: 2021-11-18T00:18:16+01:00 summary: bpo-45822: Respect PEP 263's coding cookies in the parser even if flags are not provided (GH-29582) (GH-29585) (cherry picked from commit da20d7401de97b425897d3069f71f77b039eb16f) files: A Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-41-04.bpo-45822.OT6ueS.rst M Lib/test/test_capi.py M Modules/_testcapimodule.c M Parser/pegen/pegen.c diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index 6b2fe2f1580c3..23e65df67190c 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -926,6 +926,14 @@ def test_state_access(self): with self.assertRaises(TypeError): increment_count(1, 2, 3) + 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) + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-41-04.bpo-45822.OT6ueS.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-41-04.bpo-45822.OT6ueS.rst new file mode 100644 index 0000000000000..1ac7a8becee40 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-41-04.bpo-45822.OT6ueS.rst @@ -0,0 +1,2 @@ +Fixed a bug in the parser that was causing it to not respect :pep:`263` +coding cookies when no flags are provided. Patch by Pablo Galindo diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index ae1284178dc60..d1f756395373d 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -329,6 +329,19 @@ static PyTypeObject _HashInheritanceTester_Type = { PyType_GenericNew, /* tp_new */ }; +static PyObject* +pycompilestring(PyObject* self, PyObject *obj) { + if (PyBytes_CheckExact(obj) == 0) { + PyErr_SetString(PyExc_ValueError, "Argument must be a bytes object"); + return NULL; + } + const char *the_string = PyBytes_AsString(obj); + if (the_string == NULL) { + return NULL; + } + return Py_CompileString(the_string, "blech", Py_file_input); +} + static PyObject* test_lazy_hash_inheritance(PyObject* self, PyObject *Py_UNUSED(ignored)) { @@ -5537,6 +5550,7 @@ static PyMethodDef TestMethods[] = { return_null_without_error, METH_NOARGS}, {"return_result_with_error", return_result_with_error, METH_NOARGS}, + {"Py_CompileString", pycompilestring, METH_O}, {"PyTime_FromSeconds", test_pytime_fromseconds, METH_VARARGS}, {"PyTime_FromSecondsObject", test_pytime_fromsecondsobject, METH_VARARGS}, {"PyTime_AsSecondsDouble", test_pytime_assecondsdouble, METH_VARARGS}, diff --git a/Parser/pegen/pegen.c b/Parser/pegen/pegen.c index efcf9ac1ebd74..2e986c5294f19 100644 --- a/Parser/pegen/pegen.c +++ b/Parser/pegen/pegen.c @@ -1225,7 +1225,7 @@ _PyPegen_run_parser_from_string(const char *str, int start_rule, PyObject *filen int exec_input = start_rule == Py_file_input; struct tok_state *tok; - if (flags == NULL || flags->cf_flags & PyCF_IGNORE_COOKIE) { + if (flags != NULL && flags->cf_flags & PyCF_IGNORE_COOKIE) { tok = PyTokenizer_FromUTF8(str, exec_input); } else { tok = PyTokenizer_FromString(str, exec_input); From webhook-mailer at python.org Wed Nov 17 18:25:58 2021 From: webhook-mailer at python.org (ambv) Date: Wed, 17 Nov 2021 23:25:58 -0000 Subject: [Python-checkins] [docs] Add missing word "any" in unittest -k cmdline option description (GH-29571) Message-ID: https://github.com/python/cpython/commit/abc0d754c3853c6e69ec3718505871e7e42ec93d commit: abc0d754c3853c6e69ec3718505871e7e42ec93d branch: main author: ch33zer committer: ambv date: 2021-11-18T00:25:53+01:00 summary: [docs] Add missing word "any" in unittest -k cmdline option description (GH-29571) files: M Doc/library/unittest.rst diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst index a6f9046b826a7..bf7a1e87928a6 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -227,7 +227,7 @@ Command-line options Only run test methods and classes that match the pattern or substring. This option may be used multiple times, in which case all test cases that - match of the given patterns are included. + match any of the given patterns are included. Patterns that contain a wildcard character (``*``) are matched against the test name using :meth:`fnmatch.fnmatchcase`; otherwise simple case-sensitive From webhook-mailer at python.org Wed Nov 17 18:43:49 2021 From: webhook-mailer at python.org (miss-islington) Date: Wed, 17 Nov 2021 23:43:49 -0000 Subject: [Python-checkins] bpo-45820: Fix a segfault when the parser fails without reading any input (GH-29580) Message-ID: https://github.com/python/cpython/commit/b455df59a8eca1b0c0793bc11a116ffc2829b175 commit: b455df59a8eca1b0c0793bc11a116ffc2829b175 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-17T15:43:14-08:00 summary: bpo-45820: Fix a segfault when the parser fails without reading any input (GH-29580) (cherry picked from commit df4ae55e66e34ea8de6a34f0b104871ddaf35d53) Co-authored-by: Pablo Galindo Salgado files: A Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-00-27.bpo-45820.2X6Psr.rst M Parser/pegen.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-00-27.bpo-45820.2X6Psr.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-00-27.bpo-45820.2X6Psr.rst new file mode 100644 index 0000000000000..c2ec3d690cd4b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-00-27.bpo-45820.2X6Psr.rst @@ -0,0 +1,2 @@ +Fix a segfault when the parser fails without reading any input. Patch by +Pablo Galindo diff --git a/Parser/pegen.c b/Parser/pegen.c index 170d28b94d4ee..c6570eb1bd0b4 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -389,6 +389,14 @@ tokenizer_error(Parser *p) void * _PyPegen_raise_error(Parser *p, PyObject *errtype, const char *errmsg, ...) { + if (p->fill == 0) { + va_list va; + va_start(va, errmsg); + _PyPegen_raise_error_known_location(p, errtype, 0, 0, 0, -1, errmsg, va); + va_end(va); + return NULL; + } + Token *t = p->known_err_token != NULL ? p->known_err_token : p->tokens[p->fill - 1]; Py_ssize_t col_offset; Py_ssize_t end_col_offset = -1; From webhook-mailer at python.org Wed Nov 17 19:25:05 2021 From: webhook-mailer at python.org (ambv) Date: Thu, 18 Nov 2021 00:25:05 -0000 Subject: [Python-checkins] [3.9] bpo-45820: Fix a segfault when the parser fails without reading any input (GH-29580) (GH-29584) Message-ID: https://github.com/python/cpython/commit/00ee14e814d35587ac55f89c7de871a01360c876 commit: 00ee14e814d35587ac55f89c7de871a01360c876 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-18T01:24:43+01:00 summary: [3.9] bpo-45820: Fix a segfault when the parser fails without reading any input (GH-29580) (GH-29584) Co-authored-by: Pablo Galindo Salgado Co-authored-by: ?ukasz Langa files: A Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-00-27.bpo-45820.2X6Psr.rst M .gitignore M Parser/pegen/pegen.c diff --git a/.gitignore b/.gitignore index 864152451dd9d..0dd3aee5c3151 100644 --- a/.gitignore +++ b/.gitignore @@ -136,5 +136,7 @@ Tools/ssl/win32 !/Python/ # Artifacts generated by 3.11 lying around when switching branches: +/_bootstrap_python /Programs/_freeze_module +/Python/deepfreeze/ /Python/frozen_modules/ \ No newline at end of file diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-00-27.bpo-45820.2X6Psr.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-00-27.bpo-45820.2X6Psr.rst new file mode 100644 index 0000000000000..c2ec3d690cd4b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-00-27.bpo-45820.2X6Psr.rst @@ -0,0 +1,2 @@ +Fix a segfault when the parser fails without reading any input. Patch by +Pablo Galindo diff --git a/Parser/pegen/pegen.c b/Parser/pegen/pegen.c index 2e986c5294f19..cdfbc12d16a34 100644 --- a/Parser/pegen/pegen.c +++ b/Parser/pegen/pegen.c @@ -364,6 +364,14 @@ tokenizer_error(Parser *p) void * _PyPegen_raise_error(Parser *p, PyObject *errtype, const char *errmsg, ...) { + if (p->fill == 0) { + va_list va; + va_start(va, errmsg); + _PyPegen_raise_error_known_location(p, errtype, 0, 0, errmsg, va); + va_end(va); + return NULL; + } + Token *t = p->known_err_token != NULL ? p->known_err_token : p->tokens[p->fill - 1]; Py_ssize_t col_offset; if (t->col_offset == -1) { From webhook-mailer at python.org Wed Nov 17 19:25:59 2021 From: webhook-mailer at python.org (ambv) Date: Thu, 18 Nov 2021 00:25:59 -0000 Subject: [Python-checkins] [docs] Add missing word "any" in unittest -k cmdline option description (GH-29571) (GH-29603) Message-ID: https://github.com/python/cpython/commit/563e45875a7623fc06a0fc990099b32855082b68 commit: 563e45875a7623fc06a0fc990099b32855082b68 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-18T01:25:54+01:00 summary: [docs] Add missing word "any" in unittest -k cmdline option description (GH-29571) (GH-29603) (cherry picked from commit abc0d754c3853c6e69ec3718505871e7e42ec93d) Co-authored-by: ch33zer files: M Doc/library/unittest.rst diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst index 99c2f6e029448..ae0c7d59964f1 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -223,7 +223,7 @@ Command-line options Only run test methods and classes that match the pattern or substring. This option may be used multiple times, in which case all test cases that - match of the given patterns are included. + match any of the given patterns are included. Patterns that contain a wildcard character (``*``) are matched against the test name using :meth:`fnmatch.fnmatchcase`; otherwise simple case-sensitive From webhook-mailer at python.org Wed Nov 17 19:26:18 2021 From: webhook-mailer at python.org (ambv) Date: Thu, 18 Nov 2021 00:26:18 -0000 Subject: [Python-checkins] [docs] Add missing word "any" in unittest -k cmdline option description (GH-29571) (GH-29604) Message-ID: https://github.com/python/cpython/commit/17f5c5cad3bb9bfb6eecbe47ecc35ee3aafc54a9 commit: 17f5c5cad3bb9bfb6eecbe47ecc35ee3aafc54a9 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-18T01:26:12+01:00 summary: [docs] Add missing word "any" in unittest -k cmdline option description (GH-29571) (GH-29604) (cherry picked from commit abc0d754c3853c6e69ec3718505871e7e42ec93d) Co-authored-by: ch33zer files: M Doc/library/unittest.rst diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst index 392cd2473155f..90807579266a0 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -223,7 +223,7 @@ Command-line options Only run test methods and classes that match the pattern or substring. This option may be used multiple times, in which case all test cases that - match of the given patterns are included. + match any of the given patterns are included. Patterns that contain a wildcard character (``*``) are matched against the test name using :meth:`fnmatch.fnmatchcase`; otherwise simple case-sensitive From webhook-mailer at python.org Wed Nov 17 19:27:04 2021 From: webhook-mailer at python.org (ambv) Date: Thu, 18 Nov 2021 00:27:04 -0000 Subject: [Python-checkins] bpo-45429: Merge whatsnew about time.sleep (GH-29589) Message-ID: https://github.com/python/cpython/commit/fc4474e45eecbea8e88095f28c98c5d56438d841 commit: fc4474e45eecbea8e88095f28c98c5d56438d841 branch: main author: Dong-hee Na committer: ambv date: 2021-11-18T01:26:59+01:00 summary: bpo-45429: Merge whatsnew about time.sleep (GH-29589) Co-authored-by: ?ukasz Langa files: M Doc/library/time.rst M Doc/whatsnew/3.11.rst diff --git a/Doc/library/time.rst b/Doc/library/time.rst index 0f880910c6ee6..622f66719cee7 100644 --- a/Doc/library/time.rst +++ b/Doc/library/time.rst @@ -362,7 +362,10 @@ Functions On Windows, if *secs* is zero, the thread relinquishes the remainder of its time slice to any other thread that is ready to run. If there are no other threads ready to run, the function returns immediately, and the thread - continues execution. + continues execution. On Windows 8.1 and newer the implementation uses + a `high-resolution timer + `_ + which provides resolution of 100 nanoseconds. If *secs* is zero, ``Sleep(0)`` is used. Unix implementation: @@ -370,9 +373,6 @@ Functions * Or use ``nanosleep()`` if available (resolution: 1 nanosecond); * Or use ``select()`` (resolution: 1 microsecond). - On Windows, a waitable timer is used (resolution: 100 nanosecond). If *secs* is - zero, ``Sleep(0)`` is used. - .. versionchanged:: 3.11 On Unix, the ``clock_nanosleep()`` and ``nanosleep()`` functions are now used if available. On Windows, a waitable timer is now used. diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 0c7c74e7c3242..06a24151c32cc 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -269,6 +269,7 @@ threading by system clock changes. (Contributed by Victor Stinner in :issue:`41710`.) + time ---- @@ -278,14 +279,13 @@ time of 1 microsecond (10\ :sup:`-6` seconds). (Contributed by Benjamin Sz?ke and Victor Stinner in :issue:`21302`.) -* On Windows, :func:`time.sleep` now uses a waitable timer which has a - resolution of 100 nanoseconds (10\ :sup:`-7` seconds). Previously, it had - a resolution of 1 millisecond (10\ :sup:`-3` seconds). - (Contributed by Benjamin Sz?ke and Victor Stinner in :issue:`21302`.) +* On Windows 8.1 and newer, :func:`time.sleep` now uses a waitable timer based + on `high-resolution timers + `_ + which has a resolution of 100 nanoseconds (10\ :sup:`-7` seconds). Previously, + it had a resolution of 1 millisecond (10\ :sup:`-3` seconds). + (Contributed by Benjamin Sz?ke, Dong-hee Na, Eryk Sun and Victor Stinner in :issue:`21302` and :issue:`45429`.) -* On Windows, :func:`time.sleep` now uses a waitable timer which supports high-resolution timers. - In Python 3.10, the best resolution was 1 ms, from Python 3.11 it's now smaller than 1 ms. - (Contributed by Dong-hee Na and Eryk Sun in :issue:`45429`.) unicodedata ----------- From webhook-mailer at python.org Wed Nov 17 19:28:09 2021 From: webhook-mailer at python.org (ambv) Date: Thu, 18 Nov 2021 00:28:09 -0000 Subject: [Python-checkins] [3.10] bpo-45826: Fix a crash in suggestions.c by checking for `traceback is None` (GH-29590) (GH-29602) Message-ID: https://github.com/python/cpython/commit/8eabe60108b536b942c791b5d3dc3c3020497aac commit: 8eabe60108b536b942c791b5d3dc3c3020497aac branch: 3.10 author: ?ukasz Langa committer: ambv date: 2021-11-18T01:28:04+01:00 summary: [3.10] bpo-45826: Fix a crash in suggestions.c by checking for `traceback is None` (GH-29590) (GH-29602) (cherry picked from commit 5d90c467c02ffefdb13c1abc83a171db1a99ffad) Co-authored-by: Dennis Sweeney <36520290+sweeneyde at users.noreply.github.com> files: A Misc/NEWS.d/next/Core and Builtins/2021-11-17-08-05-27.bpo-45826.OERoTm.rst M Lib/test/test_exceptions.py M Python/suggestions.c diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 4930c57d3fd7e..8419f582cbdb9 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -1885,6 +1885,37 @@ def foo(): self.assertNotIn("something", err.getvalue()) + def test_issue45826(self): + # regression test for bpo-45826 + def f(): + with self.assertRaisesRegex(NameError, 'aaa'): + aab + + try: + f() + except self.failureException: + with support.captured_stderr() as err: + sys.__excepthook__(*sys.exc_info()) + + self.assertIn("aab", err.getvalue()) + + def test_issue45826_focused(self): + def f(): + try: + nonsense + except BaseException as E: + E.with_traceback(None) + raise ZeroDivisionError() + + try: + f() + except ZeroDivisionError: + with support.captured_stderr() as err: + sys.__excepthook__(*sys.exc_info()) + + self.assertIn("nonsense", err.getvalue()) + self.assertIn("ZeroDivisionError", err.getvalue()) + class AttributeErrorTests(unittest.TestCase): def test_attributes(self): diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-17-08-05-27.bpo-45826.OERoTm.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-17-08-05-27.bpo-45826.OERoTm.rst new file mode 100644 index 0000000000000..f04373bf2fc59 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-17-08-05-27.bpo-45826.OERoTm.rst @@ -0,0 +1 @@ +Fixed a crash when calling ``.with_traceback(None)`` on ``NameError``. This occurs internally in ``unittest.TestCase.assertRaises()``. \ No newline at end of file diff --git a/Python/suggestions.c b/Python/suggestions.c index 7fd62fbfabf64..4e2f9055779b2 100644 --- a/Python/suggestions.c +++ b/Python/suggestions.c @@ -200,13 +200,21 @@ offer_suggestions_for_name_error(PyNameErrorObject *exc) PyTracebackObject *traceback = (PyTracebackObject *) exc->traceback; // borrowed reference // Abort if we don't have a variable name or we have an invalid one // or if we don't have a traceback to work with - if (name == NULL || traceback == NULL || !PyUnicode_CheckExact(name)) { + if (name == NULL || !PyUnicode_CheckExact(name) || + traceback == NULL || !Py_IS_TYPE(traceback, &PyTraceBack_Type) + ) { return NULL; } // Move to the traceback of the exception - while (traceback->tb_next != NULL) { - traceback = traceback->tb_next; + while (1) { + PyTracebackObject *next = traceback->tb_next; + if (next == NULL || !Py_IS_TYPE(next, &PyTraceBack_Type)) { + break; + } + else { + traceback = next; + } } PyFrameObject *frame = traceback->tb_frame; From webhook-mailer at python.org Thu Nov 18 02:36:39 2021 From: webhook-mailer at python.org (ethanfurman) Date: Thu, 18 Nov 2021 07:36:39 -0000 Subject: [Python-checkins] [3.9] [Enum] update member.member removal to 3.11 (GH-29607) Message-ID: https://github.com/python/cpython/commit/41365f7dc49b758717e28a5112affe14eac93775 commit: 41365f7dc49b758717e28a5112affe14eac93775 branch: 3.9 author: Ethan Furman committer: ethanfurman date: 2021-11-17T23:36:01-08:00 summary: [3.9] [Enum] update member.member removal to 3.11 (GH-29607) Accessing one enum member from another originally raised an `AttributeError`, but became possible due to a performance boost implementation detail. In 3.11 it will again raise an `AttributeError`. files: From webhook-mailer at python.org Thu Nov 18 02:39:02 2021 From: webhook-mailer at python.org (ethanfurman) Date: Thu, 18 Nov 2021 07:39:02 -0000 Subject: [Python-checkins] [3.10] [Enum] update member.member removal (GH-29608) Message-ID: https://github.com/python/cpython/commit/65c089751b81a132613f4528f16938918a013f25 commit: 65c089751b81a132613f4528f16938918a013f25 branch: 3.10 author: Ethan Furman committer: ethanfurman date: 2021-11-17T23:38:56-08:00 summary: [3.10] [Enum] update member.member removal (GH-29608) Accessing one enum member from another originally raised an `AttributeError`, but became possible due to a performance boost implementation detail. In 3.11 it will again raise an `AttributeError`. files: M Doc/library/enum.rst diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst index eb5ffd0c5d51c..7d166bfb1fcc6 100644 --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -1152,7 +1152,7 @@ all-uppercase names for members):: .. note:: - This behavior is deprecated and will be removed in 3.12. + This behavior is deprecated and will be removed in 3.11. .. versionchanged:: 3.5 From webhook-mailer at python.org Thu Nov 18 02:40:13 2021 From: webhook-mailer at python.org (ethanfurman) Date: Thu, 18 Nov 2021 07:40:13 -0000 Subject: [Python-checkins] Revert "[3.9] [Enum] update member.member removal to 3.11 (GH-29607)" (GH-29609) Message-ID: https://github.com/python/cpython/commit/d75407392759324d3aa9f6b6682c342b8a42a292 commit: d75407392759324d3aa9f6b6682c342b8a42a292 branch: 3.9 author: Ethan Furman committer: ethanfurman date: 2021-11-17T23:40:08-08:00 summary: Revert "[3.9] [Enum] update member.member removal to 3.11 (GH-29607)" (GH-29609) This reverts commit 41365f7dc49b758717e28a5112affe14eac93775. files: From webhook-mailer at python.org Thu Nov 18 03:18:50 2021 From: webhook-mailer at python.org (tiran) Date: Thu, 18 Nov 2021 08:18:50 -0000 Subject: [Python-checkins] bpo-45573: Introduce extension module flags in Makefile (GH-29594) Message-ID: https://github.com/python/cpython/commit/25ecc040d007a55e4b5c30fa739054b52c1aacac commit: 25ecc040d007a55e4b5c30fa739054b52c1aacac branch: main author: Christian Heimes committer: tiran date: 2021-11-18T09:18:44+01:00 summary: bpo-45573: Introduce extension module flags in Makefile (GH-29594) ``configure`` now uses a standardized format to forward state, compiler flags, and linker flags to ``Makefile``, ``setup.py``, and ``Modules/Setup``. ``makesetup`` use the new variables by default if a module line does not contain any compiler or linker flags. ``setup.py`` has a new function ``addext()``. For a module ``egg``, configure adds: * ``MODULE_EGG`` with value yes, missing, disabled, or n/a * ``MODULE_EGG_CFLAGS`` * ``MODULE_EGG_LDFLAGS`` ``Makefile.pre.in`` may also provide ``MODULE_EGG_DEPS`` that lists dependencies such as header files and static libs. Signed-off-by: Christian Heimes files: A Misc/NEWS.d/next/Build/2021-11-17-19-02-51.bpo-45573.GMNdun.rst M Makefile.pre.in M Modules/Setup M Modules/makesetup M aclocal.m4 M configure M configure.ac M setup.py diff --git a/Makefile.pre.in b/Makefile.pre.in index 1535cabdade9c..55336d24ed194 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -201,12 +201,26 @@ RUNSHARED= @RUNSHARED@ # ensurepip options ENSUREPIP= @ENSUREPIP@ +# Internal static libraries +LIBMPDEC_A= Modules/_decimal/libmpdec/libmpdec.a +LIBEXPAT_A= Modules/expat/libexpat.a + # OpenSSL options for setup.py so sysconfig can pick up AC_SUBST() vars. OPENSSL_INCLUDES=@OPENSSL_INCLUDES@ OPENSSL_LIBS=@OPENSSL_LIBS@ OPENSSL_LDFLAGS=@OPENSSL_LDFLAGS@ OPENSSL_RPATH=@OPENSSL_RPATH@ +# Module compiler and linker flags +# yes: module is available +# missing: build dependency is missing +# disabled: module is disabled +# n/a: module is not available on the current platform +# MODULE_EGG=yes # yes, missing, disabled, n/a +# MODULE_EGG_CFLAGS= +# MODULE_EGG_LDFLAGS= + at MODULE_BLOCK@ + # Default zoneinfo.TZPATH. Added here to expose it in sysconfig.get_config_var TZPATH=@TZPATH@ @@ -535,8 +549,6 @@ LIBMPDEC_HEADERS= \ $(srcdir)/Modules/_decimal/libmpdec/typearith.h \ $(srcdir)/Modules/_decimal/libmpdec/umodarith.h -LIBMPDEC_A= Modules/_decimal/libmpdec/libmpdec.a - ########################################################################## # pyexpat's expat library @@ -562,8 +574,6 @@ LIBEXPAT_HEADERS= \ Modules/expat/xmltok.h \ Modules/expat/xmltok_impl.h -LIBEXPAT_A= Modules/expat/libexpat.a - ######################################################################### # Rules diff --git a/Misc/NEWS.d/next/Build/2021-11-17-19-02-51.bpo-45573.GMNdun.rst b/Misc/NEWS.d/next/Build/2021-11-17-19-02-51.bpo-45573.GMNdun.rst new file mode 100644 index 0000000000000..688b22c3e48a8 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-17-19-02-51.bpo-45573.GMNdun.rst @@ -0,0 +1,3 @@ +``configure`` now uses a unified format to set state, compiler flags, and +linker flags in Makefile. The new macro ``PY_STDLIB_MOD`` sets three +variables that are consumed by ``Modules/Setup`` and ``setup.py``. diff --git a/Modules/Setup b/Modules/Setup index 608866d9cedd5..414c6af4b69c2 100644 --- a/Modules/Setup +++ b/Modules/Setup @@ -42,6 +42,15 @@ # You can also use any Make variable that is detected by configure and # defined in Makefile.pre.in, e.g. OpenSSL flags $(OPENSSL_INCLUDES). # +# Rules generated by makesetup use additional variables: +# +# - All source file rules have a dependency on $(PYTHON_HEADERS) and on +# optional variable $(MODULES_{mod_upper}_DEPS). +# - If no and no arguments are given, then makesetup +# defaults to $(MODULES_{mod_upper}_CFLAGS) cppargs and +# $(MODULES_{mod_upper}_LDFLAGS) libraries. The variables are typically +# defined by configure. +# # The build process works like this: # # 1. Build all modules that are declared as static in Modules/Setup, @@ -149,7 +158,7 @@ time timemodule.c #_contextvars _contextvarsmodule.c #_csv _csv.c #_datetime _datetimemodule.c -#_decimal _decimal/_decimal.c $(DECIMAL_CFLAGS) $(DECIMAL_LDFLAGS) +#_decimal _decimal/_decimal.c #_heapq _heapqmodule.c #_json _json.c #_lsprof _lsprof.c rotatingtree.c @@ -172,8 +181,8 @@ time timemodule.c #select selectmodule.c # XML -#_elementtree _elementtree.c $(EXPAT_CFLAGS) -#pyexpat pyexpat.c $(EXPAT_CFLAGS) $(EXPAT_LDFLAGS) +#_elementtree _elementtree.c +#pyexpat pyexpat.c # hashing builtins #_blake2 _blake2/blake2module.c _blake2/blake2b_impl.c _blake2/blake2s_impl.c diff --git a/Modules/makesetup b/Modules/makesetup index a8817fffb7c84..2335724e804cc 100755 --- a/Modules/makesetup +++ b/Modules/makesetup @@ -154,6 +154,7 @@ sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' | cpps= libs= mods= + mods_upper= skip= for arg in $line do @@ -194,11 +195,17 @@ sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' | *.*) echo 1>&2 "bad word $arg in $line" exit 1;; -u) skip=libs; libs="$libs -u";; - [a-zA-Z_]*) mods="$mods $arg";; + [a-zA-Z_]*) + mods="$mods $arg" + mods_upper=$(echo $mods | tr '[a-z]' '[A-Z]');; *) echo 1>&2 "bad word $arg in $line" exit 1;; esac done + if test -z "$cpps" -a -z "$libs"; then + cpps="\$(MODULE_${mods_upper}_CFLAGS)" + libs="\$(MODULE_${mods_upper}_LDFLAGS)" + fi case $doconfig in yes) LIBS="$LIBS $libs" @@ -245,7 +252,6 @@ sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' | *) cc="$cc \$(PY_BUILTIN_MODULE_CFLAGS)";; esac - mods_upper=$(echo $mods | tr '[a-z]' '[A-Z]') # force rebuild when header file or module build flavor (static/shared) is changed rule="$obj: $src \$(MODULE_${mods_upper}_DEPS) \$(PYTHON_HEADERS) Modules/config.c; $cc $cpps -c $src -o $obj" echo "$rule" >>$rulesf diff --git a/aclocal.m4 b/aclocal.m4 index 2f1bd37528c85..6a33c0cc9d9e8 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -619,3 +619,53 @@ AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"], [AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])]) ])dnl PKG_HAVE_DEFINE_WITH_MODULES +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 2006-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + diff --git a/configure b/configure index 53dc4a23f8063..ab5afbf0b8aef 100755 --- a/configure +++ b/configure @@ -623,6 +623,13 @@ ac_includes_default="\ #endif" ac_subst_vars='LTLIBOBJS +MODULE_BLOCK +MODULE__DECIMAL_FALSE +MODULE__DECIMAL_TRUE +MODULE__ELEMENTTREE_FALSE +MODULE__ELEMENTTREE_TRUE +MODULE_PYEXPAT_FALSE +MODULE_PYEXPAT_TRUE TEST_MODULES LIBRARY_DEPS STATIC_LIBPYTHON @@ -19196,6 +19203,183 @@ $as_echo "no" >&6; } fi +case $ac_sys_system in #( + AIX) : + py_stdlib_not_available="_scproxy spwd" ;; #( + VxWorks*) : + py_stdlib_not_available="_scproxy _crypt termios grp" ;; #( + Darwin) : + py_stdlib_not_available="ossaudiodev spwd" ;; #( + CYGWIN*) : + py_stdlib_not_available="_scproxy nis" ;; #( + QNX*) : + py_stdlib_not_available="_scproxy nis" ;; #( + FreeBSD*) : + py_stdlib_not_available="_scproxy spwd" ;; #( + *) : + py_stdlib_not_available="_scproxy" + ;; +esac + + +MODULE_BLOCK= + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module pyexpat" >&5 +$as_echo_n "checking for stdlib extension module pyexpat... " >&6; } + case $py_stdlib_not_available in #( + *pyexpat*) : + py_cv_module_pyexpat=n/a ;; #( + *) : + + if true; then : + if true; then : + py_cv_module_pyexpat=yes +else + py_cv_module_pyexpat=missing +fi +else + py_cv_module_pyexpat=disabled + +fi + + ;; +esac + as_fn_append MODULE_BLOCK "MODULE_PYEXPAT=$py_cv_module_pyexpat$as_nl" + if test "x$py_cv_module_pyexpat" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE_PYEXPAT_CFLAGS=$LIBEXPAT_CFLAGS$as_nl" + as_fn_append MODULE_BLOCK "MODULE_PYEXPAT_LDFLAGS=$LIBEXPAT_LDFLAGS$as_nl" + if true; then + MODULE_PYEXPAT_TRUE= + MODULE_PYEXPAT_FALSE='#' +else + MODULE_PYEXPAT_TRUE='#' + MODULE_PYEXPAT_FALSE= +fi + + +else + + if false; then + MODULE_PYEXPAT_TRUE= + MODULE_PYEXPAT_FALSE='#' +else + MODULE_PYEXPAT_TRUE='#' + MODULE_PYEXPAT_FALSE= +fi + + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module_pyexpat" >&5 +$as_echo "$py_cv_module_pyexpat" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _elementtree" >&5 +$as_echo_n "checking for stdlib extension module _elementtree... " >&6; } + case $py_stdlib_not_available in #( + *_elementtree*) : + py_cv_module__elementtree=n/a ;; #( + *) : + + if true; then : + if true; then : + py_cv_module__elementtree=yes +else + py_cv_module__elementtree=missing +fi +else + py_cv_module__elementtree=disabled + +fi + + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__ELEMENTTREE=$py_cv_module__elementtree$as_nl" + if test "x$py_cv_module__elementtree" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE__ELEMENTTREE_CFLAGS=$LIBEXPAT_CFLAGS$as_nl" + as_fn_append MODULE_BLOCK "MODULE__ELEMENTTREE_LDFLAGS=$as_nl" + if true; then + MODULE__ELEMENTTREE_TRUE= + MODULE__ELEMENTTREE_FALSE='#' +else + MODULE__ELEMENTTREE_TRUE='#' + MODULE__ELEMENTTREE_FALSE= +fi + + +else + + if false; then + MODULE__ELEMENTTREE_TRUE= + MODULE__ELEMENTTREE_FALSE='#' +else + MODULE__ELEMENTTREE_TRUE='#' + MODULE__ELEMENTTREE_FALSE= +fi + + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__elementtree" >&5 +$as_echo "$py_cv_module__elementtree" >&6; } + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _decimal" >&5 +$as_echo_n "checking for stdlib extension module _decimal... " >&6; } + case $py_stdlib_not_available in #( + *_decimal*) : + py_cv_module__decimal=n/a ;; #( + *) : + + if true; then : + if true; then : + py_cv_module__decimal=yes +else + py_cv_module__decimal=missing +fi +else + py_cv_module__decimal=disabled + +fi + + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__DECIMAL=$py_cv_module__decimal$as_nl" + if test "x$py_cv_module__decimal" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE__DECIMAL_CFLAGS=$LIBMPDEC_CFLAGS$as_nl" + as_fn_append MODULE_BLOCK "MODULE__DECIMAL_LDFLAGS=$LIBMPDEC_LDFLAGS$as_nl" + if true; then + MODULE__DECIMAL_TRUE= + MODULE__DECIMAL_FALSE='#' +else + MODULE__DECIMAL_TRUE='#' + MODULE__DECIMAL_FALSE= +fi + + +else + + if false; then + MODULE__DECIMAL_TRUE= + MODULE__DECIMAL_FALSE='#' +else + MODULE__DECIMAL_TRUE='#' + MODULE__DECIMAL_FALSE= +fi + + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__decimal" >&5 +$as_echo "$py_cv_module__decimal" >&6; } + + +# substitute multiline block, must come after last PY_STDLIB_MOD() + # generate output files ac_config_files="$ac_config_files Makefile.pre Misc/python.pc Misc/python-embed.pc Misc/python-config.sh" @@ -19312,6 +19496,30 @@ LTLIBOBJS=$ac_ltlibobjs +if test -z "${MODULE_PYEXPAT_TRUE}" && test -z "${MODULE_PYEXPAT_FALSE}"; then + as_fn_error $? "conditional \"MODULE_PYEXPAT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE_PYEXPAT_TRUE}" && test -z "${MODULE_PYEXPAT_FALSE}"; then + as_fn_error $? "conditional \"MODULE_PYEXPAT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__ELEMENTTREE_TRUE}" && test -z "${MODULE__ELEMENTTREE_FALSE}"; then + as_fn_error $? "conditional \"MODULE__ELEMENTTREE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__ELEMENTTREE_TRUE}" && test -z "${MODULE__ELEMENTTREE_FALSE}"; then + as_fn_error $? "conditional \"MODULE__ELEMENTTREE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__DECIMAL_TRUE}" && test -z "${MODULE__DECIMAL_FALSE}"; then + as_fn_error $? "conditional \"MODULE__DECIMAL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__DECIMAL_TRUE}" && test -z "${MODULE__DECIMAL_FALSE}"; then + as_fn_error $? "conditional \"MODULE__DECIMAL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 diff --git a/configure.ac b/configure.ac index f43030e481068..43c8f768c18f8 100644 --- a/configure.ac +++ b/configure.ac @@ -5936,6 +5936,68 @@ else fi AC_SUBST(TEST_MODULES) +dnl Modules that are not available on some platforms +dnl AIX has shadow passwords, but access is not via getspent() +dnl VxWorks does not provide crypt() function +AS_CASE([$ac_sys_system], + [AIX], [py_stdlib_not_available="_scproxy spwd"], + [VxWorks*], [py_stdlib_not_available="_scproxy _crypt termios grp"], + [Darwin], [py_stdlib_not_available="ossaudiodev spwd"], + [CYGWIN*], [py_stdlib_not_available="_scproxy nis"], + [QNX*], [py_stdlib_not_available="_scproxy nis"], + [FreeBSD*], [py_stdlib_not_available="_scproxy spwd"], + [py_stdlib_not_available="_scproxy"] +) + +dnl _MODULE_BLOCK_ADD([VAR], [VALUE]) +dnl internal: adds $1=quote($2) to MODULE_BLOCK +AC_DEFUN([_MODULE_BLOCK_ADD], [AS_VAR_APPEND([MODULE_BLOCK], ["$1=_AS_QUOTE([$2])$as_nl"])]) +MODULE_BLOCK= + +dnl Check for stdlib extension modules +dnl PY_STDLIB_MOD([NAME], [ENABLED-TEST], [SUPPORTED-TEST], [CFLAGS], [LDFLAGS]) +dnl sets MODULE_$NAME based on $py_stdlib_not_available, ENABLED-TEST, +dnl and SUPPORTED_TEST. ENABLED-TEST and SUPPORTED-TEST default to true if +dnl empty. +dnl n/a: $NAME in $py_stdlib_not_available (not available on platform) +dnl yes: enabled and supported +dnl missing: enabled and not supported +dnl disabled: not enabled +dnl sets MODULE_$NAME_CFLAGS and MODULE_$NAME_LDFLAGS +AC_DEFUN([PY_STDLIB_MOD], [ + AC_MSG_CHECKING([for stdlib extension module $1]) + m4_pushdef([modcond], [MODULE_]m4_toupper([$1]))dnl + m4_pushdef([modstate], [py_cv_module_$1])dnl + AS_CASE([$py_stdlib_not_available], + [*$1*], [modstate=n/a], + [ + AS_IF(m4_ifblank([$2], [true], [$2]), + [AS_IF([m4_ifblank([$3], [true], [$3])], [modstate=yes], [modstate=missing])], + [modstate=disabled] + ) + ] + ) + _MODULE_BLOCK_ADD(modcond, [$modstate]) + AS_VAR_IF([modstate], [yes], [ + _MODULE_BLOCK_ADD([MODULE_]m4_toupper([$1])[_CFLAGS], [$4]) + _MODULE_BLOCK_ADD([MODULE_]m4_toupper([$1])[_LDFLAGS], [$5]) + AM_CONDITIONAL(modcond, [true]) + ], [ + AM_CONDITIONAL(modcond, [false]) + ]) + AC_MSG_RESULT([$modstate]) + m4_popdef([modcond])dnl + m4_popdef([modstate])dnl +]) + +dnl _elementtree loads libexpat via CAPI hook in pyexpat +PY_STDLIB_MOD([pyexpat], [], [], [$LIBEXPAT_CFLAGS], [$LIBEXPAT_LDFLAGS]) +PY_STDLIB_MOD([_elementtree], [], [], [$LIBEXPAT_CFLAGS], []) + +PY_STDLIB_MOD([_decimal], [], [], [$LIBMPDEC_CFLAGS], [$LIBMPDEC_LDFLAGS]) + +# substitute multiline block, must come after last PY_STDLIB_MOD() +AC_SUBST([MODULE_BLOCK]) # generate output files AC_CONFIG_FILES(Makefile.pre Misc/python.pc Misc/python-embed.pc Misc/python-config.sh) diff --git a/setup.py b/setup.py index 915169e68630d..8b9566e26bffd 100644 --- a/setup.py +++ b/setup.py @@ -364,57 +364,6 @@ def find_module_file(module, dirlist): return os.path.abspath(os.path.join(dirs[0], module)) -def parse_cflags(flags): - """Parse a string with compiler flags (-I, -D, -U, extra) - - Distutils appends extra args to the compiler arguments. Some flags like - -I must appear earlier. Otherwise the pre-processor picks up files - from system inclue directories. - """ - include_dirs = [] - define_macros = [] - undef_macros = [] - extra_compile_args = [] - if flags is not None: - # shlex.split(None) reads from stdin - for token in shlex.split(flags): - switch = token[0:2] - value = token[2:] - if switch == '-I': - include_dirs.append(value) - elif switch == '-D': - key, _, val = value.partition("=") - if not val: - val = None - define_macros.append((key, val)) - elif switch == '-U': - undef_macros.append(value) - else: - extra_compile_args.append(token) - - return include_dirs, define_macros, undef_macros, extra_compile_args - - -def parse_ldflags(flags): - """Parse a string with linker flags (-L, -l, extra)""" - library_dirs = [] - libraries = [] - extra_link_args = [] - if flags is not None: - # shlex.split(None) reads from stdin - for token in shlex.split(flags): - switch = token[0:2] - value = token[2:] - if switch == '-L': - library_dirs.append(value) - elif switch == '-l': - libraries.append(value) - else: - extra_link_args.append(token) - - return library_dirs, libraries, extra_link_args - - class PyBuildExt(build_ext): def __init__(self, dist): @@ -433,6 +382,74 @@ def __init__(self, dist): def add(self, ext): self.extensions.append(ext) + def addext(self, ext, *, update_flags=True): + """Add extension with Makefile MODULE_{name} support + """ + if update_flags: + self.update_extension_flags(ext) + + state = sysconfig.get_config_var(f"MODULE_{ext.name.upper()}") + if state == "yes": + self.extensions.append(ext) + elif state == "disabled": + self.disabled_configure.append(ext.name) + elif state == "missing": + self.missing.append(ext.name) + elif state == "n/a": + # not available on current platform + pass + else: + # not migrated to MODULE_{name} yet. + self.extensions.append(ext) + + def update_extension_flags(self, ext): + """Update extension flags with module CFLAGS and LDFLAGS + + Reads MODULE_{name}_CFLAGS and _LDFLAGS + + Distutils appends extra args to the compiler arguments. Some flags like + -I must appear earlier, otherwise the pre-processor picks up files + from system inclue directories. + """ + upper_name = ext.name.upper() + # Parse compiler flags (-I, -D, -U, extra args) + cflags = sysconfig.get_config_var(f"MODULE_{upper_name}_CFLAGS") + if cflags: + for token in shlex.split(cflags): + switch = token[0:2] + value = token[2:] + if switch == '-I': + ext.include_dirs.append(value) + elif switch == '-D': + key, _, val = value.partition("=") + if not val: + val = None + ext.define_macros.append((key, val)) + elif switch == '-U': + ext.undef_macros.append(value) + else: + ext.extra_compile_args.append(token) + + # Parse linker flags (-L, -l, extra objects, extra args) + ldflags = sysconfig.get_config_var(f"MODULE_{upper_name}_LDFLAGS") + if ldflags: + for token in shlex.split(ldflags): + switch = token[0:2] + value = token[2:] + if switch == '-L': + ext.library_dirs.append(value) + elif switch == '-l': + ext.libraries.append(value) + elif ( + token[0] != '-' and + token.endswith(('.a', '.o', '.so', '.sl', '.dylib')) + ): + ext.extra_objects.append(token) + else: + ext.extra_link_args.append(token) + + return ext + def set_srcdir(self): self.srcdir = sysconfig.get_config_var('srcdir') if not self.srcdir: @@ -1527,32 +1544,11 @@ def detect_expat_elementtree(self): # # More information on Expat can be found at www.libexpat.org. # - cflags = parse_cflags(sysconfig.get_config_var("EXPAT_CFLAGS")) - include_dirs, define_macros, undef_macros, extra_compile_args = cflags - # ldflags includes either system libexpat or full path to - # our static libexpat.a. - ldflags = parse_ldflags(sysconfig.get_config_var("EXPAT_LDFLAGS")) - library_dirs, libraries, extra_link_args = ldflags - - self.add(Extension('pyexpat', - include_dirs=include_dirs, - define_macros=define_macros, - undef_macros=undef_macros, - extra_compile_args=extra_compile_args, - library_dirs=library_dirs, - libraries=libraries, - extra_link_args=extra_link_args, - sources=['pyexpat.c'])) + self.addext(Extension('pyexpat', sources=['pyexpat.c'])) # Fredrik Lundh's cElementTree module. Note that this also # uses expat (via the CAPI hook in pyexpat). - self.add(Extension('_elementtree', - include_dirs=include_dirs, - define_macros=define_macros, - undef_macros=undef_macros, - extra_compile_args=extra_compile_args, - # no EXPAT_LDFLAGS - sources=['_elementtree.c'])) + self.addext(Extension('_elementtree', sources=['_elementtree.c'])) def detect_multibytecodecs(self): # Hye-Shik Chang's CJKCodecs modules. @@ -2046,26 +2042,14 @@ def detect_ctypes(self): def detect_decimal(self): # Stefan Krah's _decimal module - sources = ['_decimal/_decimal.c'] - - cflags = parse_cflags(sysconfig.get_config_var("DECIMAL_CFLAGS")) - include_dirs, define_macros, undef_macros, extra_compile_args = cflags - # ldflags includes either system libmpdec or full path to - # our static libmpdec.a. - ldflags = parse_ldflags(sysconfig.get_config_var("DECIMAL_LDFLAGS")) - library_dirs, libraries, extra_link_args = ldflags - - # Uncomment for extra functionality: - #define_macros.append(('EXTRA_FUNCTIONALITY', 1)) - self.add(Extension('_decimal', - include_dirs=include_dirs, - define_macros=define_macros, - undef_macros=undef_macros, - extra_compile_args=extra_compile_args, - library_dirs=library_dirs, - libraries=libraries, - extra_link_args=extra_link_args, - sources=sources)) + self.addext( + Extension( + '_decimal', + ['_decimal/_decimal.c'], + # Uncomment for extra functionality: + # define_macros=[('EXTRA_FUNCTIONALITY', 1)] + ) + ) def detect_openssl_hashlib(self): # Detect SSL support for the socket module (via _ssl) From webhook-mailer at python.org Thu Nov 18 03:51:25 2021 From: webhook-mailer at python.org (ethanfurman) Date: Thu, 18 Nov 2021 08:51:25 -0000 Subject: [Python-checkins] [3.9] [Enum] update member.member removal (GH-29611) Message-ID: https://github.com/python/cpython/commit/feccea6a7eb1309513750bb4a31aee5a65c7c4bf commit: feccea6a7eb1309513750bb4a31aee5a65c7c4bf branch: 3.9 author: Ethan Furman committer: ethanfurman date: 2021-11-18T00:50:42-08:00 summary: [3.9] [Enum] update member.member removal (GH-29611) Accessing one enum member from another originally raised an `AttributeError`, but became possible due to a performance boost implementation detail. In 3.11 it will again raise an `AttributeError`. files: M Doc/library/enum.rst diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst index 4e15901c66bfc..056b9f7bf427a 100644 --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -1152,7 +1152,7 @@ all-uppercase names for members):: .. note:: - This behavior is deprecated and will be removed in 3.12. + This behavior is deprecated and will be removed in 3.11. .. versionchanged:: 3.5 From webhook-mailer at python.org Thu Nov 18 03:51:35 2021 From: webhook-mailer at python.org (pitrou) Date: Thu, 18 Nov 2021 08:51:35 -0000 Subject: [Python-checkins] bpo-45835: Fix race condition in test_queue (#29601) Message-ID: https://github.com/python/cpython/commit/df3e53d86b2ad67da9ac2b5a3f56257d1f394982 commit: df3e53d86b2ad67da9ac2b5a3f56257d1f394982 branch: main author: Sam Gross committer: pitrou date: 2021-11-18T09:51:30+01:00 summary: bpo-45835: Fix race condition in test_queue (#29601) Some of the tests in test_queue had a race condition in which a non-sentinel value could be enqueued after the final sentinel value leading to not all the inputs being processed (and test failures). This changes feed() to enqueue a sentinel once the inputs are exhausted, which guarantees that the final queued object is a sentinel. This requires the number of feeder threads to match the number of consumer threads, but that's already the case in the relevant tests. files: A Misc/NEWS.d/next/Tests/2021-11-17-14-28-08.bpo-45835.Mgyhjx.rst M Lib/test/test_queue.py diff --git a/Lib/test/test_queue.py b/Lib/test/test_queue.py index 9bb5181377698..cfa6003a867da 100644 --- a/Lib/test/test_queue.py +++ b/Lib/test/test_queue.py @@ -420,11 +420,12 @@ class BaseSimpleQueueTest: def setUp(self): self.q = self.type2test() - def feed(self, q, seq, rnd): + def feed(self, q, seq, rnd, sentinel): while True: try: val = seq.pop() except IndexError: + q.put(sentinel) return q.put(val) if rnd.random() > 0.5: @@ -463,11 +464,10 @@ def consume_timeout(self, q, results, sentinel): return results.append(val) - def run_threads(self, n_feeders, n_consumers, q, inputs, - feed_func, consume_func): + def run_threads(self, n_threads, q, inputs, feed_func, consume_func): results = [] sentinel = None - seq = inputs + [sentinel] * n_consumers + seq = inputs.copy() seq.reverse() rnd = random.Random(42) @@ -481,11 +481,11 @@ def wrapper(*args, **kwargs): return wrapper feeders = [threading.Thread(target=log_exceptions(feed_func), - args=(q, seq, rnd)) - for i in range(n_feeders)] + args=(q, seq, rnd, sentinel)) + for i in range(n_threads)] consumers = [threading.Thread(target=log_exceptions(consume_func), args=(q, results, sentinel)) - for i in range(n_consumers)] + for i in range(n_threads)] with threading_helper.start_threads(feeders + consumers): pass @@ -543,7 +543,7 @@ def test_order(self): # Test a pair of concurrent put() and get() q = self.q inputs = list(range(100)) - results = self.run_threads(1, 1, q, inputs, self.feed, self.consume) + results = self.run_threads(1, q, inputs, self.feed, self.consume) # One producer, one consumer => results appended in well-defined order self.assertEqual(results, inputs) @@ -553,7 +553,7 @@ def test_many_threads(self): N = 50 q = self.q inputs = list(range(10000)) - results = self.run_threads(N, N, q, inputs, self.feed, self.consume) + results = self.run_threads(N, q, inputs, self.feed, self.consume) # Multiple consumers without synchronization append the # results in random order @@ -564,7 +564,7 @@ def test_many_threads_nonblock(self): N = 50 q = self.q inputs = list(range(10000)) - results = self.run_threads(N, N, q, inputs, + results = self.run_threads(N, q, inputs, self.feed, self.consume_nonblock) self.assertEqual(sorted(results), inputs) @@ -574,7 +574,7 @@ def test_many_threads_timeout(self): N = 50 q = self.q inputs = list(range(1000)) - results = self.run_threads(N, N, q, inputs, + results = self.run_threads(N, q, inputs, self.feed, self.consume_timeout) self.assertEqual(sorted(results), inputs) diff --git a/Misc/NEWS.d/next/Tests/2021-11-17-14-28-08.bpo-45835.Mgyhjx.rst b/Misc/NEWS.d/next/Tests/2021-11-17-14-28-08.bpo-45835.Mgyhjx.rst new file mode 100644 index 0000000000000..6a73b01959065 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-11-17-14-28-08.bpo-45835.Mgyhjx.rst @@ -0,0 +1 @@ +Fix race condition in test_queue tests with multiple "feeder" threads. From webhook-mailer at python.org Thu Nov 18 04:18:17 2021 From: webhook-mailer at python.org (corona10) Date: Thu, 18 Nov 2021 09:18:17 -0000 Subject: [Python-checkins] bpo-45512: Use Argument Clinic to set sqlite3 isolation level (GH-29593) Message-ID: https://github.com/python/cpython/commit/0920b61a0cb30128287ebafab1df8cad3a3dffdb commit: 0920b61a0cb30128287ebafab1df8cad3a3dffdb branch: main author: Erlend Egeberg Aasland committer: corona10 date: 2021-11-18T18:18:09+09:00 summary: bpo-45512: Use Argument Clinic to set sqlite3 isolation level (GH-29593) files: M Modules/_sqlite/clinic/connection.c.h M Modules/_sqlite/connection.c diff --git a/Modules/_sqlite/clinic/connection.c.h b/Modules/_sqlite/clinic/connection.c.h index 3a3ae04e8a193..16ad2ee254eca 100644 --- a/Modules/_sqlite/clinic/connection.c.h +++ b/Modules/_sqlite/clinic/connection.c.h @@ -63,22 +63,7 @@ pysqlite_connection_init(PyObject *self, PyObject *args, PyObject *kwargs) } } if (fastargs[3]) { - if (fastargs[3] == Py_None) { - isolation_level = NULL; - } - else if (PyUnicode_Check(fastargs[3])) { - Py_ssize_t isolation_level_length; - isolation_level = PyUnicode_AsUTF8AndSize(fastargs[3], &isolation_level_length); - if (isolation_level == NULL) { - goto exit; - } - if (strlen(isolation_level) != (size_t)isolation_level_length) { - PyErr_SetString(PyExc_ValueError, "embedded null character"); - goto exit; - } - } - else { - _PyArg_BadArgument("Connection", "argument 'isolation_level'", "str or None", fastargs[3]); + if (!isolation_level_converter(fastargs[3], &isolation_level)) { goto exit; } if (!--noptargs) { @@ -851,4 +836,4 @@ getlimit(pysqlite_Connection *self, PyObject *arg) #ifndef PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF #define PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF #endif /* !defined(PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF) */ -/*[clinic end generated code: output=6f267f20e77f92d0 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c2faf6563397091b input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index f632e3359cfb9..0bc9d1d0eeda5 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -33,6 +33,60 @@ #define HAVE_TRACE_V2 #endif +static const char * +get_isolation_level(const char *level) +{ + assert(level != NULL); + static const char *const allowed_levels[] = { + "", + "DEFERRED", + "IMMEDIATE", + "EXCLUSIVE", + NULL + }; + for (int i = 0; allowed_levels[i] != NULL; i++) { + const char *candidate = allowed_levels[i]; + if (sqlite3_stricmp(level, candidate) == 0) { + return candidate; + } + } + PyErr_SetString(PyExc_ValueError, + "isolation_level string must be '', 'DEFERRED', " + "'IMMEDIATE', or 'EXCLUSIVE'"); + return NULL; +} + +static int +isolation_level_converter(PyObject *str_or_none, const char **result) +{ + if (Py_IsNone(str_or_none)) { + *result = NULL; + } + else if (PyUnicode_Check(str_or_none)) { + Py_ssize_t sz; + const char *str = PyUnicode_AsUTF8AndSize(str_or_none, &sz); + if (str == NULL) { + return 0; + } + if (strlen(str) != (size_t)sz) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + return 0; + } + + const char *level = get_isolation_level(str); + if (level == NULL) { + return 0; + } + *result = level; + } + else { + PyErr_SetString(PyExc_TypeError, + "isolation_level must be str or None"); + return 0; + } + return 1; +} + static int clinic_fsconverter(PyObject *pathlike, const char **result) { @@ -100,29 +154,6 @@ new_statement_cache(pysqlite_Connection *self, pysqlite_state *state, return res; } -static const char * -get_isolation_level(const char *level) -{ - assert(level != NULL); - static const char *const allowed_levels[] = { - "", - "DEFERRED", - "IMMEDIATE", - "EXCLUSIVE", - NULL - }; - for (int i = 0; allowed_levels[i] != NULL; i++) { - const char *candidate = allowed_levels[i]; - if (sqlite3_stricmp(level, candidate) == 0) { - return candidate; - } - } - PyErr_SetString(PyExc_ValueError, - "isolation_level string must be '', 'DEFERRED', " - "'IMMEDIATE', or 'EXCLUSIVE'"); - return NULL; -} - /*[python input] class FSConverter_converter(CConverter): type = "const char *" @@ -131,8 +162,13 @@ class FSConverter_converter(CConverter): self.c_default = "NULL" def cleanup(self): return f"PyMem_Free((void *){self.name});\n" + +class IsolationLevel_converter(CConverter): + type = "const char *" + converter = "isolation_level_converter" + [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=7b3be538bc4058c0]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=be142323885672ab]*/ /*[clinic input] _sqlite3.Connection.__init__ as pysqlite_connection_init @@ -140,7 +176,7 @@ _sqlite3.Connection.__init__ as pysqlite_connection_init database: FSConverter timeout: double = 5.0 detect_types: int = 0 - isolation_level: str(accept={str, NoneType}) = "" + isolation_level: IsolationLevel = "" check_same_thread: bool(accept={int}) = True factory: object(c_default='(PyObject*)clinic_state()->ConnectionType') = ConnectionType cached_statements as cache_size: int = 128 @@ -153,7 +189,7 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, int detect_types, const char *isolation_level, int check_same_thread, PyObject *factory, int cache_size, int uri) -/*[clinic end generated code: output=7d640ae1d83abfd4 input=35e316f66d9f70fd]*/ +/*[clinic end generated code: output=7d640ae1d83abfd4 input=342173993434ba1e]*/ { if (PySys_Audit("sqlite3.connect", "s", database) < 0) { return -1; @@ -189,15 +225,6 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, return -1; } - // Convert isolation level to begin statement. - const char *level = NULL; - if (isolation_level != NULL) { - level = get_isolation_level(isolation_level); - if (level == NULL) { - return -1; - } - } - // Create LRU statement cache; returns a new reference. PyObject *statement_cache = new_statement_cache(self, state, cache_size); if (statement_cache == NULL) { @@ -215,7 +242,7 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, self->db = db; self->state = state; self->detect_types = detect_types; - self->isolation_level = level; + self->isolation_level = isolation_level; self->check_same_thread = check_same_thread; self->thread_ident = PyThread_get_thread_ident(); self->statement_cache = statement_cache; @@ -1375,26 +1402,9 @@ pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* iso return -1; } Py_DECREF(res); + return 0; } - else if (PyUnicode_Check(isolation_level)) { - Py_ssize_t len; - const char *cstr_level = PyUnicode_AsUTF8AndSize(isolation_level, &len); - if (cstr_level == NULL) { - return -1; - } - if (strlen(cstr_level) != (size_t)len) { - PyErr_SetString(PyExc_ValueError, "embedded null character"); - return -1; - } - const char *level = get_isolation_level(cstr_level); - if (level == NULL) { - return -1; - } - self->isolation_level = level; - } - else { - PyErr_SetString(PyExc_TypeError, - "isolation_level must be str or None"); + if (!isolation_level_converter(isolation_level, &self->isolation_level)) { return -1; } return 0; From webhook-mailer at python.org Thu Nov 18 04:20:08 2021 From: webhook-mailer at python.org (markshannon) Date: Thu, 18 Nov 2021 09:20:08 -0000 Subject: [Python-checkins] bpo-45510: Specialize BINARY_SUBTRACT (GH-29523) Message-ID: https://github.com/python/cpython/commit/345ba3f080c140dee3102f472bc166c2db191bcc commit: 345ba3f080c140dee3102f472bc166c2db191bcc branch: main author: Dong-hee Na committer: markshannon date: 2021-11-18T09:19:58Z summary: bpo-45510: Specialize BINARY_SUBTRACT (GH-29523) files: M Include/internal/pycore_long.h M Include/opcode.h M Lib/opcode.py M Objects/longobject.c M Python/ceval.c M Python/opcode_targets.h M Python/specialize.c diff --git a/Include/internal/pycore_long.h b/Include/internal/pycore_long.h index 2f786083e4527..b9f926996d810 100644 --- a/Include/internal/pycore_long.h +++ b/Include/internal/pycore_long.h @@ -23,6 +23,7 @@ static inline PyObject* _PyLong_GetOne(void) PyObject *_PyLong_Add(PyLongObject *left, PyLongObject *right); PyObject *_PyLong_Multiply(PyLongObject *left, PyLongObject *right); +PyObject *_PyLong_Subtract(PyLongObject *left, PyLongObject *right); /* Used by Python/mystrtoul.c, _PyBytes_FromHex(), _PyBytes_DecodeEscape(), etc. */ diff --git a/Include/opcode.h b/Include/opcode.h index c7354de9a0687..ca20ccda1199b 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -118,39 +118,41 @@ extern "C" { #define BINARY_OP_INPLACE_ADD_UNICODE 16 #define BINARY_OP_MULTIPLY_INT 17 #define BINARY_OP_MULTIPLY_FLOAT 18 -#define BINARY_SUBSCR_ADAPTIVE 19 -#define BINARY_SUBSCR_LIST_INT 20 -#define BINARY_SUBSCR_TUPLE_INT 21 -#define BINARY_SUBSCR_DICT 22 -#define CALL_FUNCTION_ADAPTIVE 23 -#define CALL_FUNCTION_BUILTIN_O 24 -#define CALL_FUNCTION_BUILTIN_FAST 26 -#define CALL_FUNCTION_LEN 27 -#define CALL_FUNCTION_ISINSTANCE 28 -#define CALL_FUNCTION_PY_SIMPLE 29 -#define JUMP_ABSOLUTE_QUICK 34 -#define LOAD_ATTR_ADAPTIVE 36 -#define LOAD_ATTR_INSTANCE_VALUE 38 -#define LOAD_ATTR_WITH_HINT 39 -#define LOAD_ATTR_SLOT 40 -#define LOAD_ATTR_MODULE 41 -#define LOAD_GLOBAL_ADAPTIVE 42 -#define LOAD_GLOBAL_MODULE 43 -#define LOAD_GLOBAL_BUILTIN 44 -#define LOAD_METHOD_ADAPTIVE 45 -#define LOAD_METHOD_CACHED 46 -#define LOAD_METHOD_CLASS 47 -#define LOAD_METHOD_MODULE 48 -#define LOAD_METHOD_NO_DICT 55 -#define STORE_ATTR_ADAPTIVE 56 -#define STORE_ATTR_INSTANCE_VALUE 57 -#define STORE_ATTR_SLOT 58 -#define STORE_ATTR_WITH_HINT 59 -#define LOAD_FAST__LOAD_FAST 62 -#define STORE_FAST__LOAD_FAST 63 -#define LOAD_FAST__LOAD_CONST 64 -#define LOAD_CONST__LOAD_FAST 65 -#define STORE_FAST__STORE_FAST 66 +#define BINARY_OP_SUBTRACT_INT 19 +#define BINARY_OP_SUBTRACT_FLOAT 20 +#define BINARY_SUBSCR_ADAPTIVE 21 +#define BINARY_SUBSCR_LIST_INT 22 +#define BINARY_SUBSCR_TUPLE_INT 23 +#define BINARY_SUBSCR_DICT 24 +#define CALL_FUNCTION_ADAPTIVE 26 +#define CALL_FUNCTION_BUILTIN_O 27 +#define CALL_FUNCTION_BUILTIN_FAST 28 +#define CALL_FUNCTION_LEN 29 +#define CALL_FUNCTION_ISINSTANCE 34 +#define CALL_FUNCTION_PY_SIMPLE 36 +#define JUMP_ABSOLUTE_QUICK 38 +#define LOAD_ATTR_ADAPTIVE 39 +#define LOAD_ATTR_INSTANCE_VALUE 40 +#define LOAD_ATTR_WITH_HINT 41 +#define LOAD_ATTR_SLOT 42 +#define LOAD_ATTR_MODULE 43 +#define LOAD_GLOBAL_ADAPTIVE 44 +#define LOAD_GLOBAL_MODULE 45 +#define LOAD_GLOBAL_BUILTIN 46 +#define LOAD_METHOD_ADAPTIVE 47 +#define LOAD_METHOD_CACHED 48 +#define LOAD_METHOD_CLASS 55 +#define LOAD_METHOD_MODULE 56 +#define LOAD_METHOD_NO_DICT 57 +#define STORE_ATTR_ADAPTIVE 58 +#define STORE_ATTR_INSTANCE_VALUE 59 +#define STORE_ATTR_SLOT 62 +#define STORE_ATTR_WITH_HINT 63 +#define LOAD_FAST__LOAD_FAST 64 +#define STORE_FAST__LOAD_FAST 65 +#define LOAD_FAST__LOAD_CONST 66 +#define LOAD_CONST__LOAD_FAST 67 +#define STORE_FAST__STORE_FAST 75 #define DO_TRACING 255 #ifdef NEED_OPCODE_JUMP_TABLES static uint32_t _PyOpcode_RelativeJump[8] = { diff --git a/Lib/opcode.py b/Lib/opcode.py index 940e169d5597d..4abe99fcbec17 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -231,6 +231,8 @@ def jabs_op(name, op): "BINARY_OP_INPLACE_ADD_UNICODE", "BINARY_OP_MULTIPLY_INT", "BINARY_OP_MULTIPLY_FLOAT", + "BINARY_OP_SUBTRACT_INT", + "BINARY_OP_SUBTRACT_FLOAT", "BINARY_SUBSCR_ADAPTIVE", "BINARY_SUBSCR_LIST_INT", "BINARY_SUBSCR_TUPLE_INT", diff --git a/Objects/longobject.c b/Objects/longobject.c index a4d90b1704321..ce4f0d72540d3 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -3155,14 +3155,11 @@ long_add(PyLongObject *a, PyLongObject *b) return _PyLong_Add(a, b); } - -static PyObject * -long_sub(PyLongObject *a, PyLongObject *b) +PyObject * +_PyLong_Subtract(PyLongObject *a, PyLongObject *b) { PyLongObject *z; - CHECK_BINOP(a, b); - if (IS_MEDIUM_VALUE(a) && IS_MEDIUM_VALUE(b)) { return _PyLong_FromSTwoDigits(medium_value(a) - medium_value(b)); } @@ -3187,6 +3184,13 @@ long_sub(PyLongObject *a, PyLongObject *b) return (PyObject *)z; } +static PyObject * +long_sub(PyLongObject *a, PyLongObject *b) +{ + CHECK_BINOP(a, b); + return _PyLong_Subtract(a, b); +} + /* Grade school multiplication, ignoring the signs. * Returns the absolute value of the product, or NULL if error. */ diff --git a/Python/ceval.c b/Python/ceval.c index c02e3517d44f4..e579edefdb7af 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2009,6 +2009,41 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr DISPATCH(); } + TARGET(BINARY_OP_SUBTRACT_INT) { + PyObject *left = SECOND(); + PyObject *right = TOP(); + DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP); + DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP); + STAT_INC(BINARY_OP, hit); + PyObject *sub = _PyLong_Subtract((PyLongObject *)left, (PyLongObject *)right); + SET_SECOND(sub); + Py_DECREF(right); + Py_DECREF(left); + STACK_SHRINK(1); + if (sub == NULL) { + goto error; + } + DISPATCH(); + } + + TARGET(BINARY_OP_SUBTRACT_FLOAT) { + PyObject *left = SECOND(); + PyObject *right = TOP(); + DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP); + DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP); + STAT_INC(BINARY_OP, hit); + double dsub = ((PyFloatObject *)left)->ob_fval - ((PyFloatObject *)right)->ob_fval; + PyObject *sub = PyFloat_FromDouble(dsub); + SET_SECOND(sub); + Py_DECREF(right); + Py_DECREF(left); + STACK_SHRINK(1); + if (sub == NULL) { + goto error; + } + DISPATCH(); + } + TARGET(BINARY_OP_ADD_UNICODE) { PyObject *left = SECOND(); PyObject *right = TOP(); diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index a57617e022e1d..07852d167c769 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -18,25 +18,27 @@ static void *opcode_targets[256] = { &&TARGET_BINARY_OP_INPLACE_ADD_UNICODE, &&TARGET_BINARY_OP_MULTIPLY_INT, &&TARGET_BINARY_OP_MULTIPLY_FLOAT, + &&TARGET_BINARY_OP_SUBTRACT_INT, + &&TARGET_BINARY_OP_SUBTRACT_FLOAT, &&TARGET_BINARY_SUBSCR_ADAPTIVE, &&TARGET_BINARY_SUBSCR_LIST_INT, &&TARGET_BINARY_SUBSCR_TUPLE_INT, &&TARGET_BINARY_SUBSCR_DICT, + &&TARGET_BINARY_SUBSCR, &&TARGET_CALL_FUNCTION_ADAPTIVE, &&TARGET_CALL_FUNCTION_BUILTIN_O, - &&TARGET_BINARY_SUBSCR, &&TARGET_CALL_FUNCTION_BUILTIN_FAST, &&TARGET_CALL_FUNCTION_LEN, - &&TARGET_CALL_FUNCTION_ISINSTANCE, - &&TARGET_CALL_FUNCTION_PY_SIMPLE, &&TARGET_GET_LEN, &&TARGET_MATCH_MAPPING, &&TARGET_MATCH_SEQUENCE, &&TARGET_MATCH_KEYS, - &&TARGET_JUMP_ABSOLUTE_QUICK, + &&TARGET_CALL_FUNCTION_ISINSTANCE, &&TARGET_PUSH_EXC_INFO, - &&TARGET_LOAD_ATTR_ADAPTIVE, + &&TARGET_CALL_FUNCTION_PY_SIMPLE, &&TARGET_POP_EXCEPT_AND_RERAISE, + &&TARGET_JUMP_ABSOLUTE_QUICK, + &&TARGET_LOAD_ATTR_ADAPTIVE, &&TARGET_LOAD_ATTR_INSTANCE_VALUE, &&TARGET_LOAD_ATTR_WITH_HINT, &&TARGET_LOAD_ATTR_SLOT, @@ -46,27 +48,25 @@ static void *opcode_targets[256] = { &&TARGET_LOAD_GLOBAL_BUILTIN, &&TARGET_LOAD_METHOD_ADAPTIVE, &&TARGET_LOAD_METHOD_CACHED, - &&TARGET_LOAD_METHOD_CLASS, - &&TARGET_LOAD_METHOD_MODULE, &&TARGET_WITH_EXCEPT_START, &&TARGET_GET_AITER, &&TARGET_GET_ANEXT, &&TARGET_BEFORE_ASYNC_WITH, &&TARGET_BEFORE_WITH, &&TARGET_END_ASYNC_FOR, + &&TARGET_LOAD_METHOD_CLASS, + &&TARGET_LOAD_METHOD_MODULE, &&TARGET_LOAD_METHOD_NO_DICT, &&TARGET_STORE_ATTR_ADAPTIVE, &&TARGET_STORE_ATTR_INSTANCE_VALUE, - &&TARGET_STORE_ATTR_SLOT, - &&TARGET_STORE_ATTR_WITH_HINT, &&TARGET_STORE_SUBSCR, &&TARGET_DELETE_SUBSCR, + &&TARGET_STORE_ATTR_SLOT, + &&TARGET_STORE_ATTR_WITH_HINT, &&TARGET_LOAD_FAST__LOAD_FAST, &&TARGET_STORE_FAST__LOAD_FAST, &&TARGET_LOAD_FAST__LOAD_CONST, &&TARGET_LOAD_CONST__LOAD_FAST, - &&TARGET_STORE_FAST__STORE_FAST, - &&_unknown_opcode, &&TARGET_GET_ITER, &&TARGET_GET_YIELD_FROM_ITER, &&TARGET_PRINT_EXPR, @@ -74,7 +74,7 @@ static void *opcode_targets[256] = { &&TARGET_YIELD_FROM, &&TARGET_GET_AWAITABLE, &&TARGET_LOAD_ASSERTION_ERROR, - &&_unknown_opcode, + &&TARGET_STORE_FAST__STORE_FAST, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, diff --git a/Python/specialize.c b/Python/specialize.c index cfc21bf70ad6b..dd15de72d2796 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -1424,6 +1424,19 @@ _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, goto success; } break; + case NB_SUBTRACT: + case NB_INPLACE_SUBTRACT: + if (PyLong_CheckExact(lhs)) { + *instr = _Py_MAKECODEUNIT(BINARY_OP_SUBTRACT_INT, + _Py_OPARG(*instr)); + goto success; + } + if (PyFloat_CheckExact(lhs)) { + *instr = _Py_MAKECODEUNIT(BINARY_OP_SUBTRACT_FLOAT, + _Py_OPARG(*instr)); + goto success; + } + break; default: // These operators don't have any available specializations. Rather // than repeatedly attempting to specialize them, just convert them From webhook-mailer at python.org Thu Nov 18 04:56:46 2021 From: webhook-mailer at python.org (tiran) Date: Thu, 18 Nov 2021 09:56:46 -0000 Subject: [Python-checkins] bpo-45573: check for ossaudiodev in configure (GH-29614) Message-ID: https://github.com/python/cpython/commit/5275e59c0c1b26226608e6c7c2548c26192d6575 commit: 5275e59c0c1b26226608e6c7c2548c26192d6575 branch: main author: Christian Heimes committer: tiran date: 2021-11-18T10:56:26+01:00 summary: bpo-45573: check for ossaudiodev in configure (GH-29614) files: M configure M configure.ac M pyconfig.h.in M setup.py diff --git a/configure b/configure index ab5afbf0b8aef..f8987128a01cf 100755 --- a/configure +++ b/configure @@ -630,6 +630,8 @@ MODULE__ELEMENTTREE_FALSE MODULE__ELEMENTTREE_TRUE MODULE_PYEXPAT_FALSE MODULE_PYEXPAT_TRUE +MODULE_OSSAUDIODEV_FALSE +MODULE_OSSAUDIODEV_TRUE TEST_MODULES LIBRARY_DEPS STATIC_LIBPYTHON @@ -8150,7 +8152,7 @@ sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h \ libutil.h sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \ linux/tipc.h linux/random.h spawn.h util.h alloca.h endian.h \ sys/endian.h sys/sysmacros.h linux/memfd.h linux/wait.h sys/memfd.h \ -sys/mman.h sys/eventfd.h +sys/mman.h sys/eventfd.h linux/soundcard.h sys/soundcard.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" @@ -19227,6 +19229,57 @@ MODULE_BLOCK= + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module ossaudiodev" >&5 +$as_echo_n "checking for stdlib extension module ossaudiodev... " >&6; } + case $py_stdlib_not_available in #( + *ossaudiodev*) : + py_cv_module_ossaudiodev=n/a ;; #( + *) : + + if true; then : + if test "$ac_cv_header_linux_soundcard_h" = yes -o "$ac_cv_header_sys_soundcard_h" = yes; then : + py_cv_module_ossaudiodev=yes +else + py_cv_module_ossaudiodev=missing +fi +else + py_cv_module_ossaudiodev=disabled + +fi + + ;; +esac + as_fn_append MODULE_BLOCK "MODULE_OSSAUDIODEV=$py_cv_module_ossaudiodev$as_nl" + if test "x$py_cv_module_ossaudiodev" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE_OSSAUDIODEV_CFLAGS=$as_nl" + as_fn_append MODULE_BLOCK "MODULE_OSSAUDIODEV_LDFLAGS=$as_nl" + if true; then + MODULE_OSSAUDIODEV_TRUE= + MODULE_OSSAUDIODEV_FALSE='#' +else + MODULE_OSSAUDIODEV_TRUE='#' + MODULE_OSSAUDIODEV_FALSE= +fi + + +else + + if false; then + MODULE_OSSAUDIODEV_TRUE= + MODULE_OSSAUDIODEV_FALSE='#' +else + MODULE_OSSAUDIODEV_TRUE='#' + MODULE_OSSAUDIODEV_FALSE= +fi + + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module_ossaudiodev" >&5 +$as_echo "$py_cv_module_ossaudiodev" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module pyexpat" >&5 $as_echo_n "checking for stdlib extension module pyexpat... " >&6; } case $py_stdlib_not_available in #( @@ -19496,6 +19549,14 @@ LTLIBOBJS=$ac_ltlibobjs +if test -z "${MODULE_OSSAUDIODEV_TRUE}" && test -z "${MODULE_OSSAUDIODEV_FALSE}"; then + as_fn_error $? "conditional \"MODULE_OSSAUDIODEV\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE_OSSAUDIODEV_TRUE}" && test -z "${MODULE_OSSAUDIODEV_FALSE}"; then + as_fn_error $? "conditional \"MODULE_OSSAUDIODEV\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE_PYEXPAT_TRUE}" && test -z "${MODULE_PYEXPAT_FALSE}"; then as_fn_error $? "conditional \"MODULE_PYEXPAT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index 43c8f768c18f8..78b22d531b943 100644 --- a/configure.ac +++ b/configure.ac @@ -2162,7 +2162,7 @@ sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h \ libutil.h sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \ linux/tipc.h linux/random.h spawn.h util.h alloca.h endian.h \ sys/endian.h sys/sysmacros.h linux/memfd.h linux/wait.h sys/memfd.h \ -sys/mman.h sys/eventfd.h) +sys/mman.h sys/eventfd.h linux/soundcard.h sys/soundcard.h) AC_HEADER_DIRENT AC_HEADER_MAJOR @@ -5990,6 +5990,10 @@ AC_DEFUN([PY_STDLIB_MOD], [ m4_popdef([modstate])dnl ]) +dnl platform specific extensions +PY_STDLIB_MOD([ossaudiodev], + [], [test "$ac_cv_header_linux_soundcard_h" = yes -o "$ac_cv_header_sys_soundcard_h" = yes]) + dnl _elementtree loads libexpat via CAPI hook in pyexpat PY_STDLIB_MOD([pyexpat], [], [], [$LIBEXPAT_CFLAGS], [$LIBEXPAT_LDFLAGS]) PY_STDLIB_MOD([_elementtree], [], [], [$LIBEXPAT_CFLAGS], []) diff --git a/pyconfig.h.in b/pyconfig.h.in index cbab59b739f31..b8f63955e3139 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -679,6 +679,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_RANDOM_H +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_SOUNDCARD_H + /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_TIPC_H @@ -1217,6 +1220,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SOCKET_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOUNDCARD_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STATVFS_H diff --git a/setup.py b/setup.py index 8b9566e26bffd..a09cf18213f98 100644 --- a/setup.py +++ b/setup.py @@ -1485,11 +1485,8 @@ def detect_platform_specific_exts(self): else: self.missing.extend(['resource', 'termios']) - # Platform-specific libraries - if HOST_PLATFORM.startswith(('linux', 'freebsd', 'gnukfreebsd')): - self.add(Extension('ossaudiodev', ['ossaudiodev.c'])) - elif not AIX: - self.missing.append('ossaudiodev') + # linux/soundcard.h or sys/soundcard.h + self.addext(Extension('ossaudiodev', ['ossaudiodev.c'])) if MACOS: self.add(Extension('_scproxy', ['_scproxy.c'], From webhook-mailer at python.org Thu Nov 18 06:03:04 2021 From: webhook-mailer at python.org (markshannon) Date: Thu, 18 Nov 2021 11:03:04 -0000 Subject: [Python-checkins] bpo-45829: Specialize BINARY_SUBSCR for __getitem__ implemented in Python. (GH-29592) Message-ID: https://github.com/python/cpython/commit/21fa7a3e8f99a1a32467f85c877e40cbdafa9da7 commit: 21fa7a3e8f99a1a32467f85c877e40cbdafa9da7 branch: main author: Mark Shannon committer: markshannon date: 2021-11-18T11:02:14Z summary: bpo-45829: Specialize BINARY_SUBSCR for __getitem__ implemented in Python. (GH-29592) files: A Misc/NEWS.d/next/Core and Builtins/2021-11-17-10-14-35.bpo-45829.5Cf6fY.rst M Include/internal/pycore_code.h M Include/opcode.h M Lib/opcode.py M Python/ceval.c M Python/opcode_targets.h M Python/specialize.c diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index 7fe9e74b21cfe..6563f7b87b360 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -17,6 +17,7 @@ typedef struct { uint8_t original_oparg; uint8_t counter; uint16_t index; + uint32_t version; } _PyAdaptiveEntry; @@ -266,7 +267,7 @@ int _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name int _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name, SpecializedCacheEntry *cache); int _Py_Specialize_LoadGlobal(PyObject *globals, PyObject *builtins, _Py_CODEUNIT *instr, PyObject *name, SpecializedCacheEntry *cache); int _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name, SpecializedCacheEntry *cache); -int _Py_Specialize_BinarySubscr(PyObject *sub, PyObject *container, _Py_CODEUNIT *instr); +int _Py_Specialize_BinarySubscr(PyObject *sub, PyObject *container, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache); int _Py_Specialize_CallFunction(PyObject *callable, _Py_CODEUNIT *instr, int nargs, SpecializedCacheEntry *cache, PyObject *builtins); void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache); diff --git a/Include/opcode.h b/Include/opcode.h index ca20ccda1199b..2367064a89d71 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -121,38 +121,39 @@ extern "C" { #define BINARY_OP_SUBTRACT_INT 19 #define BINARY_OP_SUBTRACT_FLOAT 20 #define BINARY_SUBSCR_ADAPTIVE 21 -#define BINARY_SUBSCR_LIST_INT 22 -#define BINARY_SUBSCR_TUPLE_INT 23 -#define BINARY_SUBSCR_DICT 24 -#define CALL_FUNCTION_ADAPTIVE 26 -#define CALL_FUNCTION_BUILTIN_O 27 -#define CALL_FUNCTION_BUILTIN_FAST 28 -#define CALL_FUNCTION_LEN 29 -#define CALL_FUNCTION_ISINSTANCE 34 -#define CALL_FUNCTION_PY_SIMPLE 36 -#define JUMP_ABSOLUTE_QUICK 38 -#define LOAD_ATTR_ADAPTIVE 39 -#define LOAD_ATTR_INSTANCE_VALUE 40 -#define LOAD_ATTR_WITH_HINT 41 -#define LOAD_ATTR_SLOT 42 -#define LOAD_ATTR_MODULE 43 -#define LOAD_GLOBAL_ADAPTIVE 44 -#define LOAD_GLOBAL_MODULE 45 -#define LOAD_GLOBAL_BUILTIN 46 -#define LOAD_METHOD_ADAPTIVE 47 -#define LOAD_METHOD_CACHED 48 -#define LOAD_METHOD_CLASS 55 -#define LOAD_METHOD_MODULE 56 -#define LOAD_METHOD_NO_DICT 57 -#define STORE_ATTR_ADAPTIVE 58 -#define STORE_ATTR_INSTANCE_VALUE 59 -#define STORE_ATTR_SLOT 62 -#define STORE_ATTR_WITH_HINT 63 -#define LOAD_FAST__LOAD_FAST 64 -#define STORE_FAST__LOAD_FAST 65 -#define LOAD_FAST__LOAD_CONST 66 -#define LOAD_CONST__LOAD_FAST 67 -#define STORE_FAST__STORE_FAST 75 +#define BINARY_SUBSCR_GETITEM 22 +#define BINARY_SUBSCR_LIST_INT 23 +#define BINARY_SUBSCR_TUPLE_INT 24 +#define BINARY_SUBSCR_DICT 26 +#define CALL_FUNCTION_ADAPTIVE 27 +#define CALL_FUNCTION_BUILTIN_O 28 +#define CALL_FUNCTION_BUILTIN_FAST 29 +#define CALL_FUNCTION_LEN 34 +#define CALL_FUNCTION_ISINSTANCE 36 +#define CALL_FUNCTION_PY_SIMPLE 38 +#define JUMP_ABSOLUTE_QUICK 39 +#define LOAD_ATTR_ADAPTIVE 40 +#define LOAD_ATTR_INSTANCE_VALUE 41 +#define LOAD_ATTR_WITH_HINT 42 +#define LOAD_ATTR_SLOT 43 +#define LOAD_ATTR_MODULE 44 +#define LOAD_GLOBAL_ADAPTIVE 45 +#define LOAD_GLOBAL_MODULE 46 +#define LOAD_GLOBAL_BUILTIN 47 +#define LOAD_METHOD_ADAPTIVE 48 +#define LOAD_METHOD_CACHED 55 +#define LOAD_METHOD_CLASS 56 +#define LOAD_METHOD_MODULE 57 +#define LOAD_METHOD_NO_DICT 58 +#define STORE_ATTR_ADAPTIVE 59 +#define STORE_ATTR_INSTANCE_VALUE 62 +#define STORE_ATTR_SLOT 63 +#define STORE_ATTR_WITH_HINT 64 +#define LOAD_FAST__LOAD_FAST 65 +#define STORE_FAST__LOAD_FAST 66 +#define LOAD_FAST__LOAD_CONST 67 +#define LOAD_CONST__LOAD_FAST 75 +#define STORE_FAST__STORE_FAST 76 #define DO_TRACING 255 #ifdef NEED_OPCODE_JUMP_TABLES static uint32_t _PyOpcode_RelativeJump[8] = { diff --git a/Lib/opcode.py b/Lib/opcode.py index 4abe99fcbec17..1df192bb1247d 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -234,6 +234,7 @@ def jabs_op(name, op): "BINARY_OP_SUBTRACT_INT", "BINARY_OP_SUBTRACT_FLOAT", "BINARY_SUBSCR_ADAPTIVE", + "BINARY_SUBSCR_GETITEM", "BINARY_SUBSCR_LIST_INT", "BINARY_SUBSCR_TUPLE_INT", "BINARY_SUBSCR_DICT", diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-17-10-14-35.bpo-45829.5Cf6fY.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-17-10-14-35.bpo-45829.5Cf6fY.rst new file mode 100644 index 0000000000000..ed8bfb99f8591 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-17-10-14-35.bpo-45829.5Cf6fY.rst @@ -0,0 +1,2 @@ +Specialize :opcode:`BINARY_SUBSCR` for classes with a ``__getitem__`` method +implemented in Python diff --git a/Python/ceval.c b/Python/ceval.c index e579edefdb7af..2b7b31c091326 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2140,21 +2140,21 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } TARGET(BINARY_SUBSCR_ADAPTIVE) { - if (oparg == 0) { + SpecializedCacheEntry *cache = GET_CACHE(); + if (cache->adaptive.counter == 0) { PyObject *sub = TOP(); PyObject *container = SECOND(); next_instr--; - if (_Py_Specialize_BinarySubscr(container, sub, next_instr) < 0) { + if (_Py_Specialize_BinarySubscr(container, sub, next_instr, cache) < 0) { goto error; } DISPATCH(); } else { STAT_INC(BINARY_SUBSCR, deferred); - // oparg is the adaptive cache counter - UPDATE_PREV_INSTR_OPARG(next_instr, oparg - 1); - assert(_Py_OPCODE(next_instr[-1]) == BINARY_SUBSCR_ADAPTIVE); - assert(_Py_OPARG(next_instr[-1]) == oparg - 1); + cache->adaptive.counter--; + assert(cache->adaptive.original_oparg == 0); + /* No need to set oparg here; it isn't used by BINARY_SUBSCR */ STAT_DEC(BINARY_SUBSCR, unquickened); JUMP_TO_INSTRUCTION(BINARY_SUBSCR); } @@ -2223,6 +2223,37 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr DISPATCH(); } + TARGET(BINARY_SUBSCR_GETITEM) { + PyObject *sub = TOP(); + PyObject *container = SECOND(); + SpecializedCacheEntry *caches = GET_CACHE(); + _PyAdaptiveEntry *cache0 = &caches[0].adaptive; + _PyObjectCache *cache1 = &caches[-1].obj; + PyFunctionObject *getitem = (PyFunctionObject *)cache1->obj; + DEOPT_IF(Py_TYPE(container)->tp_version_tag != cache0->version, BINARY_SUBSCR); + DEOPT_IF(getitem->func_version != cache0->index, BINARY_SUBSCR); + PyCodeObject *code = (PyCodeObject *)getitem->func_code; + size_t size = code->co_nlocalsplus + code->co_stacksize + FRAME_SPECIALS_SIZE; + assert(code->co_argcount == 2); + InterpreterFrame *new_frame = _PyThreadState_BumpFramePointer(tstate, size); + if (new_frame == NULL) { + goto error; + } + _PyFrame_InitializeSpecials(new_frame, PyFunction_AS_FRAME_CONSTRUCTOR(getitem), + NULL, code->co_nlocalsplus); + STACK_SHRINK(2); + new_frame->localsplus[0] = container; + new_frame->localsplus[1] = sub; + for (int i = 2; i < code->co_nlocalsplus; i++) { + new_frame->localsplus[i] = NULL; + } + _PyFrame_SetStackPointer(frame, stack_pointer); + new_frame->previous = frame; + frame = cframe.current_frame = new_frame; + new_frame->depth = frame->depth + 1; + goto start_frame; + } + TARGET(LIST_APPEND) { PyObject *v = POP(); PyObject *list = PEEK(oparg); @@ -4878,29 +4909,13 @@ opname ## _miss: \ JUMP_TO_INSTRUCTION(opname); \ } -#define MISS_WITH_OPARG_COUNTER(opname) \ -opname ## _miss: \ - { \ - STAT_INC(opname, miss); \ - uint8_t oparg = _Py_OPARG(next_instr[-1])-1; \ - UPDATE_PREV_INSTR_OPARG(next_instr, oparg); \ - assert(_Py_OPARG(next_instr[-1]) == oparg); \ - if (oparg == 0) /* too many cache misses */ { \ - oparg = ADAPTIVE_CACHE_BACKOFF; \ - next_instr[-1] = _Py_MAKECODEUNIT(opname ## _ADAPTIVE, oparg); \ - STAT_INC(opname, deopt); \ - } \ - STAT_DEC(opname, unquickened); \ - JUMP_TO_INSTRUCTION(opname); \ - } - MISS_WITH_CACHE(LOAD_ATTR) MISS_WITH_CACHE(STORE_ATTR) MISS_WITH_CACHE(LOAD_GLOBAL) MISS_WITH_CACHE(LOAD_METHOD) MISS_WITH_CACHE(CALL_FUNCTION) MISS_WITH_CACHE(BINARY_OP) -MISS_WITH_OPARG_COUNTER(BINARY_SUBSCR) +MISS_WITH_CACHE(BINARY_SUBSCR) binary_subscr_dict_error: { diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 07852d167c769..4703255d79082 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -21,22 +21,23 @@ static void *opcode_targets[256] = { &&TARGET_BINARY_OP_SUBTRACT_INT, &&TARGET_BINARY_OP_SUBTRACT_FLOAT, &&TARGET_BINARY_SUBSCR_ADAPTIVE, + &&TARGET_BINARY_SUBSCR_GETITEM, &&TARGET_BINARY_SUBSCR_LIST_INT, &&TARGET_BINARY_SUBSCR_TUPLE_INT, - &&TARGET_BINARY_SUBSCR_DICT, &&TARGET_BINARY_SUBSCR, + &&TARGET_BINARY_SUBSCR_DICT, &&TARGET_CALL_FUNCTION_ADAPTIVE, &&TARGET_CALL_FUNCTION_BUILTIN_O, &&TARGET_CALL_FUNCTION_BUILTIN_FAST, - &&TARGET_CALL_FUNCTION_LEN, &&TARGET_GET_LEN, &&TARGET_MATCH_MAPPING, &&TARGET_MATCH_SEQUENCE, &&TARGET_MATCH_KEYS, - &&TARGET_CALL_FUNCTION_ISINSTANCE, + &&TARGET_CALL_FUNCTION_LEN, &&TARGET_PUSH_EXC_INFO, - &&TARGET_CALL_FUNCTION_PY_SIMPLE, + &&TARGET_CALL_FUNCTION_ISINSTANCE, &&TARGET_POP_EXCEPT_AND_RERAISE, + &&TARGET_CALL_FUNCTION_PY_SIMPLE, &&TARGET_JUMP_ABSOLUTE_QUICK, &&TARGET_LOAD_ATTR_ADAPTIVE, &&TARGET_LOAD_ATTR_INSTANCE_VALUE, @@ -47,26 +48,25 @@ static void *opcode_targets[256] = { &&TARGET_LOAD_GLOBAL_MODULE, &&TARGET_LOAD_GLOBAL_BUILTIN, &&TARGET_LOAD_METHOD_ADAPTIVE, - &&TARGET_LOAD_METHOD_CACHED, &&TARGET_WITH_EXCEPT_START, &&TARGET_GET_AITER, &&TARGET_GET_ANEXT, &&TARGET_BEFORE_ASYNC_WITH, &&TARGET_BEFORE_WITH, &&TARGET_END_ASYNC_FOR, + &&TARGET_LOAD_METHOD_CACHED, &&TARGET_LOAD_METHOD_CLASS, &&TARGET_LOAD_METHOD_MODULE, &&TARGET_LOAD_METHOD_NO_DICT, &&TARGET_STORE_ATTR_ADAPTIVE, - &&TARGET_STORE_ATTR_INSTANCE_VALUE, &&TARGET_STORE_SUBSCR, &&TARGET_DELETE_SUBSCR, + &&TARGET_STORE_ATTR_INSTANCE_VALUE, &&TARGET_STORE_ATTR_SLOT, &&TARGET_STORE_ATTR_WITH_HINT, &&TARGET_LOAD_FAST__LOAD_FAST, &&TARGET_STORE_FAST__LOAD_FAST, &&TARGET_LOAD_FAST__LOAD_CONST, - &&TARGET_LOAD_CONST__LOAD_FAST, &&TARGET_GET_ITER, &&TARGET_GET_YIELD_FROM_ITER, &&TARGET_PRINT_EXPR, @@ -74,13 +74,13 @@ static void *opcode_targets[256] = { &&TARGET_YIELD_FROM, &&TARGET_GET_AWAITABLE, &&TARGET_LOAD_ASSERTION_ERROR, + &&TARGET_LOAD_CONST__LOAD_FAST, &&TARGET_STORE_FAST__STORE_FAST, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, - &&_unknown_opcode, &&TARGET_LIST_TO_TUPLE, &&TARGET_RETURN_VALUE, &&TARGET_IMPORT_STAR, diff --git a/Python/specialize.c b/Python/specialize.c index dd15de72d2796..06b076429f57c 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -243,7 +243,7 @@ static uint8_t cache_requirements[256] = { [LOAD_ATTR] = 2, /* _PyAdaptiveEntry and _PyAttrCache */ [LOAD_GLOBAL] = 2, /* _PyAdaptiveEntry and _PyLoadGlobalCache */ [LOAD_METHOD] = 3, /* _PyAdaptiveEntry, _PyAttrCache and _PyObjectCache */ - [BINARY_SUBSCR] = 0, + [BINARY_SUBSCR] = 2, /* _PyAdaptiveEntry, _PyObjectCache */ [CALL_FUNCTION] = 2, /* _PyAdaptiveEntry and _PyObjectCache/_PyCallCache */ [STORE_ATTR] = 2, /* _PyAdaptiveEntry and _PyAttrCache */ [BINARY_OP] = 1, // _PyAdaptiveEntry @@ -1100,7 +1100,7 @@ _Py_Specialize_LoadGlobal( #if COLLECT_SPECIALIZATION_STATS_DETAILED static int -binary_subscr_faiL_kind(PyTypeObject *container_type, PyObject *sub) +binary_subscr_fail_kind(PyTypeObject *container_type, PyObject *sub) { if (container_type == &PyUnicode_Type) { if (PyLong_CheckExact(sub)) { @@ -1138,14 +1138,37 @@ binary_subscr_faiL_kind(PyTypeObject *container_type, PyObject *sub) } #endif +_Py_IDENTIFIER(__getitem__); + +#define SIMPLE_FUNCTION 0 + +static int +function_kind(PyCodeObject *code) { + int flags = code->co_flags; + if (flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR)) { + return SPEC_FAIL_GENERATOR; + } + if ((flags & (CO_VARKEYWORDS | CO_VARARGS)) || code->co_kwonlyargcount) { + return SPEC_FAIL_COMPLEX_PARAMETERS; + } + if ((flags & CO_OPTIMIZED) == 0) { + return SPEC_FAIL_CO_NOT_OPTIMIZED; + } + if (code->co_nfreevars) { + return SPEC_FAIL_FREE_VARS; + } + return SIMPLE_FUNCTION; +} + int _Py_Specialize_BinarySubscr( - PyObject *container, PyObject *sub, _Py_CODEUNIT *instr) + PyObject *container, PyObject *sub, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache) { + _PyAdaptiveEntry *cache0 = &cache->adaptive; PyTypeObject *container_type = Py_TYPE(container); if (container_type == &PyList_Type) { if (PyLong_CheckExact(sub)) { - *instr = _Py_MAKECODEUNIT(BINARY_SUBSCR_LIST_INT, initial_counter_value()); + *instr = _Py_MAKECODEUNIT(BINARY_SUBSCR_LIST_INT, _Py_OPARG(*instr)); goto success; } SPECIALIZATION_FAIL(BINARY_SUBSCR, @@ -1154,7 +1177,7 @@ _Py_Specialize_BinarySubscr( } if (container_type == &PyTuple_Type) { if (PyLong_CheckExact(sub)) { - *instr = _Py_MAKECODEUNIT(BINARY_SUBSCR_TUPLE_INT, initial_counter_value()); + *instr = _Py_MAKECODEUNIT(BINARY_SUBSCR_TUPLE_INT, _Py_OPARG(*instr)); goto success; } SPECIALIZATION_FAIL(BINARY_SUBSCR, @@ -1162,20 +1185,46 @@ _Py_Specialize_BinarySubscr( goto fail; } if (container_type == &PyDict_Type) { - *instr = _Py_MAKECODEUNIT(BINARY_SUBSCR_DICT, initial_counter_value()); + *instr = _Py_MAKECODEUNIT(BINARY_SUBSCR_DICT, _Py_OPARG(*instr)); + goto success; + } + PyTypeObject *cls = Py_TYPE(container); + PyObject *descriptor = _PyType_LookupId(cls, &PyId___getitem__); + if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type) { + PyFunctionObject *func = (PyFunctionObject *)descriptor; + PyCodeObject *code = (PyCodeObject *)func->func_code; + int kind = function_kind(code); + if (kind != SIMPLE_FUNCTION) { + SPECIALIZATION_FAIL(BINARY_SUBSCR, kind); + goto fail; + } + if (code->co_argcount != 2) { + SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS); + goto fail; + } + assert(cls->tp_version_tag != 0); + cache0->version = cls->tp_version_tag; + int version = _PyFunction_GetVersionForCurrentState(func); + if (version == 0) { + SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_OUT_OF_VERSIONS); + goto fail; + } + cache0->index = version; + cache[-1].obj.obj = descriptor; + *instr = _Py_MAKECODEUNIT(BINARY_SUBSCR_GETITEM, _Py_OPARG(*instr)); goto success; } SPECIALIZATION_FAIL(BINARY_SUBSCR, - binary_subscr_faiL_kind(container_type, sub)); - goto fail; + binary_subscr_fail_kind(container_type, sub)); fail: STAT_INC(BINARY_SUBSCR, specialization_failure); assert(!PyErr_Occurred()); - *instr = _Py_MAKECODEUNIT(_Py_OPCODE(*instr), ADAPTIVE_CACHE_BACKOFF); + cache_backoff(cache0); return 0; success: STAT_INC(BINARY_SUBSCR, specialization_success); assert(!PyErr_Occurred()); + cache0->counter = initial_counter_value(); return 0; } @@ -1194,23 +1243,10 @@ specialize_py_call( int nargs, SpecializedCacheEntry *cache) { _PyCallCache *cache1 = &cache[-1].call; - /* Exclude generator or coroutines for now */ PyCodeObject *code = (PyCodeObject *)func->func_code; - int flags = code->co_flags; - if (flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR)) { - SPECIALIZATION_FAIL(CALL_FUNCTION, SPEC_FAIL_GENERATOR); - return -1; - } - if ((flags & (CO_VARKEYWORDS | CO_VARARGS)) || code->co_kwonlyargcount) { - SPECIALIZATION_FAIL(CALL_FUNCTION, SPEC_FAIL_COMPLEX_PARAMETERS); - return -1; - } - if ((flags & CO_OPTIMIZED) == 0) { - SPECIALIZATION_FAIL(CALL_FUNCTION, SPEC_FAIL_CO_NOT_OPTIMIZED); - return -1; - } - if (code->co_nfreevars) { - SPECIALIZATION_FAIL(CALL_FUNCTION, SPEC_FAIL_FREE_VARS); + int kind = function_kind(code); + if (kind != SIMPLE_FUNCTION) { + SPECIALIZATION_FAIL(CALL_FUNCTION, kind); return -1; } int argcount = code->co_argcount; From webhook-mailer at python.org Thu Nov 18 08:40:10 2021 From: webhook-mailer at python.org (tiran) Date: Thu, 18 Nov 2021 13:40:10 -0000 Subject: [Python-checkins] bpo-45573: Add Modules/Setup.stdlib with conditional modules (GH-29615) Message-ID: https://github.com/python/cpython/commit/e4bb22fabbea72776b377733047e0f32e0388059 commit: e4bb22fabbea72776b377733047e0f32e0388059 branch: main author: Christian Heimes committer: tiran date: 2021-11-18T14:40:01+01:00 summary: bpo-45573: Add Modules/Setup.stdlib with conditional modules (GH-29615) files: A Misc/NEWS.d/next/Build/2021-11-18-12-18-43.bpo-45573.xsMZzn.rst A Modules/Setup.stdlib.in M .gitignore M Makefile.pre.in M configure M configure.ac diff --git a/.gitignore b/.gitignore index e261d6c997135..0831c58d36748 100644 --- a/.gitignore +++ b/.gitignore @@ -76,6 +76,7 @@ Misc/python-embed.pc Misc/python-config.sh Modules/Setup.config Modules/Setup.local +Modules/Setup.stdlib Modules/config.c Modules/ld_so_aix Programs/_freeze_module diff --git a/Makefile.pre.in b/Makefile.pre.in index 55336d24ed194..1afd9e1331949 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -898,11 +898,19 @@ oldsharedmods: $(SHAREDMODS) pybuilddir.txt fi; \ done +Modules/Setup.local: + @# Create empty Setup.local when file was deleted by user + echo "# Edit this file for local setup changes" > $@ + +Modules/Setup.stdlib: $(srcdir)/Modules/Setup.stdlib.in config.status + ./config.status $@ + Makefile Modules/config.c: Makefile.pre \ $(srcdir)/Modules/config.c.in \ $(MAKESETUP) \ $(srcdir)/Modules/Setup \ - Modules/Setup.local + Modules/Setup.local \ + Modules/Setup.stdlib $(SHELL) $(MAKESETUP) -c $(srcdir)/Modules/config.c.in \ -s Modules \ Modules/Setup.local \ @@ -2159,6 +2167,7 @@ libainstall: @DEF_MAKE_RULE@ python-config $(INSTALL_DATA) $(srcdir)/Modules/config.c.in $(DESTDIR)$(LIBPL)/config.c.in $(INSTALL_DATA) Makefile $(DESTDIR)$(LIBPL)/Makefile $(INSTALL_DATA) $(srcdir)/Modules/Setup $(DESTDIR)$(LIBPL)/Setup + $(INSTALL_DATA) Modules/Setup.stdlib $(DESTDIR)$(LIBPL)/Setup.stdlib $(INSTALL_DATA) Modules/Setup.local $(DESTDIR)$(LIBPL)/Setup.local $(INSTALL_DATA) Misc/python.pc $(DESTDIR)$(LIBPC)/python-$(VERSION).pc $(INSTALL_DATA) Misc/python-embed.pc $(DESTDIR)$(LIBPC)/python-$(VERSION)-embed.pc @@ -2387,7 +2396,7 @@ distclean: clobber if test "$$file" != "$(srcdir)/Lib/test/data/README"; then rm "$$file"; fi; \ done -rm -f core Makefile Makefile.pre config.status Modules/Setup.local \ - Modules/ld_so_aix Modules/python.exp Misc/python.pc \ + Modules/Setup.stdlib Modules/ld_so_aix Modules/python.exp Misc/python.pc \ Misc/python-embed.pc Misc/python-config.sh -rm -f python*-gdb.py -rm -f Python/frozen_modules/*.h diff --git a/Misc/NEWS.d/next/Build/2021-11-18-12-18-43.bpo-45573.xsMZzn.rst b/Misc/NEWS.d/next/Build/2021-11-18-12-18-43.bpo-45573.xsMZzn.rst new file mode 100644 index 0000000000000..5dac52e53a718 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-18-12-18-43.bpo-45573.xsMZzn.rst @@ -0,0 +1,2 @@ +``configure`` now creates ``Modules/Setup.stdlib`` with conditionally +enabled/disabled extension module lines. The file is not used, yet. diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in new file mode 100644 index 0000000000000..0722eae87a358 --- /dev/null +++ b/Modules/Setup.stdlib.in @@ -0,0 +1,55 @@ +# -*- makefile -*- +# +# This file is autogenerated from Modules/Setup.stdlib.in. +# + +# The file is not used by default yet. For testing do: +# +# ln -sfr Modules/Setup.stdlib Modules/Setup.local +# + +# * @MODULE_{NAME}_TRUE@ is removed when configure detects all build +# dependencies for a module. Otherwise the template variable is replaced +# by a comment "#" and the module is skipped. +# * Module lines without any compiler and linker flags automatically use +# $(MODULE_{NAME}_CFLAGS) and $(MODULE_{NAME}_LDFLAGS). These flags are +# generated by PY_STDLIB_MOD macro. +# * All source files automatically depend on $(PYTHON_HEADERS) and +# $(MODULE_{NAME}_DEPS). +# +# See Modules/Setup and Modules/makesetup +# + + +# Build modules statically or as shared extensions +*shared* +# *static* + + +############################################################################ +# Modules that should always be present (POSIX and Windows): + +# _decimal uses libmpdec +# either static libmpdec.a from Modules/_decimal/libmpdec or libmpdec.so +# with ./configure --with-system-libmpdec + at MODULE__DECIMAL_TRUE@_decimal _decimal/_decimal.c + + +############################################################################ +# XML and text + +# pyexpat module uses libexpat +# either static libexpat.a from Modules/expat or libexpat.so with +# ./configure --with-system-expat + at MODULE_PYEXPAT_TRUE@pyexpat pyexpat.c + +# _elementtree libexpat via CAPI hook in pyexpat. + at MODULE__ELEMENTTREE_TRUE@_elementtree _elementtree.c + + +############################################################################ +# Modules with some UNIX dependencies +# + +# Linux and FreeBSD, needs sys/soundcard.h or linux/soundcard.h + at MODULE_OSSAUDIODEV_TRUE@ossaudiodev ossaudiodev.c diff --git a/configure b/configure index f8987128a01cf..fc7b8dc5968ab 100755 --- a/configure +++ b/configure @@ -19437,6 +19437,8 @@ $as_echo "$py_cv_module__decimal" >&6; } # generate output files ac_config_files="$ac_config_files Makefile.pre Misc/python.pc Misc/python-embed.pc Misc/python-config.sh" +ac_config_files="$ac_config_files Modules/Setup.stdlib" + ac_config_files="$ac_config_files Modules/ld_so_aix" cat >confcache <<\_ACEOF @@ -20172,6 +20174,7 @@ do "Misc/python.pc") CONFIG_FILES="$CONFIG_FILES Misc/python.pc" ;; "Misc/python-embed.pc") CONFIG_FILES="$CONFIG_FILES Misc/python-embed.pc" ;; "Misc/python-config.sh") CONFIG_FILES="$CONFIG_FILES Misc/python-config.sh" ;; + "Modules/Setup.stdlib") CONFIG_FILES="$CONFIG_FILES Modules/Setup.stdlib" ;; "Modules/ld_so_aix") CONFIG_FILES="$CONFIG_FILES Modules/ld_so_aix" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; diff --git a/configure.ac b/configure.ac index 78b22d531b943..d2cb67a39cb4a 100644 --- a/configure.ac +++ b/configure.ac @@ -6005,6 +6005,7 @@ AC_SUBST([MODULE_BLOCK]) # generate output files AC_CONFIG_FILES(Makefile.pre Misc/python.pc Misc/python-embed.pc Misc/python-config.sh) +AC_CONFIG_FILES([Modules/Setup.stdlib]) AC_CONFIG_FILES([Modules/ld_so_aix], [chmod +x Modules/ld_so_aix]) AC_OUTPUT From webhook-mailer at python.org Thu Nov 18 10:02:58 2021 From: webhook-mailer at python.org (ambv) Date: Thu, 18 Nov 2021 15:02:58 -0000 Subject: [Python-checkins] bpo-45837: Properly deprecate turtle.RawTurtle.settiltangle (GH-29618) Message-ID: https://github.com/python/cpython/commit/c94664c262bddbff4604795d46ecd0935402df8e commit: c94664c262bddbff4604795d46ecd0935402df8e branch: main author: Hugo van Kemenade committer: ambv date: 2021-11-18T16:02:48+01:00 summary: bpo-45837: Properly deprecate turtle.RawTurtle.settiltangle (GH-29618) files: A Misc/NEWS.d/next/Library/2021-11-18-13-13-19.bpo-45837.aGyr1I.rst M Doc/whatsnew/3.11.rst M Lib/turtle.py diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 06a24151c32cc..9751f894f9a9a 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -369,6 +369,11 @@ Deprecated (Contributed by Erlend E. Aasland in :issue:`5846`.) +* The :meth:`turtle.RawTurtle.settiltangle` is deprecated since Python 3.1, + it now emits a deprecation warning and will be removed in Python 3.13. Use + :meth:`turtle.RawTurtle.tiltangle` instead (it was earlier incorrectly marked + as deprecated, its docstring is now corrected). + (Contributed by Hugo van Kemenade in :issue:`45837`.) Removed ======= diff --git a/Lib/turtle.py b/Lib/turtle.py index 2e573245b803a..d5e715efec96a 100644 --- a/Lib/turtle.py +++ b/Lib/turtle.py @@ -110,6 +110,7 @@ import time import inspect import sys +import warnings from os.path import isfile, split, join from copy import deepcopy @@ -2850,20 +2851,23 @@ def settiltangle(self, angle): regardless of its current tilt-angle. DO NOT change the turtle's heading (direction of movement). + Deprecated since Python 3.1 Examples (for a Turtle instance named turtle): >>> turtle.shape("circle") >>> turtle.shapesize(5,2) >>> turtle.settiltangle(45) - >>> stamp() + >>> turtle.stamp() >>> turtle.fd(50) >>> turtle.settiltangle(-45) - >>> stamp() + >>> turtle.stamp() >>> turtle.fd(50) """ - tilt = -angle * self._degreesPerAU * self._angleOrient - tilt = math.radians(tilt) % math.tau - self.pen(resizemode="user", tilt=tilt) + warnings.warn("turtle.RawTurtle.settiltangle() is deprecated since " + "Python 3.1 and scheduled for removal in Python 3.13." + "Use tiltangle() instead.", + DeprecationWarning) + self.tiltangle(angle) def tiltangle(self, angle=None): """Set or return the current tilt-angle. @@ -2877,19 +2881,32 @@ def tiltangle(self, angle=None): between the orientation of the turtleshape and the heading of the turtle (its direction of movement). - Deprecated since Python 3.1 + (Incorrectly marked as deprecated since Python 3.1, it is really + settiltangle that is deprecated.) Examples (for a Turtle instance named turtle): >>> turtle.shape("circle") - >>> turtle.shapesize(5,2) - >>> turtle.tilt(45) + >>> turtle.shapesize(5, 2) + >>> turtle.tiltangle() + 0.0 + >>> turtle.tiltangle(45) + >>> turtle.tiltangle() + 45.0 + >>> turtle.stamp() + >>> turtle.fd(50) + >>> turtle.tiltangle(-45) >>> turtle.tiltangle() + 315.0 + >>> turtle.stamp() + >>> turtle.fd(50) """ if angle is None: tilt = -math.degrees(self._tilt) * self._angleOrient return (tilt / self._degreesPerAU) % self._fullcircle else: - self.settiltangle(angle) + tilt = -angle * self._degreesPerAU * self._angleOrient + tilt = math.radians(tilt) % math.tau + self.pen(resizemode="user", tilt=tilt) def tilt(self, angle): """Rotate the turtleshape by angle. @@ -2908,7 +2925,7 @@ def tilt(self, angle): >>> turtle.tilt(30) >>> turtle.fd(50) """ - self.settiltangle(angle + self.tiltangle()) + self.tiltangle(angle + self.tiltangle()) def shapetransform(self, t11=None, t12=None, t21=None, t22=None): """Set or return the current transformation matrix of the turtle shape. diff --git a/Misc/NEWS.d/next/Library/2021-11-18-13-13-19.bpo-45837.aGyr1I.rst b/Misc/NEWS.d/next/Library/2021-11-18-13-13-19.bpo-45837.aGyr1I.rst new file mode 100644 index 0000000000000..771465be59798 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-18-13-13-19.bpo-45837.aGyr1I.rst @@ -0,0 +1,9 @@ +The :meth:`turtle.RawTurtle.settiltangle` is deprecated since Python 3.1, +it now emits a deprecation warning and will be removed in Python 3.13. + +Use :meth:`turtle.RawTurtle.tiltangle` instead. + +:meth:`turtle.RawTurtle.tiltangle` was earlier incorrectly marked as deprecated, +its docstring has been corrected. + +Patch by Hugo van Kemenade. From webhook-mailer at python.org Thu Nov 18 10:54:38 2021 From: webhook-mailer at python.org (ambv) Date: Thu, 18 Nov 2021 15:54:38 -0000 Subject: [Python-checkins] [doc] bpo-45680: Disambiguate ``__getitem__`` and ``__class_getitem__`` in the data model (GH-29389) Message-ID: https://github.com/python/cpython/commit/31b3a70edb1216bdc8fab3b2eafd8ddb00487f41 commit: 31b3a70edb1216bdc8fab3b2eafd8ddb00487f41 branch: main author: Alex Waygood committer: ambv date: 2021-11-18T16:54:25+01:00 summary: [doc] bpo-45680: Disambiguate ``__getitem__`` and ``__class_getitem__`` in the data model (GH-29389) The documentation explaining Python's data model does not adequately explain the differences between ``__getitem__`` and ``__class_getitem__``, nor does it explain when each is called. There is an attempt at explaining ``__class_getitem__`` in the documentation for ``GenericAlias`` objects, but this does not give sufficient clarity into how the method works. Moreover, it is the wrong place for that information to be found; the explanation of ``__class_getitem__`` should be in the documentation explaining the data model. This PR has been split off from GH-29335. files: M Doc/library/typing.rst M Doc/reference/datamodel.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index c37e97eb3e730..735d477db4371 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -256,6 +256,7 @@ called :class:`TypeVar`. def first(l: Sequence[T]) -> T: # Generic function return l[0] +.. _user-defined-generics: User-defined generic types ========================== diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index a6eee22fa332c..1ecfa81e3b336 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -2215,22 +2215,142 @@ case the instance is itself a class. Emulating generic types ----------------------- -One can implement the generic class syntax as specified by :pep:`484` -(for example ``List[int]``) by defining a special method: +When using :term:`type annotations`, it is often useful to +*parameterize* a :term:`generic type` using Python's square-brackets notation. +For example, the annotation ``list[int]`` might be used to signify a +:class:`list` in which all the elements are of type :class:`int`. + +.. seealso:: + + :pep:`484` - Type Hints + Introducing Python's framework for type annotations + + :ref:`Generic Alias Types` + Documentation for objects representing parameterized generic classes + + :ref:`Generics`, :ref:`user-defined generics` and :class:`typing.Generic` + Documentation on how to implement generic classes that can be + parameterized at runtime and understood by static type-checkers. + +A class can *generally* only be parameterized if it defines the special +class method ``__class_getitem__()``. .. classmethod:: object.__class_getitem__(cls, key) Return an object representing the specialization of a generic class by type arguments found in *key*. -This method is looked up on the class object itself, and when defined in -the class body, this method is implicitly a class method. Note, this -mechanism is primarily reserved for use with static type hints, other usage -is discouraged. + When defined on a class, ``__class_getitem__()`` is automatically a class + method. As such, there is no need for it to be decorated with + :func:`@classmethod` when it is defined. -.. seealso:: - :pep:`560` - Core support for typing module and generic types +The purpose of *__class_getitem__* +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The purpose of :meth:`~object.__class_getitem__` is to allow runtime +parameterization of standard-library generic classes in order to more easily +apply :term:`type hints` to these classes. + +To implement custom generic classes that can be parameterized at runtime and +understood by static type-checkers, users should either inherit from a standard +library class that already implements :meth:`~object.__class_getitem__`, or +inherit from :class:`typing.Generic`, which has its own implementation of +``__class_getitem__()``. + +Custom implementations of :meth:`~object.__class_getitem__` on classes defined +outside of the standard library may not be understood by third-party +type-checkers such as mypy. Using ``__class_getitem__()`` on any class for +purposes other than type hinting is discouraged. + + +.. _classgetitem-versus-getitem: + + +*__class_getitem__* versus *__getitem__* +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Usually, the :ref:`subscription` of an object using square +brackets will call the :meth:`~object.__getitem__` instance method defined on +the object's class. However, if the object being subscribed is itself a class, +the class method :meth:`~object.__class_getitem__` may be called instead. +``__class_getitem__()`` should return a :ref:`GenericAlias` +object if it is properly defined. + +Presented with the :term:`expression` ``obj[x]``, the Python interpreter +follows something like the following process to decide whether +:meth:`~object.__getitem__` or :meth:`~object.__class_getitem__` should be +called:: + + from inspect import isclass + + def subscribe(obj, x): + """Return the result of the expression `obj[x]`""" + + class_of_obj = type(obj) + + # If the class of obj defines __getitem__, + # call class_of_obj.__getitem__(obj, x) + if hasattr(class_of_obj, '__getitem__'): + return class_of_obj.__getitem__(obj, x) + + # Else, if obj is a class and defines __class_getitem__, + # call obj.__class_getitem__(x) + elif isclass(obj) and hasattr(obj, '__class_getitem__'): + return obj.__class_getitem__(x) + + # Else, raise an exception + else: + raise TypeError( + f"'{class_of_obj.__name__}' object is not subscriptable" + ) + +In Python, all classes are themselves instances of other classes. The class of +a class is known as that class's :term:`metaclass`, and most classes have the +:class:`type` class as their metaclass. :class:`type` does not define +:meth:`~object.__getitem__`, meaning that expressions such as ``list[int]``, +``dict[str, float]`` and ``tuple[str, bytes]`` all result in +:meth:`~object.__class_getitem__` being called:: + + >>> # list has class "type" as its metaclass, like most classes: + >>> type(list) + + >>> type(dict) == type(list) == type(tuple) == type(str) == type(bytes) + True + >>> # "list[int]" calls "list.__class_getitem__(int)" + >>> list[int] + list[int] + >>> # list.__class_getitem__ returns a GenericAlias object: + >>> type(list[int]) + + +However, if a class has a custom metaclass that defines +:meth:`~object.__getitem__`, subscribing the class may result in different +behaviour. An example of this can be found in the :mod:`enum` module:: + + >>> from enum import Enum + >>> class Menu(Enum): + ... """A breakfast menu""" + ... SPAM = 'spam' + ... BACON = 'bacon' + ... + >>> # Enum classes have a custom metaclass: + >>> type(Menu) + + >>> # EnumMeta defines __getitem__, + >>> # so __class_getitem__ is not called, + >>> # and the result is not a GenericAlias object: + >>> Menu['SPAM'] + + >>> type(Menu['SPAM']) + + + +.. seealso:: + :pep:`560` - Core Support for typing module and generic types + Introducing :meth:`~object.__class_getitem__`, and outlining when a + :ref:`subscription` results in ``__class_getitem__()`` + being called instead of :meth:`~object.__getitem__` .. _callable-types: @@ -2330,19 +2450,27 @@ through the object's keys; for sequences, it should iterate through the values. .. method:: object.__getitem__(self, key) - Called to implement evaluation of ``self[key]``. For sequence types, the - accepted keys should be integers and slice objects. Note that the special - interpretation of negative indexes (if the class wishes to emulate a sequence - type) is up to the :meth:`__getitem__` method. If *key* is of an inappropriate - type, :exc:`TypeError` may be raised; if of a value outside the set of indexes - for the sequence (after any special interpretation of negative values), - :exc:`IndexError` should be raised. For mapping types, if *key* is missing (not - in the container), :exc:`KeyError` should be raised. + Called to implement evaluation of ``self[key]``. For :term:`sequence` types, + the accepted keys should be integers and slice objects. Note that the + special interpretation of negative indexes (if the class wishes to emulate a + :term:`sequence` type) is up to the :meth:`__getitem__` method. If *key* is + of an inappropriate type, :exc:`TypeError` may be raised; if of a value + outside the set of indexes for the sequence (after any special + interpretation of negative values), :exc:`IndexError` should be raised. For + :term:`mapping` types, if *key* is missing (not in the container), + :exc:`KeyError` should be raised. + + .. note:: + + :keyword:`for` loops expect that an :exc:`IndexError` will be raised for + illegal indexes to allow proper detection of the end of the sequence. .. note:: - :keyword:`for` loops expect that an :exc:`IndexError` will be raised for illegal - indexes to allow proper detection of the end of the sequence. + When :ref:`subscripting` a *class*, the special + class method :meth:`~object.__class_getitem__` may be called instead of + ``__getitem__()``. See :ref:`classgetitem-versus-getitem` for more + details. .. method:: object.__setitem__(self, key, value) From webhook-mailer at python.org Thu Nov 18 11:05:50 2021 From: webhook-mailer at python.org (ambv) Date: Thu, 18 Nov 2021 16:05:50 -0000 Subject: [Python-checkins] bpo-45835: Fix race condition in test_queue (GH-29601) (GH-29612) Message-ID: https://github.com/python/cpython/commit/5cf05c71d13a4b4a94cc77da4214ee2f0b9c7de7 commit: 5cf05c71d13a4b4a94cc77da4214ee2f0b9c7de7 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-18T17:05:40+01:00 summary: bpo-45835: Fix race condition in test_queue (GH-29601) (GH-29612) Some of the tests in test_queue had a race condition in which a non-sentinel value could be enqueued after the final sentinel value leading to not all the inputs being processed (and test failures). This changes feed() to enqueue a sentinel once the inputs are exhausted, which guarantees that the final queued object is a sentinel. This requires the number of feeder threads to match the number of consumer threads, but that's already the case in the relevant tests. (cherry picked from commit df3e53d86b2ad67da9ac2b5a3f56257d1f394982) Co-authored-by: Sam Gross files: A Misc/NEWS.d/next/Tests/2021-11-17-14-28-08.bpo-45835.Mgyhjx.rst M Lib/test/test_queue.py diff --git a/Lib/test/test_queue.py b/Lib/test/test_queue.py index 9bb5181377698..cfa6003a867da 100644 --- a/Lib/test/test_queue.py +++ b/Lib/test/test_queue.py @@ -420,11 +420,12 @@ class BaseSimpleQueueTest: def setUp(self): self.q = self.type2test() - def feed(self, q, seq, rnd): + def feed(self, q, seq, rnd, sentinel): while True: try: val = seq.pop() except IndexError: + q.put(sentinel) return q.put(val) if rnd.random() > 0.5: @@ -463,11 +464,10 @@ def consume_timeout(self, q, results, sentinel): return results.append(val) - def run_threads(self, n_feeders, n_consumers, q, inputs, - feed_func, consume_func): + def run_threads(self, n_threads, q, inputs, feed_func, consume_func): results = [] sentinel = None - seq = inputs + [sentinel] * n_consumers + seq = inputs.copy() seq.reverse() rnd = random.Random(42) @@ -481,11 +481,11 @@ def wrapper(*args, **kwargs): return wrapper feeders = [threading.Thread(target=log_exceptions(feed_func), - args=(q, seq, rnd)) - for i in range(n_feeders)] + args=(q, seq, rnd, sentinel)) + for i in range(n_threads)] consumers = [threading.Thread(target=log_exceptions(consume_func), args=(q, results, sentinel)) - for i in range(n_consumers)] + for i in range(n_threads)] with threading_helper.start_threads(feeders + consumers): pass @@ -543,7 +543,7 @@ def test_order(self): # Test a pair of concurrent put() and get() q = self.q inputs = list(range(100)) - results = self.run_threads(1, 1, q, inputs, self.feed, self.consume) + results = self.run_threads(1, q, inputs, self.feed, self.consume) # One producer, one consumer => results appended in well-defined order self.assertEqual(results, inputs) @@ -553,7 +553,7 @@ def test_many_threads(self): N = 50 q = self.q inputs = list(range(10000)) - results = self.run_threads(N, N, q, inputs, self.feed, self.consume) + results = self.run_threads(N, q, inputs, self.feed, self.consume) # Multiple consumers without synchronization append the # results in random order @@ -564,7 +564,7 @@ def test_many_threads_nonblock(self): N = 50 q = self.q inputs = list(range(10000)) - results = self.run_threads(N, N, q, inputs, + results = self.run_threads(N, q, inputs, self.feed, self.consume_nonblock) self.assertEqual(sorted(results), inputs) @@ -574,7 +574,7 @@ def test_many_threads_timeout(self): N = 50 q = self.q inputs = list(range(1000)) - results = self.run_threads(N, N, q, inputs, + results = self.run_threads(N, q, inputs, self.feed, self.consume_timeout) self.assertEqual(sorted(results), inputs) diff --git a/Misc/NEWS.d/next/Tests/2021-11-17-14-28-08.bpo-45835.Mgyhjx.rst b/Misc/NEWS.d/next/Tests/2021-11-17-14-28-08.bpo-45835.Mgyhjx.rst new file mode 100644 index 0000000000000..6a73b01959065 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-11-17-14-28-08.bpo-45835.Mgyhjx.rst @@ -0,0 +1 @@ +Fix race condition in test_queue tests with multiple "feeder" threads. From webhook-mailer at python.org Thu Nov 18 11:06:47 2021 From: webhook-mailer at python.org (ambv) Date: Thu, 18 Nov 2021 16:06:47 -0000 Subject: [Python-checkins] bpo-45640: [docs] Tokens are now clickable (GH-29260) Message-ID: https://github.com/python/cpython/commit/32959108f9c543e3cb9f2b68bbc782bddded6f42 commit: 32959108f9c543e3cb9f2b68bbc782bddded6f42 branch: main author: Arthur Milchior committer: ambv date: 2021-11-18T17:06:38+01:00 summary: bpo-45640: [docs] Tokens are now clickable (GH-29260) Co-authored-by: ?ukasz Langa files: A Misc/NEWS.d/next/Documentation/2021-11-18-16-44-12.bpo-45640.lSpc2A.rst M Doc/reference/compound_stmts.rst M Doc/reference/expressions.rst M Doc/reference/lexical_analysis.rst diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst index 3011a168ede42..cf8ad1787b291 100644 --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -418,8 +418,8 @@ usage patterns to be encapsulated for convenient reuse. The execution of the :keyword:`with` statement with one "item" proceeds as follows: -#. The context expression (the expression given in the :token:`with_item`) is - evaluated to obtain a context manager. +#. The context expression (the expression given in the + :token:`~python-grammar:with_item`) is evaluated to obtain a context manager. #. The context manager's :meth:`__enter__` is loaded for later use. @@ -797,7 +797,8 @@ Syntax: capture_pattern: !'_' NAME A single underscore ``_`` is not a capture pattern (this is what ``!'_'`` -expresses). It is instead treated as a :token:`wildcard_pattern`. +expresses). It is instead treated as a +:token:`~python-grammar:wildcard_pattern`. In a given pattern, a given name can only be bound once. E.g. ``case x, x: ...`` is invalid while ``case [x] | x: ...`` is allowed. @@ -1182,9 +1183,9 @@ is roughly equivalent to :: except that the original function is not temporarily bound to the name ``func``. .. versionchanged:: 3.9 - Functions may be decorated with any valid :token:`assignment_expression`. - Previously, the grammar was much more restrictive; see :pep:`614` for - details. + Functions may be decorated with any valid + :token:`~python-grammar:assignment_expression`. Previously, the grammar was + much more restrictive; see :pep:`614` for details. .. index:: triple: default; parameter; value @@ -1360,9 +1361,9 @@ The evaluation rules for the decorator expressions are the same as for function decorators. The result is then bound to the class name. .. versionchanged:: 3.9 - Classes may be decorated with any valid :token:`assignment_expression`. - Previously, the grammar was much more restrictive; see :pep:`614` for - details. + Classes may be decorated with any valid + :token:`~python-grammar:assignment_expression`. Previously, the grammar was + much more restrictive; see :pep:`614` for details. **Programmer's note:** Variables defined in the class definition are class attributes; they are shared by instances. Instance attributes can be set in a diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index 6108c46236217..991f2d717a0a6 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -450,21 +450,20 @@ functions are described separately in section :ref:`asynchronous-generator-functions`. When a generator function is called, it returns an iterator known as a -generator. That generator then controls the execution of the generator 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:`expression_list` to the generator's -caller. 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 function can proceed exactly as if the yield expression -were just another external call. The value of the yield expression after -resuming depends on the method which resumed the execution. If -:meth:`~generator.__next__` is used (typically via either a :keyword:`for` or -the :func:`next` builtin) then the result is :const:`None`. Otherwise, if -:meth:`~generator.send` is used, then the result will be the value passed in to -that method. +generator. That generator then controls the execution of the generator +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 +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 +function can proceed exactly as if the yield expression were just another +external call. The value of the yield expression after resuming depends on the +method which resumed the execution. If :meth:`~generator.__next__` is used +(typically via either a :keyword:`for` or the :func:`next` builtin) then the +result is :const:`None`. Otherwise, if :meth:`~generator.send` is used, then +the result will be the value passed in to that method. .. index:: single: coroutine @@ -514,8 +513,8 @@ on the right hand side of an assignment statement. usable as simple coroutines. :pep:`380` - Syntax for Delegating to a Subgenerator - The proposal to introduce the :token:`yield_from` syntax, making delegation - to subgenerators easy. + The proposal to introduce the :token:`~python-grammar:yield_from` syntax, + making delegation to subgenerators easy. :pep:`525` - Asynchronous Generators The proposal that expanded on :pep:`492` by adding generator capabilities to @@ -543,9 +542,9 @@ is already executing raises a :exc:`ValueError` exception. :meth:`~generator.__next__` method, the current yield expression always evaluates to :const:`None`. The execution then continues to the next yield expression, where the generator is suspended again, and the value of the - :token:`expression_list` is returned to :meth:`__next__`'s caller. If the - generator exits without yielding another value, a :exc:`StopIteration` - exception is raised. + :token:`~python-grammar:expression_list` is returned to :meth:`__next__`'s + caller. If the generator exits without yielding another value, a + :exc:`StopIteration` exception is raised. This method is normally called implicitly, e.g. by a :keyword:`for` loop, or by the built-in :func:`next` function. @@ -634,21 +633,20 @@ An asynchronous generator object is typically used in an :keyword:`async for` statement in a coroutine function analogously to how a generator object would be used in a :keyword:`for` statement. -Calling one of the asynchronous generator's methods returns an -:term:`awaitable` object, and the execution starts when this object -is awaited on. At that time, the execution proceeds to the first yield -expression, where it is suspended again, returning the value of -:token:`expression_list` to the awaiting coroutine. As with a generator, -suspension means 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 awaiting on the next object returned by the asynchronous -generator's methods, the function can proceed exactly as if the yield -expression were just another external call. The value of the yield expression -after resuming depends on the method which resumed the execution. If +Calling one of the asynchronous generator's methods returns an :term:`awaitable` +object, and the execution starts when this object is awaited on. 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 +awaiting coroutine. As with a generator, suspension means 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 awaiting on the next object returned by the +asynchronous generator's methods, the function can proceed exactly as if the +yield expression were just another external call. The value of the yield +expression after resuming depends on the method which resumed the execution. If :meth:`~agen.__anext__` is used then the result is :const:`None`. Otherwise, if -:meth:`~agen.asend` is used, then the result will be the value passed in to -that method. +:meth:`~agen.asend` is used, then the result will be the value passed in to that +method. If an asynchronous generator happens to exit early by :keyword:`break`, the caller task being cancelled, or other exceptions, the generator's async cleanup code @@ -700,10 +698,10 @@ which are used to control the execution of a generator function. Returns an awaitable which when run starts to execute the asynchronous generator or resumes it at the last executed yield expression. When an asynchronous generator function is resumed with an :meth:`~agen.__anext__` - method, the current yield expression always evaluates to :const:`None` in - the returned awaitable, which when run will continue to the next yield - expression. The value of the :token:`expression_list` of the yield - expression is the value of the :exc:`StopIteration` exception raised by + method, the current yield expression always evaluates to :const:`None` in the + returned awaitable, which when run will continue to the next yield + expression. The value of the :token:`~python-grammar:expression_list` of the + yield expression is the value of the :exc:`StopIteration` exception raised by the completing coroutine. If the asynchronous generator exits without yielding another value, the awaitable instead raises a :exc:`StopAsyncIteration` exception, signalling that the asynchronous @@ -1706,8 +1704,9 @@ Assignment expressions assignment_expression: [`identifier` ":="] `expression` An assignment expression (sometimes also called a "named expression" or -"walrus") assigns an :token:`expression` to an :token:`identifier`, while also -returning the value of the :token:`expression`. +"walrus") assigns an :token:`~python-grammar:expression` to an +:token:`~python-grammar:identifier`, while also returning the value of the +:token:`~python-grammar:expression`. One common use case is when handling matched regular expressions: diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index 4f7f00192d749..b69d0fbdd41f8 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -469,10 +469,10 @@ String literals are described by the following lexical definitions: bytesescapeseq: "\" One syntactic restriction not indicated by these productions is that whitespace -is not allowed between the :token:`stringprefix` or :token:`bytesprefix` and the -rest of the literal. The source character set is defined by the encoding -declaration; it is UTF-8 if no encoding declaration is given in the source file; -see section :ref:`encodings`. +is not allowed between the :token:`~python-grammar:stringprefix` or +:token:`~python-grammar:bytesprefix` and the rest of the literal. The source +character set is defined by the encoding declaration; it is UTF-8 if no encoding +declaration is given in the source file; see section :ref:`encodings`. .. index:: triple-quoted string, Unicode Consortium, raw string single: """; string literal diff --git a/Misc/NEWS.d/next/Documentation/2021-11-18-16-44-12.bpo-45640.lSpc2A.rst b/Misc/NEWS.d/next/Documentation/2021-11-18-16-44-12.bpo-45640.lSpc2A.rst new file mode 100644 index 0000000000000..532288df7c76e --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-18-16-44-12.bpo-45640.lSpc2A.rst @@ -0,0 +1,3 @@ +Properly marked-up grammar tokens in the documentation are now clickable and +take you to the definition of a given piece of grammar. Patch by Arthur +Milchior. From webhook-mailer at python.org Thu Nov 18 11:09:53 2021 From: webhook-mailer at python.org (ambv) Date: Thu, 18 Nov 2021 16:09:53 -0000 Subject: [Python-checkins] bpo-29620: iterate over a copy of sys.modules (GH-4800) (GH-29605) Message-ID: https://github.com/python/cpython/commit/71d842b9c1e9d86ede449783e630b7a768b579d6 commit: 71d842b9c1e9d86ede449783e630b7a768b579d6 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-18T17:09:41+01:00 summary: bpo-29620: iterate over a copy of sys.modules (GH-4800) (GH-29605) unittest.TestCase.assertWarns no longer raises a RuntimeException when accessing a module's ``__warningregistry__`` causes importation of a new module, or when a new module is imported in another thread. Patch by Kernc. (cherry picked from commit 46398fba4d66ad342cf2504ef947b5fb857423b2) Co-authored-by: kernc files: A Misc/NEWS.d/next/Library/2018-08-21-16-20-33.bpo-29620.xxx666.rst M Lib/unittest/case.py M Lib/unittest/test/test_case.py diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py index 34f03628ed068..88f1a40865156 100644 --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -252,7 +252,7 @@ class _AssertWarnsContext(_AssertRaisesBaseContext): def __enter__(self): # The __warningregistry__'s need to be in a pristine state for tests # to work properly. - for v in sys.modules.values(): + for v in list(sys.modules.values()): if getattr(v, '__warningregistry__', None): v.__warningregistry__ = {} self.warnings_manager = warnings.catch_warnings(record=True) diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py index 590dd74997aaf..65dc0c65d5566 100644 --- a/Lib/unittest/test/test_case.py +++ b/Lib/unittest/test/test_case.py @@ -8,6 +8,7 @@ import warnings import weakref import inspect +import types from copy import deepcopy from test import support @@ -1350,6 +1351,20 @@ class MyWarn(Warning): pass self.assertRaises(TypeError, self.assertWarnsRegex, MyWarn, lambda: True) + def testAssertWarnsModifySysModules(self): + # bpo-29620: handle modified sys.modules during iteration + class Foo(types.ModuleType): + @property + def __warningregistry__(self): + sys.modules['@bar@'] = 'bar' + + sys.modules['@foo@'] = Foo('foo') + try: + self.assertWarns(UserWarning, warnings.warn, 'expected') + finally: + del sys.modules['@foo@'] + del sys.modules['@bar@'] + def testAssertRaisesRegexMismatch(self): def Stub(): raise Exception('Unexpected') diff --git a/Misc/NEWS.d/next/Library/2018-08-21-16-20-33.bpo-29620.xxx666.rst b/Misc/NEWS.d/next/Library/2018-08-21-16-20-33.bpo-29620.xxx666.rst new file mode 100644 index 0000000000000..d781919504e68 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-08-21-16-20-33.bpo-29620.xxx666.rst @@ -0,0 +1,3 @@ +:func:`~unittest.TestCase.assertWarns` no longer raises a ``RuntimeException`` +when accessing a module's ``__warningregistry__`` causes importation of a new +module, or when a new module is imported in another thread. Patch by Kernc. From webhook-mailer at python.org Thu Nov 18 11:12:17 2021 From: webhook-mailer at python.org (ambv) Date: Thu, 18 Nov 2021 16:12:17 -0000 Subject: [Python-checkins] bpo-45701: Improve documentation for *typed* parameter (GH-29498) (GH-29509) Message-ID: https://github.com/python/cpython/commit/0df5d31ac7b32d3b948952c834783cd357fa3e22 commit: 0df5d31ac7b32d3b948952c834783cd357fa3e22 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-18T17:12:07+01:00 summary: bpo-45701: Improve documentation for *typed* parameter (GH-29498) (GH-29509) (cherry picked from commit 912a4ccc3a523e2990cc501393adfc661614c73a) Co-authored-by: Raymond Hettinger files: M Doc/library/functools.rst diff --git a/Doc/library/functools.rst b/Doc/library/functools.rst index a01b17287878c..c78818bfab1a5 100644 --- a/Doc/library/functools.rst +++ b/Doc/library/functools.rst @@ -160,10 +160,16 @@ The :mod:`functools` module defines the following functions: grow without bound. If *typed* is set to true, function arguments of different types will be - cached separately. For example, ``f(3)`` and ``f(3.0)`` will always be - treated as distinct calls with distinct results. If *typed* is false, - the implementation will usually but not always regard them as equivalent - calls and only cache a single result. + cached separately. If *typed* is false, the implementation will usually + regard them as equivalent calls and only cache a single result. (Some + types such as *str* and *int* may be cached separately even when *typed* + is false.) + + Note, type specificity applies only to the function's immediate arguments + rather than their contents. The scalar arguments, ``Decimal(42)`` and + ``Fraction(42)`` are be treated as distinct calls with distinct results. + In contrast, the tuple arguments ``('answer', Decimal(42))`` and + ``('answer', Fraction(42))`` are treated as equivalent. The wrapped function is instrumented with a :func:`cache_parameters` function that returns a new :class:`dict` showing the values for *maxsize* From webhook-mailer at python.org Thu Nov 18 11:16:20 2021 From: webhook-mailer at python.org (miss-islington) Date: Thu, 18 Nov 2021 16:16:20 -0000 Subject: [Python-checkins] bpo-45835: Fix race condition in test_queue (GH-29601) Message-ID: https://github.com/python/cpython/commit/9450c751cc2053b1c2e03ec92ed822a41223b142 commit: 9450c751cc2053b1c2e03ec92ed822a41223b142 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-18T08:16:06-08:00 summary: bpo-45835: Fix race condition in test_queue (GH-29601) Some of the tests in test_queue had a race condition in which a non-sentinel value could be enqueued after the final sentinel value leading to not all the inputs being processed (and test failures). This changes feed() to enqueue a sentinel once the inputs are exhausted, which guarantees that the final queued object is a sentinel. This requires the number of feeder threads to match the number of consumer threads, but that's already the case in the relevant tests. (cherry picked from commit df3e53d86b2ad67da9ac2b5a3f56257d1f394982) Co-authored-by: Sam Gross files: A Misc/NEWS.d/next/Tests/2021-11-17-14-28-08.bpo-45835.Mgyhjx.rst M Lib/test/test_queue.py diff --git a/Lib/test/test_queue.py b/Lib/test/test_queue.py index dd7f0b1124c7a..ee58c6218ef65 100644 --- a/Lib/test/test_queue.py +++ b/Lib/test/test_queue.py @@ -418,11 +418,12 @@ class BaseSimpleQueueTest: def setUp(self): self.q = self.type2test() - def feed(self, q, seq, rnd): + def feed(self, q, seq, rnd, sentinel): while True: try: val = seq.pop() except IndexError: + q.put(sentinel) return q.put(val) if rnd.random() > 0.5: @@ -461,11 +462,10 @@ def consume_timeout(self, q, results, sentinel): return results.append(val) - def run_threads(self, n_feeders, n_consumers, q, inputs, - feed_func, consume_func): + def run_threads(self, n_threads, q, inputs, feed_func, consume_func): results = [] sentinel = None - seq = inputs + [sentinel] * n_consumers + seq = inputs.copy() seq.reverse() rnd = random.Random(42) @@ -479,11 +479,11 @@ def wrapper(*args, **kwargs): return wrapper feeders = [threading.Thread(target=log_exceptions(feed_func), - args=(q, seq, rnd)) - for i in range(n_feeders)] + args=(q, seq, rnd, sentinel)) + for i in range(n_threads)] consumers = [threading.Thread(target=log_exceptions(consume_func), args=(q, results, sentinel)) - for i in range(n_consumers)] + for i in range(n_threads)] with support.start_threads(feeders + consumers): pass @@ -541,7 +541,7 @@ def test_order(self): # Test a pair of concurrent put() and get() q = self.q inputs = list(range(100)) - results = self.run_threads(1, 1, q, inputs, self.feed, self.consume) + results = self.run_threads(1, q, inputs, self.feed, self.consume) # One producer, one consumer => results appended in well-defined order self.assertEqual(results, inputs) @@ -551,7 +551,7 @@ def test_many_threads(self): N = 50 q = self.q inputs = list(range(10000)) - results = self.run_threads(N, N, q, inputs, self.feed, self.consume) + results = self.run_threads(N, q, inputs, self.feed, self.consume) # Multiple consumers without synchronization append the # results in random order @@ -562,7 +562,7 @@ def test_many_threads_nonblock(self): N = 50 q = self.q inputs = list(range(10000)) - results = self.run_threads(N, N, q, inputs, + results = self.run_threads(N, q, inputs, self.feed, self.consume_nonblock) self.assertEqual(sorted(results), inputs) @@ -572,7 +572,7 @@ def test_many_threads_timeout(self): N = 50 q = self.q inputs = list(range(1000)) - results = self.run_threads(N, N, q, inputs, + results = self.run_threads(N, q, inputs, self.feed, self.consume_timeout) self.assertEqual(sorted(results), inputs) diff --git a/Misc/NEWS.d/next/Tests/2021-11-17-14-28-08.bpo-45835.Mgyhjx.rst b/Misc/NEWS.d/next/Tests/2021-11-17-14-28-08.bpo-45835.Mgyhjx.rst new file mode 100644 index 0000000000000..6a73b01959065 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-11-17-14-28-08.bpo-45835.Mgyhjx.rst @@ -0,0 +1 @@ +Fix race condition in test_queue tests with multiple "feeder" threads. From webhook-mailer at python.org Thu Nov 18 11:19:29 2021 From: webhook-mailer at python.org (ambv) Date: Thu, 18 Nov 2021 16:19:29 -0000 Subject: [Python-checkins] bpo-44959: Add fallback to extension modules with '.sl' suffix on HP-UX (GH-27857) (GH-29152) Message-ID: https://github.com/python/cpython/commit/6d66de97f814fb504296c153957d87e49993f8ec commit: 6d66de97f814fb504296c153957d87e49993f8ec branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-18T17:19:19+01:00 summary: bpo-44959: Add fallback to extension modules with '.sl' suffix on HP-UX (GH-27857) (GH-29152) (cherry picked from commit 2396fa6537d79554ac694dbd2b0b30eeb3476c80) Co-authored-by: Florin Sp?tar files: A Misc/NEWS.d/next/Core and Builtins/2021-09-08-08-29-41.bpo-44959.OSwwPf.rst M Python/dynload_hpux.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-08-08-29-41.bpo-44959.OSwwPf.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-08-08-29-41.bpo-44959.OSwwPf.rst new file mode 100644 index 0000000000000..02e11ae94e430 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-09-08-08-29-41.bpo-44959.OSwwPf.rst @@ -0,0 +1 @@ +Added fallback to extension modules with '.sl' suffix on HP-UX \ No newline at end of file diff --git a/Python/dynload_hpux.c b/Python/dynload_hpux.c index e36d608c6dca4..a53373038ed85 100644 --- a/Python/dynload_hpux.c +++ b/Python/dynload_hpux.c @@ -13,7 +13,7 @@ #define FUNCNAME_PATTERN "%.20s_%.200s" #endif -const char *_PyImport_DynLoadFiletab[] = {SHLIB_EXT, NULL}; +const char *_PyImport_DynLoadFiletab[] = {SHLIB_EXT, ".sl", NULL}; dl_funcptr _PyImport_FindSharedFuncptr(const char *prefix, const char *shortname, From webhook-mailer at python.org Thu Nov 18 11:23:18 2021 From: webhook-mailer at python.org (ambv) Date: Thu, 18 Nov 2021 16:23:18 -0000 Subject: [Python-checkins] [doc] Expand on soft keywords in the docs for keyword.py (GH-29139) (GH-29195) Message-ID: https://github.com/python/cpython/commit/02531f1d7e59dcb0ae284bf83b62b5b908542a72 commit: 02531f1d7e59dcb0ae284bf83b62b5b908542a72 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-18T17:23:03+01:00 summary: [doc] Expand on soft keywords in the docs for keyword.py (GH-29139) (GH-29195) Add link at the top and fix the existing links to point to the "[soft keywords](https://docs.python.org/3.10/reference/lexical_analysis.htmlGH-soft-keywords)" section created in the Python 3.10 docs. (cherry picked from commit 9e05da62241877a871c7b22ef723d7028ce03c90) Co-authored-by: William Andrea files: M Doc/library/keyword.rst diff --git a/Doc/library/keyword.rst b/Doc/library/keyword.rst index 5cae79f5dc9db..c3b4699cb05af 100644 --- a/Doc/library/keyword.rst +++ b/Doc/library/keyword.rst @@ -9,7 +9,7 @@ -------------- This module allows a Python program to determine if a string is a -:ref:`keyword `. +:ref:`keyword ` or :ref:`soft keyword `. .. function:: iskeyword(s) @@ -26,14 +26,14 @@ This module allows a Python program to determine if a string is a .. function:: issoftkeyword(s) - Return ``True`` if *s* is a Python soft :ref:`keyword `. + Return ``True`` if *s* is a Python :ref:`soft keyword `. .. versionadded:: 3.9 .. data:: softkwlist - Sequence containing all the soft :ref:`keywords ` defined for the + Sequence containing all the :ref:`soft keywords ` defined for the interpreter. If any soft keywords are defined to only be active when particular :mod:`__future__` statements are in effect, these will be included as well. From webhook-mailer at python.org Thu Nov 18 11:28:49 2021 From: webhook-mailer at python.org (ambv) Date: Thu, 18 Nov 2021 16:28:49 -0000 Subject: [Python-checkins] bpo-45640: [docs] Tokens are now clickable (GH-29260) (GH-29621) Message-ID: https://github.com/python/cpython/commit/252d83cbf1bf0a6ac22a1347e760cd3e551bb834 commit: 252d83cbf1bf0a6ac22a1347e760cd3e551bb834 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-18T17:28:39+01:00 summary: bpo-45640: [docs] Tokens are now clickable (GH-29260) (GH-29621) Co-authored-by: ?ukasz Langa (cherry picked from commit 32959108f9c543e3cb9f2b68bbc782bddded6f42) Co-authored-by: Arthur Milchior files: A Misc/NEWS.d/next/Documentation/2021-11-18-16-44-12.bpo-45640.lSpc2A.rst M Doc/reference/compound_stmts.rst M Doc/reference/expressions.rst M Doc/reference/lexical_analysis.rst diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst index 3e5ef687922ff..63d885deae93f 100644 --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -418,8 +418,8 @@ usage patterns to be encapsulated for convenient reuse. The execution of the :keyword:`with` statement with one "item" proceeds as follows: -#. The context expression (the expression given in the :token:`with_item`) is - evaluated to obtain a context manager. +#. The context expression (the expression given in the + :token:`~python-grammar:with_item`) is evaluated to obtain a context manager. #. The context manager's :meth:`__enter__` is loaded for later use. @@ -797,7 +797,8 @@ Syntax: capture_pattern: !'_' NAME A single underscore ``_`` is not a capture pattern (this is what ``!'_'`` -expresses). It is instead treated as a :token:`wildcard_pattern`. +expresses). It is instead treated as a +:token:`~python-grammar:wildcard_pattern`. In a given pattern, a given name can only be bound once. E.g. ``case x, x: ...`` is invalid while ``case [x] | x: ...`` is allowed. @@ -1182,9 +1183,9 @@ is roughly equivalent to :: except that the original function is not temporarily bound to the name ``func``. .. versionchanged:: 3.9 - Functions may be decorated with any valid :token:`assignment_expression`. - Previously, the grammar was much more restrictive; see :pep:`614` for - details. + Functions may be decorated with any valid + :token:`~python-grammar:assignment_expression`. Previously, the grammar was + much more restrictive; see :pep:`614` for details. .. index:: triple: default; parameter; value @@ -1360,9 +1361,9 @@ The evaluation rules for the decorator expressions are the same as for function decorators. The result is then bound to the class name. .. versionchanged:: 3.9 - Classes may be decorated with any valid :token:`assignment_expression`. - Previously, the grammar was much more restrictive; see :pep:`614` for - details. + Classes may be decorated with any valid + :token:`~python-grammar:assignment_expression`. Previously, the grammar was + much more restrictive; see :pep:`614` for details. **Programmer's note:** Variables defined in the class definition are class attributes; they are shared by instances. Instance attributes can be set in a diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index ab47f37c77c79..c3f58fc841616 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -445,21 +445,20 @@ functions are described separately in section :ref:`asynchronous-generator-functions`. When a generator function is called, it returns an iterator known as a -generator. That generator then controls the execution of the generator 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:`expression_list` to the generator's -caller. 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 function can proceed exactly as if the yield expression -were just another external call. The value of the yield expression after -resuming depends on the method which resumed the execution. If -:meth:`~generator.__next__` is used (typically via either a :keyword:`for` or -the :func:`next` builtin) then the result is :const:`None`. Otherwise, if -:meth:`~generator.send` is used, then the result will be the value passed in to -that method. +generator. That generator then controls the execution of the generator +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 +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 +function can proceed exactly as if the yield expression were just another +external call. The value of the yield expression after resuming depends on the +method which resumed the execution. If :meth:`~generator.__next__` is used +(typically via either a :keyword:`for` or the :func:`next` builtin) then the +result is :const:`None`. Otherwise, if :meth:`~generator.send` is used, then +the result will be the value passed in to that method. .. index:: single: coroutine @@ -509,8 +508,8 @@ on the right hand side of an assignment statement. usable as simple coroutines. :pep:`380` - Syntax for Delegating to a Subgenerator - The proposal to introduce the :token:`yield_from` syntax, making delegation - to subgenerators easy. + The proposal to introduce the :token:`~python-grammar:yield_from` syntax, + making delegation to subgenerators easy. :pep:`525` - Asynchronous Generators The proposal that expanded on :pep:`492` by adding generator capabilities to @@ -538,9 +537,9 @@ is already executing raises a :exc:`ValueError` exception. :meth:`~generator.__next__` method, the current yield expression always evaluates to :const:`None`. The execution then continues to the next yield expression, where the generator is suspended again, and the value of the - :token:`expression_list` is returned to :meth:`__next__`'s caller. If the - generator exits without yielding another value, a :exc:`StopIteration` - exception is raised. + :token:`~python-grammar:expression_list` is returned to :meth:`__next__`'s + caller. If the generator exits without yielding another value, a + :exc:`StopIteration` exception is raised. This method is normally called implicitly, e.g. by a :keyword:`for` loop, or by the built-in :func:`next` function. @@ -629,21 +628,20 @@ An asynchronous generator object is typically used in an :keyword:`async for` statement in a coroutine function analogously to how a generator object would be used in a :keyword:`for` statement. -Calling one of the asynchronous generator's methods returns an -:term:`awaitable` object, and the execution starts when this object -is awaited on. At that time, the execution proceeds to the first yield -expression, where it is suspended again, returning the value of -:token:`expression_list` to the awaiting coroutine. As with a generator, -suspension means 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 awaiting on the next object returned by the asynchronous -generator's methods, the function can proceed exactly as if the yield -expression were just another external call. The value of the yield expression -after resuming depends on the method which resumed the execution. If +Calling one of the asynchronous generator's methods returns an :term:`awaitable` +object, and the execution starts when this object is awaited on. 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 +awaiting coroutine. As with a generator, suspension means 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 awaiting on the next object returned by the +asynchronous generator's methods, the function can proceed exactly as if the +yield expression were just another external call. The value of the yield +expression after resuming depends on the method which resumed the execution. If :meth:`~agen.__anext__` is used then the result is :const:`None`. Otherwise, if -:meth:`~agen.asend` is used, then the result will be the value passed in to -that method. +:meth:`~agen.asend` is used, then the result will be the value passed in to that +method. If an asynchronous generator happens to exit early by :keyword:`break`, the caller task being cancelled, or other exceptions, the generator's async cleanup code @@ -695,10 +693,10 @@ which are used to control the execution of a generator function. Returns an awaitable which when run starts to execute the asynchronous generator or resumes it at the last executed yield expression. When an asynchronous generator function is resumed with an :meth:`~agen.__anext__` - method, the current yield expression always evaluates to :const:`None` in - the returned awaitable, which when run will continue to the next yield - expression. The value of the :token:`expression_list` of the yield - expression is the value of the :exc:`StopIteration` exception raised by + method, the current yield expression always evaluates to :const:`None` in the + returned awaitable, which when run will continue to the next yield + expression. The value of the :token:`~python-grammar:expression_list` of the + yield expression is the value of the :exc:`StopIteration` exception raised by the completing coroutine. If the asynchronous generator exits without yielding another value, the awaitable instead raises a :exc:`StopAsyncIteration` exception, signalling that the asynchronous @@ -1699,8 +1697,9 @@ Assignment expressions assignment_expression: [`identifier` ":="] `expression` An assignment expression (sometimes also called a "named expression" or -"walrus") assigns an :token:`expression` to an :token:`identifier`, while also -returning the value of the :token:`expression`. +"walrus") assigns an :token:`~python-grammar:expression` to an +:token:`~python-grammar:identifier`, while also returning the value of the +:token:`~python-grammar:expression`. One common use case is when handling matched regular expressions: diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index daa746eea00c3..21ad3731a3246 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -469,10 +469,10 @@ String literals are described by the following lexical definitions: bytesescapeseq: "\" One syntactic restriction not indicated by these productions is that whitespace -is not allowed between the :token:`stringprefix` or :token:`bytesprefix` and the -rest of the literal. The source character set is defined by the encoding -declaration; it is UTF-8 if no encoding declaration is given in the source file; -see section :ref:`encodings`. +is not allowed between the :token:`~python-grammar:stringprefix` or +:token:`~python-grammar:bytesprefix` and the rest of the literal. The source +character set is defined by the encoding declaration; it is UTF-8 if no encoding +declaration is given in the source file; see section :ref:`encodings`. .. index:: triple-quoted string, Unicode Consortium, raw string single: """; string literal diff --git a/Misc/NEWS.d/next/Documentation/2021-11-18-16-44-12.bpo-45640.lSpc2A.rst b/Misc/NEWS.d/next/Documentation/2021-11-18-16-44-12.bpo-45640.lSpc2A.rst new file mode 100644 index 0000000000000..532288df7c76e --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-18-16-44-12.bpo-45640.lSpc2A.rst @@ -0,0 +1,3 @@ +Properly marked-up grammar tokens in the documentation are now clickable and +take you to the definition of a given piece of grammar. Patch by Arthur +Milchior. From webhook-mailer at python.org Thu Nov 18 12:34:19 2021 From: webhook-mailer at python.org (ambv) Date: Thu, 18 Nov 2021 17:34:19 -0000 Subject: [Python-checkins] [3.10] [doc] bpo-45680: Disambiguate ``__getitem__`` and ``__class_getitem__`` in the data model (GH-29389) (GH-29620) Message-ID: https://github.com/python/cpython/commit/fde9f61e70bc38850783c81bf7c80c764ba6d9fa commit: fde9f61e70bc38850783c81bf7c80c764ba6d9fa branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-18T18:34:08+01:00 summary: [3.10] [doc] bpo-45680: Disambiguate ``__getitem__`` and ``__class_getitem__`` in the data model (GH-29389) (GH-29620) The documentation explaining Python's data model does not adequately explain the differences between ``__getitem__`` and ``__class_getitem__``, nor does it explain when each is called. There is an attempt at explaining ``__class_getitem__`` in the documentation for ``GenericAlias`` objects, but this does not give sufficient clarity into how the method works. Moreover, it is the wrong place for that information to be found; the explanation of ``__class_getitem__`` should be in the documentation explaining the data model. This PR has been split off from GH-29335. (cherry picked from commit 31b3a70edb1216bdc8fab3b2eafd8ddb00487f41) Co-authored-by: Alex Waygood Co-authored-by: ?ukasz Langa files: M Doc/library/typing.rst M Doc/reference/datamodel.rst M Doc/tools/susp-ignored.csv diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index c59afdd5e9025..14e5c8fc7efea 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -256,6 +256,7 @@ called :class:`TypeVar`. def first(l: Sequence[T]) -> T: # Generic function return l[0] +.. _user-defined-generics: User-defined generic types ========================== diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 195e8c2d16f10..f480915eeb50b 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -2180,22 +2180,142 @@ case the instance is itself a class. Emulating generic types ----------------------- -One can implement the generic class syntax as specified by :pep:`484` -(for example ``List[int]``) by defining a special method: +When using :term:`type annotations`, it is often useful to +*parameterize* a :term:`generic type` using Python's square-brackets notation. +For example, the annotation ``list[int]`` might be used to signify a +:class:`list` in which all the elements are of type :class:`int`. + +.. seealso:: + + :pep:`484` - Type Hints + Introducing Python's framework for type annotations + + :ref:`Generic Alias Types` + Documentation for objects representing parameterized generic classes + + :ref:`Generics`, :ref:`user-defined generics` and :class:`typing.Generic` + Documentation on how to implement generic classes that can be + parameterized at runtime and understood by static type-checkers. + +A class can *generally* only be parameterized if it defines the special +class method ``__class_getitem__()``. .. classmethod:: object.__class_getitem__(cls, key) Return an object representing the specialization of a generic class by type arguments found in *key*. -This method is looked up on the class object itself, and when defined in -the class body, this method is implicitly a class method. Note, this -mechanism is primarily reserved for use with static type hints, other usage -is discouraged. + When defined on a class, ``__class_getitem__()`` is automatically a class + method. As such, there is no need for it to be decorated with + :func:`@classmethod` when it is defined. -.. seealso:: - :pep:`560` - Core support for typing module and generic types +The purpose of *__class_getitem__* +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The purpose of :meth:`~object.__class_getitem__` is to allow runtime +parameterization of standard-library generic classes in order to more easily +apply :term:`type hints` to these classes. + +To implement custom generic classes that can be parameterized at runtime and +understood by static type-checkers, users should either inherit from a standard +library class that already implements :meth:`~object.__class_getitem__`, or +inherit from :class:`typing.Generic`, which has its own implementation of +``__class_getitem__()``. + +Custom implementations of :meth:`~object.__class_getitem__` on classes defined +outside of the standard library may not be understood by third-party +type-checkers such as mypy. Using ``__class_getitem__()`` on any class for +purposes other than type hinting is discouraged. + + +.. _classgetitem-versus-getitem: + + +*__class_getitem__* versus *__getitem__* +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Usually, the :ref:`subscription` of an object using square +brackets will call the :meth:`~object.__getitem__` instance method defined on +the object's class. However, if the object being subscribed is itself a class, +the class method :meth:`~object.__class_getitem__` may be called instead. +``__class_getitem__()`` should return a :ref:`GenericAlias` +object if it is properly defined. + +Presented with the :term:`expression` ``obj[x]``, the Python interpreter +follows something like the following process to decide whether +:meth:`~object.__getitem__` or :meth:`~object.__class_getitem__` should be +called:: + + from inspect import isclass + + def subscribe(obj, x): + """Return the result of the expression `obj[x]`""" + + class_of_obj = type(obj) + + # If the class of obj defines __getitem__, + # call class_of_obj.__getitem__(obj, x) + if hasattr(class_of_obj, '__getitem__'): + return class_of_obj.__getitem__(obj, x) + + # Else, if obj is a class and defines __class_getitem__, + # call obj.__class_getitem__(x) + elif isclass(obj) and hasattr(obj, '__class_getitem__'): + return obj.__class_getitem__(x) + + # Else, raise an exception + else: + raise TypeError( + f"'{class_of_obj.__name__}' object is not subscriptable" + ) + +In Python, all classes are themselves instances of other classes. The class of +a class is known as that class's :term:`metaclass`, and most classes have the +:class:`type` class as their metaclass. :class:`type` does not define +:meth:`~object.__getitem__`, meaning that expressions such as ``list[int]``, +``dict[str, float]`` and ``tuple[str, bytes]`` all result in +:meth:`~object.__class_getitem__` being called:: + + >>> # list has class "type" as its metaclass, like most classes: + >>> type(list) + + >>> type(dict) == type(list) == type(tuple) == type(str) == type(bytes) + True + >>> # "list[int]" calls "list.__class_getitem__(int)" + >>> list[int] + list[int] + >>> # list.__class_getitem__ returns a GenericAlias object: + >>> type(list[int]) + + +However, if a class has a custom metaclass that defines +:meth:`~object.__getitem__`, subscribing the class may result in different +behaviour. An example of this can be found in the :mod:`enum` module:: + + >>> from enum import Enum + >>> class Menu(Enum): + ... """A breakfast menu""" + ... SPAM = 'spam' + ... BACON = 'bacon' + ... + >>> # Enum classes have a custom metaclass: + >>> type(Menu) + + >>> # EnumMeta defines __getitem__, + >>> # so __class_getitem__ is not called, + >>> # and the result is not a GenericAlias object: + >>> Menu['SPAM'] + + >>> type(Menu['SPAM']) + + + +.. seealso:: + :pep:`560` - Core Support for typing module and generic types + Introducing :meth:`~object.__class_getitem__`, and outlining when a + :ref:`subscription` results in ``__class_getitem__()`` + being called instead of :meth:`~object.__getitem__` .. _callable-types: @@ -2295,19 +2415,27 @@ through the object's keys; for sequences, it should iterate through the values. .. method:: object.__getitem__(self, key) - Called to implement evaluation of ``self[key]``. For sequence types, the - accepted keys should be integers and slice objects. Note that the special - interpretation of negative indexes (if the class wishes to emulate a sequence - type) is up to the :meth:`__getitem__` method. If *key* is of an inappropriate - type, :exc:`TypeError` may be raised; if of a value outside the set of indexes - for the sequence (after any special interpretation of negative values), - :exc:`IndexError` should be raised. For mapping types, if *key* is missing (not - in the container), :exc:`KeyError` should be raised. + Called to implement evaluation of ``self[key]``. For :term:`sequence` types, + the accepted keys should be integers and slice objects. Note that the + special interpretation of negative indexes (if the class wishes to emulate a + :term:`sequence` type) is up to the :meth:`__getitem__` method. If *key* is + of an inappropriate type, :exc:`TypeError` may be raised; if of a value + outside the set of indexes for the sequence (after any special + interpretation of negative values), :exc:`IndexError` should be raised. For + :term:`mapping` types, if *key* is missing (not in the container), + :exc:`KeyError` should be raised. + + .. note:: + + :keyword:`for` loops expect that an :exc:`IndexError` will be raised for + illegal indexes to allow proper detection of the end of the sequence. .. note:: - :keyword:`for` loops expect that an :exc:`IndexError` will be raised for illegal - indexes to allow proper detection of the end of the sequence. + When :ref:`subscripting` a *class*, the special + class method :meth:`~object.__class_getitem__` may be called instead of + ``__getitem__()``. See :ref:`classgetitem-versus-getitem` for more + details. .. method:: object.__setitem__(self, key, value) diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv index 9cbd09ad20357..2453faa8ccd74 100644 --- a/Doc/tools/susp-ignored.csv +++ b/Doc/tools/susp-ignored.csv @@ -271,6 +271,7 @@ license,,:zooko,mailto:zooko at zooko.com reference/expressions,,:index,x[index:index] reference/lexical_analysis,,`,$ ? ` reference/lexical_analysis,,:fileencoding,# vim:fileencoding= +reference/datamodel,,`, """Return the result of the expression `obj[x]`""" tutorial/datastructures,,:value,It is also possible to delete a key:value tutorial/datastructures,,:value,key:value pairs within the braces adds initial key:value pairs tutorial/stdlib2,,:config,"logging.warning('Warning:config file %s not found', 'server.conf')" From webhook-mailer at python.org Thu Nov 18 12:41:17 2021 From: webhook-mailer at python.org (ambv) Date: Thu, 18 Nov 2021 17:41:17 -0000 Subject: [Python-checkins] [3.9] [doc] bpo-45680: Disambiguate ``__getitem__`` and ``__class_getitem__`` in the data model (GH-29389) (GH-29619) Message-ID: https://github.com/python/cpython/commit/591bf416090fb00795eed51f6863e3c5d9036c89 commit: 591bf416090fb00795eed51f6863e3c5d9036c89 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-18T18:41:09+01:00 summary: [3.9] [doc] bpo-45680: Disambiguate ``__getitem__`` and ``__class_getitem__`` in the data model (GH-29389) (GH-29619) The documentation explaining Python's data model does not adequately explain the differences between ``__getitem__`` and ``__class_getitem__``, nor does it explain when each is called. There is an attempt at explaining ``__class_getitem__`` in the documentation for ``GenericAlias`` objects, but this does not give sufficient clarity into how the method works. Moreover, it is the wrong place for that information to be found; the explanation of ``__class_getitem__`` should be in the documentation explaining the data model. This PR has been split off from GH-29335. (cherry picked from commit 31b3a70edb1216bdc8fab3b2eafd8ddb00487f41) Co-authored-by: Alex Waygood Co-authored-by: ?ukasz Langa files: M Doc/library/typing.rst M Doc/reference/datamodel.rst M Doc/tools/susp-ignored.csv diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 3b50d76c5a8fe..0eeaffb4352bf 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -223,6 +223,7 @@ called :class:`TypeVar`. def first(l: Sequence[T]) -> T: # Generic function return l[0] +.. _user-defined-generics: User-defined generic types ========================== diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 29a6987054df4..986a36cd804dd 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -2144,22 +2144,142 @@ case the instance is itself a class. Emulating generic types ----------------------- -One can implement the generic class syntax as specified by :pep:`484` -(for example ``List[int]``) by defining a special method: +When using :term:`type annotations`, it is often useful to +*parameterize* a :term:`generic type` using Python's square-brackets notation. +For example, the annotation ``list[int]`` might be used to signify a +:class:`list` in which all the elements are of type :class:`int`. + +.. seealso:: + + :pep:`484` - Type Hints + Introducing Python's framework for type annotations + + :ref:`Generic Alias Types` + Documentation for objects representing parameterized generic classes + + :ref:`Generics`, :ref:`user-defined generics` and :class:`typing.Generic` + Documentation on how to implement generic classes that can be + parameterized at runtime and understood by static type-checkers. + +A class can *generally* only be parameterized if it defines the special +class method ``__class_getitem__()``. .. classmethod:: object.__class_getitem__(cls, key) Return an object representing the specialization of a generic class by type arguments found in *key*. -This method is looked up on the class object itself, and when defined in -the class body, this method is implicitly a class method. Note, this -mechanism is primarily reserved for use with static type hints, other usage -is discouraged. + When defined on a class, ``__class_getitem__()`` is automatically a class + method. As such, there is no need for it to be decorated with + :func:`@classmethod` when it is defined. -.. seealso:: - :pep:`560` - Core support for typing module and generic types +The purpose of *__class_getitem__* +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The purpose of :meth:`~object.__class_getitem__` is to allow runtime +parameterization of standard-library generic classes in order to more easily +apply :term:`type hints` to these classes. + +To implement custom generic classes that can be parameterized at runtime and +understood by static type-checkers, users should either inherit from a standard +library class that already implements :meth:`~object.__class_getitem__`, or +inherit from :class:`typing.Generic`, which has its own implementation of +``__class_getitem__()``. + +Custom implementations of :meth:`~object.__class_getitem__` on classes defined +outside of the standard library may not be understood by third-party +type-checkers such as mypy. Using ``__class_getitem__()`` on any class for +purposes other than type hinting is discouraged. + + +.. _classgetitem-versus-getitem: + + +*__class_getitem__* versus *__getitem__* +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Usually, the :ref:`subscription` of an object using square +brackets will call the :meth:`~object.__getitem__` instance method defined on +the object's class. However, if the object being subscribed is itself a class, +the class method :meth:`~object.__class_getitem__` may be called instead. +``__class_getitem__()`` should return a :ref:`GenericAlias` +object if it is properly defined. + +Presented with the :term:`expression` ``obj[x]``, the Python interpreter +follows something like the following process to decide whether +:meth:`~object.__getitem__` or :meth:`~object.__class_getitem__` should be +called:: + + from inspect import isclass + + def subscribe(obj, x): + """Return the result of the expression `obj[x]`""" + + class_of_obj = type(obj) + + # If the class of obj defines __getitem__, + # call class_of_obj.__getitem__(obj, x) + if hasattr(class_of_obj, '__getitem__'): + return class_of_obj.__getitem__(obj, x) + + # Else, if obj is a class and defines __class_getitem__, + # call obj.__class_getitem__(x) + elif isclass(obj) and hasattr(obj, '__class_getitem__'): + return obj.__class_getitem__(x) + + # Else, raise an exception + else: + raise TypeError( + f"'{class_of_obj.__name__}' object is not subscriptable" + ) + +In Python, all classes are themselves instances of other classes. The class of +a class is known as that class's :term:`metaclass`, and most classes have the +:class:`type` class as their metaclass. :class:`type` does not define +:meth:`~object.__getitem__`, meaning that expressions such as ``list[int]``, +``dict[str, float]`` and ``tuple[str, bytes]`` all result in +:meth:`~object.__class_getitem__` being called:: + + >>> # list has class "type" as its metaclass, like most classes: + >>> type(list) + + >>> type(dict) == type(list) == type(tuple) == type(str) == type(bytes) + True + >>> # "list[int]" calls "list.__class_getitem__(int)" + >>> list[int] + list[int] + >>> # list.__class_getitem__ returns a GenericAlias object: + >>> type(list[int]) + + +However, if a class has a custom metaclass that defines +:meth:`~object.__getitem__`, subscribing the class may result in different +behaviour. An example of this can be found in the :mod:`enum` module:: + + >>> from enum import Enum + >>> class Menu(Enum): + ... """A breakfast menu""" + ... SPAM = 'spam' + ... BACON = 'bacon' + ... + >>> # Enum classes have a custom metaclass: + >>> type(Menu) + + >>> # EnumMeta defines __getitem__, + >>> # so __class_getitem__ is not called, + >>> # and the result is not a GenericAlias object: + >>> Menu['SPAM'] + + >>> type(Menu['SPAM']) + + + +.. seealso:: + :pep:`560` - Core Support for typing module and generic types + Introducing :meth:`~object.__class_getitem__`, and outlining when a + :ref:`subscription` results in ``__class_getitem__()`` + being called instead of :meth:`~object.__getitem__` .. _callable-types: @@ -2259,19 +2379,27 @@ through the object's keys; for sequences, it should iterate through the values. .. method:: object.__getitem__(self, key) - Called to implement evaluation of ``self[key]``. For sequence types, the - accepted keys should be integers and slice objects. Note that the special - interpretation of negative indexes (if the class wishes to emulate a sequence - type) is up to the :meth:`__getitem__` method. If *key* is of an inappropriate - type, :exc:`TypeError` may be raised; if of a value outside the set of indexes - for the sequence (after any special interpretation of negative values), - :exc:`IndexError` should be raised. For mapping types, if *key* is missing (not - in the container), :exc:`KeyError` should be raised. + Called to implement evaluation of ``self[key]``. For :term:`sequence` types, + the accepted keys should be integers and slice objects. Note that the + special interpretation of negative indexes (if the class wishes to emulate a + :term:`sequence` type) is up to the :meth:`__getitem__` method. If *key* is + of an inappropriate type, :exc:`TypeError` may be raised; if of a value + outside the set of indexes for the sequence (after any special + interpretation of negative values), :exc:`IndexError` should be raised. For + :term:`mapping` types, if *key* is missing (not in the container), + :exc:`KeyError` should be raised. + + .. note:: + + :keyword:`for` loops expect that an :exc:`IndexError` will be raised for + illegal indexes to allow proper detection of the end of the sequence. .. note:: - :keyword:`for` loops expect that an :exc:`IndexError` will be raised for illegal - indexes to allow proper detection of the end of the sequence. + When :ref:`subscripting` a *class*, the special + class method :meth:`~object.__class_getitem__` may be called instead of + ``__getitem__()``. See :ref:`classgetitem-versus-getitem` for more + details. .. method:: object.__setitem__(self, key, value) diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv index ad5f55e803852..02fe9175278c5 100644 --- a/Doc/tools/susp-ignored.csv +++ b/Doc/tools/susp-ignored.csv @@ -266,6 +266,7 @@ license,,:zooko,mailto:zooko at zooko.com reference/expressions,,:index,x[index:index] reference/lexical_analysis,,`,$ ? ` reference/lexical_analysis,,:fileencoding,# vim:fileencoding= +reference/datamodel,,`, """Return the result of the expression `obj[x]`""" tutorial/datastructures,,:value,It is also possible to delete a key:value tutorial/datastructures,,:value,key:value pairs within the braces adds initial key:value pairs tutorial/stdlib2,,:config,"logging.warning('Warning:config file %s not found', 'server.conf')" From webhook-mailer at python.org Thu Nov 18 15:08:42 2021 From: webhook-mailer at python.org (terryjreedy) Date: Thu, 18 Nov 2021 20:08:42 -0000 Subject: [Python-checkins] bpo-45788: Link sys.prefix doc to 'Installation paths' (#29606) Message-ID: https://github.com/python/cpython/commit/4575c01b750cd26377e803247c38d65dad15e26a commit: 4575c01b750cd26377e803247c38d65dad15e26a branch: main author: Terry Jan Reedy committer: terryjreedy date: 2021-11-18T15:08:24-05:00 summary: bpo-45788: Link sys.prefix doc to 'Installation paths' (#29606) ... To the Installation paths section of the sysconfig doc. files: A Misc/NEWS.d/next/Documentation/2021-11-18-00-07-40.bpo-45788.qibUoB.rst M Doc/library/sys.rst M Doc/library/sysconfig.rst diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index ee07ba1042f623..175fc091652068 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -1216,13 +1216,10 @@ always available. .. data:: prefix A string giving the site-specific directory prefix where the platform - independent Python files are installed; by default, this is the string + independent Python files are installed; on Unix, the default is ``'/usr/local'``. This can be set at build time with the ``--prefix`` - argument to the :program:`configure` script. The main collection of Python - library modules is installed in the directory :file:`{prefix}/lib/python{X.Y}` - while the platform independent header files (all except :file:`pyconfig.h`) are - stored in :file:`{prefix}/include/python{X.Y}`, where *X.Y* is the version - number of Python, for example ``3.2``. + argument to the :program:`configure` script. See + :ref:`installation_paths` for derived paths. .. note:: If a :ref:`virtual environment ` is in effect, this value will be changed in ``site.py`` to point to the virtual diff --git a/Doc/library/sysconfig.rst b/Doc/library/sysconfig.rst index 6327318eb108da..7ef3b2489673e6 100644 --- a/Doc/library/sysconfig.rst +++ b/Doc/library/sysconfig.rst @@ -60,6 +60,7 @@ Example of usage:: >>> sysconfig.get_config_vars('AR', 'CXX') ['ar', 'g++'] +.. _installation_paths: Installation paths ------------------ @@ -72,7 +73,7 @@ Every new component that is installed using :mod:`distutils` or a Distutils-based system will follow the same scheme to copy its file in the right places. -Python currently supports seven schemes: +Python currently supports six schemes: - *posix_prefix*: scheme for POSIX platforms like Linux or macOS. This is the default scheme used when Python or a component is installed. @@ -84,6 +85,7 @@ Python currently supports seven schemes: located under the user home directory. - *nt*: scheme for NT platforms like Windows. - *nt_user*: scheme for NT platforms, when the *user* option is used. +- *osx_framework_user*: scheme for macOS, when the *user* option is used. Each scheme is itself composed of a series of paths and each path has a unique identifier. Python currently uses eight paths: diff --git a/Misc/NEWS.d/next/Documentation/2021-11-18-00-07-40.bpo-45788.qibUoB.rst b/Misc/NEWS.d/next/Documentation/2021-11-18-00-07-40.bpo-45788.qibUoB.rst new file mode 100644 index 00000000000000..8aa3293673e1ff --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-18-00-07-40.bpo-45788.qibUoB.rst @@ -0,0 +1 @@ +Link doc for sys.prefix to sysconfig doc on installation paths. From webhook-mailer at python.org Thu Nov 18 16:45:25 2021 From: webhook-mailer at python.org (terryjreedy) Date: Thu, 18 Nov 2021 21:45:25 -0000 Subject: [Python-checkins] [3.9] bpo-45788: Link sys.prefix doc to 'Installation paths' (GH-29606) (GH-29632) Message-ID: https://github.com/python/cpython/commit/c06c7c489a82b2db023bb947f0c4d21ad93b8308 commit: c06c7c489a82b2db023bb947f0c4d21ad93b8308 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: terryjreedy date: 2021-11-18T16:45:15-05:00 summary: [3.9] bpo-45788: Link sys.prefix doc to 'Installation paths' (GH-29606) (GH-29632) ... To the Installation paths section of the sysconfig doc. (cherry picked from commit 4575c01b750cd26377e803247c38d65dad15e26a) Co-authored-by: Terry Jan Reedy files: A Misc/NEWS.d/next/Documentation/2021-11-18-00-07-40.bpo-45788.qibUoB.rst M Doc/library/sys.rst M Doc/library/sysconfig.rst diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index 6b23b6f0ab74a..9e182826b7343 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -1183,13 +1183,10 @@ always available. .. data:: prefix A string giving the site-specific directory prefix where the platform - independent Python files are installed; by default, this is the string + independent Python files are installed; on Unix, the default is ``'/usr/local'``. This can be set at build time with the ``--prefix`` - argument to the :program:`configure` script. The main collection of Python - library modules is installed in the directory :file:`{prefix}/lib/python{X.Y}` - while the platform independent header files (all except :file:`pyconfig.h`) are - stored in :file:`{prefix}/include/python{X.Y}`, where *X.Y* is the version - number of Python, for example ``3.2``. + argument to the :program:`configure` script. See + :ref:`installation_paths` for derived paths. .. note:: If a :ref:`virtual environment ` is in effect, this value will be changed in ``site.py`` to point to the virtual diff --git a/Doc/library/sysconfig.rst b/Doc/library/sysconfig.rst index ee27efd869d00..e2ee6db38dd44 100644 --- a/Doc/library/sysconfig.rst +++ b/Doc/library/sysconfig.rst @@ -60,6 +60,7 @@ Example of usage:: >>> sysconfig.get_config_vars('AR', 'CXX') ['ar', 'g++'] +.. _installation_paths: Installation paths ------------------ @@ -72,7 +73,7 @@ Every new component that is installed using :mod:`distutils` or a Distutils-based system will follow the same scheme to copy its file in the right places. -Python currently supports seven schemes: +Python currently supports six schemes: - *posix_prefix*: scheme for POSIX platforms like Linux or macOS. This is the default scheme used when Python or a component is installed. @@ -84,6 +85,7 @@ Python currently supports seven schemes: located under the user home directory. - *nt*: scheme for NT platforms like Windows. - *nt_user*: scheme for NT platforms, when the *user* option is used. +- *osx_framework_user*: scheme for macOS, when the *user* option is used. Each scheme is itself composed of a series of paths and each path has a unique identifier. Python currently uses eight paths: diff --git a/Misc/NEWS.d/next/Documentation/2021-11-18-00-07-40.bpo-45788.qibUoB.rst b/Misc/NEWS.d/next/Documentation/2021-11-18-00-07-40.bpo-45788.qibUoB.rst new file mode 100644 index 0000000000000..8aa3293673e1f --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-18-00-07-40.bpo-45788.qibUoB.rst @@ -0,0 +1 @@ +Link doc for sys.prefix to sysconfig doc on installation paths. From webhook-mailer at python.org Thu Nov 18 16:46:16 2021 From: webhook-mailer at python.org (terryjreedy) Date: Thu, 18 Nov 2021 21:46:16 -0000 Subject: [Python-checkins] [3.10] bpo-45788: Link sys.prefix doc to 'Installation paths' (GH-29606) Message-ID: https://github.com/python/cpython/commit/2a630e716e488ac420d308736568829f76e388a3 commit: 2a630e716e488ac420d308736568829f76e388a3 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: terryjreedy date: 2021-11-18T16:46:06-05:00 summary: [3.10] bpo-45788: Link sys.prefix doc to 'Installation paths' (GH-29606) ... To the Installation paths section of the sysconfig doc. (cherry picked from commit 4575c01b750cd26377e803247c38d65dad15e26a) Co-authored-by: Terry Jan Reedy files: A Misc/NEWS.d/next/Documentation/2021-11-18-00-07-40.bpo-45788.qibUoB.rst M Doc/library/sys.rst M Doc/library/sysconfig.rst diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index 8b3c6fd762731..29cb54b5d1ac3 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -1216,13 +1216,10 @@ always available. .. data:: prefix A string giving the site-specific directory prefix where the platform - independent Python files are installed; by default, this is the string + independent Python files are installed; on Unix, the default is ``'/usr/local'``. This can be set at build time with the ``--prefix`` - argument to the :program:`configure` script. The main collection of Python - library modules is installed in the directory :file:`{prefix}/lib/python{X.Y}` - while the platform independent header files (all except :file:`pyconfig.h`) are - stored in :file:`{prefix}/include/python{X.Y}`, where *X.Y* is the version - number of Python, for example ``3.2``. + argument to the :program:`configure` script. See + :ref:`installation_paths` for derived paths. .. note:: If a :ref:`virtual environment ` is in effect, this value will be changed in ``site.py`` to point to the virtual diff --git a/Doc/library/sysconfig.rst b/Doc/library/sysconfig.rst index 6327318eb108d..7ef3b2489673e 100644 --- a/Doc/library/sysconfig.rst +++ b/Doc/library/sysconfig.rst @@ -60,6 +60,7 @@ Example of usage:: >>> sysconfig.get_config_vars('AR', 'CXX') ['ar', 'g++'] +.. _installation_paths: Installation paths ------------------ @@ -72,7 +73,7 @@ Every new component that is installed using :mod:`distutils` or a Distutils-based system will follow the same scheme to copy its file in the right places. -Python currently supports seven schemes: +Python currently supports six schemes: - *posix_prefix*: scheme for POSIX platforms like Linux or macOS. This is the default scheme used when Python or a component is installed. @@ -84,6 +85,7 @@ Python currently supports seven schemes: located under the user home directory. - *nt*: scheme for NT platforms like Windows. - *nt_user*: scheme for NT platforms, when the *user* option is used. +- *osx_framework_user*: scheme for macOS, when the *user* option is used. Each scheme is itself composed of a series of paths and each path has a unique identifier. Python currently uses eight paths: diff --git a/Misc/NEWS.d/next/Documentation/2021-11-18-00-07-40.bpo-45788.qibUoB.rst b/Misc/NEWS.d/next/Documentation/2021-11-18-00-07-40.bpo-45788.qibUoB.rst new file mode 100644 index 0000000000000..8aa3293673e1f --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-18-00-07-40.bpo-45788.qibUoB.rst @@ -0,0 +1 @@ +Link doc for sys.prefix to sysconfig doc on installation paths. From webhook-mailer at python.org Fri Nov 19 05:30:50 2021 From: webhook-mailer at python.org (markshannon) Date: Fri, 19 Nov 2021 10:30:50 -0000 Subject: [Python-checkins] bpo-45609: Specialize STORE_SUBSCR (GH-29242) Message-ID: https://github.com/python/cpython/commit/036fead695a9a1e1082992d16ab46bca1cd61a25 commit: 036fead695a9a1e1082992d16ab46bca1cd61a25 branch: main author: Dennis Sweeney <36520290+sweeneyde at users.noreply.github.com> committer: markshannon date: 2021-11-19T10:30:37Z summary: bpo-45609: Specialize STORE_SUBSCR (GH-29242) * Specialize STORE_SUBSCR for list[int], and dict[object] * Adds _PyDict_SetItem_Take2 which consumes references to the key and values. files: A Misc/NEWS.d/next/Core and Builtins/2021-10-27-21-00-49.bpo-45609.L1GKPX.rst M Include/internal/pycore_code.h M Include/internal/pycore_dict.h M Include/opcode.h M Lib/opcode.py M Lib/test/test_dict.py M Objects/dictobject.c M Python/ceval.c M Python/opcode_targets.h M Python/specialize.c diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index 6563f7b87b360..194af46a3a274 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -268,6 +268,7 @@ int _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *nam int _Py_Specialize_LoadGlobal(PyObject *globals, PyObject *builtins, _Py_CODEUNIT *instr, PyObject *name, SpecializedCacheEntry *cache); int _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name, SpecializedCacheEntry *cache); int _Py_Specialize_BinarySubscr(PyObject *sub, PyObject *container, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache); +int _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT *instr); int _Py_Specialize_CallFunction(PyObject *callable, _Py_CODEUNIT *instr, int nargs, SpecializedCacheEntry *cache, PyObject *builtins); void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache); diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h index 13cb7ccc7b819..2f0536801ec6e 100644 --- a/Include/internal/pycore_dict.h +++ b/Include/internal/pycore_dict.h @@ -22,6 +22,8 @@ typedef struct { */ Py_ssize_t _Py_dict_lookup(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr); +/* Consumes references to key and value */ +int _PyDict_SetItem_Take2(PyDictObject *op, PyObject *key, PyObject *value); #define DKIX_EMPTY (-1) #define DKIX_DUMMY (-2) /* Used internally */ diff --git a/Include/opcode.h b/Include/opcode.h index 2367064a89d71..3ec89bd4c0be6 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -125,35 +125,38 @@ extern "C" { #define BINARY_SUBSCR_LIST_INT 23 #define BINARY_SUBSCR_TUPLE_INT 24 #define BINARY_SUBSCR_DICT 26 -#define CALL_FUNCTION_ADAPTIVE 27 -#define CALL_FUNCTION_BUILTIN_O 28 -#define CALL_FUNCTION_BUILTIN_FAST 29 -#define CALL_FUNCTION_LEN 34 -#define CALL_FUNCTION_ISINSTANCE 36 -#define CALL_FUNCTION_PY_SIMPLE 38 -#define JUMP_ABSOLUTE_QUICK 39 -#define LOAD_ATTR_ADAPTIVE 40 -#define LOAD_ATTR_INSTANCE_VALUE 41 -#define LOAD_ATTR_WITH_HINT 42 -#define LOAD_ATTR_SLOT 43 -#define LOAD_ATTR_MODULE 44 -#define LOAD_GLOBAL_ADAPTIVE 45 -#define LOAD_GLOBAL_MODULE 46 -#define LOAD_GLOBAL_BUILTIN 47 -#define LOAD_METHOD_ADAPTIVE 48 -#define LOAD_METHOD_CACHED 55 -#define LOAD_METHOD_CLASS 56 -#define LOAD_METHOD_MODULE 57 -#define LOAD_METHOD_NO_DICT 58 -#define STORE_ATTR_ADAPTIVE 59 -#define STORE_ATTR_INSTANCE_VALUE 62 -#define STORE_ATTR_SLOT 63 -#define STORE_ATTR_WITH_HINT 64 -#define LOAD_FAST__LOAD_FAST 65 -#define STORE_FAST__LOAD_FAST 66 -#define LOAD_FAST__LOAD_CONST 67 -#define LOAD_CONST__LOAD_FAST 75 -#define STORE_FAST__STORE_FAST 76 +#define STORE_SUBSCR_ADAPTIVE 27 +#define STORE_SUBSCR_LIST_INT 28 +#define STORE_SUBSCR_DICT 29 +#define CALL_FUNCTION_ADAPTIVE 34 +#define CALL_FUNCTION_BUILTIN_O 36 +#define CALL_FUNCTION_BUILTIN_FAST 38 +#define CALL_FUNCTION_LEN 39 +#define CALL_FUNCTION_ISINSTANCE 40 +#define CALL_FUNCTION_PY_SIMPLE 41 +#define JUMP_ABSOLUTE_QUICK 42 +#define LOAD_ATTR_ADAPTIVE 43 +#define LOAD_ATTR_INSTANCE_VALUE 44 +#define LOAD_ATTR_WITH_HINT 45 +#define LOAD_ATTR_SLOT 46 +#define LOAD_ATTR_MODULE 47 +#define LOAD_GLOBAL_ADAPTIVE 48 +#define LOAD_GLOBAL_MODULE 55 +#define LOAD_GLOBAL_BUILTIN 56 +#define LOAD_METHOD_ADAPTIVE 57 +#define LOAD_METHOD_CACHED 58 +#define LOAD_METHOD_CLASS 59 +#define LOAD_METHOD_MODULE 62 +#define LOAD_METHOD_NO_DICT 63 +#define STORE_ATTR_ADAPTIVE 64 +#define STORE_ATTR_INSTANCE_VALUE 65 +#define STORE_ATTR_SLOT 66 +#define STORE_ATTR_WITH_HINT 67 +#define LOAD_FAST__LOAD_FAST 75 +#define STORE_FAST__LOAD_FAST 76 +#define LOAD_FAST__LOAD_CONST 77 +#define LOAD_CONST__LOAD_FAST 78 +#define STORE_FAST__STORE_FAST 79 #define DO_TRACING 255 #ifdef NEED_OPCODE_JUMP_TABLES static uint32_t _PyOpcode_RelativeJump[8] = { diff --git a/Lib/opcode.py b/Lib/opcode.py index 1df192bb1247d..3603bb422b150 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -238,6 +238,9 @@ def jabs_op(name, op): "BINARY_SUBSCR_LIST_INT", "BINARY_SUBSCR_TUPLE_INT", "BINARY_SUBSCR_DICT", + "STORE_SUBSCR_ADAPTIVE", + "STORE_SUBSCR_LIST_INT", + "STORE_SUBSCR_DICT", "CALL_FUNCTION_ADAPTIVE", "CALL_FUNCTION_BUILTIN_O", "CALL_FUNCTION_BUILTIN_FAST", diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py index 32ffd38f03576..66f5d56deeaaf 100644 --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -892,6 +892,14 @@ def _tracked(self, t): gc.collect() self.assertTrue(gc.is_tracked(t), t) + def test_string_keys_can_track_values(self): + # Test that this doesn't leak. + for i in range(10): + d = {} + for j in range(10): + d[str(j)] = j + d["foo"] = d + @support.cpython_only def test_track_literals(self): # Test GC-optimization of dict literals diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-27-21-00-49.bpo-45609.L1GKPX.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-27-21-00-49.bpo-45609.L1GKPX.rst new file mode 100644 index 0000000000000..f7df7d4b90eee --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-10-27-21-00-49.bpo-45609.L1GKPX.rst @@ -0,0 +1 @@ +Specialized the ``STORE_SUBSCR`` opcode using the PEP 659 machinery. \ No newline at end of file diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 6dcd5a1d19715..475d92d329828 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -1055,6 +1055,7 @@ insert_into_dictkeys(PyDictKeysObject *keys, PyObject *name) Internal routine to insert a new item into the table. Used both by the internal resize routine and by the public insert routine. Returns -1 if an error occurred, or 0 on success. +Consumes key and value references. */ static int insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value) @@ -1062,8 +1063,6 @@ insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value) PyObject *old_value; PyDictKeyEntry *ep; - Py_INCREF(key); - Py_INCREF(value); if (mp->ma_values != NULL && !PyUnicode_CheckExact(key)) { if (insertion_resize(mp) < 0) goto Fail; @@ -1138,6 +1137,7 @@ insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value) } // Same to insertdict but specialized for ma_keys = Py_EMPTY_KEYS. +// Consumes key and value references. static int insert_to_emptydict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value) @@ -1146,6 +1146,8 @@ insert_to_emptydict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyDictKeysObject *newkeys = new_keys_object(PyDict_LOG_MINSIZE); if (newkeys == NULL) { + Py_DECREF(key); + Py_DECREF(value); return -1; } if (!PyUnicode_CheckExact(key)) { @@ -1155,8 +1157,6 @@ insert_to_emptydict(PyDictObject *mp, PyObject *key, Py_hash_t hash, mp->ma_keys = newkeys; mp->ma_values = NULL; - Py_INCREF(key); - Py_INCREF(value); MAINTAIN_TRACKING(mp, key, value); size_t hashpos = (size_t)hash & (PyDict_MINSIZE-1); @@ -1529,32 +1529,24 @@ _PyDict_LoadGlobal(PyDictObject *globals, PyDictObject *builtins, PyObject *key) return value; } -/* CAUTION: PyDict_SetItem() must guarantee that it won't resize the - * dictionary if it's merely replacing the value for an existing key. - * This means that it's safe to loop over a dictionary with PyDict_Next() - * and occasionally replace a value -- but you can't insert new keys or - * remove them. - */ +/* Consumes references to key and value */ int -PyDict_SetItem(PyObject *op, PyObject *key, PyObject *value) +_PyDict_SetItem_Take2(PyDictObject *mp, PyObject *key, PyObject *value) { - PyDictObject *mp; - Py_hash_t hash; - if (!PyDict_Check(op)) { - PyErr_BadInternalCall(); - return -1; - } assert(key); assert(value); - mp = (PyDictObject *)op; + assert(PyDict_Check(mp)); + Py_hash_t hash; if (!PyUnicode_CheckExact(key) || (hash = ((PyASCIIObject *) key)->hash) == -1) { hash = PyObject_Hash(key); - if (hash == -1) + if (hash == -1) { + Py_DECREF(key); + Py_DECREF(value); return -1; + } } - if (mp->ma_keys == Py_EMPTY_KEYS) { return insert_to_emptydict(mp, key, hash, value); } @@ -1562,6 +1554,26 @@ PyDict_SetItem(PyObject *op, PyObject *key, PyObject *value) return insertdict(mp, key, hash, value); } +/* CAUTION: PyDict_SetItem() must guarantee that it won't resize the + * dictionary if it's merely replacing the value for an existing key. + * This means that it's safe to loop over a dictionary with PyDict_Next() + * and occasionally replace a value -- but you can't insert new keys or + * remove them. + */ +int +PyDict_SetItem(PyObject *op, PyObject *key, PyObject *value) +{ + if (!PyDict_Check(op)) { + PyErr_BadInternalCall(); + return -1; + } + assert(key); + assert(value); + Py_INCREF(key); + Py_INCREF(value); + return _PyDict_SetItem_Take2((PyDictObject *)op, key, value); +} + int _PyDict_SetItem_KnownHash(PyObject *op, PyObject *key, PyObject *value, Py_hash_t hash) @@ -1577,6 +1589,8 @@ _PyDict_SetItem_KnownHash(PyObject *op, PyObject *key, PyObject *value, assert(hash != -1); mp = (PyDictObject *)op; + Py_INCREF(key); + Py_INCREF(value); if (mp->ma_keys == Py_EMPTY_KEYS) { return insert_to_emptydict(mp, key, hash, value); } @@ -1917,6 +1931,8 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value) } while (_PyDict_Next(iterable, &pos, &key, &oldvalue, &hash)) { + Py_INCREF(key); + Py_INCREF(value); if (insertdict(mp, key, hash, value)) { Py_DECREF(d); return NULL; @@ -1936,6 +1952,8 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value) } while (_PySet_NextEntry(iterable, &pos, &key, &hash)) { + Py_INCREF(key); + Py_INCREF(value); if (insertdict(mp, key, hash, value)) { Py_DECREF(d); return NULL; @@ -2562,11 +2580,16 @@ dict_merge(PyObject *a, PyObject *b, int override) int err = 0; Py_INCREF(key); Py_INCREF(value); - if (override == 1) + if (override == 1) { + Py_INCREF(key); + Py_INCREF(value); err = insertdict(mp, key, hash, value); + } else { err = _PyDict_Contains_KnownHash(a, key, hash); if (err == 0) { + Py_INCREF(key); + Py_INCREF(value); err = insertdict(mp, key, hash, value); } else if (err > 0) { @@ -2967,7 +2990,10 @@ PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj) if (hash == -1) return NULL; } + if (mp->ma_keys == Py_EMPTY_KEYS) { + Py_INCREF(key); + Py_INCREF(defaultobj); if (insert_to_emptydict(mp, key, hash, defaultobj) < 0) { return NULL; } diff --git a/Python/ceval.c b/Python/ceval.c index 2b7b31c091326..9d3ff74bace6c 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2279,6 +2279,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } TARGET(STORE_SUBSCR) { + PREDICTED(STORE_SUBSCR); + STAT_INC(STORE_SUBSCR, unquickened); PyObject *sub = TOP(); PyObject *container = SECOND(); PyObject *v = THIRD(); @@ -2294,6 +2296,64 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr DISPATCH(); } + TARGET(STORE_SUBSCR_ADAPTIVE) { + if (oparg == 0) { + PyObject *sub = TOP(); + PyObject *container = SECOND(); + next_instr--; + if (_Py_Specialize_StoreSubscr(container, sub, next_instr) < 0) { + goto error; + } + DISPATCH(); + } + else { + STAT_INC(STORE_SUBSCR, deferred); + // oparg is the adaptive cache counter + UPDATE_PREV_INSTR_OPARG(next_instr, oparg - 1); + STAT_DEC(STORE_SUBSCR, unquickened); + JUMP_TO_INSTRUCTION(STORE_SUBSCR); + } + } + + TARGET(STORE_SUBSCR_LIST_INT) { + PyObject *sub = TOP(); + PyObject *list = SECOND(); + PyObject *value = THIRD(); + DEOPT_IF(!PyLong_CheckExact(sub), STORE_SUBSCR); + DEOPT_IF(!PyList_CheckExact(list), STORE_SUBSCR); + + // Ensure nonnegative, zero-or-one-digit ints. + DEOPT_IF(((size_t)Py_SIZE(sub)) > 1, STORE_SUBSCR); + Py_ssize_t index = ((PyLongObject*)sub)->ob_digit[0]; + // Ensure index < len(list) + DEOPT_IF(index >= PyList_GET_SIZE(list), STORE_SUBSCR); + STAT_INC(STORE_SUBSCR, hit); + + PyObject *old_value = PyList_GET_ITEM(list, index); + PyList_SET_ITEM(list, index, value); + STACK_SHRINK(3); + assert(old_value != NULL); + Py_DECREF(old_value); + Py_DECREF(sub); + Py_DECREF(list); + DISPATCH(); + } + + TARGET(STORE_SUBSCR_DICT) { + PyObject *sub = TOP(); + PyObject *dict = SECOND(); + PyObject *value = THIRD(); + DEOPT_IF(!PyDict_CheckExact(dict), STORE_SUBSCR); + STACK_SHRINK(3); + STAT_INC(STORE_SUBSCR, hit); + int err = _PyDict_SetItem_Take2((PyDictObject *)dict, sub, value); + Py_DECREF(dict); + if (err != 0) { + goto error; + } + DISPATCH(); + } + TARGET(DELETE_SUBSCR) { PyObject *sub = TOP(); PyObject *container = SECOND(); @@ -3374,15 +3434,13 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr PyObject *value = TOP(); PyObject *key = SECOND(); PyObject *map; - int err; STACK_SHRINK(2); map = PEEK(oparg); /* dict */ assert(PyDict_CheckExact(map)); - err = PyDict_SetItem(map, key, value); /* map[key] = value */ - Py_DECREF(value); - Py_DECREF(key); - if (err != 0) + /* map[key] = value */ + if (_PyDict_SetItem_Take2((PyDictObject *)map, key, value) != 0) { goto error; + } PREDICT(JUMP_ABSOLUTE); DISPATCH(); } @@ -4909,6 +4967,22 @@ opname ## _miss: \ JUMP_TO_INSTRUCTION(opname); \ } +#define MISS_WITH_OPARG_COUNTER(opname) \ +opname ## _miss: \ + { \ + STAT_INC(opname, miss); \ + uint8_t oparg = _Py_OPARG(next_instr[-1])-1; \ + UPDATE_PREV_INSTR_OPARG(next_instr, oparg); \ + assert(_Py_OPARG(next_instr[-1]) == oparg); \ + if (oparg == 0) /* too many cache misses */ { \ + oparg = ADAPTIVE_CACHE_BACKOFF; \ + next_instr[-1] = _Py_MAKECODEUNIT(opname ## _ADAPTIVE, oparg); \ + STAT_INC(opname, deopt); \ + } \ + STAT_DEC(opname, unquickened); \ + JUMP_TO_INSTRUCTION(opname); \ + } + MISS_WITH_CACHE(LOAD_ATTR) MISS_WITH_CACHE(STORE_ATTR) MISS_WITH_CACHE(LOAD_GLOBAL) @@ -4916,6 +4990,7 @@ MISS_WITH_CACHE(LOAD_METHOD) MISS_WITH_CACHE(CALL_FUNCTION) MISS_WITH_CACHE(BINARY_OP) MISS_WITH_CACHE(BINARY_SUBSCR) +MISS_WITH_OPARG_COUNTER(STORE_SUBSCR) binary_subscr_dict_error: { diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 4703255d79082..903b967c3a52e 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -26,17 +26,20 @@ static void *opcode_targets[256] = { &&TARGET_BINARY_SUBSCR_TUPLE_INT, &&TARGET_BINARY_SUBSCR, &&TARGET_BINARY_SUBSCR_DICT, - &&TARGET_CALL_FUNCTION_ADAPTIVE, - &&TARGET_CALL_FUNCTION_BUILTIN_O, - &&TARGET_CALL_FUNCTION_BUILTIN_FAST, + &&TARGET_STORE_SUBSCR_ADAPTIVE, + &&TARGET_STORE_SUBSCR_LIST_INT, + &&TARGET_STORE_SUBSCR_DICT, &&TARGET_GET_LEN, &&TARGET_MATCH_MAPPING, &&TARGET_MATCH_SEQUENCE, &&TARGET_MATCH_KEYS, - &&TARGET_CALL_FUNCTION_LEN, + &&TARGET_CALL_FUNCTION_ADAPTIVE, &&TARGET_PUSH_EXC_INFO, - &&TARGET_CALL_FUNCTION_ISINSTANCE, + &&TARGET_CALL_FUNCTION_BUILTIN_O, &&TARGET_POP_EXCEPT_AND_RERAISE, + &&TARGET_CALL_FUNCTION_BUILTIN_FAST, + &&TARGET_CALL_FUNCTION_LEN, + &&TARGET_CALL_FUNCTION_ISINSTANCE, &&TARGET_CALL_FUNCTION_PY_SIMPLE, &&TARGET_JUMP_ABSOLUTE_QUICK, &&TARGET_LOAD_ATTR_ADAPTIVE, @@ -45,28 +48,25 @@ static void *opcode_targets[256] = { &&TARGET_LOAD_ATTR_SLOT, &&TARGET_LOAD_ATTR_MODULE, &&TARGET_LOAD_GLOBAL_ADAPTIVE, - &&TARGET_LOAD_GLOBAL_MODULE, - &&TARGET_LOAD_GLOBAL_BUILTIN, - &&TARGET_LOAD_METHOD_ADAPTIVE, &&TARGET_WITH_EXCEPT_START, &&TARGET_GET_AITER, &&TARGET_GET_ANEXT, &&TARGET_BEFORE_ASYNC_WITH, &&TARGET_BEFORE_WITH, &&TARGET_END_ASYNC_FOR, + &&TARGET_LOAD_GLOBAL_MODULE, + &&TARGET_LOAD_GLOBAL_BUILTIN, + &&TARGET_LOAD_METHOD_ADAPTIVE, &&TARGET_LOAD_METHOD_CACHED, &&TARGET_LOAD_METHOD_CLASS, + &&TARGET_STORE_SUBSCR, + &&TARGET_DELETE_SUBSCR, &&TARGET_LOAD_METHOD_MODULE, &&TARGET_LOAD_METHOD_NO_DICT, &&TARGET_STORE_ATTR_ADAPTIVE, - &&TARGET_STORE_SUBSCR, - &&TARGET_DELETE_SUBSCR, &&TARGET_STORE_ATTR_INSTANCE_VALUE, &&TARGET_STORE_ATTR_SLOT, &&TARGET_STORE_ATTR_WITH_HINT, - &&TARGET_LOAD_FAST__LOAD_FAST, - &&TARGET_STORE_FAST__LOAD_FAST, - &&TARGET_LOAD_FAST__LOAD_CONST, &&TARGET_GET_ITER, &&TARGET_GET_YIELD_FROM_ITER, &&TARGET_PRINT_EXPR, @@ -74,13 +74,13 @@ static void *opcode_targets[256] = { &&TARGET_YIELD_FROM, &&TARGET_GET_AWAITABLE, &&TARGET_LOAD_ASSERTION_ERROR, + &&TARGET_LOAD_FAST__LOAD_FAST, + &&TARGET_STORE_FAST__LOAD_FAST, + &&TARGET_LOAD_FAST__LOAD_CONST, &&TARGET_LOAD_CONST__LOAD_FAST, &&TARGET_STORE_FAST__STORE_FAST, &&_unknown_opcode, &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, &&TARGET_LIST_TO_TUPLE, &&TARGET_RETURN_VALUE, &&TARGET_IMPORT_STAR, diff --git a/Python/specialize.c b/Python/specialize.c index 06b076429f57c..130da008ad8ce 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -125,6 +125,7 @@ _Py_GetSpecializationStats(void) { err += add_stat_dict(stats, LOAD_GLOBAL, "load_global"); err += add_stat_dict(stats, LOAD_METHOD, "load_method"); err += add_stat_dict(stats, BINARY_SUBSCR, "binary_subscr"); + err += add_stat_dict(stats, STORE_SUBSCR, "store_subscr"); err += add_stat_dict(stats, STORE_ATTR, "store_attr"); err += add_stat_dict(stats, CALL_FUNCTION, "call_function"); err += add_stat_dict(stats, BINARY_OP, "binary_op"); @@ -182,6 +183,7 @@ _Py_PrintSpecializationStats(void) print_stats(out, &_specialization_stats[LOAD_GLOBAL], "load_global"); print_stats(out, &_specialization_stats[LOAD_METHOD], "load_method"); print_stats(out, &_specialization_stats[BINARY_SUBSCR], "binary_subscr"); + print_stats(out, &_specialization_stats[STORE_SUBSCR], "store_subscr"); print_stats(out, &_specialization_stats[STORE_ATTR], "store_attr"); print_stats(out, &_specialization_stats[CALL_FUNCTION], "call_function"); print_stats(out, &_specialization_stats[BINARY_OP], "binary_op"); @@ -233,6 +235,7 @@ static uint8_t adaptive_opcodes[256] = { [LOAD_GLOBAL] = LOAD_GLOBAL_ADAPTIVE, [LOAD_METHOD] = LOAD_METHOD_ADAPTIVE, [BINARY_SUBSCR] = BINARY_SUBSCR_ADAPTIVE, + [STORE_SUBSCR] = STORE_SUBSCR_ADAPTIVE, [CALL_FUNCTION] = CALL_FUNCTION_ADAPTIVE, [STORE_ATTR] = STORE_ATTR_ADAPTIVE, [BINARY_OP] = BINARY_OP_ADAPTIVE, @@ -244,6 +247,7 @@ static uint8_t cache_requirements[256] = { [LOAD_GLOBAL] = 2, /* _PyAdaptiveEntry and _PyLoadGlobalCache */ [LOAD_METHOD] = 3, /* _PyAdaptiveEntry, _PyAttrCache and _PyObjectCache */ [BINARY_SUBSCR] = 2, /* _PyAdaptiveEntry, _PyObjectCache */ + [STORE_SUBSCR] = 0, [CALL_FUNCTION] = 2, /* _PyAdaptiveEntry and _PyObjectCache/_PyCallCache */ [STORE_ATTR] = 2, /* _PyAdaptiveEntry and _PyAttrCache */ [BINARY_OP] = 1, // _PyAdaptiveEntry @@ -1228,6 +1232,53 @@ _Py_Specialize_BinarySubscr( return 0; } +int +_Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT *instr) +{ + PyTypeObject *container_type = Py_TYPE(container); + if (container_type == &PyList_Type) { + if (PyLong_CheckExact(sub)) { + if ((Py_SIZE(sub) == 0 || Py_SIZE(sub) == 1) + && ((PyLongObject *)sub)->ob_digit[0] < PyList_GET_SIZE(container)) + { + *instr = _Py_MAKECODEUNIT(STORE_SUBSCR_LIST_INT, + initial_counter_value()); + goto success; + } + else { + SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OUT_OF_RANGE); + goto fail; + } + } + else if (PySlice_Check(sub)) { + SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_LIST_SLICE); + goto fail; + } + else { + SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER); + goto fail; + } + } + else if (container_type == &PyDict_Type) { + *instr = _Py_MAKECODEUNIT(STORE_SUBSCR_DICT, + initial_counter_value()); + goto success; + } + else { + SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER); + goto fail; + } +fail: + STAT_INC(STORE_SUBSCR, specialization_failure); + assert(!PyErr_Occurred()); + *instr = _Py_MAKECODEUNIT(_Py_OPCODE(*instr), ADAPTIVE_CACHE_BACKOFF); + return 0; +success: + STAT_INC(STORE_SUBSCR, specialization_success); + assert(!PyErr_Occurred()); + return 0; +} + static int specialize_class_call( PyObject *callable, _Py_CODEUNIT *instr, From webhook-mailer at python.org Fri Nov 19 09:10:46 2021 From: webhook-mailer at python.org (tiran) Date: Fri, 19 Nov 2021 14:10:46 -0000 Subject: [Python-checkins] bpo-45774: Autoconfiscate SQLite detection (GH-29507) Message-ID: https://github.com/python/cpython/commit/29e5874d5a9205c488f783356d0cf3f115399327 commit: 29e5874d5a9205c488f783356d0cf3f115399327 branch: main author: Erlend Egeberg Aasland committer: tiran date: 2021-11-19T15:10:41+01:00 summary: bpo-45774: Autoconfiscate SQLite detection (GH-29507) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Build/2021-11-09-23-30-12.bpo-45774.Mwm3ZR.rst M Makefile.pre.in M Modules/Setup M Modules/Setup.stdlib.in M configure M configure.ac M pyconfig.h.in M setup.py diff --git a/Makefile.pre.in b/Makefile.pre.in index 1afd9e1331949..2e42d53d5b986 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -2490,6 +2490,7 @@ MODULE__SHA512_DEPS=$(srcdir)/Modules/hashlib.h MODULE__SOCKET_DEPS=$(srcdir)/Modules/socketmodule.h MODULE__SSL_DEPS=$(srcdir)/Modules/_ssl.h $(srcdir)/Modules/_ssl/cert.c $(srcdir)/Modules/_ssl/debughelpers.c $(srcdir)/Modules/_ssl/misc.c $(srcdir)/Modules/_ssl_data.h $(srcdir)/Modules/_ssl_data_111.h $(srcdir)/Modules/_ssl_data_300.h $(srcdir)/Modules/socketmodule.h MODULE__TESTCAPI_DEPS=$(srcdir)/Modules/testcapi_long.h +MODULE__SQLITE3_DEPS=$(srcdir)/Modules/_sqlite/connection.h $(srcdir)/Modules/_sqlite/cursor.h $(srcdir)/Modules/_sqlite/microprotocols.h $(srcdir)/Modules/_sqlite/module.h $(srcdir)/Modules/_sqlite/prepare_protocol.h $(srcdir)/Modules/_sqlite/row.h $(srcdir)/Modules/_sqlite/util.h # IF YOU PUT ANYTHING HERE IT WILL GO AWAY # Local Variables: diff --git a/Misc/NEWS.d/next/Build/2021-11-09-23-30-12.bpo-45774.Mwm3ZR.rst b/Misc/NEWS.d/next/Build/2021-11-09-23-30-12.bpo-45774.Mwm3ZR.rst new file mode 100644 index 0000000000000..09095ab2cf9f5 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-09-23-30-12.bpo-45774.Mwm3ZR.rst @@ -0,0 +1,2 @@ +The build dependencies for :mod:`sqlite3` are now detected by ``configure`` and +``pkg-config``. Patch by Erlend E. Aasland. diff --git a/Modules/Setup b/Modules/Setup index 414c6af4b69c2..f8c90ea77721d 100644 --- a/Modules/Setup +++ b/Modules/Setup @@ -227,7 +227,6 @@ time timemodule.c #_dbm _dbmmodule.c -lgdbm_compat -DUSE_GDBM_COMPAT #_gdbm _gdbmmodule.c -lgdbm #_lzma _lzmamodule.c -llzma -#_sqlite3 _sqlite/connection.c _sqlite/cursor.c _sqlite/microprotocols.c _sqlite/module.c _sqlite/prepare_protocol.c _sqlite/row.c _sqlite/statement.c _sqlite/util.c -lsqlite3 #_uuid _uuidmodule.c -luuid #zlib zlibmodule.c -lz diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 0722eae87a358..2e87b032e35e8 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -53,3 +53,9 @@ # Linux and FreeBSD, needs sys/soundcard.h or linux/soundcard.h @MODULE_OSSAUDIODEV_TRUE at ossaudiodev ossaudiodev.c + + +############################################################################ +# Modules with third party dependencies +# + at MODULE__SQLITE3_TRUE@_sqlite3 _sqlite/connection.c _sqlite/cursor.c _sqlite/microprotocols.c _sqlite/module.c _sqlite/prepare_protocol.c _sqlite/row.c _sqlite/statement.c _sqlite/util.c diff --git a/configure b/configure index fc7b8dc5968ab..657c71dca62bd 100755 --- a/configure +++ b/configure @@ -624,6 +624,8 @@ ac_includes_default="\ ac_subst_vars='LTLIBOBJS MODULE_BLOCK +MODULE__SQLITE3_FALSE +MODULE__SQLITE3_TRUE MODULE__DECIMAL_FALSE MODULE__DECIMAL_TRUE MODULE__ELEMENTTREE_FALSE @@ -669,6 +671,8 @@ DFLAGS DTRACE TCLTK_LIBS TCLTK_INCLUDES +LIBSQLITE3_LIBS +LIBSQLITE3_CFLAGS LIBMPDEC_INTERNAL LIBMPDEC_LDFLAGS LIBMPDEC_CFLAGS @@ -895,7 +899,9 @@ LDFLAGS LIBS CPPFLAGS CPP -PROFILE_TASK' +PROFILE_TASK +LIBSQLITE3_CFLAGS +LIBSQLITE3_LIBS' # Initialize some variables set by options. @@ -1669,6 +1675,10 @@ Some influential environment variables: CPP C preprocessor PROFILE_TASK Python args for PGO generation task + LIBSQLITE3_CFLAGS + C compiler flags for LIBSQLITE3, overriding pkg-config + LIBSQLITE3_LIBS + linker flags for LIBSQLITE3, overriding pkg-config Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. @@ -10930,12 +10940,229 @@ if test "$have_glibc_memmove_bug" = yes; then as_fn_append LIBMPDEC_CFLAGS " -U_FORTIFY_SOURCE" fi + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBSQLITE3" >&5 +$as_echo_n "checking for LIBSQLITE3... " >&6; } + +if test -n "$LIBSQLITE3_CFLAGS"; then + pkg_cv_LIBSQLITE3_CFLAGS="$LIBSQLITE3_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sqlite3 >= 3.7.15\""; } >&5 + ($PKG_CONFIG --exists --print-errors "sqlite3 >= 3.7.15") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBSQLITE3_CFLAGS=`$PKG_CONFIG --cflags "sqlite3 >= 3.7.15" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LIBSQLITE3_LIBS"; then + pkg_cv_LIBSQLITE3_LIBS="$LIBSQLITE3_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sqlite3 >= 3.7.15\""; } >&5 + ($PKG_CONFIG --exists --print-errors "sqlite3 >= 3.7.15") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBSQLITE3_LIBS=`$PKG_CONFIG --libs "sqlite3 >= 3.7.15" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LIBSQLITE3_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "sqlite3 >= 3.7.15" 2>&1` + else + LIBSQLITE3_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "sqlite3 >= 3.7.15" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LIBSQLITE3_PKG_ERRORS" >&5 + + + LIBSQLITE3_LIBS="-lsqlite3" + LIBSQLITE3_CFLAGS= + + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + LIBSQLITE3_LIBS="-lsqlite3" + LIBSQLITE3_CFLAGS= + + +else + LIBSQLITE3_CFLAGS=$pkg_cv_LIBSQLITE3_CFLAGS + LIBSQLITE3_LIBS=$pkg_cv_LIBSQLITE3_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi +as_fn_append LIBSQLITE3_CFLAGS ' -I$(srcdir)/Modules/_sqlite' + +save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS +CPPFLAGS="$LIBSQLITE3_CFLAGS $CFLAGS" +LDFLAGS="$LIBSQLITE3_LIBS $LDFLAGS" + +ac_fn_c_check_header_mongrel "$LINENO" "sqlite3.h" "ac_cv_header_sqlite3_h" "$ac_includes_default" +if test "x$ac_cv_header_sqlite3_h" = xyes; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sqlite3_open_v2 in -lsqlite3" >&5 +$as_echo_n "checking for sqlite3_open_v2 in -lsqlite3... " >&6; } +if ${ac_cv_lib_sqlite3_sqlite3_open_v2+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsqlite3 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char sqlite3_open_v2 (); +int +main () +{ +return sqlite3_open_v2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_sqlite3_sqlite3_open_v2=yes +else + ac_cv_lib_sqlite3_sqlite3_open_v2=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sqlite3_sqlite3_open_v2" >&5 +$as_echo "$ac_cv_lib_sqlite3_sqlite3_open_v2" >&6; } +if test "x$ac_cv_lib_sqlite3_sqlite3_open_v2" = xyes; then : + + have_sqlite3=yes + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + + #include + #if SQLITE_VERSION_NUMBER < 3007015 + # error "SQLite 3.7.15 or higher required" + #endif + +int +main () +{ + + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + have_supported_sqlite3=yes +else + have_supported_sqlite3=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +else + have_sqlite3=no +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sqlite3_load_extension in -lsqlite3" >&5 +$as_echo_n "checking for sqlite3_load_extension in -lsqlite3... " >&6; } +if ${ac_cv_lib_sqlite3_sqlite3_load_extension+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsqlite3 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char sqlite3_load_extension (); +int +main () +{ +return sqlite3_load_extension (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_sqlite3_sqlite3_load_extension=yes +else + ac_cv_lib_sqlite3_sqlite3_load_extension=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sqlite3_sqlite3_load_extension" >&5 +$as_echo "$ac_cv_lib_sqlite3_sqlite3_load_extension" >&6; } +if test "x$ac_cv_lib_sqlite3_sqlite3_load_extension" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBSQLITE3 1 +_ACEOF + + LIBS="-lsqlite3 $LIBS" + +fi + + +fi + + + +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS + # Check for support for loadable sqlite extensions { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --enable-loadable-sqlite-extensions" >&5 $as_echo_n "checking for --enable-loadable-sqlite-extensions... " >&6; } # Check whether --enable-loadable-sqlite-extensions was given. if test "${enable_loadable_sqlite_extensions+set}" = set; then : - enableval=$enable_loadable_sqlite_extensions; + enableval=$enable_loadable_sqlite_extensions; if test "x$have_sqlite3_load_extension" = xno; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Your version of SQLite does not support loadable extensions" >&5 +$as_echo "$as_me: WARNING: Your version of SQLite does not support loadable extensions" >&2;} +fi else enable_loadable_sqlite_extensions=no fi @@ -19431,6 +19658,56 @@ fi $as_echo "$py_cv_module__decimal" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _sqlite3" >&5 +$as_echo_n "checking for stdlib extension module _sqlite3... " >&6; } + case $py_stdlib_not_available in #( + *_sqlite3*) : + py_cv_module__sqlite3=n/a ;; #( + *) : + + if test "$have_sqlite3" = "yes"; then : + if test "$have_supported_sqlite3" = "yes"; then : + py_cv_module__sqlite3=yes +else + py_cv_module__sqlite3=missing +fi +else + py_cv_module__sqlite3=disabled + +fi + + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__SQLITE3=$py_cv_module__sqlite3$as_nl" + if test "x$py_cv_module__sqlite3" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE__SQLITE3_CFLAGS=$LIBSQLITE3_CFLAGS$as_nl" + as_fn_append MODULE_BLOCK "MODULE__SQLITE3_LDFLAGS=$LIBSQLITE3_LIBS$as_nl" + if true; then + MODULE__SQLITE3_TRUE= + MODULE__SQLITE3_FALSE='#' +else + MODULE__SQLITE3_TRUE='#' + MODULE__SQLITE3_FALSE= +fi + + +else + + if false; then + MODULE__SQLITE3_TRUE= + MODULE__SQLITE3_FALSE='#' +else + MODULE__SQLITE3_TRUE='#' + MODULE__SQLITE3_FALSE= +fi + + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__sqlite3" >&5 +$as_echo "$py_cv_module__sqlite3" >&6; } + + # substitute multiline block, must come after last PY_STDLIB_MOD() @@ -19583,6 +19860,14 @@ if test -z "${MODULE__DECIMAL_TRUE}" && test -z "${MODULE__DECIMAL_FALSE}"; then as_fn_error $? "conditional \"MODULE__DECIMAL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__SQLITE3_TRUE}" && test -z "${MODULE__SQLITE3_FALSE}"; then + as_fn_error $? "conditional \"MODULE__SQLITE3\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__SQLITE3_TRUE}" && test -z "${MODULE__SQLITE3_FALSE}"; then + as_fn_error $? "conditional \"MODULE__SQLITE3\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 diff --git a/configure.ac b/configure.ac index d2cb67a39cb4a..4bac7ccf2484e 100644 --- a/configure.ac +++ b/configure.ac @@ -3165,12 +3165,52 @@ if test "$have_glibc_memmove_bug" = yes; then AS_VAR_APPEND([LIBMPDEC_CFLAGS], [" -U_FORTIFY_SOURCE"]) fi +dnl Check for SQLite library. Use pkg-config if available. +PKG_CHECK_MODULES( + [LIBSQLITE3], [sqlite3 >= 3.7.15], [], [ + LIBSQLITE3_LIBS="-lsqlite3" + LIBSQLITE3_CFLAGS= + ] +) +AS_VAR_APPEND([LIBSQLITE3_CFLAGS], [' -I$(srcdir)/Modules/_sqlite']) + +dnl bpo-45774/GH-29507: The CPP check in AC_CHECK_HEADER can fail on FreeBSD, +dnl hence CPPFLAGS instead of CFLAGS. We still need to save CFLAGS, because it +dnl is touched by AC_CHECK_HEADER. +AS_VAR_COPY([save_CFLAGS], [CFLAGS]) +AS_VAR_COPY([save_CPPFLAGS], [CPPFLAGS]) +AS_VAR_COPY([save_LDFLAGS], [LDFLAGS]) +AS_VAR_COPY([save_LIBS], [LIBS]) +CPPFLAGS="$LIBSQLITE3_CFLAGS $CFLAGS" +LDFLAGS="$LIBSQLITE3_LIBS $LDFLAGS" + +AC_CHECK_HEADER([sqlite3.h], [ + AC_CHECK_LIB([sqlite3], [sqlite3_open_v2], [ + have_sqlite3=yes + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([ + #include + #if SQLITE_VERSION_NUMBER < 3007015 + # error "SQLite 3.7.15 or higher required" + #endif + ], []) + ], [have_supported_sqlite3=yes], [have_supported_sqlite3=no]) + ], [have_sqlite3=no]) + AC_CHECK_LIB([sqlite3], [sqlite3_load_extension]) +]) + +AS_VAR_COPY([CFLAGS], [save_CFLAGS]) +AS_VAR_COPY([CPPFLAGS], [save_CPPFLAGS]) +AS_VAR_COPY([LDFLAGS], [save_LDFLAGS]) +AS_VAR_COPY([LIBS], [save_LIBS]) + # Check for support for loadable sqlite extensions AC_MSG_CHECKING(for --enable-loadable-sqlite-extensions) AC_ARG_ENABLE(loadable-sqlite-extensions, AS_HELP_STRING([--enable-loadable-sqlite-extensions], [support loadable extensions in _sqlite module, see Doc/library/sqlite3.rst (default is no)]), - [], + [AS_VAR_IF([have_sqlite3_load_extension], [no], + [AC_MSG_WARN([Your version of SQLite does not support loadable extensions])])], [enable_loadable_sqlite_extensions=no]) AC_MSG_RESULT($enable_loadable_sqlite_extensions) @@ -5999,6 +6039,10 @@ PY_STDLIB_MOD([pyexpat], [], [], [$LIBEXPAT_CFLAGS], [$LIBEXPAT_LDFLAGS]) PY_STDLIB_MOD([_elementtree], [], [], [$LIBEXPAT_CFLAGS], []) PY_STDLIB_MOD([_decimal], [], [], [$LIBMPDEC_CFLAGS], [$LIBMPDEC_LDFLAGS]) +PY_STDLIB_MOD([_sqlite3], + [test "$have_sqlite3" = "yes"], + [test "$have_supported_sqlite3" = "yes"], + [$LIBSQLITE3_CFLAGS], [$LIBSQLITE3_LIBS]) # substitute multiline block, must come after last PY_STDLIB_MOD() AC_SUBST([MODULE_BLOCK]) diff --git a/pyconfig.h.in b/pyconfig.h.in index b8f63955e3139..0cc593fdfc569 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -634,6 +634,9 @@ /* Define to 1 if you have the `sendfile' library (-lsendfile). */ #undef HAVE_LIBSENDFILE +/* Define to 1 if you have the `sqlite3' library (-lsqlite3). */ +#undef HAVE_LIBSQLITE3 + /* Define to 1 if you have the header file. */ #undef HAVE_LIBUTIL_H diff --git a/setup.py b/setup.py index a09cf18213f98..040f90af601cc 100644 --- a/setup.py +++ b/setup.py @@ -1371,108 +1371,17 @@ def detect_dbm_gdbm(self): self.missing.append('_gdbm') def detect_sqlite(self): - # The sqlite interface - sqlite_setup_debug = False # verbose debug prints from this script? - - # We hunt for #define SQLITE_VERSION "n.n.n" - sqlite_incdir = sqlite_libdir = None - sqlite_inc_paths = [ '/usr/include', - '/usr/include/sqlite', - '/usr/include/sqlite3', - '/usr/local/include', - '/usr/local/include/sqlite', - '/usr/local/include/sqlite3', - ] - if CROSS_COMPILING: - sqlite_inc_paths = [] - MIN_SQLITE_VERSION_NUMBER = (3, 7, 15) # Issue 40810 - MIN_SQLITE_VERSION = ".".join([str(x) - for x in MIN_SQLITE_VERSION_NUMBER]) - - # Scan the default include directories before the SQLite specific - # ones. This allows one to override the copy of sqlite on OSX, - # where /usr/include contains an old version of sqlite. - if MACOS: - sysroot = macosx_sdk_root() - - for d_ in self.inc_dirs + sqlite_inc_paths: - d = d_ - if MACOS and is_macosx_sdk_path(d): - d = os.path.join(sysroot, d[1:]) - - f = os.path.join(d, "sqlite3.h") - if os.path.exists(f): - if sqlite_setup_debug: print("sqlite: found %s"%f) - with open(f) as file: - incf = file.read() - m = re.search( - r'\s*.*#\s*.*define\s.*SQLITE_VERSION\W*"([\d\.]*)"', incf) - if m: - sqlite_version = m.group(1) - sqlite_version_tuple = tuple([int(x) - for x in sqlite_version.split(".")]) - if sqlite_version_tuple >= MIN_SQLITE_VERSION_NUMBER: - # we win! - if sqlite_setup_debug: - print("%s/sqlite3.h: version %s"%(d, sqlite_version)) - sqlite_incdir = d - break - else: - if sqlite_setup_debug: - print("%s: version %s is too old, need >= %s"%(d, - sqlite_version, MIN_SQLITE_VERSION)) - elif sqlite_setup_debug: - print("sqlite: %s had no SQLITE_VERSION"%(f,)) - - if sqlite_incdir: - sqlite_dirs_to_check = [ - os.path.join(sqlite_incdir, '..', 'lib64'), - os.path.join(sqlite_incdir, '..', 'lib'), - os.path.join(sqlite_incdir, '..', '..', 'lib64'), - os.path.join(sqlite_incdir, '..', '..', 'lib'), - ] - sqlite_libfile = self.compiler.find_library_file( - sqlite_dirs_to_check + self.lib_dirs, 'sqlite3') - if sqlite_libfile: - sqlite_libdir = [os.path.abspath(os.path.dirname(sqlite_libfile))] - - if sqlite_incdir and sqlite_libdir: - sqlite_srcs = [ - '_sqlite/connection.c', - '_sqlite/cursor.c', - '_sqlite/microprotocols.c', - '_sqlite/module.c', - '_sqlite/prepare_protocol.c', - '_sqlite/row.c', - '_sqlite/statement.c', - '_sqlite/util.c', ] - sqlite_defines = [] - - # Enable support for loadable extensions in the sqlite3 module - # if --enable-loadable-sqlite-extensions configure option is used. - if ( - MACOS and - sqlite_incdir == os.path.join(MACOS_SDK_ROOT, "usr/include") and - sysconfig.get_config_var("PY_SQLITE_ENABLE_LOAD_EXTENSION") - ): - raise DistutilsError("System version of SQLite does not support loadable extensions") - - include_dirs = ["Modules/_sqlite"] - # Only include the directory where sqlite was found if it does - # not already exist in set include directories, otherwise you - # can end up with a bad search path order. - if sqlite_incdir not in self.compiler.include_dirs: - include_dirs.append(sqlite_incdir) - # avoid a runtime library path for a system library dir - if sqlite_libdir and sqlite_libdir[0] in self.lib_dirs: - sqlite_libdir = None - self.add(Extension('_sqlite3', sqlite_srcs, - define_macros=sqlite_defines, - include_dirs=include_dirs, - library_dirs=sqlite_libdir, - libraries=["sqlite3",])) - else: - self.missing.append('_sqlite3') + sources = [ + "_sqlite/connection.c", + "_sqlite/cursor.c", + "_sqlite/microprotocols.c", + "_sqlite/module.c", + "_sqlite/prepare_protocol.c", + "_sqlite/row.c", + "_sqlite/statement.c", + "_sqlite/util.c", + ] + self.addext(Extension("_sqlite3", sources=sources)) def detect_platform_specific_exts(self): # Unix-only modules From webhook-mailer at python.org Fri Nov 19 10:16:59 2021 From: webhook-mailer at python.org (markshannon) Date: Fri, 19 Nov 2021 15:16:59 -0000 Subject: [Python-checkins] bpo-45709: Fix tracing when exception is handled. (GH-29638) Message-ID: https://github.com/python/cpython/commit/337cb480e9dc1d27594ebd87a0045d00ec8b1c3a commit: 337cb480e9dc1d27594ebd87a0045d00ec8b1c3a branch: main author: Mark Shannon committer: markshannon date: 2021-11-19T15:16:49Z summary: bpo-45709: Fix tracing when exception is handled. (GH-29638) files: A Misc/NEWS.d/next/Core and Builtins/2021-11-19-13-17-47.bpo-45709.H_t7ut.rst M Lib/test/test_sys_settrace.py M Python/ceval.c diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py index 3fe0bb7f460b9..b565bef4c4423 100644 --- a/Lib/test/test_sys_settrace.py +++ b/Lib/test/test_sys_settrace.py @@ -1137,6 +1137,38 @@ def func(): (7, 'line'), (7, 'return')]) + def test_tracing_exception_raised_in_with(self): + + class NullCtx: + def __enter__(self): + return self + def __exit__(self, *excinfo): + pass + + def func(): + try: + with NullCtx(): + 1/0 + except ZeroDivisionError: + pass + + self.run_and_compare(func, + [(0, 'call'), + (1, 'line'), + (2, 'line'), + (-5, 'call'), + (-4, 'line'), + (-4, 'return'), + (3, 'line'), + (3, 'exception'), + (2, 'line'), + (-3, 'call'), + (-2, 'line'), + (-2, 'return'), + (4, 'line'), + (5, 'line'), + (5, 'return')]) + class SkipLineEventsTraceTestCase(TraceTestCase): """Repeat the trace tests, but with per-line events skipped""" diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-19-13-17-47.bpo-45709.H_t7ut.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-19-13-17-47.bpo-45709.H_t7ut.rst new file mode 100644 index 0000000000000..e3b007048cd6c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-19-13-17-47.bpo-45709.H_t7ut.rst @@ -0,0 +1,2 @@ +Restore behavior from 3.10 when tracing an exception raised within a with +statement. diff --git a/Python/ceval.c b/Python/ceval.c index 9d3ff74bace6c..9e56b50ee844b 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -5093,10 +5093,7 @@ MISS_WITH_OPARG_COUNTER(STORE_SUBSCR) JUMPTO(handler); /* Resume normal execution */ frame->f_state = FRAME_EXECUTING; - frame->f_lasti = handler; - NEXTOPARG(); - PRE_DISPATCH_GOTO(); - DISPATCH_GOTO(); + DISPATCH(); } exiting: From webhook-mailer at python.org Fri Nov 19 10:40:27 2021 From: webhook-mailer at python.org (iritkatriel) Date: Fri, 19 Nov 2021 15:40:27 -0000 Subject: [Python-checkins] Fix link to exception handling notes (GH-29617) Message-ID: https://github.com/python/cpython/commit/d64659d8cdd90bf52950563c945b30b5f0ca8dd2 commit: d64659d8cdd90bf52950563c945b30b5f0ca8dd2 branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-11-19T15:40:18Z summary: Fix link to exception handling notes (GH-29617) files: M Python/compile.c diff --git a/Python/compile.c b/Python/compile.c index 1ae4b6575a7f4..40bd1fde0a9fd 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -6983,7 +6983,7 @@ assemble_emit_exception_table_item(struct assembler *a, int value, int msb) write_except_byte(a, (value&0x3f) | msb); } -/* See Objects/exception_table_notes.txt for details of layout */ +/* See Objects/exception_handling_notes.txt for details of layout */ #define MAX_SIZE_OF_ENTRY 20 static int From webhook-mailer at python.org Fri Nov 19 10:41:04 2021 From: webhook-mailer at python.org (tiran) Date: Fri, 19 Nov 2021 15:41:04 -0000 Subject: [Python-checkins] bpo-45573: Move mandatory core modules to Modules/Setup.bootstrap (GH-29616) Message-ID: https://github.com/python/cpython/commit/7e44dc0ba768451f287a541cd1c85f7d87a41561 commit: 7e44dc0ba768451f287a541cd1c85f7d87a41561 branch: main author: Christian Heimes committer: tiran date: 2021-11-19T16:40:57+01:00 summary: bpo-45573: Move mandatory core modules to Modules/Setup.bootstrap (GH-29616) files: A Misc/NEWS.d/next/Build/2021-11-18-13-31-02.bpo-45573.LCjGB8.rst A Modules/Setup.bootstrap M Makefile.pre.in M Modules/Setup M Modules/Setup.stdlib.in M configure M configure.ac M setup.py diff --git a/Makefile.pre.in b/Makefile.pre.in index 2e42d53d5b986..312e52486f296 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -910,10 +910,12 @@ Makefile Modules/config.c: Makefile.pre \ $(MAKESETUP) \ $(srcdir)/Modules/Setup \ Modules/Setup.local \ + $(srcdir)/Modules/Setup.bootstrap \ Modules/Setup.stdlib $(SHELL) $(MAKESETUP) -c $(srcdir)/Modules/config.c.in \ -s Modules \ Modules/Setup.local \ + $(srcdir)/Modules/Setup.bootstrap \ $(srcdir)/Modules/Setup @mv config.c Modules @echo "The Makefile was updated, you may need to re-run make." @@ -2167,6 +2169,7 @@ libainstall: @DEF_MAKE_RULE@ python-config $(INSTALL_DATA) $(srcdir)/Modules/config.c.in $(DESTDIR)$(LIBPL)/config.c.in $(INSTALL_DATA) Makefile $(DESTDIR)$(LIBPL)/Makefile $(INSTALL_DATA) $(srcdir)/Modules/Setup $(DESTDIR)$(LIBPL)/Setup + $(INSTALL_DATA) $(srcdir)/Modules/Setup.bootstrap $(DESTDIR)$(LIBPL)/Setup.bootstrap $(INSTALL_DATA) Modules/Setup.stdlib $(DESTDIR)$(LIBPL)/Setup.stdlib $(INSTALL_DATA) Modules/Setup.local $(DESTDIR)$(LIBPL)/Setup.local $(INSTALL_DATA) Misc/python.pc $(DESTDIR)$(LIBPC)/python-$(VERSION).pc diff --git a/Misc/NEWS.d/next/Build/2021-11-18-13-31-02.bpo-45573.LCjGB8.rst b/Misc/NEWS.d/next/Build/2021-11-18-13-31-02.bpo-45573.LCjGB8.rst new file mode 100644 index 0000000000000..5f388948fb50f --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-18-13-31-02.bpo-45573.LCjGB8.rst @@ -0,0 +1,2 @@ +Mandatory core modules, that are required to bootstrap Python, are now in +``Modules/Setup.bootstrap``. diff --git a/Modules/Setup b/Modules/Setup index f8c90ea77721d..5a7c232d3c555 100644 --- a/Modules/Setup +++ b/Modules/Setup @@ -111,31 +111,8 @@ PYTHONPATH=$(COREPYTHONPATH) # --- -# Built-in modules required to get a functioning interpreter; -# cannot be built as shared! - -_collections _collectionsmodule.c -_abc _abc.c -_codecs _codecsmodule.c -_functools _functoolsmodule.c -_io -I$(srcdir)/Modules/_io _io/_iomodule.c _io/iobase.c _io/fileio.c _io/bytesio.c _io/bufferedio.c _io/textio.c _io/stringio.c -_locale _localemodule.c -_operator _operator.c -_signal signalmodule.c -_sre _sre.c -_stat _stat.c -_symtable symtablemodule.c -_thread _threadmodule.c -_tracemalloc _tracemalloc.c # See bpo-35053 as to why this is built in. -_weakref _weakref.c -atexit atexitmodule.c -errno errnomodule.c -faulthandler faulthandler.c -itertools itertoolsmodule.c -posix posixmodule.c -pwd pwdmodule.c -time timemodule.c - +# Built-in modules required to get a functioning interpreter are listed in +# Modules/Setup.bootstrap. # --- # The rest of the modules listed in this file are all commented out by diff --git a/Modules/Setup.bootstrap b/Modules/Setup.bootstrap new file mode 100644 index 0000000000000..d543f087b89fc --- /dev/null +++ b/Modules/Setup.bootstrap @@ -0,0 +1,34 @@ +# -*- makefile -*- + +# --- +# Built-in modules required to get a functioning interpreter; +# cannot be built as shared! + +# module C APIs are used in core +atexit atexitmodule.c +faulthandler faulthandler.c +posix posixmodule.c +_signal signalmodule.c +_tracemalloc _tracemalloc.c + +# modules used by importlib, deepfreeze, freeze, runpy, and sysconfig +_codecs _codecsmodule.c +_collections _collectionsmodule.c +errno errnomodule.c +_io _io/_iomodule.c _io/iobase.c _io/fileio.c _io/bytesio.c _io/bufferedio.c _io/textio.c _io/stringio.c +itertools itertoolsmodule.c +_sre _sre.c +_thread _threadmodule.c +time timemodule.c +_weakref _weakref.c + +# commonly used core modules +_abc _abc.c +_functools _functoolsmodule.c +_locale _localemodule.c +_operator _operator.c +_stat _stat.c +_symtable symtablemodule.c + +# for systems without $HOME env, used by site._getuserbase() +pwd pwdmodule.c diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 2e87b032e35e8..3b0d3227bc5b0 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -29,6 +29,9 @@ ############################################################################ # Modules that should always be present (POSIX and Windows): +# needs libm and on some platforms librt + at MODULE__DATETIME_TRUE@_datetime _datetimemodule.c + # _decimal uses libmpdec # either static libmpdec.a from Modules/_decimal/libmpdec or libmpdec.so # with ./configure --with-system-libmpdec diff --git a/configure b/configure index 657c71dca62bd..96005cb63aff0 100755 --- a/configure +++ b/configure @@ -634,6 +634,12 @@ MODULE_PYEXPAT_FALSE MODULE_PYEXPAT_TRUE MODULE_OSSAUDIODEV_FALSE MODULE_OSSAUDIODEV_TRUE +MODULE__DATETIME_FALSE +MODULE__DATETIME_TRUE +MODULE_TIME_FALSE +MODULE_TIME_TRUE +MODULE__IO_FALSE +MODULE__IO_TRUE TEST_MODULES LIBRARY_DEPS STATIC_LIBPYTHON @@ -19456,6 +19462,52 @@ MODULE_BLOCK= + + + if true; then + MODULE__IO_TRUE= + MODULE__IO_FALSE='#' +else + MODULE__IO_TRUE='#' + MODULE__IO_FALSE= +fi + + + as_fn_append MODULE_BLOCK "MODULE__IO_CFLAGS=-I\$(srcdir)/Modules/_io$as_nl" + + + + + if true; then + MODULE_TIME_TRUE= + MODULE_TIME_FALSE='#' +else + MODULE_TIME_TRUE='#' + MODULE_TIME_FALSE= +fi + + + + as_fn_append MODULE_BLOCK "MODULE_TIME_LDFLAGS=$TIMEMODULE_LIB$as_nl" + + + + + if true; then + MODULE__DATETIME_TRUE= + MODULE__DATETIME_FALSE='#' +else + MODULE__DATETIME_TRUE='#' + MODULE__DATETIME_FALSE= +fi + + + + as_fn_append MODULE_BLOCK "MODULE__DATETIME_LDFLAGS=$TIMEMODULE_LIB $LIBM$as_nl" + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module ossaudiodev" >&5 $as_echo_n "checking for stdlib extension module ossaudiodev... " >&6; } case $py_stdlib_not_available in #( @@ -19828,6 +19880,18 @@ LTLIBOBJS=$ac_ltlibobjs +if test -z "${MODULE__IO_TRUE}" && test -z "${MODULE__IO_FALSE}"; then + as_fn_error $? "conditional \"MODULE__IO\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE_TIME_TRUE}" && test -z "${MODULE_TIME_FALSE}"; then + as_fn_error $? "conditional \"MODULE_TIME\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__DATETIME_TRUE}" && test -z "${MODULE__DATETIME_FALSE}"; then + as_fn_error $? "conditional \"MODULE__DATETIME\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE_OSSAUDIODEV_TRUE}" && test -z "${MODULE_OSSAUDIODEV_FALSE}"; then as_fn_error $? "conditional \"MODULE_OSSAUDIODEV\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -21068,7 +21132,7 @@ fi echo "creating Makefile" >&6 $SHELL $srcdir/Modules/makesetup -c $srcdir/Modules/config.c.in \ -s Modules \ - Modules/Setup.local $srcdir/Modules/Setup + Modules/Setup.local $srcdir/Modules/Setup.bootstrap $srcdir/Modules/Setup mv config.c Modules if test -z "$PKG_CONFIG"; then diff --git a/configure.ac b/configure.ac index 4bac7ccf2484e..d4c9bef424265 100644 --- a/configure.ac +++ b/configure.ac @@ -6030,6 +6030,28 @@ AC_DEFUN([PY_STDLIB_MOD], [ m4_popdef([modstate])dnl ]) +dnl Define simple, always enabled stdlib extension module +dnl PY_STDLIB_MOD_SIMPLE([NAME], [CFLAGS], [LDFLAGS]) +dnl cflags and ldflags are optional +AC_DEFUN([PY_STDLIB_MOD_SIMPLE], [ + m4_pushdef([modcond], [MODULE_]m4_toupper([$1]))dnl + AM_CONDITIONAL(modcond, [true]) + m4_ifval([$2], [ + _MODULE_BLOCK_ADD([MODULE_]m4_toupper([$1])[_CFLAGS], [$2]) + ]) + m4_ifval([$3], [ + _MODULE_BLOCK_ADD([MODULE_]m4_toupper([$1])[_LDFLAGS], [$3]) + ]) + m4_popdef([modcond])dnl +]) + +dnl static modules in Modules/Setup.bootstrap +PY_STDLIB_MOD_SIMPLE([_io], [-I\$(srcdir)/Modules/_io], []) +PY_STDLIB_MOD_SIMPLE([time], [], [$TIMEMODULE_LIB]) + +dnl always enabled extension modules +PY_STDLIB_MOD_SIMPLE([_datetime], [], [$TIMEMODULE_LIB $LIBM]) + dnl platform specific extensions PY_STDLIB_MOD([ossaudiodev], [], [test "$ac_cv_header_linux_soundcard_h" = yes -o "$ac_cv_header_sys_soundcard_h" = yes]) @@ -6062,7 +6084,7 @@ fi echo "creating Makefile" >&AS_MESSAGE_FD $SHELL $srcdir/Modules/makesetup -c $srcdir/Modules/config.c.in \ -s Modules \ - Modules/Setup.local $srcdir/Modules/Setup + Modules/Setup.local $srcdir/Modules/Setup.bootstrap $srcdir/Modules/Setup mv config.c Modules if test -z "$PKG_CONFIG"; then diff --git a/setup.py b/setup.py index 040f90af601cc..0b7e7ab0a3061 100644 --- a/setup.py +++ b/setup.py @@ -1006,13 +1006,9 @@ def detect_simple_extensions(self): if lib: time_libs.append(lib) - # time operations and variables - self.add(Extension('time', ['timemodule.c'], - libraries=time_libs)) # libm is needed by delta_new() that uses round() and by accum() that # uses modf(). - self.add(Extension('_datetime', ['_datetimemodule.c'], - libraries=['m'])) + self.addext(Extension('_datetime', ['_datetimemodule.c'])) # zoneinfo module self.add(Extension('_zoneinfo', ['_zoneinfo.c'])) # random number generator implemented in C @@ -1034,8 +1030,6 @@ def detect_simple_extensions(self): self.add(Extension('_opcode', ['_opcode.c'])) # asyncio speedups self.add(Extension("_asyncio", ["_asynciomodule.c"])) - # _abc speedups - self.add(Extension("_abc", ["_abc.c"])) # _queue module self.add(Extension("_queue", ["_queuemodule.c"])) # _statistics module @@ -1054,8 +1048,6 @@ def detect_simple_extensions(self): libs = ['bsd'] self.add(Extension('fcntl', ['fcntlmodule.c'], libraries=libs)) - # pwd(3) - self.add(Extension('pwd', ['pwdmodule.c'])) # grp(3) if not VXWORKS: self.add(Extension('grp', ['grpmodule.c'])) @@ -1510,6 +1502,9 @@ def detect_modules(self): self.configure_compiler() self.init_inc_lib_dirs() + # Some C extensions are built by entries in Modules/Setup.bootstrap. + # These are extensions are required to bootstrap the interpreter or + # build process. self.detect_simple_extensions() if TEST_EXTENSIONS: self.detect_test_extensions() From webhook-mailer at python.org Fri Nov 19 13:07:16 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 19 Nov 2021 18:07:16 -0000 Subject: [Python-checkins] bpo-45507: EOFErrors should be thrown for truncated gzip members (GH-29029) Message-ID: https://github.com/python/cpython/commit/0ff3d95b9875805ac03aeffc37ae4458ce3b8ac0 commit: 0ff3d95b9875805ac03aeffc37ae4458ce3b8ac0 branch: main author: Ruben Vorderman committer: ambv date: 2021-11-19T19:07:05+01:00 summary: bpo-45507: EOFErrors should be thrown for truncated gzip members (GH-29029) files: A Misc/NEWS.d/next/Library/2021-10-18-14-00-01.bpo-45507.lDotNV.rst M Lib/gzip.py M Lib/test/test_gzip.py diff --git a/Lib/gzip.py b/Lib/gzip.py index ac1781042b264..6773ea3eef097 100644 --- a/Lib/gzip.py +++ b/Lib/gzip.py @@ -603,6 +603,9 @@ def decompress(data): do = zlib.decompressobj(wbits=-zlib.MAX_WBITS) # Read all the data except the header decompressed = do.decompress(data[fp.tell():]) + if not do.eof or len(do.unused_data) < 8: + raise EOFError("Compressed file ended before the end-of-stream " + "marker was reached") crc, length = struct.unpack(" https://github.com/python/cpython/commit/d32316a2aacc3b3c4f6f56f96edb09a4437c8bdb commit: d32316a2aacc3b3c4f6f56f96edb09a4437c8bdb branch: main author: Julien Palard committer: ambv date: 2021-11-19T19:11:24+01:00 summary: bpo-42238: [doc]: Hide false positive in make suspicious. (GH-29636) files: M Doc/tools/susp-ignored.csv diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv index 0d9d109c0971e..280e9a63cdcc3 100644 --- a/Doc/tools/susp-ignored.csv +++ b/Doc/tools/susp-ignored.csv @@ -380,3 +380,4 @@ library/tkinter,,::,"grid [ttk::button .frm.btn -text ""Quit"" -command ""destro library/tkinter,,::,ttk::frame library/tkinter,,::,ttk::button library/tkinter,,::,ttk::widget +reference/datamodel,2285,`,"""""""Return the result of the expression `obj[x]`""""""" From webhook-mailer at python.org Fri Nov 19 13:44:00 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 19 Nov 2021 18:44:00 -0000 Subject: [Python-checkins] bpo-19072: Classmethod can wrap other classmethod like descriptors (GH-29634) Message-ID: https://github.com/python/cpython/commit/e34809e1c2a09478f4e0651d551c9c12d3c556ab commit: e34809e1c2a09478f4e0651d551c9c12d3c556ab branch: main author: Raymond Hettinger committer: ambv date: 2021-11-19T19:43:49+01:00 summary: bpo-19072: Classmethod can wrap other classmethod like descriptors (GH-29634) staticmethod() also became callable in Python 3.10. See: b83861f02. files: M Doc/howto/descriptor.rst diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst index 575caeb720f3d..6ce062d0fa853 100644 --- a/Doc/howto/descriptor.rst +++ b/Doc/howto/descriptor.rst @@ -1264,6 +1264,9 @@ Using the non-data descriptor protocol, a pure Python version of def __get__(self, obj, objtype=None): return self.f + def __call__(self, *args, **kwds): + return self.f(*args, **kwds) + .. testcode:: :hide: @@ -1272,6 +1275,8 @@ Using the non-data descriptor protocol, a pure Python version of def f(x): return x * 10 + wrapped_ord = StaticMethod(ord) + .. doctest:: :hide: @@ -1279,6 +1284,8 @@ Using the non-data descriptor protocol, a pure Python version of 30 >>> E_sim().f(3) 30 + >>> wrapped_ord('A') + 65 Class methods @@ -1344,7 +1351,7 @@ Using the non-data descriptor protocol, a pure Python version of if cls is None: cls = type(obj) if hasattr(type(self.f), '__get__'): - return self.f.__get__(cls) + return self.f.__get__(cls, cls) return MethodType(self.f, cls) .. testcode:: From webhook-mailer at python.org Fri Nov 19 13:51:59 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 19 Nov 2021 18:51:59 -0000 Subject: [Python-checkins] [3.9] bpo-45806: Fix recovery from stack overflow for 3.9. Again. (GH-29640) Message-ID: https://github.com/python/cpython/commit/4296396db017d782d3aa16100b366748c9ea4a04 commit: 4296396db017d782d3aa16100b366748c9ea4a04 branch: 3.9 author: Mark Shannon committer: ambv date: 2021-11-19T19:51:50+01:00 summary: [3.9] bpo-45806: Fix recovery from stack overflow for 3.9. Again. (GH-29640) Co-authored-by: ?ukasz Langa files: A Misc/NEWS.d/next/Core and Builtins/2021-11-19-19-21-48.bpo-45806.DflDMe.rst M Include/internal/pycore_ceval.h M Lib/test/test_exceptions.py M Lib/test/test_sys.py M Python/ceval.c M Python/errors.c M Python/sysmodule.c diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index 18c8f027af16e..e7ace9bd01c2a 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -90,24 +90,8 @@ static inline int _Py_EnterRecursiveCall_inline(const char *where) { #define Py_EnterRecursiveCall(where) _Py_EnterRecursiveCall_inline(where) -/* Compute the "lower-water mark" for a recursion limit. When - * Py_LeaveRecursiveCall() is called with a recursion depth below this mark, - * the overflowed flag is reset to 0. */ -static inline int _Py_RecursionLimitLowerWaterMark(int limit) { - if (limit > 200) { - return (limit - 50); - } - else { - return (3 * (limit >> 2)); - } -} - static inline void _Py_LeaveRecursiveCall(PyThreadState *tstate) { tstate->recursion_depth--; - int limit = tstate->interp->ceval.recursion_limit; - if (tstate->recursion_depth < _Py_RecursionLimitLowerWaterMark(limit)) { - tstate->overflowed = 0; - } } static inline void _Py_LeaveRecursiveCall_inline(void) { diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 4a7ca60b39bc5..5168b0b8a0831 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -1213,7 +1213,7 @@ def gen(): # tstate->recursion_depth is equal to (recursion_limit - 1) # and is equal to recursion_limit when _gen_throw() calls # PyErr_NormalizeException(). - recurse(setrecursionlimit(depth + 2) - depth - 1) + recurse(setrecursionlimit(depth + 2) - depth) finally: sys.setrecursionlimit(recursionlimit) print('Done.') @@ -1243,6 +1243,52 @@ def test_recursion_normalizing_infinite_exception(self): b'while normalizing an exception', err) self.assertIn(b'Done.', out) + def test_recursion_in_except_handler(self): + + def set_relative_recursion_limit(n): + depth = 1 + while True: + try: + sys.setrecursionlimit(depth) + except RecursionError: + depth += 1 + else: + break + sys.setrecursionlimit(depth+n) + + def recurse_in_except(): + try: + 1/0 + except: + recurse_in_except() + + def recurse_after_except(): + try: + 1/0 + except: + pass + recurse_after_except() + + def recurse_in_body_and_except(): + try: + recurse_in_body_and_except() + except: + recurse_in_body_and_except() + + recursionlimit = sys.getrecursionlimit() + try: + set_relative_recursion_limit(10) + for func in (recurse_in_except, recurse_after_except, recurse_in_body_and_except): + with self.subTest(func=func): + try: + func() + except RecursionError: + pass + else: + self.fail("Should have raised a RecursionError") + finally: + sys.setrecursionlimit(recursionlimit) + @cpython_only def test_recursion_normalizing_with_no_memory(self): # Issue #30697. Test that in the abort that occurs when there is no diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 450e3920efa7c..2f1e5e971e8e9 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -260,42 +260,10 @@ def set_recursion_limit_at_depth(depth, limit): sys.setrecursionlimit(1000) for limit in (10, 25, 50, 75, 100, 150, 200): - # formula extracted from _Py_RecursionLimitLowerWaterMark() - if limit > 200: - depth = limit - 50 - else: - depth = limit * 3 // 4 - set_recursion_limit_at_depth(depth, limit) + set_recursion_limit_at_depth(limit, limit) finally: sys.setrecursionlimit(oldlimit) - # The error message is specific to CPython - @test.support.cpython_only - def test_recursionlimit_fatalerror(self): - # A fatal error occurs if a second recursion limit is hit when recovering - # from a first one. - code = textwrap.dedent(""" - import sys - - def f(): - try: - f() - except RecursionError: - f() - - sys.setrecursionlimit(%d) - f()""") - with test.support.SuppressCrashReport(): - for i in (50, 1000): - sub = subprocess.Popen([sys.executable, '-c', code % i], - stderr=subprocess.PIPE) - err = sub.communicate()[1] - self.assertTrue(sub.returncode, sub.returncode) - self.assertIn( - b"Fatal Python error: _Py_CheckRecursiveCall: " - b"Cannot recover from stack overflow", - err) - def test_getwindowsversion(self): # Raise SkipTest if sys doesn't have getwindowsversion attribute test.support.get_attribute(sys, "getwindowsversion") diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-19-19-21-48.bpo-45806.DflDMe.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-19-19-21-48.bpo-45806.DflDMe.rst new file mode 100644 index 0000000000000..f8c47cae4b0b9 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-19-19-21-48.bpo-45806.DflDMe.rst @@ -0,0 +1,5 @@ +Re-introduced fix that allows recovery from stack overflow without crashing +the interpreter. The original fix as part of :issue:`42500` was reverted +(see release notes for Python 3.9.4) since it introduced an ABI change in a +bugfix release which is not allowed. The new fix doesn't introduce any ABI +changes. Patch by Mark Shannon. diff --git a/Python/ceval.c b/Python/ceval.c index 86a5d81b7669a..9a61f8a3c3cf5 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -797,19 +797,21 @@ _Py_CheckRecursiveCall(PyThreadState *tstate, const char *where) /* Somebody asked that we don't check for recursion. */ return 0; if (tstate->overflowed) { - if (tstate->recursion_depth > recursion_limit + 50) { + if (tstate->recursion_depth > recursion_limit + 50 || tstate->overflowed > 50) { /* Overflowing while handling an overflow. Give up. */ Py_FatalError("Cannot recover from stack overflow."); } - return 0; } - if (tstate->recursion_depth > recursion_limit) { - --tstate->recursion_depth; - tstate->overflowed = 1; - _PyErr_Format(tstate, PyExc_RecursionError, - "maximum recursion depth exceeded%s", - where); - return -1; + else { + if (tstate->recursion_depth > recursion_limit) { + tstate->overflowed++; + _PyErr_Format(tstate, PyExc_RecursionError, + "maximum recursion depth exceeded%s", + where); + tstate->overflowed--; + --tstate->recursion_depth; + return -1; + } } return 0; } diff --git a/Python/errors.c b/Python/errors.c index 40d8e68bde783..79278764cc512 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -317,12 +317,14 @@ _PyErr_NormalizeException(PyThreadState *tstate, PyObject **exc, PyObject **val, PyObject **tb) { int recursion_depth = 0; + tstate->overflowed++; PyObject *type, *value, *initial_tb; restart: type = *exc; if (type == NULL) { /* There was no exception, so nothing to do. */ + tstate->overflowed--; return; } @@ -374,6 +376,7 @@ _PyErr_NormalizeException(PyThreadState *tstate, PyObject **exc, } *exc = type; *val = value; + tstate->overflowed--; return; error: diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 3e4115fe8e1f9..a52b299474c5d 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -17,7 +17,7 @@ Data members: #include "Python.h" #include "code.h" #include "frameobject.h" // PyFrame_GetBack() -#include "pycore_ceval.h" // _Py_RecursionLimitLowerWaterMark() +#include "pycore_ceval.h" #include "pycore_initconfig.h" #include "pycore_object.h" #include "pycore_pathconfig.h" @@ -1160,7 +1160,6 @@ static PyObject * sys_setrecursionlimit_impl(PyObject *module, int new_limit) /*[clinic end generated code: output=35e1c64754800ace input=b0f7a23393924af3]*/ { - int mark; PyThreadState *tstate = _PyThreadState_GET(); if (new_limit < 1) { @@ -1178,8 +1177,7 @@ sys_setrecursionlimit_impl(PyObject *module, int new_limit) Reject too low new limit if the current recursion depth is higher than the new low-water mark. Otherwise it may not be possible anymore to reset the overflowed flag to 0. */ - mark = _Py_RecursionLimitLowerWaterMark(new_limit); - if (tstate->recursion_depth >= mark) { + if (tstate->recursion_depth >= new_limit) { _PyErr_Format(tstate, PyExc_RecursionError, "cannot set the recursion limit to %i at " "the recursion depth %i: the limit is too low", From webhook-mailer at python.org Fri Nov 19 13:53:55 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 19 Nov 2021 18:53:55 -0000 Subject: [Python-checkins] [3.9] bpo-45838: Fix incorrect line numbers in Tools/gdb/libpython.py (GH-29628) Message-ID: https://github.com/python/cpython/commit/2a32dbf110cf80ec9a00290ea6bc84f409948cb0 commit: 2a32dbf110cf80ec9a00290ea6bc84f409948cb0 branch: 3.9 author: Sam Gross committer: ambv date: 2021-11-19T19:53:46+01:00 summary: [3.9] bpo-45838: Fix incorrect line numbers in Tools/gdb/libpython.py (GH-29628) The line number calculation in libpython.py did not properly handle negative (signed) line table deltas. files: A Misc/NEWS.d/next/Tools-Demos/2021-11-18-11-20-21.bpo-45838.TH6mwc.rst M Lib/test/test_gdb.py M Tools/gdb/libpython.py diff --git a/Lib/test/test_gdb.py b/Lib/test/test_gdb.py index 5f554897f86a0..b3aa855a5bd5e 100644 --- a/Lib/test/test_gdb.py +++ b/Lib/test/test_gdb.py @@ -955,6 +955,31 @@ def __init__(self): self.assertRegex(gdb_output, r" + File "", line 7, in foo + File "", line 11, in +''') + class PyPrintTests(DebuggerTests): @unittest.skipIf(python_is_optimized(), diff --git a/Misc/NEWS.d/next/Tools-Demos/2021-11-18-11-20-21.bpo-45838.TH6mwc.rst b/Misc/NEWS.d/next/Tools-Demos/2021-11-18-11-20-21.bpo-45838.TH6mwc.rst new file mode 100644 index 0000000000000..b6dafc5c3edc4 --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2021-11-18-11-20-21.bpo-45838.TH6mwc.rst @@ -0,0 +1 @@ +Fix line number calculation when debugging Python with GDB. diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py index aeaa63e540d8b..45be5ab9bb9b3 100755 --- a/Tools/gdb/libpython.py +++ b/Tools/gdb/libpython.py @@ -659,7 +659,10 @@ def addr2line(self, addrq): addr += ord(addr_incr) if addr > addrq: return lineno - lineno += ord(line_incr) + line_delta = ord(line_incr) + if line_delta >= 128: + line_delta -= 256 + lineno += line_delta return lineno From webhook-mailer at python.org Fri Nov 19 13:55:29 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 19 Nov 2021 18:55:29 -0000 Subject: [Python-checkins] bpo-45837: Note tiltangle is not deprecated, it's really settiltangle (GH-29630) Message-ID: https://github.com/python/cpython/commit/e8d41eea7a73a91cf1da2a4e60245902226bc599 commit: e8d41eea7a73a91cf1da2a4e60245902226bc599 branch: 3.9 author: Hugo van Kemenade committer: ambv date: 2021-11-19T19:55:15+01:00 summary: bpo-45837: Note tiltangle is not deprecated, it's really settiltangle (GH-29630) files: M Lib/turtle.py diff --git a/Lib/turtle.py b/Lib/turtle.py index 793b35e2403d1..9c8f6ced25084 100644 --- a/Lib/turtle.py +++ b/Lib/turtle.py @@ -2877,7 +2877,8 @@ def tiltangle(self, angle=None): between the orientation of the turtleshape and the heading of the turtle (its direction of movement). - Deprecated since Python 3.1 + (Incorrectly marked as deprecated since Python 3.1, it is really + settiltangle that is deprecated.) Examples (for a Turtle instance named turtle): >>> turtle.shape("circle") From webhook-mailer at python.org Fri Nov 19 13:55:49 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 19 Nov 2021 18:55:49 -0000 Subject: [Python-checkins] bpo-45837: Note tiltangle is not deprecated, it's really settiltangle (GH-29629) Message-ID: https://github.com/python/cpython/commit/9501e8d3a339c5a9217b7d90275d2a8c8cba5d13 commit: 9501e8d3a339c5a9217b7d90275d2a8c8cba5d13 branch: 3.10 author: Hugo van Kemenade committer: ambv date: 2021-11-19T19:55:40+01:00 summary: bpo-45837: Note tiltangle is not deprecated, it's really settiltangle (GH-29629) files: M Lib/turtle.py diff --git a/Lib/turtle.py b/Lib/turtle.py index 7e36c2c51d3be..f3b320b90caeb 100644 --- a/Lib/turtle.py +++ b/Lib/turtle.py @@ -2877,7 +2877,8 @@ def tiltangle(self, angle=None): between the orientation of the turtleshape and the heading of the turtle (its direction of movement). - Deprecated since Python 3.1 + (Incorrectly marked as deprecated since Python 3.1, it is really + settiltangle that is deprecated.) Examples (for a Turtle instance named turtle): >>> turtle.shape("circle") From webhook-mailer at python.org Fri Nov 19 14:12:25 2021 From: webhook-mailer at python.org (ambv) Date: Fri, 19 Nov 2021 19:12:25 -0000 Subject: [Python-checkins] bpo-19072: Classmethod can wrap other classmethod like descriptors (GH-29634) (GH-29643) Message-ID: https://github.com/python/cpython/commit/bbe3c57c865439f2194eb760a4362b5506d221a7 commit: bbe3c57c865439f2194eb760a4362b5506d221a7 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-19T20:12:16+01:00 summary: bpo-19072: Classmethod can wrap other classmethod like descriptors (GH-29634) (GH-29643) staticmethod() also became callable in Python 3.10. See: b83861f02. (cherry picked from commit e34809e1c2a09478f4e0651d551c9c12d3c556ab) Co-authored-by: Raymond Hettinger files: M Doc/howto/descriptor.rst diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst index 575caeb720f3d..6ce062d0fa853 100644 --- a/Doc/howto/descriptor.rst +++ b/Doc/howto/descriptor.rst @@ -1264,6 +1264,9 @@ Using the non-data descriptor protocol, a pure Python version of def __get__(self, obj, objtype=None): return self.f + def __call__(self, *args, **kwds): + return self.f(*args, **kwds) + .. testcode:: :hide: @@ -1272,6 +1275,8 @@ Using the non-data descriptor protocol, a pure Python version of def f(x): return x * 10 + wrapped_ord = StaticMethod(ord) + .. doctest:: :hide: @@ -1279,6 +1284,8 @@ Using the non-data descriptor protocol, a pure Python version of 30 >>> E_sim().f(3) 30 + >>> wrapped_ord('A') + 65 Class methods @@ -1344,7 +1351,7 @@ Using the non-data descriptor protocol, a pure Python version of if cls is None: cls = type(obj) if hasattr(type(self.f), '__get__'): - return self.f.__get__(cls) + return self.f.__get__(cls, cls) return MethodType(self.f, cls) .. testcode:: From webhook-mailer at python.org Fri Nov 19 14:20:41 2021 From: webhook-mailer at python.org (tiran) Date: Fri, 19 Nov 2021 19:20:41 -0000 Subject: [Python-checkins] bpo-45847: Port builtin hashlib extensions to PY_STDLIB_MOD (GH-29642) Message-ID: https://github.com/python/cpython/commit/c8c21bdd199f9feb75fc6cdb398a686dc133b99f commit: c8c21bdd199f9feb75fc6cdb398a686dc133b99f branch: main author: Christian Heimes committer: tiran date: 2021-11-19T20:20:32+01:00 summary: bpo-45847: Port builtin hashlib extensions to PY_STDLIB_MOD (GH-29642) files: A Misc/NEWS.d/next/Build/2021-11-19-17-57-57.bpo-45847.9phcpd.rst M Modules/Setup.stdlib.in M configure M configure.ac M setup.py diff --git a/Misc/NEWS.d/next/Build/2021-11-19-17-57-57.bpo-45847.9phcpd.rst b/Misc/NEWS.d/next/Build/2021-11-19-17-57-57.bpo-45847.9phcpd.rst new file mode 100644 index 0000000000000..05bc9ccdb3af8 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-19-17-57-57.bpo-45847.9phcpd.rst @@ -0,0 +1 @@ +Port builtin hashlib extensions to ``PY_STDLIB_MOD`` macro and ``addext()``. diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 3b0d3227bc5b0..ee07f4d5d8ea4 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -37,6 +37,13 @@ # with ./configure --with-system-libmpdec @MODULE__DECIMAL_TRUE at _decimal _decimal/_decimal.c +# hashing builtins, can be disabled with --without-builtin-hashlib-hashes + at MODULE__MD5_TRUE@_md5 md5module.c + at MODULE__SHA1_TRUE@_sha1 sha1module.c + at MODULE__SHA256_TRUE@_sha256 sha256module.c + at MODULE__SHA512_TRUE@_sha512 sha512module.c + at MODULE__SHA3_TRUE@_sha3 _sha3/sha3module.c + at MODULE__BLAKE2_TRUE@_blake2 _blake2/blake2module.c _blake2/blake2b_impl.c _blake2/blake2s_impl.c ############################################################################ # XML and text diff --git a/configure b/configure index 96005cb63aff0..e8935dfb625fe 100755 --- a/configure +++ b/configure @@ -628,6 +628,18 @@ MODULE__SQLITE3_FALSE MODULE__SQLITE3_TRUE MODULE__DECIMAL_FALSE MODULE__DECIMAL_TRUE +MODULE__BLAKE2_FALSE +MODULE__BLAKE2_TRUE +MODULE__SHA3_FALSE +MODULE__SHA3_TRUE +MODULE__SHA512_FALSE +MODULE__SHA512_TRUE +MODULE__SHA256_FALSE +MODULE__SHA256_TRUE +MODULE__SHA1_FALSE +MODULE__SHA1_TRUE +MODULE__MD5_FALSE +MODULE__MD5_TRUE MODULE__ELEMENTTREE_FALSE MODULE__ELEMENTTREE_TRUE MODULE_PYEXPAT_FALSE @@ -19333,33 +19345,51 @@ $as_echo_n "checking for --with-builtin-hashlib-hashes... " >&6; } # Check whether --with-builtin-hashlib-hashes was given. if test "${with_builtin_hashlib_hashes+set}" = set; then : withval=$with_builtin_hashlib_hashes; -case "$withval" in - yes) - withval=$default_hashlib_hashes - ;; - no) - withval="" - ;; + case $with_builtin_hashlib_hashes in #( + yes) : + with_builtin_hashlib_hashes=$default_hashlib_hashes ;; #( + no) : + with_builtin_hashlib_hashes="" + ;; #( + *) : + ;; esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $withval" >&5 -$as_echo "$withval" >&6; } -cat >>confdefs.h <<_ACEOF -#define PY_BUILTIN_HASHLIB_HASHES "$withval" -_ACEOF - else - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $default_hashlib_hashes" >&5 -$as_echo "$default_hashlib_hashes" >&6; }; -cat >>confdefs.h <<_ACEOF -#define PY_BUILTIN_HASHLIB_HASHES "$default_hashlib_hashes" -_ACEOF - - + with_builtin_hashlib_hashes=$default_hashlib_hashes fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_builtin_hashlib_hashes" >&5 +$as_echo "$with_builtin_hashlib_hashes" >&6; } +cat >>confdefs.h <<_ACEOF +#define PY_BUILTIN_HASHLIB_HASHES "$with_builtin_hashlib_hashes" +_ACEOF + + +as_save_IFS=$IFS +IFS=, +for builtin_hash in $with_builtin_hashlib_hashes; do + case $builtin_hash in #( + md5) : + with_builtin_md5=yes ;; #( + sha1) : + with_builtin_sha1=yes ;; #( + sha256) : + with_builtin_sha256=yes ;; #( + sha512) : + with_builtin_sha512=yes ;; #( + sha3) : + with_builtin_sha3=yes ;; #( + blake2) : + with_builtin_blake2=yes + ;; #( + *) : + ;; +esac +done +IFS=$as_save_IFS + # --with-experimental-isolated-subinterpreters { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-experimental-isolated-subinterpreters" >&5 @@ -19660,6 +19690,307 @@ $as_echo "$py_cv_module__elementtree" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _md5" >&5 +$as_echo_n "checking for stdlib extension module _md5... " >&6; } + case $py_stdlib_not_available in #( + *_md5*) : + py_cv_module__md5=n/a ;; #( + *) : + + if test "$with_builtin_md5" = yes; then : + if true; then : + py_cv_module__md5=yes +else + py_cv_module__md5=missing +fi +else + py_cv_module__md5=disabled + +fi + + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__MD5=$py_cv_module__md5$as_nl" + if test "x$py_cv_module__md5" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE__MD5_CFLAGS=$as_nl" + as_fn_append MODULE_BLOCK "MODULE__MD5_LDFLAGS=$as_nl" + if true; then + MODULE__MD5_TRUE= + MODULE__MD5_FALSE='#' +else + MODULE__MD5_TRUE='#' + MODULE__MD5_FALSE= +fi + + +else + + if false; then + MODULE__MD5_TRUE= + MODULE__MD5_FALSE='#' +else + MODULE__MD5_TRUE='#' + MODULE__MD5_FALSE= +fi + + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__md5" >&5 +$as_echo "$py_cv_module__md5" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _sha1" >&5 +$as_echo_n "checking for stdlib extension module _sha1... " >&6; } + case $py_stdlib_not_available in #( + *_sha1*) : + py_cv_module__sha1=n/a ;; #( + *) : + + if test "$with_builtin_sha1" = yes; then : + if true; then : + py_cv_module__sha1=yes +else + py_cv_module__sha1=missing +fi +else + py_cv_module__sha1=disabled + +fi + + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__SHA1=$py_cv_module__sha1$as_nl" + if test "x$py_cv_module__sha1" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE__SHA1_CFLAGS=$as_nl" + as_fn_append MODULE_BLOCK "MODULE__SHA1_LDFLAGS=$as_nl" + if true; then + MODULE__SHA1_TRUE= + MODULE__SHA1_FALSE='#' +else + MODULE__SHA1_TRUE='#' + MODULE__SHA1_FALSE= +fi + + +else + + if false; then + MODULE__SHA1_TRUE= + MODULE__SHA1_FALSE='#' +else + MODULE__SHA1_TRUE='#' + MODULE__SHA1_FALSE= +fi + + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__sha1" >&5 +$as_echo "$py_cv_module__sha1" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _sha256" >&5 +$as_echo_n "checking for stdlib extension module _sha256... " >&6; } + case $py_stdlib_not_available in #( + *_sha256*) : + py_cv_module__sha256=n/a ;; #( + *) : + + if test "$with_builtin_sha256" = yes; then : + if true; then : + py_cv_module__sha256=yes +else + py_cv_module__sha256=missing +fi +else + py_cv_module__sha256=disabled + +fi + + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__SHA256=$py_cv_module__sha256$as_nl" + if test "x$py_cv_module__sha256" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE__SHA256_CFLAGS=$as_nl" + as_fn_append MODULE_BLOCK "MODULE__SHA256_LDFLAGS=$as_nl" + if true; then + MODULE__SHA256_TRUE= + MODULE__SHA256_FALSE='#' +else + MODULE__SHA256_TRUE='#' + MODULE__SHA256_FALSE= +fi + + +else + + if false; then + MODULE__SHA256_TRUE= + MODULE__SHA256_FALSE='#' +else + MODULE__SHA256_TRUE='#' + MODULE__SHA256_FALSE= +fi + + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__sha256" >&5 +$as_echo "$py_cv_module__sha256" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _sha512" >&5 +$as_echo_n "checking for stdlib extension module _sha512... " >&6; } + case $py_stdlib_not_available in #( + *_sha512*) : + py_cv_module__sha512=n/a ;; #( + *) : + + if test "$with_builtin_sha512" = yes; then : + if true; then : + py_cv_module__sha512=yes +else + py_cv_module__sha512=missing +fi +else + py_cv_module__sha512=disabled + +fi + + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__SHA512=$py_cv_module__sha512$as_nl" + if test "x$py_cv_module__sha512" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE__SHA512_CFLAGS=$as_nl" + as_fn_append MODULE_BLOCK "MODULE__SHA512_LDFLAGS=$as_nl" + if true; then + MODULE__SHA512_TRUE= + MODULE__SHA512_FALSE='#' +else + MODULE__SHA512_TRUE='#' + MODULE__SHA512_FALSE= +fi + + +else + + if false; then + MODULE__SHA512_TRUE= + MODULE__SHA512_FALSE='#' +else + MODULE__SHA512_TRUE='#' + MODULE__SHA512_FALSE= +fi + + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__sha512" >&5 +$as_echo "$py_cv_module__sha512" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _sha3" >&5 +$as_echo_n "checking for stdlib extension module _sha3... " >&6; } + case $py_stdlib_not_available in #( + *_sha3*) : + py_cv_module__sha3=n/a ;; #( + *) : + + if test "$with_builtin_sha3" = yes; then : + if true; then : + py_cv_module__sha3=yes +else + py_cv_module__sha3=missing +fi +else + py_cv_module__sha3=disabled + +fi + + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__SHA3=$py_cv_module__sha3$as_nl" + if test "x$py_cv_module__sha3" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE__SHA3_CFLAGS=$as_nl" + as_fn_append MODULE_BLOCK "MODULE__SHA3_LDFLAGS=$as_nl" + if true; then + MODULE__SHA3_TRUE= + MODULE__SHA3_FALSE='#' +else + MODULE__SHA3_TRUE='#' + MODULE__SHA3_FALSE= +fi + + +else + + if false; then + MODULE__SHA3_TRUE= + MODULE__SHA3_FALSE='#' +else + MODULE__SHA3_TRUE='#' + MODULE__SHA3_FALSE= +fi + + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__sha3" >&5 +$as_echo "$py_cv_module__sha3" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _blake2" >&5 +$as_echo_n "checking for stdlib extension module _blake2... " >&6; } + case $py_stdlib_not_available in #( + *_blake2*) : + py_cv_module__blake2=n/a ;; #( + *) : + + if test "$with_builtin_blake2" = yes; then : + if true; then : + py_cv_module__blake2=yes +else + py_cv_module__blake2=missing +fi +else + py_cv_module__blake2=disabled + +fi + + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__BLAKE2=$py_cv_module__blake2$as_nl" + if test "x$py_cv_module__blake2" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE__BLAKE2_CFLAGS=$as_nl" + as_fn_append MODULE_BLOCK "MODULE__BLAKE2_LDFLAGS=$as_nl" + if true; then + MODULE__BLAKE2_TRUE= + MODULE__BLAKE2_FALSE='#' +else + MODULE__BLAKE2_TRUE='#' + MODULE__BLAKE2_FALSE= +fi + + +else + + if false; then + MODULE__BLAKE2_TRUE= + MODULE__BLAKE2_FALSE='#' +else + MODULE__BLAKE2_TRUE='#' + MODULE__BLAKE2_FALSE= +fi + + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__blake2" >&5 +$as_echo "$py_cv_module__blake2" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _decimal" >&5 $as_echo_n "checking for stdlib extension module _decimal... " >&6; } case $py_stdlib_not_available in #( @@ -19916,6 +20247,54 @@ if test -z "${MODULE__ELEMENTTREE_TRUE}" && test -z "${MODULE__ELEMENTTREE_FALSE as_fn_error $? "conditional \"MODULE__ELEMENTTREE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__MD5_TRUE}" && test -z "${MODULE__MD5_FALSE}"; then + as_fn_error $? "conditional \"MODULE__MD5\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__MD5_TRUE}" && test -z "${MODULE__MD5_FALSE}"; then + as_fn_error $? "conditional \"MODULE__MD5\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__SHA1_TRUE}" && test -z "${MODULE__SHA1_FALSE}"; then + as_fn_error $? "conditional \"MODULE__SHA1\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__SHA1_TRUE}" && test -z "${MODULE__SHA1_FALSE}"; then + as_fn_error $? "conditional \"MODULE__SHA1\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__SHA256_TRUE}" && test -z "${MODULE__SHA256_FALSE}"; then + as_fn_error $? "conditional \"MODULE__SHA256\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__SHA256_TRUE}" && test -z "${MODULE__SHA256_FALSE}"; then + as_fn_error $? "conditional \"MODULE__SHA256\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__SHA512_TRUE}" && test -z "${MODULE__SHA512_FALSE}"; then + as_fn_error $? "conditional \"MODULE__SHA512\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__SHA512_TRUE}" && test -z "${MODULE__SHA512_FALSE}"; then + as_fn_error $? "conditional \"MODULE__SHA512\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__SHA3_TRUE}" && test -z "${MODULE__SHA3_FALSE}"; then + as_fn_error $? "conditional \"MODULE__SHA3\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__SHA3_TRUE}" && test -z "${MODULE__SHA3_FALSE}"; then + as_fn_error $? "conditional \"MODULE__SHA3\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__BLAKE2_TRUE}" && test -z "${MODULE__BLAKE2_FALSE}"; then + as_fn_error $? "conditional \"MODULE__BLAKE2\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__BLAKE2_TRUE}" && test -z "${MODULE__BLAKE2_FALSE}"; then + as_fn_error $? "conditional \"MODULE__BLAKE2\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__DECIMAL_TRUE}" && test -z "${MODULE__DECIMAL_FALSE}"; then as_fn_error $? "conditional \"MODULE__DECIMAL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index d4c9bef424265..754b066f52ed0 100644 --- a/configure.ac +++ b/configure.ac @@ -5902,21 +5902,28 @@ AC_ARG_WITH(builtin-hashlib-hashes, [builtin hash modules, md5, sha1, sha256, sha512, sha3 (with shake), blake2]), [ -case "$withval" in - yes) - withval=$default_hashlib_hashes - ;; - no) - withval="" - ;; -esac -AC_MSG_RESULT($withval) -AC_DEFINE_UNQUOTED(PY_BUILTIN_HASHLIB_HASHES, "$withval") -], -[ -AC_MSG_RESULT($default_hashlib_hashes); -AC_DEFINE_UNQUOTED(PY_BUILTIN_HASHLIB_HASHES, "$default_hashlib_hashes") -]) + AS_CASE([$with_builtin_hashlib_hashes], + [yes], [with_builtin_hashlib_hashes=$default_hashlib_hashes], + [no], [with_builtin_hashlib_hashes=""] + ) +], [with_builtin_hashlib_hashes=$default_hashlib_hashes]) + +AC_MSG_RESULT($with_builtin_hashlib_hashes) +AC_DEFINE_UNQUOTED(PY_BUILTIN_HASHLIB_HASHES, "$with_builtin_hashlib_hashes") + +as_save_IFS=$IFS +IFS=, +for builtin_hash in $with_builtin_hashlib_hashes; do + AS_CASE($builtin_hash, + [md5], [with_builtin_md5=yes], + [sha1], [with_builtin_sha1=yes], + [sha256], [with_builtin_sha256=yes], + [sha512], [with_builtin_sha512=yes], + [sha3], [with_builtin_sha3=yes], + [blake2], [with_builtin_blake2=yes] + ) +done +IFS=$as_save_IFS # --with-experimental-isolated-subinterpreters AH_TEMPLATE(EXPERIMENTAL_ISOLATED_SUBINTERPRETERS, @@ -6060,6 +6067,15 @@ dnl _elementtree loads libexpat via CAPI hook in pyexpat PY_STDLIB_MOD([pyexpat], [], [], [$LIBEXPAT_CFLAGS], [$LIBEXPAT_LDFLAGS]) PY_STDLIB_MOD([_elementtree], [], [], [$LIBEXPAT_CFLAGS], []) +dnl By default we always compile these even when OpenSSL is available +dnl (issue #14693). The modules are small. +PY_STDLIB_MOD([_md5], [test "$with_builtin_md5" = yes]) +PY_STDLIB_MOD([_sha1], [test "$with_builtin_sha1" = yes]) +PY_STDLIB_MOD([_sha256], [test "$with_builtin_sha256" = yes]) +PY_STDLIB_MOD([_sha512], [test "$with_builtin_sha512" = yes]) +PY_STDLIB_MOD([_sha3], [test "$with_builtin_sha3" = yes]) +PY_STDLIB_MOD([_blake2], [test "$with_builtin_blake2" = yes]) + PY_STDLIB_MOD([_decimal], [], [], [$LIBMPDEC_CFLAGS], [$LIBMPDEC_LDFLAGS]) PY_STDLIB_MOD([_sqlite3], [test "$have_sqlite3" = "yes"], diff --git a/setup.py b/setup.py index 0b7e7ab0a3061..3e3075d8d9ac6 100644 --- a/setup.py +++ b/setup.py @@ -2034,53 +2034,19 @@ def detect_hash_builtins(self): # (issue #14693). It's harmless and the object code is tiny # (40-50 KiB per module, only loaded when actually used). Modules can # be disabled via the --with-builtin-hashlib-hashes configure flag. - supported = {"md5", "sha1", "sha256", "sha512", "sha3", "blake2"} - configured = sysconfig.get_config_var("PY_BUILTIN_HASHLIB_HASHES") - configured = configured.strip('"').lower() - configured = { - m.strip() for m in configured.split(",") - } - - self.disabled_configure.extend( - sorted(supported.difference(configured)) - ) - - if "sha256" in configured: - self.add(Extension( - '_sha256', ['sha256module.c'] - )) - - if "sha512" in configured: - self.add(Extension( - '_sha512', ['sha512module.c'], - )) - - if "md5" in configured: - self.add(Extension( - '_md5', ['md5module.c'], - )) - - if "sha1" in configured: - self.add(Extension( - '_sha1', ['sha1module.c'], - )) - - if "blake2" in configured: - self.add(Extension( - '_blake2', - [ - '_blake2/blake2module.c', - '_blake2/blake2b_impl.c', - '_blake2/blake2s_impl.c' - ] - )) - - if "sha3" in configured: - self.add(Extension( - '_sha3', - ['_sha3/sha3module.c'], - )) + self.addext(Extension('_md5', ['md5module.c'])) + self.addext(Extension('_sha1', ['sha1module.c'])) + self.addext(Extension('_sha256', ['sha256module.c'])) + self.addext(Extension('_sha512', ['sha512module.c'])) + self.addext(Extension('_sha3', ['_sha3/sha3module.c'])) + self.addext(Extension('_blake2', + [ + '_blake2/blake2module.c', + '_blake2/blake2b_impl.c', + '_blake2/blake2s_impl.c' + ] + )) def detect_nis(self): if MS_WINDOWS or CYGWIN or HOST_PLATFORM == 'qnx6': From webhook-mailer at python.org Fri Nov 19 18:12:05 2021 From: webhook-mailer at python.org (pablogsal) Date: Fri, 19 Nov 2021 23:12:05 -0000 Subject: [Python-checkins] bpo-45727: Make the syntax error for missing comma more consistent (GH-29427) Message-ID: https://github.com/python/cpython/commit/546cefcda75d7150b55c8bc1724bea35a1e12890 commit: 546cefcda75d7150b55c8bc1724bea35a1e12890 branch: main author: Pablo Galindo Salgado committer: pablogsal date: 2021-11-19T23:11:57Z summary: bpo-45727: Make the syntax error for missing comma more consistent (GH-29427) files: M Grammar/python.gram M Lib/test/test_exceptions.py M Parser/parser.c M Parser/pegen.c diff --git a/Grammar/python.gram b/Grammar/python.gram index d1901a5a9a2bc..168bb3c05e6c9 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -618,6 +618,7 @@ expressions[expr_ty]: expression[expr_ty] (memo): | invalid_expression + | invalid_legacy_expression | a=disjunction 'if' b=disjunction 'else' c=expression { _PyAST_IfExp(b, a, c, EXTRA) } | disjunction | lambdef @@ -1080,11 +1081,10 @@ invalid_legacy_expression: "Missing parentheses in call to '%U'. Did you mean %U(...)?", a->v.Name.id, a->v.Name.id) : NULL} invalid_expression: - | invalid_legacy_expression # !(NAME STRING) is not matched so we don't show this error with some invalid string prefixes like: kf"dsfsdf" # Soft keywords need to also be ignored because they can be parsed as NAME NAME | !(NAME STRING | SOFT_KEYWORD) a=disjunction b=expression_without_invalid { - RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "invalid syntax. Perhaps you forgot a comma?") } + _PyPegen_check_legacy_stmt(p, a) ? NULL : RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "invalid syntax. Perhaps you forgot a comma?") } | a=disjunction 'if' b=disjunction !('else'|':') { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "expected 'else' after 'if' expression") } invalid_named_expression: diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 098804fad5e2d..1341f77ac45cb 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -233,6 +233,7 @@ def testSyntaxErrorOffset(self): check('[file for\n str(file) in []]', 2, 2) check("ages = {'Alice'=22, 'Bob'=23}", 1, 16) check('match ...:\n case {**rest, "key": value}:\n ...', 2, 19) + check("a b c d e f", 1, 1) # Errors thrown by compile.c check('class foo:return 1', 1, 11) diff --git a/Parser/parser.c b/Parser/parser.c index b508c1ddec15c..87f492d50c611 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -9719,6 +9719,7 @@ expressions_rule(Parser *p) // expression: // | invalid_expression +// | invalid_legacy_expression // | disjunction 'if' disjunction 'else' expression // | disjunction // | lambdef @@ -9764,6 +9765,25 @@ expression_rule(Parser *p) D(fprintf(stderr, "%*c%s expression[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_expression")); } + if (p->call_invalid_rules) { // invalid_legacy_expression + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_legacy_expression")); + void *invalid_legacy_expression_var; + if ( + (invalid_legacy_expression_var = invalid_legacy_expression_rule(p)) // invalid_legacy_expression + ) + { + D(fprintf(stderr, "%*c+ expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "invalid_legacy_expression")); + _res = invalid_legacy_expression_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s expression[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_legacy_expression")); + } { // disjunction 'if' disjunction 'else' expression if (p->error_indicator) { D(p->level--); @@ -18239,7 +18259,6 @@ invalid_legacy_expression_rule(Parser *p) } // invalid_expression: -// | invalid_legacy_expression // | !(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid // | disjunction 'if' disjunction !('else' | ':') static void * @@ -18252,25 +18271,6 @@ invalid_expression_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - if (p->call_invalid_rules) { // invalid_legacy_expression - if (p->error_indicator) { - D(p->level--); - return NULL; - } - D(fprintf(stderr, "%*c> invalid_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_legacy_expression")); - void *invalid_legacy_expression_var; - if ( - (invalid_legacy_expression_var = invalid_legacy_expression_rule(p)) // invalid_legacy_expression - ) - { - D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "invalid_legacy_expression")); - _res = invalid_legacy_expression_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s invalid_expression[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_legacy_expression")); - } { // !(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid if (p->error_indicator) { D(p->level--); @@ -18288,7 +18288,7 @@ invalid_expression_rule(Parser *p) ) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid")); - _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Perhaps you forgot a comma?" ); + _res = _PyPegen_check_legacy_stmt ( p , a ) ? NULL : RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Perhaps you forgot a comma?" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; D(p->level--); diff --git a/Parser/pegen.c b/Parser/pegen.c index 15879a64f279c..09c1a19a79364 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -79,7 +79,9 @@ _PyPegen_check_barry_as_flufl(Parser *p, Token* t) { int _PyPegen_check_legacy_stmt(Parser *p, expr_ty name) { - assert(name->kind == Name_kind); + if (name->kind != Name_kind) { + return 0; + } const char* candidates[2] = {"print", "exec"}; for (int i=0; i<2; i++) { if (PyUnicode_CompareWithASCIIString(name->v.Name.id, candidates[i]) == 0) { From webhook-mailer at python.org Fri Nov 19 19:11:44 2021 From: webhook-mailer at python.org (zooba) Date: Sat, 20 Nov 2021 00:11:44 -0000 Subject: [Python-checkins] bpo-45506: Fix test_embed expecting to not find stdlib in source tree build when stdlib has been installed. (GH-29649) Message-ID: https://github.com/python/cpython/commit/4c616911b69ce07fb35da1721506bfaba0998c30 commit: 4c616911b69ce07fb35da1721506bfaba0998c30 branch: main author: Steve Dower committer: zooba date: 2021-11-20T00:11:40Z summary: bpo-45506: Fix test_embed expecting to not find stdlib in source tree build when stdlib has been installed. (GH-29649) files: M Lib/test/test_embed.py diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index a0d61504f427d..e1af15dd70ff9 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -35,6 +35,13 @@ MAX_HASH_SEED = 4294967295 +# If we are running from a build dir, but the stdlib has been installed, +# some tests need to expect different results. +STDLIB_INSTALL = os.path.join(sys.prefix, sys.platlibdir, + f'python{sys.version_info.major}.{sys.version_info.minor}') +if not os.path.isfile(os.path.join(STDLIB_INSTALL, 'os.py')): + STDLIB_INSTALL = None + def debug_build(program): program = os.path.basename(program) name = os.path.splitext(program)[0] @@ -1307,10 +1314,8 @@ def test_init_pybuilddir(self): 'base_executable': executable, 'executable': executable, 'module_search_paths': module_search_paths, - # The current getpath.c doesn't determine the stdlib dir - # in this case. - 'stdlib_dir': None, - 'use_frozen_modules': -1, + 'stdlib_dir': STDLIB_INSTALL, + 'use_frozen_modules': 1 if STDLIB_INSTALL else -1, } env = self.copy_paths_by_env(config) self.check_all_configs("test_init_compat_config", config, @@ -1381,8 +1386,8 @@ def test_init_pyvenv_cfg(self): else: # The current getpath.c doesn't determine the stdlib dir # in this case. - config['stdlib_dir'] = None - config['use_frozen_modules'] = -1 + config['stdlib_dir'] = STDLIB_INSTALL + config['use_frozen_modules'] = 1 if STDLIB_INSTALL else -1 env = self.copy_paths_by_env(config) self.check_all_configs("test_init_compat_config", config, From webhook-mailer at python.org Fri Nov 19 19:40:39 2021 From: webhook-mailer at python.org (brettcannon) Date: Sat, 20 Nov 2021 00:40:39 -0000 Subject: [Python-checkins] bpo-45250: fix docs regarding `__iter__` and iterators being inconsistently required by CPython (GH-29170) Message-ID: https://github.com/python/cpython/commit/be36e0634060c7d5dee8e8876fb888bbb53d992a commit: be36e0634060c7d5dee8e8876fb888bbb53d992a branch: main author: Brett Cannon committer: brettcannon date: 2021-11-19T16:40:34-08:00 summary: bpo-45250: fix docs regarding `__iter__` and iterators being inconsistently required by CPython (GH-29170) It is now considered a historical accident that e.g. `for` loops and the `iter()` built-in function do not require the iterators they work with to define `__iter__`, only `__next__`. files: A Misc/NEWS.d/next/Documentation/2021-10-22-12-09-18.bpo-45250.Iit5-Y.rst M Doc/c-api/iter.rst M Doc/c-api/typeobj.rst M Doc/glossary.rst M Doc/library/functions.rst M Doc/library/stdtypes.rst M Doc/reference/datamodel.rst diff --git a/Doc/c-api/iter.rst b/Doc/c-api/iter.rst index f7106f4ef0990..3e388bb917a02 100644 --- a/Doc/c-api/iter.rst +++ b/Doc/c-api/iter.rst @@ -9,8 +9,8 @@ There are two functions specifically for working with iterators. .. c:function:: int PyIter_Check(PyObject *o) - Return non-zero if the object *o* supports the iterator protocol, and ``0`` - otherwise. This function always succeeds. + Return non-zero if the object *o* can be safely passed to + :c:func:`PyIter_Next`, and ``0`` otherwise. This function always succeeds. .. c:function:: int PyAIter_Check(PyObject *o) @@ -21,10 +21,11 @@ There are two functions specifically for working with iterators. .. c:function:: PyObject* PyIter_Next(PyObject *o) - Return the next value from the iteration *o*. The object must be an iterator - (it is up to the caller to check this). If there are no remaining values, - returns ``NULL`` with no exception set. If an error occurs while retrieving - the item, returns ``NULL`` and passes along the exception. + Return the next value from the iterator *o*. The object must be an iterator + according to :c:func:`PyIter_Check` (it is up to the caller to check this). + If there are no remaining values, returns ``NULL`` with no exception set. + If an error occurs while retrieving the item, returns ``NULL`` and passes + along the exception. To write a loop which iterates over an iterator, the C code should look something like this:: diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index 541287956f0a5..cd8723efef6bb 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -1521,9 +1521,9 @@ and :c:type:`PyType_Type` effectively act as defaults.) .. c:member:: getiterfunc PyTypeObject.tp_iter - An optional pointer to a function that returns an iterator for the object. Its - presence normally signals that the instances of this type are iterable (although - sequences may be iterable without this function). + An optional pointer to a function that returns an :term:`iterator` for the + object. Its presence normally signals that the instances of this type are + :term:`iterable` (although sequences may be iterable without this function). This function has the same signature as :c:func:`PyObject_GetIter`:: @@ -1536,8 +1536,8 @@ and :c:type:`PyType_Type` effectively act as defaults.) .. c:member:: iternextfunc PyTypeObject.tp_iternext - An optional pointer to a function that returns the next item in an iterator. - The signature is:: + An optional pointer to a function that returns the next item in an + :term:`iterator`. The signature is:: PyObject *tp_iternext(PyObject *self); @@ -2429,8 +2429,8 @@ Async Object Structures PyObject *am_await(PyObject *self); - The returned object must be an iterator, i.e. :c:func:`PyIter_Check` must - return ``1`` for it. + The returned object must be an :term:`iterator`, i.e. :c:func:`PyIter_Check` + must return ``1`` for it. This slot may be set to ``NULL`` if an object is not an :term:`awaitable`. diff --git a/Doc/glossary.rst b/Doc/glossary.rst index ccbfc0e6c36c7..e71f6c0406a23 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -659,6 +659,11 @@ Glossary More information can be found in :ref:`typeiter`. + .. impl-detail:: + + CPython does not consistently apply the requirement that an iterator + define :meth:`__iter__`. + key function A key function or collation function is a callable that returns a value used for sorting or ordering. For example, :func:`locale.strxfrm` is diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index cf4a96097074f..0da2619685bff 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -66,9 +66,6 @@ are always available. They are listed here in alphabetical order. Return an :term:`asynchronous iterator` for an :term:`asynchronous iterable`. Equivalent to calling ``x.__aiter__()``. - ``aiter(x)`` itself has an ``__aiter__()`` method that returns ``x``, - so ``aiter(aiter(x))`` is the same as ``aiter(x)``. - Note: Unlike :func:`iter`, :func:`aiter` has no 2-argument variant. .. versionadded:: 3.10 @@ -929,8 +926,8 @@ are always available. They are listed here in alphabetical order. Return an :term:`iterator` object. The first argument is interpreted very differently depending on the presence of the second argument. Without a second argument, *object* must be a collection object which supports the - iteration protocol (the :meth:`__iter__` method), or it must support the - sequence protocol (the :meth:`__getitem__` method with integer arguments + :term:`iterable` protocol (the :meth:`__iter__` method), or it must support + the sequence protocol (the :meth:`__getitem__` method with integer arguments starting at ``0``). If it does not support either of those protocols, :exc:`TypeError` is raised. If the second argument, *sentinel*, is given, then *object* must be a callable object. The iterator created in this case @@ -1060,7 +1057,7 @@ are always available. They are listed here in alphabetical order. .. function:: next(iterator[, default]) - Retrieve the next item from the *iterator* by calling its + Retrieve the next item from the :term:`iterator` by calling its :meth:`~iterator.__next__` method. If *default* is given, it is returned if the iterator is exhausted, otherwise :exc:`StopIteration` is raised. diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index eea9ddcc14003..de77507458a0a 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -810,21 +810,21 @@ using two distinct methods; these are used to allow user-defined classes to support iteration. Sequences, described below in more detail, always support the iteration methods. -One method needs to be defined for container objects to provide iteration +One method needs to be defined for container objects to provide :term:`iterable` support: .. XXX duplicated in reference/datamodel! .. method:: container.__iter__() - Return an iterator object. The object is required to support the iterator - protocol described below. If a container supports different types of - iteration, additional methods can be provided to specifically request + Return an :term:`iterator` object. The object is required to support the + iterator protocol described below. If a container supports different types + of iteration, additional methods can be provided to specifically request iterators for those iteration types. (An example of an object supporting multiple forms of iteration would be a tree structure which supports both breadth-first and depth-first traversal.) This method corresponds to the - :c:member:`~PyTypeObject.tp_iter` slot of the type structure for Python objects in the Python/C - API. + :c:member:`~PyTypeObject.tp_iter` slot of the type structure for Python + objects in the Python/C API. The iterator objects themselves are required to support the following two methods, which together form the :dfn:`iterator protocol`: @@ -832,18 +832,19 @@ methods, which together form the :dfn:`iterator protocol`: .. method:: iterator.__iter__() - Return the iterator object itself. This is required to allow both containers - and iterators to be used with the :keyword:`for` and :keyword:`in` statements. - This method corresponds to the :c:member:`~PyTypeObject.tp_iter` slot of the type structure for - Python objects in the Python/C API. + Return the :term:`iterator` object itself. This is required to allow both + containers and iterators to be used with the :keyword:`for` and + :keyword:`in` statements. This method corresponds to the + :c:member:`~PyTypeObject.tp_iter` slot of the type structure for Python + objects in the Python/C API. .. method:: iterator.__next__() - Return the next item from the container. If there are no further items, raise - the :exc:`StopIteration` exception. This method corresponds to the - :c:member:`~PyTypeObject.tp_iternext` slot of the type structure for Python objects in the - Python/C API. + Return the next item from the :term:`iterator`. If there are no further + items, raise the :exc:`StopIteration` exception. This method corresponds to + the :c:member:`~PyTypeObject.tp_iternext` slot of the type structure for + Python objects in the Python/C API. Python defines several iterator objects to support iteration over general and specific sequence types, dictionaries, and other more specialized forms. The diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 1ecfa81e3b336..b04c95f7779b4 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -648,13 +648,13 @@ Callable types A function or method which uses the :keyword:`yield` statement (see section :ref:`yield`) is called a :dfn:`generator function`. Such a function, when - called, always returns an iterator object which can be used to execute the - body of the function: calling the iterator's :meth:`iterator.__next__` - method will cause the function to execute until it provides a value - using the :keyword:`!yield` statement. When the function executes a - :keyword:`return` statement or falls off the end, a :exc:`StopIteration` - exception is raised and the iterator will have reached the end of the set of - values to be returned. + called, always returns an :term:`iterator` object which can be used to + execute the body of the function: calling the iterator's + :meth:`iterator.__next__` method will cause the function to execute until + it provides a value using the :keyword:`!yield` statement. When the + function executes a :keyword:`return` statement or falls off the end, a + :exc:`StopIteration` exception is raised and the iterator will have + reached the end of the set of values to be returned. Coroutine functions .. index:: @@ -674,7 +674,7 @@ Callable types A function or method which is defined using :keyword:`async def` and which uses the :keyword:`yield` statement is called a :dfn:`asynchronous generator function`. Such a function, when called, - returns an asynchronous iterator object which can be used in an + returns an :term:`asynchronous iterator` object which can be used in an :keyword:`async for` statement to execute the body of the function. Calling the asynchronous iterator's :meth:`aiterator.__anext__` method @@ -2499,12 +2499,10 @@ through the object's keys; for sequences, it should iterate through the values. .. method:: object.__iter__(self) - This method is called when an iterator is required for a container. This method - should return a new iterator object that can iterate over all the objects in the - container. For mappings, it should iterate over the keys of the container. - - Iterator objects also need to implement this method; they are required to return - themselves. For more information on iterator objects, see :ref:`typeiter`. + This method is called when an :term:`iterator` is required for a container. + This method should return a new iterator object that can iterate over all the + objects in the container. For mappings, it should iterate over the keys of + the container. .. method:: object.__reversed__(self) diff --git a/Misc/NEWS.d/next/Documentation/2021-10-22-12-09-18.bpo-45250.Iit5-Y.rst b/Misc/NEWS.d/next/Documentation/2021-10-22-12-09-18.bpo-45250.Iit5-Y.rst new file mode 100644 index 0000000000000..0c2bf18b20010 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-10-22-12-09-18.bpo-45250.Iit5-Y.rst @@ -0,0 +1,2 @@ +Update the documentation to note that CPython does not consistently +require iterators to define ``__iter__``. From webhook-mailer at python.org Sat Nov 20 04:18:59 2021 From: webhook-mailer at python.org (tiran) Date: Sat, 20 Nov 2021 09:18:59 -0000 Subject: [Python-checkins] bpo-45847: Port _scproxy to PY_STDLIB_MOD (GH-29644) Message-ID: https://github.com/python/cpython/commit/5596909eac4abdc9927c2e7751bea34fbcfdc624 commit: 5596909eac4abdc9927c2e7751bea34fbcfdc624 branch: main author: Christian Heimes committer: tiran date: 2021-11-20T10:18:48+01:00 summary: bpo-45847: Port _scproxy to PY_STDLIB_MOD (GH-29644) files: M Modules/Setup M Modules/Setup.stdlib.in M configure M configure.ac M setup.py diff --git a/Modules/Setup b/Modules/Setup index 5a7c232d3c555..d3647ecb99592 100644 --- a/Modules/Setup +++ b/Modules/Setup @@ -267,8 +267,8 @@ PYTHONPATH=$(COREPYTHONPATH) #_curses -lncurses -lncursesw -ltermcap _cursesmodule.c #_curses_panel -lpanel -lncurses _curses_panel.c -# macOS specific modules -# _scproxy _scproxy.c -framework SystemConfiguration -framework CoreFoundation +# macOS specific module, needs SystemConfiguration and CoreFoundation framework +# _scproxy _scproxy.c # Examples diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index ee07f4d5d8ea4..4e5c158c0fdb2 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -69,3 +69,10 @@ # Modules with third party dependencies # @MODULE__SQLITE3_TRUE at _sqlite3 _sqlite/connection.c _sqlite/cursor.c _sqlite/microprotocols.c _sqlite/module.c _sqlite/prepare_protocol.c _sqlite/row.c _sqlite/statement.c _sqlite/util.c + + +############################################################################ +# macOS specific modules + +# _scproxy needs SystemConfiguration and CoreFoundation framework + at MODULE__SCPROXY_TRUE@_scproxy _scproxy.c diff --git a/configure b/configure index e8935dfb625fe..9340cb072199c 100755 --- a/configure +++ b/configure @@ -644,6 +644,8 @@ MODULE__ELEMENTTREE_FALSE MODULE__ELEMENTTREE_TRUE MODULE_PYEXPAT_FALSE MODULE_PYEXPAT_TRUE +MODULE__SCPROXY_FALSE +MODULE__SCPROXY_TRUE MODULE_OSSAUDIODEV_FALSE MODULE_OSSAUDIODEV_TRUE MODULE__DATETIME_FALSE @@ -19588,6 +19590,56 @@ fi $as_echo "$py_cv_module_ossaudiodev" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _scproxy" >&5 +$as_echo_n "checking for stdlib extension module _scproxy... " >&6; } + case $py_stdlib_not_available in #( + *_scproxy*) : + py_cv_module__scproxy=n/a ;; #( + *) : + + if test "$ac_sys_system" = "Darwin"; then : + if true; then : + py_cv_module__scproxy=yes +else + py_cv_module__scproxy=missing +fi +else + py_cv_module__scproxy=disabled + +fi + + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__SCPROXY=$py_cv_module__scproxy$as_nl" + if test "x$py_cv_module__scproxy" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE__SCPROXY_CFLAGS=$as_nl" + as_fn_append MODULE_BLOCK "MODULE__SCPROXY_LDFLAGS=-framework SystemConfiguration -framework CoreFoundation$as_nl" + if true; then + MODULE__SCPROXY_TRUE= + MODULE__SCPROXY_FALSE='#' +else + MODULE__SCPROXY_TRUE='#' + MODULE__SCPROXY_FALSE= +fi + + +else + + if false; then + MODULE__SCPROXY_TRUE= + MODULE__SCPROXY_FALSE='#' +else + MODULE__SCPROXY_TRUE='#' + MODULE__SCPROXY_FALSE= +fi + + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__scproxy" >&5 +$as_echo "$py_cv_module__scproxy" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module pyexpat" >&5 $as_echo_n "checking for stdlib extension module pyexpat... " >&6; } @@ -20231,6 +20283,14 @@ if test -z "${MODULE_OSSAUDIODEV_TRUE}" && test -z "${MODULE_OSSAUDIODEV_FALSE}" as_fn_error $? "conditional \"MODULE_OSSAUDIODEV\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__SCPROXY_TRUE}" && test -z "${MODULE__SCPROXY_FALSE}"; then + as_fn_error $? "conditional \"MODULE__SCPROXY\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__SCPROXY_TRUE}" && test -z "${MODULE__SCPROXY_FALSE}"; then + as_fn_error $? "conditional \"MODULE__SCPROXY\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE_PYEXPAT_TRUE}" && test -z "${MODULE_PYEXPAT_FALSE}"; then as_fn_error $? "conditional \"MODULE_PYEXPAT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index 754b066f52ed0..924659713e474 100644 --- a/configure.ac +++ b/configure.ac @@ -6062,6 +6062,9 @@ PY_STDLIB_MOD_SIMPLE([_datetime], [], [$TIMEMODULE_LIB $LIBM]) dnl platform specific extensions PY_STDLIB_MOD([ossaudiodev], [], [test "$ac_cv_header_linux_soundcard_h" = yes -o "$ac_cv_header_sys_soundcard_h" = yes]) +PY_STDLIB_MOD([_scproxy], + [test "$ac_sys_system" = "Darwin"], [], + [], [-framework SystemConfiguration -framework CoreFoundation]) dnl _elementtree loads libexpat via CAPI hook in pyexpat PY_STDLIB_MOD([pyexpat], [], [], [$LIBEXPAT_CFLAGS], [$LIBEXPAT_LDFLAGS]) diff --git a/setup.py b/setup.py index 3e3075d8d9ac6..83a676bfefbbe 100644 --- a/setup.py +++ b/setup.py @@ -1389,11 +1389,8 @@ def detect_platform_specific_exts(self): # linux/soundcard.h or sys/soundcard.h self.addext(Extension('ossaudiodev', ['ossaudiodev.c'])) - if MACOS: - self.add(Extension('_scproxy', ['_scproxy.c'], - extra_link_args=[ - '-framework', 'SystemConfiguration', - '-framework', 'CoreFoundation'])) + # macOS-only, needs SystemConfiguration and CoreFoundation framework + self.addext(Extension('_scproxy', ['_scproxy.c'])) def detect_compress_exts(self): # Andrew Kuchling's zlib module. From webhook-mailer at python.org Sat Nov 20 04:35:43 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Sat, 20 Nov 2021 09:35:43 -0000 Subject: [Python-checkins] bpo-45846: Fix capitalisation of Van Rossum at the start of sentence (GH-29641) Message-ID: https://github.com/python/cpython/commit/bc2bc0dbdb52498d009f9f9771452e6aa4faff2b commit: bc2bc0dbdb52498d009f9f9771452e6aa4faff2b branch: main author: JMcB committer: serhiy-storchaka date: 2021-11-20T11:35:39+02:00 summary: bpo-45846: Fix capitalisation of Van Rossum at the start of sentence (GH-29641) files: M Doc/faq/programming.rst diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst index 12b70dbbe7302..154563a859e31 100644 --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -2092,7 +2092,7 @@ Jim Roskind suggests performing steps in the following order in each module: * ``import`` statements * active code (including globals that are initialized from imported values). -van Rossum doesn't like this approach much because the imports appear in a +Van Rossum doesn't like this approach much because the imports appear in a strange place, but it does work. Matthias Urlichs recommends restructuring your code so that the recursive import From webhook-mailer at python.org Sat Nov 20 09:03:00 2021 From: webhook-mailer at python.org (tiran) Date: Sat, 20 Nov 2021 14:03:00 -0000 Subject: [Python-checkins] bpo-45774: Fix SQLite load extension autodetection (GH-29659) Message-ID: https://github.com/python/cpython/commit/6d430ef5ab62158a200b94dff31b89524a9576bb commit: 6d430ef5ab62158a200b94dff31b89524a9576bb branch: main author: Erlend Egeberg Aasland committer: tiran date: 2021-11-20T15:02:52+01:00 summary: bpo-45774: Fix SQLite load extension autodetection (GH-29659) files: M configure M configure.ac M pyconfig.h.in diff --git a/configure b/configure index 9340cb072199c..dec3aa0586b83 100755 --- a/configure +++ b/configure @@ -11156,12 +11156,9 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sqlite3_sqlite3_load_extension" >&5 $as_echo "$ac_cv_lib_sqlite3_sqlite3_load_extension" >&6; } if test "x$ac_cv_lib_sqlite3_sqlite3_load_extension" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBSQLITE3 1 -_ACEOF - - LIBS="-lsqlite3 $LIBS" - + have_sqlite3_load_extension=yes +else + have_sqlite3_load_extension=no fi diff --git a/configure.ac b/configure.ac index 924659713e474..f4adab19d6138 100644 --- a/configure.ac +++ b/configure.ac @@ -3196,7 +3196,9 @@ AC_CHECK_HEADER([sqlite3.h], [ ], []) ], [have_supported_sqlite3=yes], [have_supported_sqlite3=no]) ], [have_sqlite3=no]) - AC_CHECK_LIB([sqlite3], [sqlite3_load_extension]) + AC_CHECK_LIB([sqlite3], [sqlite3_load_extension], + [have_sqlite3_load_extension=yes], + [have_sqlite3_load_extension=no]) ]) AS_VAR_COPY([CFLAGS], [save_CFLAGS]) diff --git a/pyconfig.h.in b/pyconfig.h.in index 0cc593fdfc569..b8f63955e3139 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -634,9 +634,6 @@ /* Define to 1 if you have the `sendfile' library (-lsendfile). */ #undef HAVE_LIBSENDFILE -/* Define to 1 if you have the `sqlite3' library (-lsqlite3). */ -#undef HAVE_LIBSQLITE3 - /* Define to 1 if you have the header file. */ #undef HAVE_LIBUTIL_H From webhook-mailer at python.org Sat Nov 20 09:36:16 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 20 Nov 2021 14:36:16 -0000 Subject: [Python-checkins] bpo-45848: Allow the parser to get error lines from encoded files (GH-29646) Message-ID: https://github.com/python/cpython/commit/fdcc46d9554094994f78bedf6dc9220e5d5ee668 commit: fdcc46d9554094994f78bedf6dc9220e5d5ee668 branch: main author: Pablo Galindo Salgado committer: ambv date: 2021-11-20T15:36:07+01:00 summary: bpo-45848: Allow the parser to get error lines from encoded files (GH-29646) files: A Misc/NEWS.d/next/Core and Builtins/2021-11-19-22-57-42.bpo-45848.HgVBJ5.rst M Include/cpython/pyerrors.h M Lib/test/test_exceptions.py M Parser/pegen.c M Python/errors.c diff --git a/Include/cpython/pyerrors.h b/Include/cpython/pyerrors.h index 28ab565dde423..a07018abae0cf 100644 --- a/Include/cpython/pyerrors.h +++ b/Include/cpython/pyerrors.h @@ -149,6 +149,11 @@ PyAPI_FUNC(PyObject *) PyErr_ProgramTextObject( PyObject *filename, int lineno); +PyAPI_FUNC(PyObject *) _PyErr_ProgramDecodedTextObject( + PyObject *filename, + int lineno, + const char* encoding); + PyAPI_FUNC(PyObject *) _PyUnicodeTranslateError_Create( PyObject *object, Py_ssize_t start, diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 1341f77ac45cb..4c18a59f6e92c 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -2353,6 +2353,19 @@ def test_encodings(self): finally: unlink(TESTFN) + # Check backwards tokenizer errors + source = '# -*- coding: ascii -*-\n\n(\n' + try: + with open(TESTFN, 'w', encoding='ascii') as testfile: + testfile.write(source) + rc, out, err = script_helper.assert_python_failure('-Wd', '-X', 'utf8', TESTFN) + err = err.decode('utf-8').splitlines() + + self.assertEqual(err[-3], ' (') + self.assertEqual(err[-2], ' ^') + finally: + unlink(TESTFN) + def test_attributes_new_constructor(self): args = ("bad.py", 1, 2, "abcdefg", 1, 100) the_exception = SyntaxError("bad bad", args) diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-19-22-57-42.bpo-45848.HgVBJ5.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-19-22-57-42.bpo-45848.HgVBJ5.rst new file mode 100644 index 0000000000000..d9394c9c1f08b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-19-22-57-42.bpo-45848.HgVBJ5.rst @@ -0,0 +1,2 @@ +Allow the parser to obtain error lines directly from encoded files. Patch by +Pablo Galindo diff --git a/Parser/pegen.c b/Parser/pegen.c index 09c1a19a79364..b3fdae487d970 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -482,14 +482,12 @@ _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, goto error; } - // PyErr_ProgramTextObject assumes that the text is utf-8 so we cannot call it with a file - // with an arbitrary encoding or otherwise we could get some badly decoded text. - int uses_utf8_codec = (!p->tok->encoding || strcmp(p->tok->encoding, "utf-8") == 0); if (p->tok->fp_interactive) { error_line = get_error_line(p, lineno); } - else if (uses_utf8_codec && p->start_rule == Py_file_input) { - error_line = PyErr_ProgramTextObject(p->tok->filename, (int) lineno); + else if (p->start_rule == Py_file_input) { + error_line = _PyErr_ProgramDecodedTextObject(p->tok->filename, + (int) lineno, p->tok->encoding); } if (!error_line) { @@ -500,15 +498,18 @@ _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, we're actually parsing from a file, which has an E_EOF SyntaxError and in that case `PyErr_ProgramTextObject` fails because lineno points to last_file_line + 1, which does not physically exist */ - assert(p->tok->fp == NULL || p->tok->fp == stdin || p->tok->done == E_EOF || !uses_utf8_codec); + assert(p->tok->fp == NULL || p->tok->fp == stdin || p->tok->done == E_EOF); if (p->tok->lineno <= lineno && p->tok->inp > p->tok->buf) { Py_ssize_t size = p->tok->inp - p->tok->buf; error_line = PyUnicode_DecodeUTF8(p->tok->buf, size, "replace"); } - else { + else if (p->tok->fp == NULL || p->tok->fp == stdin) { error_line = get_error_line(p, lineno); } + else { + error_line = PyUnicode_FromStringAndSize("", 0); + } if (!error_line) { goto error; } diff --git a/Python/errors.c b/Python/errors.c index 519f2d459effd..cb3938d20856f 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -1692,7 +1692,7 @@ PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset) functionality in tb_displayline() in traceback.c. */ static PyObject * -err_programtext(PyThreadState *tstate, FILE *fp, int lineno) +err_programtext(PyThreadState *tstate, FILE *fp, int lineno, const char* encoding) { int i; char linebuf[1000]; @@ -1720,7 +1720,11 @@ err_programtext(PyThreadState *tstate, FILE *fp, int lineno) fclose(fp); if (i == lineno) { PyObject *res; - res = PyUnicode_FromString(linebuf); + if (encoding != NULL) { + res = PyUnicode_Decode(linebuf, strlen(linebuf), encoding, "replace"); + } else { + res = PyUnicode_FromString(linebuf); + } if (res == NULL) _PyErr_Clear(tstate); return res; @@ -1746,7 +1750,7 @@ PyErr_ProgramText(const char *filename, int lineno) } PyObject * -PyErr_ProgramTextObject(PyObject *filename, int lineno) +_PyErr_ProgramDecodedTextObject(PyObject *filename, int lineno, const char* encoding) { if (filename == NULL || lineno <= 0) { return NULL; @@ -1758,7 +1762,13 @@ PyErr_ProgramTextObject(PyObject *filename, int lineno) _PyErr_Clear(tstate); return NULL; } - return err_programtext(tstate, fp, lineno); + return err_programtext(tstate, fp, lineno, encoding); +} + +PyObject * +PyErr_ProgramTextObject(PyObject *filename, int lineno) +{ + return _PyErr_ProgramDecodedTextObject(filename, lineno, NULL); } #ifdef __cplusplus From webhook-mailer at python.org Sat Nov 20 10:35:06 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 20 Nov 2021 15:35:06 -0000 Subject: [Python-checkins] [3.10] bpo-45848: Allow the parser to get error lines from encoded files (GH-29646) (GH-29661) Message-ID: https://github.com/python/cpython/commit/904af3de2bef6d971463a564541cb6dadf22d7f8 commit: 904af3de2bef6d971463a564541cb6dadf22d7f8 branch: 3.10 author: ?ukasz Langa committer: ambv date: 2021-11-20T16:34:56+01:00 summary: [3.10] bpo-45848: Allow the parser to get error lines from encoded files (GH-29646) (GH-29661) (cherry picked from commit fdcc46d9554094994f78bedf6dc9220e5d5ee668) Co-authored-by: Pablo Galindo Salgado files: A Misc/NEWS.d/next/Core and Builtins/2021-11-19-22-57-42.bpo-45848.HgVBJ5.rst M .gitignore M Include/cpython/pyerrors.h M Lib/test/test_exceptions.py M Parser/pegen.c M Python/errors.c diff --git a/.gitignore b/.gitignore index d0b608892a87c..19b4214a9aea0 100644 --- a/.gitignore +++ b/.gitignore @@ -134,3 +134,9 @@ Tools/ssl/win32 # Ignore ./python binary on Unix but still look into ./Python/ directory. /python !/Python/ + +# Artifacts generated by 3.11 lying around when switching branches: +/_bootstrap_python +/Programs/_freeze_module +/Python/deepfreeze/ +/Python/frozen_modules/ \ No newline at end of file diff --git a/Include/cpython/pyerrors.h b/Include/cpython/pyerrors.h index 5e57129c3b82c..3f952456679ec 100644 --- a/Include/cpython/pyerrors.h +++ b/Include/cpython/pyerrors.h @@ -185,6 +185,12 @@ Py_DEPRECATED(3.3) PyAPI_FUNC(PyObject *) PyUnicodeTranslateError_Create( Py_ssize_t end, const char *reason /* UTF-8 encoded string */ ); + +PyAPI_FUNC(PyObject *) _PyErr_ProgramDecodedTextObject( + PyObject *filename, + int lineno, + const char* encoding); + PyAPI_FUNC(PyObject *) _PyUnicodeTranslateError_Create( PyObject *object, Py_ssize_t start, diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 8419f582cbdb9..04c883cf53ba3 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -2352,6 +2352,19 @@ def test_encodings(self): finally: unlink(TESTFN) + # Check backwards tokenizer errors + source = '# -*- coding: ascii -*-\n\n(\n' + try: + with open(TESTFN, 'w', encoding='ascii') as testfile: + testfile.write(source) + rc, out, err = script_helper.assert_python_failure('-Wd', '-X', 'utf8', TESTFN) + err = err.decode('utf-8').splitlines() + + self.assertEqual(err[-3], ' (') + self.assertEqual(err[-2], ' ^') + finally: + unlink(TESTFN) + def test_attributes_new_constructor(self): args = ("bad.py", 1, 2, "abcdefg", 1, 100) the_exception = SyntaxError("bad bad", args) diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-19-22-57-42.bpo-45848.HgVBJ5.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-19-22-57-42.bpo-45848.HgVBJ5.rst new file mode 100644 index 0000000000000..d9394c9c1f08b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-19-22-57-42.bpo-45848.HgVBJ5.rst @@ -0,0 +1,2 @@ +Allow the parser to obtain error lines directly from encoded files. Patch by +Pablo Galindo diff --git a/Parser/pegen.c b/Parser/pegen.c index c6570eb1bd0b4..9bf4fe7ecd89d 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -480,14 +480,12 @@ _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, goto error; } - // PyErr_ProgramTextObject assumes that the text is utf-8 so we cannot call it with a file - // with an arbitrary encoding or otherwise we could get some badly decoded text. - int uses_utf8_codec = (!p->tok->encoding || strcmp(p->tok->encoding, "utf-8") == 0); if (p->tok->fp_interactive) { error_line = get_error_line(p, lineno); } - else if (uses_utf8_codec && p->start_rule == Py_file_input) { - error_line = PyErr_ProgramTextObject(p->tok->filename, (int) lineno); + else if (p->start_rule == Py_file_input) { + error_line = _PyErr_ProgramDecodedTextObject(p->tok->filename, + (int) lineno, p->tok->encoding); } if (!error_line) { @@ -498,15 +496,18 @@ _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, we're actually parsing from a file, which has an E_EOF SyntaxError and in that case `PyErr_ProgramTextObject` fails because lineno points to last_file_line + 1, which does not physically exist */ - assert(p->tok->fp == NULL || p->tok->fp == stdin || p->tok->done == E_EOF || !uses_utf8_codec); + assert(p->tok->fp == NULL || p->tok->fp == stdin || p->tok->done == E_EOF); if (p->tok->lineno <= lineno && p->tok->inp > p->tok->buf) { Py_ssize_t size = p->tok->inp - p->tok->buf; error_line = PyUnicode_DecodeUTF8(p->tok->buf, size, "replace"); } - else { + else if (p->tok->fp == NULL || p->tok->fp == stdin) { error_line = get_error_line(p, lineno); } + else { + error_line = PyUnicode_FromStringAndSize("", 0); + } if (!error_line) { goto error; } diff --git a/Python/errors.c b/Python/errors.c index 600300e263d09..bc1b55e440e8a 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -1724,7 +1724,7 @@ PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset) functionality in tb_displayline() in traceback.c. */ static PyObject * -err_programtext(PyThreadState *tstate, FILE *fp, int lineno) +err_programtext(PyThreadState *tstate, FILE *fp, int lineno, const char* encoding) { int i; char linebuf[1000]; @@ -1752,7 +1752,11 @@ err_programtext(PyThreadState *tstate, FILE *fp, int lineno) fclose(fp); if (i == lineno) { PyObject *res; - res = PyUnicode_FromString(linebuf); + if (encoding != NULL) { + res = PyUnicode_Decode(linebuf, strlen(linebuf), encoding, "replace"); + } else { + res = PyUnicode_FromString(linebuf); + } if (res == NULL) _PyErr_Clear(tstate); return res; @@ -1778,7 +1782,7 @@ PyErr_ProgramText(const char *filename, int lineno) } PyObject * -PyErr_ProgramTextObject(PyObject *filename, int lineno) +_PyErr_ProgramDecodedTextObject(PyObject *filename, int lineno, const char* encoding) { if (filename == NULL || lineno <= 0) { return NULL; @@ -1790,7 +1794,13 @@ PyErr_ProgramTextObject(PyObject *filename, int lineno) _PyErr_Clear(tstate); return NULL; } - return err_programtext(tstate, fp, lineno); + return err_programtext(tstate, fp, lineno, encoding); +} + +PyObject * +PyErr_ProgramTextObject(PyObject *filename, int lineno) +{ + return _PyErr_ProgramDecodedTextObject(filename, lineno, NULL); } #ifdef __cplusplus From webhook-mailer at python.org Sat Nov 20 10:43:17 2021 From: webhook-mailer at python.org (tiran) Date: Sat, 20 Nov 2021 15:43:17 -0000 Subject: [Python-checkins] bpo-45847: Port test modules to PY_STDLIB_MOD (GH-29660) Message-ID: https://github.com/python/cpython/commit/f36c69a26ee880acf62a5ae8c5da49312e84c66d commit: f36c69a26ee880acf62a5ae8c5da49312e84c66d branch: main author: Christian Heimes committer: tiran date: 2021-11-20T16:43:10+01:00 summary: bpo-45847: Port test modules to PY_STDLIB_MOD (GH-29660) files: M Makefile.pre.in M Modules/Setup.stdlib.in M configure M configure.ac M setup.py diff --git a/Makefile.pre.in b/Makefile.pre.in index 312e52486f296..11ffdaabc617b 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -211,11 +211,13 @@ OPENSSL_LIBS=@OPENSSL_LIBS@ OPENSSL_LDFLAGS=@OPENSSL_LDFLAGS@ OPENSSL_RPATH=@OPENSSL_RPATH@ -# Module compiler and linker flags -# yes: module is available -# missing: build dependency is missing -# disabled: module is disabled -# n/a: module is not available on the current platform +# Module state, compiler flags and linker flags +# Empty CFLAGS and LDFLAGS are omitted. +# states: +# * yes: module is available +# * missing: build dependency is missing +# * disabled: module is disabled +# * n/a: module is not available on the current platform # MODULE_EGG=yes # yes, missing, disabled, n/a # MODULE_EGG_CFLAGS= # MODULE_EGG_LDFLAGS= diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 4e5c158c0fdb2..fa553fb524f56 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -76,3 +76,18 @@ # _scproxy needs SystemConfiguration and CoreFoundation framework @MODULE__SCPROXY_TRUE at _scproxy _scproxy.c + + +############################################################################ +# Test modules + + at MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c + at MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c + at MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c + +# Some testing modules MUST be built as shared libraries. +*shared* + at MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c + at MODULE__TESTIMPORTMULTIPLE_TRUE@_testimportmultiple _testimportmultiple.c + at MODULE__TESTMULTIPHASE_TRUE@_testmultiphase _testmultiphase.c + at MODULE__CTYPES_TEST_TRUE@_ctypes_test _ctypes/_ctypes_test.c diff --git a/configure b/configure index dec3aa0586b83..7d2ef8f912073 100755 --- a/configure +++ b/configure @@ -624,6 +624,20 @@ ac_includes_default="\ ac_subst_vars='LTLIBOBJS MODULE_BLOCK +MODULE__CTYPES_TEST_FALSE +MODULE__CTYPES_TEST_TRUE +MODULE__XXTESTFUZZ_FALSE +MODULE__XXTESTFUZZ_TRUE +MODULE__TESTMULTIPHASE_FALSE +MODULE__TESTMULTIPHASE_TRUE +MODULE__TESTIMPORTMULTIPLE_FALSE +MODULE__TESTIMPORTMULTIPLE_TRUE +MODULE__TESTBUFFER_FALSE +MODULE__TESTBUFFER_TRUE +MODULE__TESTINTERNALCAPI_FALSE +MODULE__TESTINTERNALCAPI_TRUE +MODULE__TESTCAPI_FALSE +MODULE__TESTCAPI_TRUE MODULE__SQLITE3_FALSE MODULE__SQLITE3_TRUE MODULE__DECIMAL_FALSE @@ -19560,20 +19574,11 @@ esac as_fn_append MODULE_BLOCK "MODULE_OSSAUDIODEV=$py_cv_module_ossaudiodev$as_nl" if test "x$py_cv_module_ossaudiodev" = xyes; then : - as_fn_append MODULE_BLOCK "MODULE_OSSAUDIODEV_CFLAGS=$as_nl" - as_fn_append MODULE_BLOCK "MODULE_OSSAUDIODEV_LDFLAGS=$as_nl" - if true; then - MODULE_OSSAUDIODEV_TRUE= - MODULE_OSSAUDIODEV_FALSE='#' -else - MODULE_OSSAUDIODEV_TRUE='#' - MODULE_OSSAUDIODEV_FALSE= -fi -else - if false; then +fi + if test "$py_cv_module_ossaudiodev" = yes; then MODULE_OSSAUDIODEV_TRUE= MODULE_OSSAUDIODEV_FALSE='#' else @@ -19581,8 +19586,6 @@ else MODULE_OSSAUDIODEV_FALSE= fi - -fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module_ossaudiodev" >&5 $as_echo "$py_cv_module_ossaudiodev" >&6; } @@ -19610,20 +19613,11 @@ esac as_fn_append MODULE_BLOCK "MODULE__SCPROXY=$py_cv_module__scproxy$as_nl" if test "x$py_cv_module__scproxy" = xyes; then : - as_fn_append MODULE_BLOCK "MODULE__SCPROXY_CFLAGS=$as_nl" - as_fn_append MODULE_BLOCK "MODULE__SCPROXY_LDFLAGS=-framework SystemConfiguration -framework CoreFoundation$as_nl" - if true; then - MODULE__SCPROXY_TRUE= - MODULE__SCPROXY_FALSE='#' -else - MODULE__SCPROXY_TRUE='#' - MODULE__SCPROXY_FALSE= -fi - -else + as_fn_append MODULE_BLOCK "MODULE__SCPROXY_LDFLAGS=-framework SystemConfiguration -framework CoreFoundation$as_nl" - if false; then +fi + if test "$py_cv_module__scproxy" = yes; then MODULE__SCPROXY_TRUE= MODULE__SCPROXY_FALSE='#' else @@ -19631,8 +19625,6 @@ else MODULE__SCPROXY_FALSE= fi - -fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__scproxy" >&5 $as_echo "$py_cv_module__scproxy" >&6; } @@ -19663,18 +19655,9 @@ esac as_fn_append MODULE_BLOCK "MODULE_PYEXPAT_CFLAGS=$LIBEXPAT_CFLAGS$as_nl" as_fn_append MODULE_BLOCK "MODULE_PYEXPAT_LDFLAGS=$LIBEXPAT_LDFLAGS$as_nl" - if true; then - MODULE_PYEXPAT_TRUE= - MODULE_PYEXPAT_FALSE='#' -else - MODULE_PYEXPAT_TRUE='#' - MODULE_PYEXPAT_FALSE= -fi - -else - - if false; then +fi + if test "$py_cv_module_pyexpat" = yes; then MODULE_PYEXPAT_TRUE= MODULE_PYEXPAT_FALSE='#' else @@ -19682,8 +19665,6 @@ else MODULE_PYEXPAT_FALSE= fi - -fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module_pyexpat" >&5 $as_echo "$py_cv_module_pyexpat" >&6; } @@ -19712,19 +19693,10 @@ esac if test "x$py_cv_module__elementtree" = xyes; then : as_fn_append MODULE_BLOCK "MODULE__ELEMENTTREE_CFLAGS=$LIBEXPAT_CFLAGS$as_nl" - as_fn_append MODULE_BLOCK "MODULE__ELEMENTTREE_LDFLAGS=$as_nl" - if true; then - MODULE__ELEMENTTREE_TRUE= - MODULE__ELEMENTTREE_FALSE='#' -else - MODULE__ELEMENTTREE_TRUE='#' - MODULE__ELEMENTTREE_FALSE= -fi - -else - if false; then +fi + if test "$py_cv_module__elementtree" = yes; then MODULE__ELEMENTTREE_TRUE= MODULE__ELEMENTTREE_FALSE='#' else @@ -19732,8 +19704,6 @@ else MODULE__ELEMENTTREE_FALSE= fi - -fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__elementtree" >&5 $as_echo "$py_cv_module__elementtree" >&6; } @@ -19762,20 +19732,11 @@ esac as_fn_append MODULE_BLOCK "MODULE__MD5=$py_cv_module__md5$as_nl" if test "x$py_cv_module__md5" = xyes; then : - as_fn_append MODULE_BLOCK "MODULE__MD5_CFLAGS=$as_nl" - as_fn_append MODULE_BLOCK "MODULE__MD5_LDFLAGS=$as_nl" - if true; then - MODULE__MD5_TRUE= - MODULE__MD5_FALSE='#' -else - MODULE__MD5_TRUE='#' - MODULE__MD5_FALSE= -fi -else - if false; then +fi + if test "$py_cv_module__md5" = yes; then MODULE__MD5_TRUE= MODULE__MD5_FALSE='#' else @@ -19783,8 +19744,6 @@ else MODULE__MD5_FALSE= fi - -fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__md5" >&5 $as_echo "$py_cv_module__md5" >&6; } @@ -19812,20 +19771,11 @@ esac as_fn_append MODULE_BLOCK "MODULE__SHA1=$py_cv_module__sha1$as_nl" if test "x$py_cv_module__sha1" = xyes; then : - as_fn_append MODULE_BLOCK "MODULE__SHA1_CFLAGS=$as_nl" - as_fn_append MODULE_BLOCK "MODULE__SHA1_LDFLAGS=$as_nl" - if true; then - MODULE__SHA1_TRUE= - MODULE__SHA1_FALSE='#' -else - MODULE__SHA1_TRUE='#' - MODULE__SHA1_FALSE= -fi -else - if false; then +fi + if test "$py_cv_module__sha1" = yes; then MODULE__SHA1_TRUE= MODULE__SHA1_FALSE='#' else @@ -19833,8 +19783,6 @@ else MODULE__SHA1_FALSE= fi - -fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__sha1" >&5 $as_echo "$py_cv_module__sha1" >&6; } @@ -19862,20 +19810,11 @@ esac as_fn_append MODULE_BLOCK "MODULE__SHA256=$py_cv_module__sha256$as_nl" if test "x$py_cv_module__sha256" = xyes; then : - as_fn_append MODULE_BLOCK "MODULE__SHA256_CFLAGS=$as_nl" - as_fn_append MODULE_BLOCK "MODULE__SHA256_LDFLAGS=$as_nl" - if true; then - MODULE__SHA256_TRUE= - MODULE__SHA256_FALSE='#' -else - MODULE__SHA256_TRUE='#' - MODULE__SHA256_FALSE= -fi -else - if false; then +fi + if test "$py_cv_module__sha256" = yes; then MODULE__SHA256_TRUE= MODULE__SHA256_FALSE='#' else @@ -19883,8 +19822,6 @@ else MODULE__SHA256_FALSE= fi - -fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__sha256" >&5 $as_echo "$py_cv_module__sha256" >&6; } @@ -19912,20 +19849,11 @@ esac as_fn_append MODULE_BLOCK "MODULE__SHA512=$py_cv_module__sha512$as_nl" if test "x$py_cv_module__sha512" = xyes; then : - as_fn_append MODULE_BLOCK "MODULE__SHA512_CFLAGS=$as_nl" - as_fn_append MODULE_BLOCK "MODULE__SHA512_LDFLAGS=$as_nl" - if true; then - MODULE__SHA512_TRUE= - MODULE__SHA512_FALSE='#' -else - MODULE__SHA512_TRUE='#' - MODULE__SHA512_FALSE= -fi -else - if false; then +fi + if test "$py_cv_module__sha512" = yes; then MODULE__SHA512_TRUE= MODULE__SHA512_FALSE='#' else @@ -19933,8 +19861,6 @@ else MODULE__SHA512_FALSE= fi - -fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__sha512" >&5 $as_echo "$py_cv_module__sha512" >&6; } @@ -19962,20 +19888,11 @@ esac as_fn_append MODULE_BLOCK "MODULE__SHA3=$py_cv_module__sha3$as_nl" if test "x$py_cv_module__sha3" = xyes; then : - as_fn_append MODULE_BLOCK "MODULE__SHA3_CFLAGS=$as_nl" - as_fn_append MODULE_BLOCK "MODULE__SHA3_LDFLAGS=$as_nl" - if true; then - MODULE__SHA3_TRUE= - MODULE__SHA3_FALSE='#' -else - MODULE__SHA3_TRUE='#' - MODULE__SHA3_FALSE= -fi -else - if false; then +fi + if test "$py_cv_module__sha3" = yes; then MODULE__SHA3_TRUE= MODULE__SHA3_FALSE='#' else @@ -19983,8 +19900,6 @@ else MODULE__SHA3_FALSE= fi - -fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__sha3" >&5 $as_echo "$py_cv_module__sha3" >&6; } @@ -20012,20 +19927,11 @@ esac as_fn_append MODULE_BLOCK "MODULE__BLAKE2=$py_cv_module__blake2$as_nl" if test "x$py_cv_module__blake2" = xyes; then : - as_fn_append MODULE_BLOCK "MODULE__BLAKE2_CFLAGS=$as_nl" - as_fn_append MODULE_BLOCK "MODULE__BLAKE2_LDFLAGS=$as_nl" - if true; then - MODULE__BLAKE2_TRUE= - MODULE__BLAKE2_FALSE='#' -else - MODULE__BLAKE2_TRUE='#' - MODULE__BLAKE2_FALSE= -fi -else - if false; then +fi + if test "$py_cv_module__blake2" = yes; then MODULE__BLAKE2_TRUE= MODULE__BLAKE2_FALSE='#' else @@ -20033,8 +19939,6 @@ else MODULE__BLAKE2_FALSE= fi - -fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__blake2" >&5 $as_echo "$py_cv_module__blake2" >&6; } @@ -20065,18 +19969,9 @@ esac as_fn_append MODULE_BLOCK "MODULE__DECIMAL_CFLAGS=$LIBMPDEC_CFLAGS$as_nl" as_fn_append MODULE_BLOCK "MODULE__DECIMAL_LDFLAGS=$LIBMPDEC_LDFLAGS$as_nl" - if true; then - MODULE__DECIMAL_TRUE= - MODULE__DECIMAL_FALSE='#' -else - MODULE__DECIMAL_TRUE='#' - MODULE__DECIMAL_FALSE= -fi - -else - - if false; then +fi + if test "$py_cv_module__decimal" = yes; then MODULE__DECIMAL_TRUE= MODULE__DECIMAL_FALSE='#' else @@ -20084,8 +19979,6 @@ else MODULE__DECIMAL_FALSE= fi - -fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__decimal" >&5 $as_echo "$py_cv_module__decimal" >&6; } @@ -20115,7 +20008,9 @@ esac as_fn_append MODULE_BLOCK "MODULE__SQLITE3_CFLAGS=$LIBSQLITE3_CFLAGS$as_nl" as_fn_append MODULE_BLOCK "MODULE__SQLITE3_LDFLAGS=$LIBSQLITE3_LIBS$as_nl" - if true; then + +fi + if test "$py_cv_module__sqlite3" = yes; then MODULE__SQLITE3_TRUE= MODULE__SQLITE3_FALSE='#' else @@ -20123,21 +20018,282 @@ else MODULE__SQLITE3_FALSE= fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__sqlite3" >&5 +$as_echo "$py_cv_module__sqlite3" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _testcapi" >&5 +$as_echo_n "checking for stdlib extension module _testcapi... " >&6; } + case $py_stdlib_not_available in #( + *_testcapi*) : + py_cv_module__testcapi=n/a ;; #( + *) : + + if test "$TEST_MODULES" = yes; then : + if true; then : + py_cv_module__testcapi=yes else + py_cv_module__testcapi=missing +fi +else + py_cv_module__testcapi=disabled - if false; then - MODULE__SQLITE3_TRUE= - MODULE__SQLITE3_FALSE='#' +fi + + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__TESTCAPI=$py_cv_module__testcapi$as_nl" + if test "x$py_cv_module__testcapi" = xyes; then : + + + + +fi + if test "$py_cv_module__testcapi" = yes; then + MODULE__TESTCAPI_TRUE= + MODULE__TESTCAPI_FALSE='#' else - MODULE__SQLITE3_TRUE='#' - MODULE__SQLITE3_FALSE= + MODULE__TESTCAPI_TRUE='#' + MODULE__TESTCAPI_FALSE= fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__testcapi" >&5 +$as_echo "$py_cv_module__testcapi" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _testinternalcapi" >&5 +$as_echo_n "checking for stdlib extension module _testinternalcapi... " >&6; } + case $py_stdlib_not_available in #( + *_testinternalcapi*) : + py_cv_module__testinternalcapi=n/a ;; #( + *) : + + if test "$TEST_MODULES" = yes; then : + if true; then : + py_cv_module__testinternalcapi=yes +else + py_cv_module__testinternalcapi=missing fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__sqlite3" >&5 -$as_echo "$py_cv_module__sqlite3" >&6; } +else + py_cv_module__testinternalcapi=disabled + +fi + + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__TESTINTERNALCAPI=$py_cv_module__testinternalcapi$as_nl" + if test "x$py_cv_module__testinternalcapi" = xyes; then : + + + + +fi + if test "$py_cv_module__testinternalcapi" = yes; then + MODULE__TESTINTERNALCAPI_TRUE= + MODULE__TESTINTERNALCAPI_FALSE='#' +else + MODULE__TESTINTERNALCAPI_TRUE='#' + MODULE__TESTINTERNALCAPI_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__testinternalcapi" >&5 +$as_echo "$py_cv_module__testinternalcapi" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _testbuffer" >&5 +$as_echo_n "checking for stdlib extension module _testbuffer... " >&6; } + case $py_stdlib_not_available in #( + *_testbuffer*) : + py_cv_module__testbuffer=n/a ;; #( + *) : + + if test "$TEST_MODULES" = yes; then : + if true; then : + py_cv_module__testbuffer=yes +else + py_cv_module__testbuffer=missing +fi +else + py_cv_module__testbuffer=disabled + +fi + + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__TESTBUFFER=$py_cv_module__testbuffer$as_nl" + if test "x$py_cv_module__testbuffer" = xyes; then : + + + + +fi + if test "$py_cv_module__testbuffer" = yes; then + MODULE__TESTBUFFER_TRUE= + MODULE__TESTBUFFER_FALSE='#' +else + MODULE__TESTBUFFER_TRUE='#' + MODULE__TESTBUFFER_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__testbuffer" >&5 +$as_echo "$py_cv_module__testbuffer" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _testimportmultiple" >&5 +$as_echo_n "checking for stdlib extension module _testimportmultiple... " >&6; } + case $py_stdlib_not_available in #( + *_testimportmultiple*) : + py_cv_module__testimportmultiple=n/a ;; #( + *) : + + if test "$TEST_MODULES" = yes; then : + if true; then : + py_cv_module__testimportmultiple=yes +else + py_cv_module__testimportmultiple=missing +fi +else + py_cv_module__testimportmultiple=disabled + +fi + + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__TESTIMPORTMULTIPLE=$py_cv_module__testimportmultiple$as_nl" + if test "x$py_cv_module__testimportmultiple" = xyes; then : + + + + +fi + if test "$py_cv_module__testimportmultiple" = yes; then + MODULE__TESTIMPORTMULTIPLE_TRUE= + MODULE__TESTIMPORTMULTIPLE_FALSE='#' +else + MODULE__TESTIMPORTMULTIPLE_TRUE='#' + MODULE__TESTIMPORTMULTIPLE_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__testimportmultiple" >&5 +$as_echo "$py_cv_module__testimportmultiple" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _testmultiphase" >&5 +$as_echo_n "checking for stdlib extension module _testmultiphase... " >&6; } + case $py_stdlib_not_available in #( + *_testmultiphase*) : + py_cv_module__testmultiphase=n/a ;; #( + *) : + + if test "$TEST_MODULES" = yes; then : + if true; then : + py_cv_module__testmultiphase=yes +else + py_cv_module__testmultiphase=missing +fi +else + py_cv_module__testmultiphase=disabled + +fi + + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__TESTMULTIPHASE=$py_cv_module__testmultiphase$as_nl" + if test "x$py_cv_module__testmultiphase" = xyes; then : + + + + +fi + if test "$py_cv_module__testmultiphase" = yes; then + MODULE__TESTMULTIPHASE_TRUE= + MODULE__TESTMULTIPHASE_FALSE='#' +else + MODULE__TESTMULTIPHASE_TRUE='#' + MODULE__TESTMULTIPHASE_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__testmultiphase" >&5 +$as_echo "$py_cv_module__testmultiphase" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _xxtestfuzz" >&5 +$as_echo_n "checking for stdlib extension module _xxtestfuzz... " >&6; } + case $py_stdlib_not_available in #( + *_xxtestfuzz*) : + py_cv_module__xxtestfuzz=n/a ;; #( + *) : + + if test "$TEST_MODULES" = yes; then : + if true; then : + py_cv_module__xxtestfuzz=yes +else + py_cv_module__xxtestfuzz=missing +fi +else + py_cv_module__xxtestfuzz=disabled + +fi + + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__XXTESTFUZZ=$py_cv_module__xxtestfuzz$as_nl" + if test "x$py_cv_module__xxtestfuzz" = xyes; then : + + + + +fi + if test "$py_cv_module__xxtestfuzz" = yes; then + MODULE__XXTESTFUZZ_TRUE= + MODULE__XXTESTFUZZ_FALSE='#' +else + MODULE__XXTESTFUZZ_TRUE='#' + MODULE__XXTESTFUZZ_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__xxtestfuzz" >&5 +$as_echo "$py_cv_module__xxtestfuzz" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _ctypes_test" >&5 +$as_echo_n "checking for stdlib extension module _ctypes_test... " >&6; } + case $py_stdlib_not_available in #( + *_ctypes_test*) : + py_cv_module__ctypes_test=n/a ;; #( + *) : + + if test "$TEST_MODULES" = yes; then : + if true; then : + py_cv_module__ctypes_test=yes +else + py_cv_module__ctypes_test=missing +fi +else + py_cv_module__ctypes_test=disabled + +fi + + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__CTYPES_TEST=$py_cv_module__ctypes_test$as_nl" + if test "x$py_cv_module__ctypes_test" = xyes; then : + + + as_fn_append MODULE_BLOCK "MODULE__CTYPES_TEST_LDFLAGS=-lm$as_nl" + +fi + if test "$py_cv_module__ctypes_test" = yes; then + MODULE__CTYPES_TEST_TRUE= + MODULE__CTYPES_TEST_FALSE='#' +else + MODULE__CTYPES_TEST_TRUE='#' + MODULE__CTYPES_TEST_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__ctypes_test" >&5 +$as_echo "$py_cv_module__ctypes_test" >&6; } # substitute multiline block, must come after last PY_STDLIB_MOD() @@ -20276,22 +20432,10 @@ if test -z "${MODULE_OSSAUDIODEV_TRUE}" && test -z "${MODULE_OSSAUDIODEV_FALSE}" as_fn_error $? "conditional \"MODULE_OSSAUDIODEV\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${MODULE_OSSAUDIODEV_TRUE}" && test -z "${MODULE_OSSAUDIODEV_FALSE}"; then - as_fn_error $? "conditional \"MODULE_OSSAUDIODEV\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${MODULE__SCPROXY_TRUE}" && test -z "${MODULE__SCPROXY_FALSE}"; then as_fn_error $? "conditional \"MODULE__SCPROXY\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${MODULE__SCPROXY_TRUE}" && test -z "${MODULE__SCPROXY_FALSE}"; then - as_fn_error $? "conditional \"MODULE__SCPROXY\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${MODULE_PYEXPAT_TRUE}" && test -z "${MODULE_PYEXPAT_FALSE}"; then - as_fn_error $? "conditional \"MODULE_PYEXPAT\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${MODULE_PYEXPAT_TRUE}" && test -z "${MODULE_PYEXPAT_FALSE}"; then as_fn_error $? "conditional \"MODULE_PYEXPAT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -20300,14 +20444,6 @@ if test -z "${MODULE__ELEMENTTREE_TRUE}" && test -z "${MODULE__ELEMENTTREE_FALSE as_fn_error $? "conditional \"MODULE__ELEMENTTREE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${MODULE__ELEMENTTREE_TRUE}" && test -z "${MODULE__ELEMENTTREE_FALSE}"; then - as_fn_error $? "conditional \"MODULE__ELEMENTTREE\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${MODULE__MD5_TRUE}" && test -z "${MODULE__MD5_FALSE}"; then - as_fn_error $? "conditional \"MODULE__MD5\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${MODULE__MD5_TRUE}" && test -z "${MODULE__MD5_FALSE}"; then as_fn_error $? "conditional \"MODULE__MD5\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -20316,14 +20452,6 @@ if test -z "${MODULE__SHA1_TRUE}" && test -z "${MODULE__SHA1_FALSE}"; then as_fn_error $? "conditional \"MODULE__SHA1\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${MODULE__SHA1_TRUE}" && test -z "${MODULE__SHA1_FALSE}"; then - as_fn_error $? "conditional \"MODULE__SHA1\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${MODULE__SHA256_TRUE}" && test -z "${MODULE__SHA256_FALSE}"; then - as_fn_error $? "conditional \"MODULE__SHA256\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${MODULE__SHA256_TRUE}" && test -z "${MODULE__SHA256_FALSE}"; then as_fn_error $? "conditional \"MODULE__SHA256\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -20332,14 +20460,6 @@ if test -z "${MODULE__SHA512_TRUE}" && test -z "${MODULE__SHA512_FALSE}"; then as_fn_error $? "conditional \"MODULE__SHA512\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${MODULE__SHA512_TRUE}" && test -z "${MODULE__SHA512_FALSE}"; then - as_fn_error $? "conditional \"MODULE__SHA512\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${MODULE__SHA3_TRUE}" && test -z "${MODULE__SHA3_FALSE}"; then - as_fn_error $? "conditional \"MODULE__SHA3\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${MODULE__SHA3_TRUE}" && test -z "${MODULE__SHA3_FALSE}"; then as_fn_error $? "conditional \"MODULE__SHA3\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -20348,14 +20468,6 @@ if test -z "${MODULE__BLAKE2_TRUE}" && test -z "${MODULE__BLAKE2_FALSE}"; then as_fn_error $? "conditional \"MODULE__BLAKE2\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${MODULE__BLAKE2_TRUE}" && test -z "${MODULE__BLAKE2_FALSE}"; then - as_fn_error $? "conditional \"MODULE__BLAKE2\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${MODULE__DECIMAL_TRUE}" && test -z "${MODULE__DECIMAL_FALSE}"; then - as_fn_error $? "conditional \"MODULE__DECIMAL\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${MODULE__DECIMAL_TRUE}" && test -z "${MODULE__DECIMAL_FALSE}"; then as_fn_error $? "conditional \"MODULE__DECIMAL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -20364,8 +20476,32 @@ if test -z "${MODULE__SQLITE3_TRUE}" && test -z "${MODULE__SQLITE3_FALSE}"; then as_fn_error $? "conditional \"MODULE__SQLITE3\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${MODULE__SQLITE3_TRUE}" && test -z "${MODULE__SQLITE3_FALSE}"; then - as_fn_error $? "conditional \"MODULE__SQLITE3\" was never defined. +if test -z "${MODULE__TESTCAPI_TRUE}" && test -z "${MODULE__TESTCAPI_FALSE}"; then + as_fn_error $? "conditional \"MODULE__TESTCAPI\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__TESTINTERNALCAPI_TRUE}" && test -z "${MODULE__TESTINTERNALCAPI_FALSE}"; then + as_fn_error $? "conditional \"MODULE__TESTINTERNALCAPI\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__TESTBUFFER_TRUE}" && test -z "${MODULE__TESTBUFFER_FALSE}"; then + as_fn_error $? "conditional \"MODULE__TESTBUFFER\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__TESTIMPORTMULTIPLE_TRUE}" && test -z "${MODULE__TESTIMPORTMULTIPLE_FALSE}"; then + as_fn_error $? "conditional \"MODULE__TESTIMPORTMULTIPLE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__TESTMULTIPHASE_TRUE}" && test -z "${MODULE__TESTMULTIPHASE_FALSE}"; then + as_fn_error $? "conditional \"MODULE__TESTMULTIPHASE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__XXTESTFUZZ_TRUE}" && test -z "${MODULE__XXTESTFUZZ_FALSE}"; then + as_fn_error $? "conditional \"MODULE__XXTESTFUZZ\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__CTYPES_TEST_TRUE}" && test -z "${MODULE__CTYPES_TEST_FALSE}"; then + as_fn_error $? "conditional \"MODULE__CTYPES_TEST\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi diff --git a/configure.ac b/configure.ac index f4adab19d6138..6c24a278595a6 100644 --- a/configure.ac +++ b/configure.ac @@ -6028,12 +6028,10 @@ AC_DEFUN([PY_STDLIB_MOD], [ ) _MODULE_BLOCK_ADD(modcond, [$modstate]) AS_VAR_IF([modstate], [yes], [ - _MODULE_BLOCK_ADD([MODULE_]m4_toupper([$1])[_CFLAGS], [$4]) - _MODULE_BLOCK_ADD([MODULE_]m4_toupper([$1])[_LDFLAGS], [$5]) - AM_CONDITIONAL(modcond, [true]) - ], [ - AM_CONDITIONAL(modcond, [false]) + m4_ifblank([$4], [], [_MODULE_BLOCK_ADD([MODULE_]m4_toupper([$1])[_CFLAGS], [$4])]) + m4_ifblank([$5], [], [_MODULE_BLOCK_ADD([MODULE_]m4_toupper([$1])[_LDFLAGS], [$5])]) ]) + AM_CONDITIONAL(modcond, [test "$modstate" = yes]) AC_MSG_RESULT([$modstate]) m4_popdef([modcond])dnl m4_popdef([modstate])dnl @@ -6087,6 +6085,15 @@ PY_STDLIB_MOD([_sqlite3], [test "$have_supported_sqlite3" = "yes"], [$LIBSQLITE3_CFLAGS], [$LIBSQLITE3_LIBS]) +dnl test modules +PY_STDLIB_MOD([_testcapi], [test "$TEST_MODULES" = yes]) +PY_STDLIB_MOD([_testinternalcapi], [test "$TEST_MODULES" = yes]) +PY_STDLIB_MOD([_testbuffer], [test "$TEST_MODULES" = yes]) +PY_STDLIB_MOD([_testimportmultiple], [test "$TEST_MODULES" = yes]) +PY_STDLIB_MOD([_testmultiphase], [test "$TEST_MODULES" = yes]) +PY_STDLIB_MOD([_xxtestfuzz], [test "$TEST_MODULES" = yes]) +PY_STDLIB_MOD([_ctypes_test], [test "$TEST_MODULES" = yes], [], [], [-lm]) + # substitute multiline block, must come after last PY_STDLIB_MOD() AC_SUBST([MODULE_BLOCK]) diff --git a/setup.py b/setup.py index 83a676bfefbbe..d01cc4f7169ec 100644 --- a/setup.py +++ b/setup.py @@ -55,9 +55,6 @@ from distutils.spawn import find_executable -# Compile extensions used to test Python? -TEST_EXTENSIONS = (sysconfig.get_config_var('TEST_MODULES') == 'yes') - # This global variable is used to hold the list of modules to be disabled. DISABLED_MODULE_LIST = [] @@ -1098,24 +1095,25 @@ def detect_simple_extensions(self): def detect_test_extensions(self): # Python C API test module - self.add(Extension('_testcapi', ['_testcapimodule.c'])) + self.addext(Extension('_testcapi', ['_testcapimodule.c'])) # Python Internal C API test module - self.add(Extension('_testinternalcapi', ['_testinternalcapi.c'])) + self.addext(Extension('_testinternalcapi', ['_testinternalcapi.c'])) # Python PEP-3118 (buffer protocol) test module - self.add(Extension('_testbuffer', ['_testbuffer.c'])) + self.addext(Extension('_testbuffer', ['_testbuffer.c'])) # Test loading multiple modules from one compiled file (https://bugs.python.org/issue16421) - self.add(Extension('_testimportmultiple', ['_testimportmultiple.c'])) + self.addext(Extension('_testimportmultiple', ['_testimportmultiple.c'])) # Test multi-phase extension module init (PEP 489) - self.add(Extension('_testmultiphase', ['_testmultiphase.c'])) + self.addext(Extension('_testmultiphase', ['_testmultiphase.c'])) # Fuzz tests. - self.add(Extension('_xxtestfuzz', - ['_xxtestfuzz/_xxtestfuzz.c', - '_xxtestfuzz/fuzzer.c'])) + self.addext(Extension( + '_xxtestfuzz', + ['_xxtestfuzz/_xxtestfuzz.c', '_xxtestfuzz/fuzzer.c'] + )) def detect_readline_curses(self): # readline @@ -1503,8 +1501,7 @@ def detect_modules(self): # These are extensions are required to bootstrap the interpreter or # build process. self.detect_simple_extensions() - if TEST_EXTENSIONS: - self.detect_test_extensions() + self.detect_test_extensions() self.detect_readline_curses() self.detect_crypt() self.detect_socket() @@ -1883,11 +1880,8 @@ def detect_ctypes(self): libraries=[], sources=sources) self.add(ext) - if TEST_EXTENSIONS: - # function my_sqrt() needs libm for sqrt() - self.add(Extension('_ctypes_test', - sources=['_ctypes/_ctypes_test.c'], - libraries=['m'])) + # function my_sqrt() needs libm for sqrt() + self.addext(Extension('_ctypes_test', ['_ctypes/_ctypes_test.c'])) ffi_inc = sysconfig.get_config_var("LIBFFI_INCLUDEDIR") ffi_lib = None From webhook-mailer at python.org Sat Nov 20 10:52:08 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 20 Nov 2021 15:52:08 -0000 Subject: [Python-checkins] bpo-42158: Add MIME types for n-triples, n-quads, n3 and trig (GH-23230) Message-ID: https://github.com/python/cpython/commit/ef5305819ff9b283d92dbf004f977592f4e64165 commit: ef5305819ff9b283d92dbf004f977592f4e64165 branch: main author: Dylan Van Assche committer: ambv date: 2021-11-20T16:52:00+01:00 summary: bpo-42158: Add MIME types for n-triples, n-quads, n3 and trig (GH-23230) Co-authored-by: ?ric Araujo files: A Misc/NEWS.d/next/Library/2020-11-10-17-46-12.bpo-42158.OhxAiH.rst M Lib/mimetypes.py diff --git a/Lib/mimetypes.py b/Lib/mimetypes.py index e14d0719bed48..4750408173ec0 100644 --- a/Lib/mimetypes.py +++ b/Lib/mimetypes.py @@ -436,6 +436,8 @@ def _default_mime_types(): '.doc' : 'application/msword', '.dot' : 'application/msword', '.wiz' : 'application/msword', + '.nq' : 'application/n-quads', + '.nt' : 'application/n-triples', '.bin' : 'application/octet-stream', '.a' : 'application/octet-stream', '.dll' : 'application/octet-stream', @@ -449,6 +451,7 @@ def _default_mime_types(): '.ps' : 'application/postscript', '.ai' : 'application/postscript', '.eps' : 'application/postscript', + '.trig' : 'application/trig', '.m3u' : 'application/vnd.apple.mpegurl', '.m3u8' : 'application/vnd.apple.mpegurl', '.xls' : 'application/vnd.ms-excel', @@ -546,6 +549,7 @@ def _default_mime_types(): '.csv' : 'text/csv', '.html' : 'text/html', '.htm' : 'text/html', + '.n3' : 'text/n3', '.txt' : 'text/plain', '.bat' : 'text/plain', '.c' : 'text/plain', diff --git a/Misc/NEWS.d/next/Library/2020-11-10-17-46-12.bpo-42158.OhxAiH.rst b/Misc/NEWS.d/next/Library/2020-11-10-17-46-12.bpo-42158.OhxAiH.rst new file mode 100644 index 0000000000000..a71b481219e80 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-11-10-17-46-12.bpo-42158.OhxAiH.rst @@ -0,0 +1 @@ +Add MIME types for N-quads, N-triples, Notation3 and TriG to ``mimetypes``. From webhook-mailer at python.org Sat Nov 20 10:57:24 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 20 Nov 2021 15:57:24 -0000 Subject: [Python-checkins] bpo-45846: Fix capitalisation of Van Rossum at the start of sentence (GH-29641) (GH-29656) Message-ID: https://github.com/python/cpython/commit/82f1a6edfb645abef934ae1b568dd887ff7a56b9 commit: 82f1a6edfb645abef934ae1b568dd887ff7a56b9 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-20T16:57:16+01:00 summary: bpo-45846: Fix capitalisation of Van Rossum at the start of sentence (GH-29641) (GH-29656) (cherry picked from commit bc2bc0dbdb52498d009f9f9771452e6aa4faff2b) Co-authored-by: JMcB files: M Doc/faq/programming.rst diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst index 12b70dbbe7302..154563a859e31 100644 --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -2092,7 +2092,7 @@ Jim Roskind suggests performing steps in the following order in each module: * ``import`` statements * active code (including globals that are initialized from imported values). -van Rossum doesn't like this approach much because the imports appear in a +Van Rossum doesn't like this approach much because the imports appear in a strange place, but it does work. Matthias Urlichs recommends restructuring your code so that the recursive import From webhook-mailer at python.org Sat Nov 20 10:57:42 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 20 Nov 2021 15:57:42 -0000 Subject: [Python-checkins] bpo-45846: Fix capitalisation of Van Rossum at the start of sentence (GH-29641) (GH-29657) Message-ID: https://github.com/python/cpython/commit/e88f9787aba2ab95df75baa6cb6ee5eacb450489 commit: e88f9787aba2ab95df75baa6cb6ee5eacb450489 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ambv date: 2021-11-20T16:57:37+01:00 summary: bpo-45846: Fix capitalisation of Van Rossum at the start of sentence (GH-29641) (GH-29657) (cherry picked from commit bc2bc0dbdb52498d009f9f9771452e6aa4faff2b) Co-authored-by: JMcB files: M Doc/faq/programming.rst diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst index 5286bbbccf073..d838e6141f8d4 100644 --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -2013,7 +2013,7 @@ Jim Roskind suggests performing steps in the following order in each module: * ``import`` statements * active code (including globals that are initialized from imported values). -van Rossum doesn't like this approach much because the imports appear in a +Van Rossum doesn't like this approach much because the imports appear in a strange place, but it does work. Matthias Urlichs recommends restructuring your code so that the recursive import From webhook-mailer at python.org Sat Nov 20 11:04:45 2021 From: webhook-mailer at python.org (rhettinger) Date: Sat, 20 Nov 2021 16:04:45 -0000 Subject: [Python-checkins] bpo-45851: Avoid full sort in statistics.multimode() (#29662) Message-ID: https://github.com/python/cpython/commit/04e03f496cf7da48ce4f545b41579d7d45f59ad2 commit: 04e03f496cf7da48ce4f545b41579d7d45f59ad2 branch: main author: Raymond Hettinger committer: rhettinger date: 2021-11-20T10:04:37-06:00 summary: bpo-45851: Avoid full sort in statistics.multimode() (#29662) Suggested by Stefan Pochmann. files: M Lib/statistics.py diff --git a/Lib/statistics.py b/Lib/statistics.py index e67c51709136a..4f3ab49b40219 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -609,9 +609,11 @@ def multimode(data): >>> multimode('') [] """ - counts = Counter(iter(data)).most_common() - maxcount, mode_items = next(groupby(counts, key=itemgetter(1)), (0, [])) - return list(map(itemgetter(0), mode_items)) + counts = Counter(iter(data)) + if not counts: + return [] + maxcount = max(counts.values()) + return [value for value, count in counts.items() if count == maxcount] # Notes on methods for computing quantiles From webhook-mailer at python.org Sat Nov 20 11:55:44 2021 From: webhook-mailer at python.org (ambv) Date: Sat, 20 Nov 2021 16:55:44 -0000 Subject: [Python-checkins] [doc] Clarify MRO precedence in descriptor super binding section (GH-29539) Message-ID: https://github.com/python/cpython/commit/ee49484c0f0d0d79e8fc40835da10b78f89ae503 commit: ee49484c0f0d0d79e8fc40835da10b78f89ae503 branch: main author: Jouke Witteveen committer: ambv date: 2021-11-20T17:55:35+01:00 summary: [doc] Clarify MRO precedence in descriptor super binding section (GH-29539) A similar sentence is present in the 'Invocation from super' section of the descriptor HOWTO, where it is already correct. files: M Doc/reference/datamodel.rst diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index b04c95f7779b4..b14b2cb1ef5e4 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1820,7 +1820,7 @@ Class Binding Super Binding If ``a`` is an instance of :class:`super`, then the binding ``super(B, obj).m()`` searches ``obj.__class__.__mro__`` for the base class ``A`` - immediately preceding ``B`` and then invokes the descriptor with the call: + immediately following ``B`` and then invokes the descriptor with the call: ``A.__dict__['m'].__get__(obj, obj.__class__)``. For instance bindings, the precedence of descriptor invocation depends on From webhook-mailer at python.org Sat Nov 20 12:01:13 2021 From: webhook-mailer at python.org (rhettinger) Date: Sat, 20 Nov 2021 17:01:13 -0000 Subject: [Python-checkins] bpo-45852: Fix the Counter/iter test for statistics.mode() (GH-29667) Message-ID: https://github.com/python/cpython/commit/48744db70ed519c1566c22bf123a0e1f5c69253f commit: 48744db70ed519c1566c22bf123a0e1f5c69253f branch: main author: Raymond Hettinger committer: rhettinger date: 2021-11-20T11:01:09-06:00 summary: bpo-45852: Fix the Counter/iter test for statistics.mode() (GH-29667) Suggested by Stefan Pochmann. files: M Lib/test/test_statistics.py diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py index 5cb055c981c44..fbc6a071cfd34 100644 --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -1900,10 +1900,13 @@ def test_none_data(self): def test_counter_data(self): # Test that a Counter is treated like any other iterable. - data = collections.Counter([1, 1, 1, 2]) - # Since the keys of the counter are treated as data points, not the - # counts, this should return the first mode encountered, 1 - self.assertEqual(self.func(data), 1) + # We're making sure mode() first calls iter() on its input. + # The concern is that a Counter of a Counter returns the original + # unchanged rather than counting its keys. + c = collections.Counter(a=1, b=2) + # If iter() is called, mode(c) loops over the keys, ['a', 'b'], + # all the counts will be 1, and the first encountered mode is 'a'. + self.assertEqual(self.func(c), 'a') class TestMultiMode(unittest.TestCase): From webhook-mailer at python.org Sat Nov 20 12:39:21 2021 From: webhook-mailer at python.org (pablogsal) Date: Sat, 20 Nov 2021 17:39:21 -0000 Subject: [Python-checkins] [3.10] bpo-45727: Make the syntax error for missing comma more consistent (GH-29427) (GH-29647) Message-ID: https://github.com/python/cpython/commit/511ee1c0fa4dedf32cc2b9f9fa13aa61e07bd165 commit: 511ee1c0fa4dedf32cc2b9f9fa13aa61e07bd165 branch: 3.10 author: Pablo Galindo Salgado committer: pablogsal date: 2021-11-20T17:39:17Z summary: [3.10] bpo-45727: Make the syntax error for missing comma more consistent (GH-29427) (GH-29647) (cherry picked from commit 546cefcda75d7150b55c8bc1724bea35a1e12890) Co-authored-by: Pablo Galindo Salgado files: M Grammar/python.gram M Lib/test/test_exceptions.py M Parser/parser.c M Parser/pegen.c diff --git a/Grammar/python.gram b/Grammar/python.gram index 7934ccdfcc5aa..20cccfd8368af 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -529,6 +529,7 @@ expressions[expr_ty]: | expression expression[expr_ty] (memo): | invalid_expression + | invalid_legacy_expression | a=disjunction 'if' b=disjunction 'else' c=expression { _PyAST_IfExp(b, a, c, EXTRA) } | disjunction | lambdef @@ -666,7 +667,6 @@ await_primary[expr_ty] (memo): | AWAIT a=primary { CHECK_VERSION(expr_ty, 5, "Await expressions are", _PyAST_Await(a, EXTRA)) } | primary primary[expr_ty]: - | invalid_primary # must be before 'primay genexp' because of invalid_genexp | a=primary '.' b=NAME { _PyAST_Attribute(a, b->v.Name.id, Load, EXTRA) } | a=primary b=genexp { _PyAST_Call(a, CHECK(asdl_expr_seq*, (asdl_expr_seq*)_PyPegen_singleton_seq(p, b)), NULL, EXTRA) } | a=primary '(' b=[arguments] ')' { @@ -856,11 +856,11 @@ invalid_legacy_expression: "Missing parentheses in call to '%U'. Did you mean %U(...)?", a->v.Name.id, a->v.Name.id) : NULL} invalid_expression: - | invalid_legacy_expression # !(NAME STRING) is not matched so we don't show this error with some invalid string prefixes like: kf"dsfsdf" # Soft keywords need to also be ignored because they can be parsed as NAME NAME | !(NAME STRING | SOFT_KEYWORD) a=disjunction b=expression_without_invalid { - RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "invalid syntax. Perhaps you forgot a comma?") } + _PyPegen_check_legacy_stmt(p, a) ? NULL : RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, + "invalid syntax. Perhaps you forgot a comma?") } | a=disjunction 'if' b=disjunction !('else'|':') { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "expected 'else' after 'if' expression") } invalid_named_expression: @@ -902,8 +902,6 @@ invalid_del_stmt: RAISE_SYNTAX_ERROR_INVALID_TARGET(DEL_TARGETS, a) } invalid_block: | NEWLINE !INDENT { RAISE_INDENTATION_ERROR("expected an indented block") } -invalid_primary: - | primary a='{' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "invalid syntax") } invalid_comprehension: | ('[' | '(' | '{') a=starred_expression for_if_clauses { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "iterable unpacking cannot be used in comprehension") } diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 04c883cf53ba3..4c18a59f6e92c 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -226,13 +226,14 @@ def testSyntaxErrorOffset(self): check(b'Python = "\xcf\xb3\xf2\xee\xed" +', 1, 18) check('x = "a', 1, 5) check('lambda x: x = 2', 1, 1) - check('f{a + b + c}', 1, 2) + check('f{a + b + c}', 1, 1) check('[file for str(file) in []\n])', 1, 11) check('a = ? hello ? ? world ?', 1, 5) check('[\nfile\nfor str(file)\nin\n[]\n]', 3, 5) check('[file for\n str(file) in []]', 2, 2) check("ages = {'Alice'=22, 'Bob'=23}", 1, 16) check('match ...:\n case {**rest, "key": value}:\n ...', 2, 19) + check("a b c d e f", 1, 1) # Errors thrown by compile.c check('class foo:return 1', 1, 11) diff --git a/Parser/parser.c b/Parser/parser.c index bda24a3de52ce..b14092a483c32 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -259,246 +259,245 @@ static char *soft_keywords[] = { #define invalid_ann_assign_target_type 1185 #define invalid_del_stmt_type 1186 #define invalid_block_type 1187 -#define invalid_primary_type 1188 // Left-recursive -#define invalid_comprehension_type 1189 -#define invalid_dict_comprehension_type 1190 -#define invalid_parameters_type 1191 -#define invalid_parameters_helper_type 1192 -#define invalid_lambda_parameters_type 1193 -#define invalid_lambda_parameters_helper_type 1194 -#define invalid_star_etc_type 1195 -#define invalid_lambda_star_etc_type 1196 -#define invalid_double_type_comments_type 1197 -#define invalid_with_item_type 1198 -#define invalid_for_target_type 1199 -#define invalid_group_type 1200 -#define invalid_import_from_targets_type 1201 -#define invalid_with_stmt_type 1202 -#define invalid_with_stmt_indent_type 1203 -#define invalid_try_stmt_type 1204 -#define invalid_except_stmt_type 1205 -#define invalid_finally_stmt_type 1206 -#define invalid_except_stmt_indent_type 1207 -#define invalid_match_stmt_type 1208 -#define invalid_case_block_type 1209 -#define invalid_as_pattern_type 1210 -#define invalid_class_pattern_type 1211 -#define invalid_class_argument_pattern_type 1212 -#define invalid_if_stmt_type 1213 -#define invalid_elif_stmt_type 1214 -#define invalid_else_stmt_type 1215 -#define invalid_while_stmt_type 1216 -#define invalid_for_stmt_type 1217 -#define invalid_def_raw_type 1218 -#define invalid_class_def_raw_type 1219 -#define invalid_double_starred_kvpairs_type 1220 -#define invalid_kvpair_type 1221 -#define _loop0_1_type 1222 -#define _loop0_2_type 1223 -#define _loop0_4_type 1224 -#define _gather_3_type 1225 -#define _loop0_6_type 1226 -#define _gather_5_type 1227 -#define _loop0_8_type 1228 -#define _gather_7_type 1229 -#define _loop0_10_type 1230 -#define _gather_9_type 1231 -#define _loop1_11_type 1232 -#define _loop0_13_type 1233 -#define _gather_12_type 1234 -#define _tmp_14_type 1235 -#define _tmp_15_type 1236 -#define _tmp_16_type 1237 -#define _tmp_17_type 1238 -#define _tmp_18_type 1239 -#define _tmp_19_type 1240 -#define _tmp_20_type 1241 -#define _tmp_21_type 1242 -#define _loop1_22_type 1243 -#define _tmp_23_type 1244 -#define _tmp_24_type 1245 -#define _loop0_26_type 1246 -#define _gather_25_type 1247 -#define _loop0_28_type 1248 -#define _gather_27_type 1249 -#define _tmp_29_type 1250 -#define _tmp_30_type 1251 -#define _loop0_31_type 1252 -#define _loop1_32_type 1253 -#define _loop0_34_type 1254 -#define _gather_33_type 1255 -#define _tmp_35_type 1256 -#define _loop0_37_type 1257 -#define _gather_36_type 1258 -#define _tmp_38_type 1259 -#define _loop0_40_type 1260 -#define _gather_39_type 1261 -#define _loop0_42_type 1262 -#define _gather_41_type 1263 -#define _loop0_44_type 1264 -#define _gather_43_type 1265 -#define _loop0_46_type 1266 -#define _gather_45_type 1267 -#define _tmp_47_type 1268 -#define _loop1_48_type 1269 -#define _tmp_49_type 1270 -#define _loop1_50_type 1271 -#define _loop0_52_type 1272 -#define _gather_51_type 1273 -#define _tmp_53_type 1274 -#define _tmp_54_type 1275 -#define _tmp_55_type 1276 -#define _tmp_56_type 1277 -#define _loop0_58_type 1278 -#define _gather_57_type 1279 -#define _loop0_60_type 1280 -#define _gather_59_type 1281 -#define _tmp_61_type 1282 -#define _loop0_63_type 1283 -#define _gather_62_type 1284 -#define _loop0_65_type 1285 -#define _gather_64_type 1286 -#define _tmp_66_type 1287 -#define _tmp_67_type 1288 -#define _tmp_68_type 1289 -#define _tmp_69_type 1290 -#define _loop0_70_type 1291 -#define _loop0_71_type 1292 -#define _loop0_72_type 1293 -#define _loop1_73_type 1294 -#define _loop0_74_type 1295 -#define _loop1_75_type 1296 -#define _loop1_76_type 1297 -#define _loop1_77_type 1298 -#define _loop0_78_type 1299 -#define _loop1_79_type 1300 -#define _loop0_80_type 1301 -#define _loop1_81_type 1302 -#define _loop0_82_type 1303 -#define _loop1_83_type 1304 -#define _loop1_84_type 1305 -#define _tmp_85_type 1306 -#define _loop1_86_type 1307 -#define _loop0_88_type 1308 -#define _gather_87_type 1309 -#define _loop1_89_type 1310 -#define _loop0_90_type 1311 -#define _loop0_91_type 1312 -#define _loop0_92_type 1313 -#define _loop1_93_type 1314 -#define _loop0_94_type 1315 -#define _loop1_95_type 1316 -#define _loop1_96_type 1317 -#define _loop1_97_type 1318 -#define _loop0_98_type 1319 -#define _loop1_99_type 1320 -#define _loop0_100_type 1321 -#define _loop1_101_type 1322 -#define _loop0_102_type 1323 -#define _loop1_103_type 1324 -#define _loop1_104_type 1325 -#define _loop1_105_type 1326 -#define _loop1_106_type 1327 -#define _tmp_107_type 1328 -#define _loop0_109_type 1329 -#define _gather_108_type 1330 -#define _tmp_110_type 1331 -#define _tmp_111_type 1332 -#define _tmp_112_type 1333 -#define _tmp_113_type 1334 -#define _loop1_114_type 1335 -#define _tmp_115_type 1336 -#define _tmp_116_type 1337 -#define _tmp_117_type 1338 -#define _loop0_119_type 1339 -#define _gather_118_type 1340 -#define _loop1_120_type 1341 -#define _loop0_121_type 1342 -#define _loop0_122_type 1343 -#define _loop0_124_type 1344 -#define _gather_123_type 1345 -#define _tmp_125_type 1346 -#define _loop0_127_type 1347 -#define _gather_126_type 1348 -#define _loop0_129_type 1349 -#define _gather_128_type 1350 -#define _loop0_131_type 1351 -#define _gather_130_type 1352 -#define _loop0_133_type 1353 -#define _gather_132_type 1354 -#define _loop0_134_type 1355 -#define _loop0_136_type 1356 -#define _gather_135_type 1357 -#define _loop1_137_type 1358 -#define _tmp_138_type 1359 -#define _loop0_140_type 1360 -#define _gather_139_type 1361 -#define _tmp_141_type 1362 -#define _tmp_142_type 1363 -#define _tmp_143_type 1364 -#define _tmp_144_type 1365 -#define _tmp_145_type 1366 -#define _tmp_146_type 1367 -#define _tmp_147_type 1368 -#define _tmp_148_type 1369 -#define _loop0_149_type 1370 -#define _loop0_150_type 1371 -#define _loop0_151_type 1372 -#define _tmp_152_type 1373 -#define _tmp_153_type 1374 -#define _tmp_154_type 1375 -#define _tmp_155_type 1376 -#define _loop0_156_type 1377 -#define _loop1_157_type 1378 -#define _loop0_158_type 1379 -#define _loop1_159_type 1380 -#define _tmp_160_type 1381 -#define _tmp_161_type 1382 -#define _tmp_162_type 1383 -#define _loop0_164_type 1384 -#define _gather_163_type 1385 -#define _loop0_166_type 1386 -#define _gather_165_type 1387 -#define _loop0_168_type 1388 -#define _gather_167_type 1389 -#define _loop0_170_type 1390 -#define _gather_169_type 1391 -#define _tmp_171_type 1392 -#define _tmp_172_type 1393 -#define _tmp_173_type 1394 -#define _tmp_174_type 1395 -#define _tmp_175_type 1396 -#define _tmp_176_type 1397 -#define _tmp_177_type 1398 -#define _loop0_179_type 1399 -#define _gather_178_type 1400 -#define _tmp_180_type 1401 -#define _tmp_181_type 1402 -#define _tmp_182_type 1403 -#define _tmp_183_type 1404 -#define _tmp_184_type 1405 -#define _tmp_185_type 1406 -#define _tmp_186_type 1407 -#define _tmp_187_type 1408 -#define _tmp_188_type 1409 -#define _tmp_189_type 1410 -#define _tmp_190_type 1411 -#define _tmp_191_type 1412 -#define _tmp_192_type 1413 -#define _tmp_193_type 1414 -#define _tmp_194_type 1415 -#define _tmp_195_type 1416 -#define _tmp_196_type 1417 -#define _tmp_197_type 1418 -#define _tmp_198_type 1419 -#define _tmp_199_type 1420 -#define _tmp_200_type 1421 -#define _tmp_201_type 1422 -#define _tmp_202_type 1423 -#define _tmp_203_type 1424 -#define _tmp_204_type 1425 -#define _tmp_205_type 1426 -#define _tmp_206_type 1427 +#define invalid_comprehension_type 1188 +#define invalid_dict_comprehension_type 1189 +#define invalid_parameters_type 1190 +#define invalid_parameters_helper_type 1191 +#define invalid_lambda_parameters_type 1192 +#define invalid_lambda_parameters_helper_type 1193 +#define invalid_star_etc_type 1194 +#define invalid_lambda_star_etc_type 1195 +#define invalid_double_type_comments_type 1196 +#define invalid_with_item_type 1197 +#define invalid_for_target_type 1198 +#define invalid_group_type 1199 +#define invalid_import_from_targets_type 1200 +#define invalid_with_stmt_type 1201 +#define invalid_with_stmt_indent_type 1202 +#define invalid_try_stmt_type 1203 +#define invalid_except_stmt_type 1204 +#define invalid_finally_stmt_type 1205 +#define invalid_except_stmt_indent_type 1206 +#define invalid_match_stmt_type 1207 +#define invalid_case_block_type 1208 +#define invalid_as_pattern_type 1209 +#define invalid_class_pattern_type 1210 +#define invalid_class_argument_pattern_type 1211 +#define invalid_if_stmt_type 1212 +#define invalid_elif_stmt_type 1213 +#define invalid_else_stmt_type 1214 +#define invalid_while_stmt_type 1215 +#define invalid_for_stmt_type 1216 +#define invalid_def_raw_type 1217 +#define invalid_class_def_raw_type 1218 +#define invalid_double_starred_kvpairs_type 1219 +#define invalid_kvpair_type 1220 +#define _loop0_1_type 1221 +#define _loop0_2_type 1222 +#define _loop0_4_type 1223 +#define _gather_3_type 1224 +#define _loop0_6_type 1225 +#define _gather_5_type 1226 +#define _loop0_8_type 1227 +#define _gather_7_type 1228 +#define _loop0_10_type 1229 +#define _gather_9_type 1230 +#define _loop1_11_type 1231 +#define _loop0_13_type 1232 +#define _gather_12_type 1233 +#define _tmp_14_type 1234 +#define _tmp_15_type 1235 +#define _tmp_16_type 1236 +#define _tmp_17_type 1237 +#define _tmp_18_type 1238 +#define _tmp_19_type 1239 +#define _tmp_20_type 1240 +#define _tmp_21_type 1241 +#define _loop1_22_type 1242 +#define _tmp_23_type 1243 +#define _tmp_24_type 1244 +#define _loop0_26_type 1245 +#define _gather_25_type 1246 +#define _loop0_28_type 1247 +#define _gather_27_type 1248 +#define _tmp_29_type 1249 +#define _tmp_30_type 1250 +#define _loop0_31_type 1251 +#define _loop1_32_type 1252 +#define _loop0_34_type 1253 +#define _gather_33_type 1254 +#define _tmp_35_type 1255 +#define _loop0_37_type 1256 +#define _gather_36_type 1257 +#define _tmp_38_type 1258 +#define _loop0_40_type 1259 +#define _gather_39_type 1260 +#define _loop0_42_type 1261 +#define _gather_41_type 1262 +#define _loop0_44_type 1263 +#define _gather_43_type 1264 +#define _loop0_46_type 1265 +#define _gather_45_type 1266 +#define _tmp_47_type 1267 +#define _loop1_48_type 1268 +#define _tmp_49_type 1269 +#define _loop1_50_type 1270 +#define _loop0_52_type 1271 +#define _gather_51_type 1272 +#define _tmp_53_type 1273 +#define _tmp_54_type 1274 +#define _tmp_55_type 1275 +#define _tmp_56_type 1276 +#define _loop0_58_type 1277 +#define _gather_57_type 1278 +#define _loop0_60_type 1279 +#define _gather_59_type 1280 +#define _tmp_61_type 1281 +#define _loop0_63_type 1282 +#define _gather_62_type 1283 +#define _loop0_65_type 1284 +#define _gather_64_type 1285 +#define _tmp_66_type 1286 +#define _tmp_67_type 1287 +#define _tmp_68_type 1288 +#define _tmp_69_type 1289 +#define _loop0_70_type 1290 +#define _loop0_71_type 1291 +#define _loop0_72_type 1292 +#define _loop1_73_type 1293 +#define _loop0_74_type 1294 +#define _loop1_75_type 1295 +#define _loop1_76_type 1296 +#define _loop1_77_type 1297 +#define _loop0_78_type 1298 +#define _loop1_79_type 1299 +#define _loop0_80_type 1300 +#define _loop1_81_type 1301 +#define _loop0_82_type 1302 +#define _loop1_83_type 1303 +#define _loop1_84_type 1304 +#define _tmp_85_type 1305 +#define _loop1_86_type 1306 +#define _loop0_88_type 1307 +#define _gather_87_type 1308 +#define _loop1_89_type 1309 +#define _loop0_90_type 1310 +#define _loop0_91_type 1311 +#define _loop0_92_type 1312 +#define _loop1_93_type 1313 +#define _loop0_94_type 1314 +#define _loop1_95_type 1315 +#define _loop1_96_type 1316 +#define _loop1_97_type 1317 +#define _loop0_98_type 1318 +#define _loop1_99_type 1319 +#define _loop0_100_type 1320 +#define _loop1_101_type 1321 +#define _loop0_102_type 1322 +#define _loop1_103_type 1323 +#define _loop1_104_type 1324 +#define _loop1_105_type 1325 +#define _loop1_106_type 1326 +#define _tmp_107_type 1327 +#define _loop0_109_type 1328 +#define _gather_108_type 1329 +#define _tmp_110_type 1330 +#define _tmp_111_type 1331 +#define _tmp_112_type 1332 +#define _tmp_113_type 1333 +#define _loop1_114_type 1334 +#define _tmp_115_type 1335 +#define _tmp_116_type 1336 +#define _tmp_117_type 1337 +#define _loop0_119_type 1338 +#define _gather_118_type 1339 +#define _loop1_120_type 1340 +#define _loop0_121_type 1341 +#define _loop0_122_type 1342 +#define _loop0_124_type 1343 +#define _gather_123_type 1344 +#define _tmp_125_type 1345 +#define _loop0_127_type 1346 +#define _gather_126_type 1347 +#define _loop0_129_type 1348 +#define _gather_128_type 1349 +#define _loop0_131_type 1350 +#define _gather_130_type 1351 +#define _loop0_133_type 1352 +#define _gather_132_type 1353 +#define _loop0_134_type 1354 +#define _loop0_136_type 1355 +#define _gather_135_type 1356 +#define _loop1_137_type 1357 +#define _tmp_138_type 1358 +#define _loop0_140_type 1359 +#define _gather_139_type 1360 +#define _tmp_141_type 1361 +#define _tmp_142_type 1362 +#define _tmp_143_type 1363 +#define _tmp_144_type 1364 +#define _tmp_145_type 1365 +#define _tmp_146_type 1366 +#define _tmp_147_type 1367 +#define _tmp_148_type 1368 +#define _loop0_149_type 1369 +#define _loop0_150_type 1370 +#define _loop0_151_type 1371 +#define _tmp_152_type 1372 +#define _tmp_153_type 1373 +#define _tmp_154_type 1374 +#define _tmp_155_type 1375 +#define _loop0_156_type 1376 +#define _loop1_157_type 1377 +#define _loop0_158_type 1378 +#define _loop1_159_type 1379 +#define _tmp_160_type 1380 +#define _tmp_161_type 1381 +#define _tmp_162_type 1382 +#define _loop0_164_type 1383 +#define _gather_163_type 1384 +#define _loop0_166_type 1385 +#define _gather_165_type 1386 +#define _loop0_168_type 1387 +#define _gather_167_type 1388 +#define _loop0_170_type 1389 +#define _gather_169_type 1390 +#define _tmp_171_type 1391 +#define _tmp_172_type 1392 +#define _tmp_173_type 1393 +#define _tmp_174_type 1394 +#define _tmp_175_type 1395 +#define _tmp_176_type 1396 +#define _tmp_177_type 1397 +#define _loop0_179_type 1398 +#define _gather_178_type 1399 +#define _tmp_180_type 1400 +#define _tmp_181_type 1401 +#define _tmp_182_type 1402 +#define _tmp_183_type 1403 +#define _tmp_184_type 1404 +#define _tmp_185_type 1405 +#define _tmp_186_type 1406 +#define _tmp_187_type 1407 +#define _tmp_188_type 1408 +#define _tmp_189_type 1409 +#define _tmp_190_type 1410 +#define _tmp_191_type 1411 +#define _tmp_192_type 1412 +#define _tmp_193_type 1413 +#define _tmp_194_type 1414 +#define _tmp_195_type 1415 +#define _tmp_196_type 1416 +#define _tmp_197_type 1417 +#define _tmp_198_type 1418 +#define _tmp_199_type 1419 +#define _tmp_200_type 1420 +#define _tmp_201_type 1421 +#define _tmp_202_type 1422 +#define _tmp_203_type 1423 +#define _tmp_204_type 1424 +#define _tmp_205_type 1425 +#define _tmp_206_type 1426 static mod_ty file_rule(Parser *p); static mod_ty interactive_rule(Parser *p); @@ -688,7 +687,6 @@ static void *invalid_assignment_rule(Parser *p); static expr_ty invalid_ann_assign_target_rule(Parser *p); static void *invalid_del_stmt_rule(Parser *p); static void *invalid_block_rule(Parser *p); -static void *invalid_primary_rule(Parser *p); static void *invalid_comprehension_rule(Parser *p); static void *invalid_dict_comprehension_rule(Parser *p); static void *invalid_parameters_rule(Parser *p); @@ -10538,6 +10536,7 @@ expressions_rule(Parser *p) // expression: // | invalid_expression +// | invalid_legacy_expression // | disjunction 'if' disjunction 'else' expression // | disjunction // | lambdef @@ -10583,6 +10582,25 @@ expression_rule(Parser *p) D(fprintf(stderr, "%*c%s expression[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_expression")); } + if (p->call_invalid_rules) { // invalid_legacy_expression + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_legacy_expression")); + void *invalid_legacy_expression_var; + if ( + (invalid_legacy_expression_var = invalid_legacy_expression_rule(p)) // invalid_legacy_expression + ) + { + D(fprintf(stderr, "%*c+ expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "invalid_legacy_expression")); + _res = invalid_legacy_expression_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s expression[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_legacy_expression")); + } { // disjunction 'if' disjunction 'else' expression if (p->error_indicator) { D(p->level--); @@ -13859,7 +13877,6 @@ await_primary_rule(Parser *p) // Left-recursive // primary: -// | invalid_primary // | primary '.' NAME // | primary genexp // | primary '(' arguments? ')' @@ -13917,25 +13934,6 @@ primary_raw(Parser *p) UNUSED(_start_lineno); // Only used by EXTRA macro int _start_col_offset = p->tokens[_mark]->col_offset; UNUSED(_start_col_offset); // Only used by EXTRA macro - if (p->call_invalid_rules) { // invalid_primary - if (p->error_indicator) { - D(p->level--); - return NULL; - } - D(fprintf(stderr, "%*c> primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_primary")); - void *invalid_primary_var; - if ( - (invalid_primary_var = invalid_primary_rule(p)) // invalid_primary - ) - { - D(fprintf(stderr, "%*c+ primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "invalid_primary")); - _res = invalid_primary_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s primary[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_primary")); - } { // primary '.' NAME if (p->error_indicator) { D(p->level--); @@ -18261,7 +18259,6 @@ invalid_legacy_expression_rule(Parser *p) } // invalid_expression: -// | invalid_legacy_expression // | !(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid // | disjunction 'if' disjunction !('else' | ':') static void * @@ -18274,25 +18271,6 @@ invalid_expression_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - if (p->call_invalid_rules) { // invalid_legacy_expression - if (p->error_indicator) { - D(p->level--); - return NULL; - } - D(fprintf(stderr, "%*c> invalid_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_legacy_expression")); - void *invalid_legacy_expression_var; - if ( - (invalid_legacy_expression_var = invalid_legacy_expression_rule(p)) // invalid_legacy_expression - ) - { - D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "invalid_legacy_expression")); - _res = invalid_legacy_expression_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s invalid_expression[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_legacy_expression")); - } { // !(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid if (p->error_indicator) { D(p->level--); @@ -18310,7 +18288,7 @@ invalid_expression_rule(Parser *p) ) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid")); - _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Perhaps you forgot a comma?" ); + _res = _PyPegen_check_legacy_stmt ( p , a ) ? NULL : RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Perhaps you forgot a comma?" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; D(p->level--); @@ -18857,51 +18835,6 @@ invalid_block_rule(Parser *p) return _res; } -// Left-recursive -// invalid_primary: primary '{' -static void * -invalid_primary_rule(Parser *p) -{ - D(p->level++); - if (p->error_indicator) { - D(p->level--); - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // primary '{' - if (p->error_indicator) { - D(p->level--); - return NULL; - } - D(fprintf(stderr, "%*c> invalid_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "primary '{'")); - Token * a; - expr_ty primary_var; - if ( - (primary_var = primary_rule(p)) // primary - && - (a = _PyPegen_expect_token(p, 25)) // token='{' - ) - { - D(fprintf(stderr, "%*c+ invalid_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "primary '{'")); - _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "invalid syntax" ); - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - D(p->level--); - return NULL; - } - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s invalid_primary[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "primary '{'")); - } - _res = NULL; - done: - D(p->level--); - return _res; -} - // invalid_comprehension: // | ('[' | '(' | '{') starred_expression for_if_clauses // | ('[' | '{') star_named_expression ',' star_named_expressions for_if_clauses diff --git a/Parser/pegen.c b/Parser/pegen.c index 9bf4fe7ecd89d..98f07a13c92cb 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -79,7 +79,9 @@ _PyPegen_check_barry_as_flufl(Parser *p, Token* t) { int _PyPegen_check_legacy_stmt(Parser *p, expr_ty name) { - assert(name->kind == Name_kind); + if (name->kind != Name_kind) { + return 0; + } const char* candidates[2] = {"print", "exec"}; for (int i=0; i<2; i++) { if (PyUnicode_CompareWithASCIIString(name->v.Name.id, candidates[i]) == 0) { From webhook-mailer at python.org Sat Nov 20 12:41:04 2021 From: webhook-mailer at python.org (pablogsal) Date: Sat, 20 Nov 2021 17:41:04 -0000 Subject: [Python-checkins] bpo-45494: Fix error location in EOF tokenizer errors (GH-29108) Message-ID: https://github.com/python/cpython/commit/79ff0d1687e3f823fb121a19f0297ad052871b1b commit: 79ff0d1687e3f823fb121a19f0297ad052871b1b branch: main author: Pablo Galindo Salgado committer: pablogsal date: 2021-11-20T17:40:59Z summary: bpo-45494: Fix error location in EOF tokenizer errors (GH-29108) files: M Parser/pegen.c diff --git a/Parser/pegen.c b/Parser/pegen.c index b3fdae487d970..b760730189073 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -382,8 +382,12 @@ _PyPegen_raise_error(Parser *p, PyObject *errtype, const char *errmsg, ...) Py_ssize_t col_offset; Py_ssize_t end_col_offset = -1; if (t->col_offset == -1) { - col_offset = Py_SAFE_DOWNCAST(p->tok->cur - p->tok->buf, - intptr_t, int); + if (p->tok->cur == p->tok->buf) { + col_offset = 0; + } else { + const char* start = p->tok->buf ? p->tok->line_start : p->tok->buf; + col_offset = Py_SAFE_DOWNCAST(p->tok->cur - start, intptr_t, int); + } } else { col_offset = t->col_offset + 1; } @@ -410,6 +414,7 @@ get_error_line(Parser *p, Py_ssize_t lineno) assert(p->tok->fp == NULL || p->tok->fp == stdin); char *cur_line = p->tok->fp_interactive ? p->tok->interactive_src_start : p->tok->str; + assert(cur_line != NULL); for (int i = 0; i < lineno - 1; i++) { cur_line = strchr(cur_line, '\n') + 1; From webhook-mailer at python.org Sat Nov 20 12:59:42 2021 From: webhook-mailer at python.org (miss-islington) Date: Sat, 20 Nov 2021 17:59:42 -0000 Subject: [Python-checkins] bpo-45494: Fix error location in EOF tokenizer errors (GH-29108) Message-ID: https://github.com/python/cpython/commit/a427eb862f11888fa69fee520eb8a20bd396fcdb commit: a427eb862f11888fa69fee520eb8a20bd396fcdb branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-20T09:59:34-08:00 summary: bpo-45494: Fix error location in EOF tokenizer errors (GH-29108) (cherry picked from commit 79ff0d1687e3f823fb121a19f0297ad052871b1b) Co-authored-by: Pablo Galindo Salgado files: M Parser/pegen.c diff --git a/Parser/pegen.c b/Parser/pegen.c index 98f07a13c92cb..464a902173dfb 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -403,8 +403,12 @@ _PyPegen_raise_error(Parser *p, PyObject *errtype, const char *errmsg, ...) Py_ssize_t col_offset; Py_ssize_t end_col_offset = -1; if (t->col_offset == -1) { - col_offset = Py_SAFE_DOWNCAST(p->tok->cur - p->tok->buf, - intptr_t, int); + if (p->tok->cur == p->tok->buf) { + col_offset = 0; + } else { + const char* start = p->tok->buf ? p->tok->line_start : p->tok->buf; + col_offset = Py_SAFE_DOWNCAST(p->tok->cur - start, intptr_t, int); + } } else { col_offset = t->col_offset + 1; } @@ -431,6 +435,7 @@ get_error_line(Parser *p, Py_ssize_t lineno) assert(p->tok->fp == NULL || p->tok->fp == stdin); char *cur_line = p->tok->fp_interactive ? p->tok->interactive_src_start : p->tok->str; + assert(cur_line != NULL); for (int i = 0; i < lineno - 1; i++) { cur_line = strchr(cur_line, '\n') + 1; From webhook-mailer at python.org Sat Nov 20 13:21:29 2021 From: webhook-mailer at python.org (terryjreedy) Date: Sat, 20 Nov 2021 18:21:29 -0000 Subject: [Python-checkins] bpo-44844: Remove unresponsive web link (GH-29651) Message-ID: https://github.com/python/cpython/commit/985233914504c73f14a23af1c68a3709079e6913 commit: 985233914504c73f14a23af1c68a3709079e6913 branch: main author: Terry Jan Reedy committer: terryjreedy date: 2021-11-20T13:21:14-05:00 summary: bpo-44844: Remove unresponsive web link (GH-29651) Threading notes by Aahz from OSCON 2001. files: M Doc/faq/library.rst diff --git a/Doc/faq/library.rst b/Doc/faq/library.rst index e92973a2e8fa9..78f5a06120879 100644 --- a/Doc/faq/library.rst +++ b/Doc/faq/library.rst @@ -240,9 +240,6 @@ Be sure to use the :mod:`threading` module and not the :mod:`_thread` module. The :mod:`threading` module builds convenient abstractions on top of the low-level primitives provided by the :mod:`_thread` module. -Aahz has a set of slides from his threading tutorial that are helpful; see -http://www.pythoncraft.com/OSCON2001/. - None of my threads seem to run: why? ------------------------------------ From webhook-mailer at python.org Sat Nov 20 13:27:51 2021 From: webhook-mailer at python.org (pablogsal) Date: Sat, 20 Nov 2021 18:27:51 -0000 Subject: [Python-checkins] bpo-45450: Improve syntax error for parenthesized arguments (GH-28906) Message-ID: https://github.com/python/cpython/commit/7a1d9325287a39528b795b1e8037146777abfe3e commit: 7a1d9325287a39528b795b1e8037146777abfe3e branch: main author: Pablo Galindo Salgado committer: pablogsal date: 2021-11-20T18:27:40Z summary: bpo-45450: Improve syntax error for parenthesized arguments (GH-28906) files: A Misc/NEWS.d/next/Core and Builtins/2021-10-12-18-22-44.bpo-45450.d9a-bX.rst M Grammar/python.gram M Lib/test/test_syntax.py M Parser/parser.c diff --git a/Grammar/python.gram b/Grammar/python.gram index 168bb3c05e6c9..60fbc400cf284 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -1140,12 +1140,16 @@ invalid_dict_comprehension: invalid_parameters: | param_no_default* invalid_parameters_helper a=param_no_default { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "non-default argument follows default argument") } + | param_no_default* a='(' param_no_default+ ','? b=')' { + RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "Function parameters cannot be parenthesized") } invalid_parameters_helper: # This is only there to avoid type errors | a=slash_with_default { _PyPegen_singleton_seq(p, a) } | param_with_default+ invalid_lambda_parameters: | lambda_param_no_default* invalid_lambda_parameters_helper a=lambda_param_no_default { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "non-default argument follows default argument") } + | lambda_param_no_default* a='(' ','.lambda_param+ ','? b=')' { + RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "Lambda expression parameters cannot be parenthesized") } invalid_lambda_parameters_helper: | a=lambda_slash_with_default { _PyPegen_singleton_seq(p, a) } | lambda_param_with_default+ diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index f41df8ca49aa6..28414ba59493b 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -909,6 +909,44 @@ Traceback (most recent call last): SyntaxError: expected '(' +Parenthesized arguments in function definitions + + >>> def f(x, (y, z), w): + ... pass + Traceback (most recent call last): + SyntaxError: Function parameters cannot be parenthesized + + >>> def f((x, y, z, w)): + ... pass + Traceback (most recent call last): + SyntaxError: Function parameters cannot be parenthesized + + >>> def f(x, (y, z, w)): + ... pass + Traceback (most recent call last): + SyntaxError: Function parameters cannot be parenthesized + + >>> def f((x, y, z), w): + ... pass + Traceback (most recent call last): + SyntaxError: Function parameters cannot be parenthesized + + >>> lambda x, (y, z), w: None + Traceback (most recent call last): + SyntaxError: Lambda expression parameters cannot be parenthesized + + >>> lambda (x, y, z, w): None + Traceback (most recent call last): + SyntaxError: Lambda expression parameters cannot be parenthesized + + >>> lambda x, (y, z, w): None + Traceback (most recent call last): + SyntaxError: Lambda expression parameters cannot be parenthesized + + >>> lambda (x, y, z), w: None + Traceback (most recent call last): + SyntaxError: Lambda expression parameters cannot be parenthesized + Custom error messages for try blocks that are not followed by except/finally >>> try: diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-10-12-18-22-44.bpo-45450.d9a-bX.rst b/Misc/NEWS.d/next/Core and Builtins/2021-10-12-18-22-44.bpo-45450.d9a-bX.rst new file mode 100644 index 0000000000000..78f825f2706d8 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-10-12-18-22-44.bpo-45450.d9a-bX.rst @@ -0,0 +1,2 @@ +Improve the syntax error message for parenthesized arguments. Patch by Pablo +Galindo. diff --git a/Parser/parser.c b/Parser/parser.c index 87f492d50c611..b3aa35989edcd 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -448,34 +448,34 @@ static char *soft_keywords[] = { #define _tmp_154_type 1374 #define _tmp_155_type 1375 #define _loop0_156_type 1376 -#define _loop1_157_type 1377 -#define _loop0_158_type 1378 +#define _loop0_157_type 1377 +#define _loop1_158_type 1378 #define _loop1_159_type 1379 -#define _tmp_160_type 1380 -#define _tmp_161_type 1381 -#define _tmp_162_type 1382 -#define _loop0_164_type 1383 -#define _gather_163_type 1384 -#define _loop0_166_type 1385 -#define _gather_165_type 1386 -#define _loop0_168_type 1387 -#define _gather_167_type 1388 -#define _loop0_170_type 1389 -#define _gather_169_type 1390 -#define _tmp_171_type 1391 -#define _tmp_172_type 1392 -#define _tmp_173_type 1393 -#define _tmp_174_type 1394 -#define _tmp_175_type 1395 +#define _loop0_160_type 1380 +#define _loop0_161_type 1381 +#define _loop0_163_type 1382 +#define _gather_162_type 1383 +#define _loop1_164_type 1384 +#define _tmp_165_type 1385 +#define _tmp_166_type 1386 +#define _tmp_167_type 1387 +#define _loop0_169_type 1388 +#define _gather_168_type 1389 +#define _loop0_171_type 1390 +#define _gather_170_type 1391 +#define _loop0_173_type 1392 +#define _gather_172_type 1393 +#define _loop0_175_type 1394 +#define _gather_174_type 1395 #define _tmp_176_type 1396 #define _tmp_177_type 1397 -#define _loop0_179_type 1398 -#define _gather_178_type 1399 +#define _tmp_178_type 1398 +#define _tmp_179_type 1399 #define _tmp_180_type 1400 #define _tmp_181_type 1401 #define _tmp_182_type 1402 -#define _tmp_183_type 1403 -#define _tmp_184_type 1404 +#define _loop0_184_type 1403 +#define _gather_183_type 1404 #define _tmp_185_type 1405 #define _tmp_186_type 1406 #define _tmp_187_type 1407 @@ -498,6 +498,11 @@ static char *soft_keywords[] = { #define _tmp_204_type 1424 #define _tmp_205_type 1425 #define _tmp_206_type 1426 +#define _tmp_207_type 1427 +#define _tmp_208_type 1428 +#define _tmp_209_type 1429 +#define _tmp_210_type 1430 +#define _tmp_211_type 1431 static mod_ty file_rule(Parser *p); static mod_ty interactive_rule(Parser *p); @@ -876,34 +881,34 @@ static void *_tmp_153_rule(Parser *p); static void *_tmp_154_rule(Parser *p); static void *_tmp_155_rule(Parser *p); static asdl_seq *_loop0_156_rule(Parser *p); -static asdl_seq *_loop1_157_rule(Parser *p); -static asdl_seq *_loop0_158_rule(Parser *p); +static asdl_seq *_loop0_157_rule(Parser *p); +static asdl_seq *_loop1_158_rule(Parser *p); static asdl_seq *_loop1_159_rule(Parser *p); -static void *_tmp_160_rule(Parser *p); -static void *_tmp_161_rule(Parser *p); -static void *_tmp_162_rule(Parser *p); -static asdl_seq *_loop0_164_rule(Parser *p); -static asdl_seq *_gather_163_rule(Parser *p); -static asdl_seq *_loop0_166_rule(Parser *p); -static asdl_seq *_gather_165_rule(Parser *p); -static asdl_seq *_loop0_168_rule(Parser *p); -static asdl_seq *_gather_167_rule(Parser *p); -static asdl_seq *_loop0_170_rule(Parser *p); -static asdl_seq *_gather_169_rule(Parser *p); -static void *_tmp_171_rule(Parser *p); -static void *_tmp_172_rule(Parser *p); -static void *_tmp_173_rule(Parser *p); -static void *_tmp_174_rule(Parser *p); -static void *_tmp_175_rule(Parser *p); +static asdl_seq *_loop0_160_rule(Parser *p); +static asdl_seq *_loop0_161_rule(Parser *p); +static asdl_seq *_loop0_163_rule(Parser *p); +static asdl_seq *_gather_162_rule(Parser *p); +static asdl_seq *_loop1_164_rule(Parser *p); +static void *_tmp_165_rule(Parser *p); +static void *_tmp_166_rule(Parser *p); +static void *_tmp_167_rule(Parser *p); +static asdl_seq *_loop0_169_rule(Parser *p); +static asdl_seq *_gather_168_rule(Parser *p); +static asdl_seq *_loop0_171_rule(Parser *p); +static asdl_seq *_gather_170_rule(Parser *p); +static asdl_seq *_loop0_173_rule(Parser *p); +static asdl_seq *_gather_172_rule(Parser *p); +static asdl_seq *_loop0_175_rule(Parser *p); +static asdl_seq *_gather_174_rule(Parser *p); static void *_tmp_176_rule(Parser *p); static void *_tmp_177_rule(Parser *p); -static asdl_seq *_loop0_179_rule(Parser *p); -static asdl_seq *_gather_178_rule(Parser *p); +static void *_tmp_178_rule(Parser *p); +static void *_tmp_179_rule(Parser *p); static void *_tmp_180_rule(Parser *p); static void *_tmp_181_rule(Parser *p); static void *_tmp_182_rule(Parser *p); -static void *_tmp_183_rule(Parser *p); -static void *_tmp_184_rule(Parser *p); +static asdl_seq *_loop0_184_rule(Parser *p); +static asdl_seq *_gather_183_rule(Parser *p); static void *_tmp_185_rule(Parser *p); static void *_tmp_186_rule(Parser *p); static void *_tmp_187_rule(Parser *p); @@ -926,6 +931,11 @@ static void *_tmp_203_rule(Parser *p); static void *_tmp_204_rule(Parser *p); static void *_tmp_205_rule(Parser *p); static void *_tmp_206_rule(Parser *p); +static void *_tmp_207_rule(Parser *p); +static void *_tmp_208_rule(Parser *p); +static void *_tmp_209_rule(Parser *p); +static void *_tmp_210_rule(Parser *p); +static void *_tmp_211_rule(Parser *p); // file: statements? $ @@ -19007,7 +19017,9 @@ invalid_dict_comprehension_rule(Parser *p) return _res; } -// invalid_parameters: param_no_default* invalid_parameters_helper param_no_default +// invalid_parameters: +// | param_no_default* invalid_parameters_helper param_no_default +// | param_no_default* '(' param_no_default+ ','? ')' static void * invalid_parameters_rule(Parser *p) { @@ -19048,6 +19060,43 @@ invalid_parameters_rule(Parser *p) D(fprintf(stderr, "%*c%s invalid_parameters[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default* invalid_parameters_helper param_no_default")); } + { // param_no_default* '(' param_no_default+ ','? ')' + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* '(' param_no_default+ ','? ')'")); + asdl_seq * _loop0_157_var; + asdl_seq * _loop1_158_var; + void *_opt_var; + UNUSED(_opt_var); // Silence compiler warnings + Token * a; + Token * b; + if ( + (_loop0_157_var = _loop0_157_rule(p)) // param_no_default* + && + (a = _PyPegen_expect_token(p, 7)) // token='(' + && + (_loop1_158_var = _loop1_158_rule(p)) // param_no_default+ + && + (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? + && + (b = _PyPegen_expect_token(p, 8)) // token=')' + ) + { + D(fprintf(stderr, "%*c+ invalid_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default* '(' param_no_default+ ','? ')'")); + _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "Function parameters cannot be parenthesized" ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + D(p->level--); + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s invalid_parameters[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default* '(' param_no_default+ ','? ')'")); + } _res = NULL; done: D(p->level--); @@ -19095,13 +19144,13 @@ invalid_parameters_helper_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default+")); - asdl_seq * _loop1_157_var; + asdl_seq * _loop1_159_var; if ( - (_loop1_157_var = _loop1_157_rule(p)) // param_with_default+ + (_loop1_159_var = _loop1_159_rule(p)) // param_with_default+ ) { D(fprintf(stderr, "%*c+ invalid_parameters_helper[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_with_default+")); - _res = _loop1_157_var; + _res = _loop1_159_var; goto done; } p->mark = _mark; @@ -19116,6 +19165,7 @@ invalid_parameters_helper_rule(Parser *p) // invalid_lambda_parameters: // | lambda_param_no_default* invalid_lambda_parameters_helper lambda_param_no_default +// | lambda_param_no_default* '(' ','.lambda_param+ ','? ')' static void * invalid_lambda_parameters_rule(Parser *p) { @@ -19132,11 +19182,11 @@ invalid_lambda_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* invalid_lambda_parameters_helper lambda_param_no_default")); - asdl_seq * _loop0_158_var; + asdl_seq * _loop0_160_var; arg_ty a; void *invalid_lambda_parameters_helper_var; if ( - (_loop0_158_var = _loop0_158_rule(p)) // lambda_param_no_default* + (_loop0_160_var = _loop0_160_rule(p)) // lambda_param_no_default* && (invalid_lambda_parameters_helper_var = invalid_lambda_parameters_helper_rule(p)) // invalid_lambda_parameters_helper && @@ -19156,6 +19206,43 @@ invalid_lambda_parameters_rule(Parser *p) D(fprintf(stderr, "%*c%s invalid_lambda_parameters[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default* invalid_lambda_parameters_helper lambda_param_no_default")); } + { // lambda_param_no_default* '(' ','.lambda_param+ ','? ')' + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* '(' ','.lambda_param+ ','? ')'")); + asdl_seq * _gather_162_var; + asdl_seq * _loop0_161_var; + void *_opt_var; + UNUSED(_opt_var); // Silence compiler warnings + Token * a; + Token * b; + if ( + (_loop0_161_var = _loop0_161_rule(p)) // lambda_param_no_default* + && + (a = _PyPegen_expect_token(p, 7)) // token='(' + && + (_gather_162_var = _gather_162_rule(p)) // ','.lambda_param+ + && + (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? + && + (b = _PyPegen_expect_token(p, 8)) // token=')' + ) + { + D(fprintf(stderr, "%*c+ invalid_lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* '(' ','.lambda_param+ ','? ')'")); + _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "Lambda expression parameters cannot be parenthesized" ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + D(p->level--); + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s invalid_lambda_parameters[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default* '(' ','.lambda_param+ ','? ')'")); + } _res = NULL; done: D(p->level--); @@ -19205,13 +19292,13 @@ invalid_lambda_parameters_helper_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+")); - asdl_seq * _loop1_159_var; + asdl_seq * _loop1_164_var; if ( - (_loop1_159_var = _loop1_159_rule(p)) // lambda_param_with_default+ + (_loop1_164_var = _loop1_164_rule(p)) // lambda_param_with_default+ ) { D(fprintf(stderr, "%*c+ invalid_lambda_parameters_helper[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+")); - _res = _loop1_159_var; + _res = _loop1_164_var; goto done; } p->mark = _mark; @@ -19241,12 +19328,12 @@ invalid_star_etc_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))")); - void *_tmp_160_var; + void *_tmp_165_var; Token * a; if ( (a = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_160_var = _tmp_160_rule(p)) // ')' | ',' (')' | '**') + (_tmp_165_var = _tmp_165_rule(p)) // ')' | ',' (')' | '**') ) { D(fprintf(stderr, "%*c+ invalid_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))")); @@ -19316,11 +19403,11 @@ invalid_lambda_star_etc_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))")); Token * _literal; - void *_tmp_161_var; + void *_tmp_166_var; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_161_var = _tmp_161_rule(p)) // ':' | ',' (':' | '**') + (_tmp_166_var = _tmp_166_rule(p)) // ':' | ',' (':' | '**') ) { D(fprintf(stderr, "%*c+ invalid_lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))")); @@ -19422,7 +19509,7 @@ invalid_with_item_rule(Parser *p) && (a = expression_rule(p)) // expression && - _PyPegen_lookahead(1, _tmp_162_rule, p) + _PyPegen_lookahead(1, _tmp_167_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_with_item[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression 'as' expression &(',' | ')' | ':')")); @@ -19638,7 +19725,7 @@ invalid_with_stmt_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' ','.(expression ['as' star_target])+ &&':'")); - asdl_seq * _gather_163_var; + asdl_seq * _gather_168_var; Token * _keyword; Token * _literal; void *_opt_var; @@ -19648,13 +19735,13 @@ invalid_with_stmt_rule(Parser *p) && (_keyword = _PyPegen_expect_token(p, 609)) // token='with' && - (_gather_163_var = _gather_163_rule(p)) // ','.(expression ['as' star_target])+ + (_gather_168_var = _gather_168_rule(p)) // ','.(expression ['as' star_target])+ && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' ) { D(fprintf(stderr, "%*c+ invalid_with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' ','.(expression ['as' star_target])+ &&':'")); - _res = _PyPegen_dummy_name(p, _opt_var, _keyword, _gather_163_var, _literal); + _res = _PyPegen_dummy_name(p, _opt_var, _keyword, _gather_168_var, _literal); goto done; } p->mark = _mark; @@ -19667,7 +19754,7 @@ invalid_with_stmt_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' &&':'")); - asdl_seq * _gather_165_var; + asdl_seq * _gather_170_var; Token * _keyword; Token * _literal; Token * _literal_1; @@ -19683,7 +19770,7 @@ invalid_with_stmt_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_165_var = _gather_165_rule(p)) // ','.(expressions ['as' star_target])+ + (_gather_170_var = _gather_170_rule(p)) // ','.(expressions ['as' star_target])+ && (_opt_var_1 = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -19693,7 +19780,7 @@ invalid_with_stmt_rule(Parser *p) ) { D(fprintf(stderr, "%*c+ invalid_with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' &&':'")); - _res = _PyPegen_dummy_name(p, _opt_var, _keyword, _literal, _gather_165_var, _opt_var_1, _literal_1, _literal_2); + _res = _PyPegen_dummy_name(p, _opt_var, _keyword, _literal, _gather_170_var, _opt_var_1, _literal_1, _literal_2); goto done; } p->mark = _mark; @@ -19725,7 +19812,7 @@ invalid_with_stmt_indent_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' ','.(expression ['as' star_target])+ ':' NEWLINE !INDENT")); - asdl_seq * _gather_167_var; + asdl_seq * _gather_172_var; Token * _literal; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings @@ -19736,7 +19823,7 @@ invalid_with_stmt_indent_rule(Parser *p) && (a = _PyPegen_expect_token(p, 609)) // token='with' && - (_gather_167_var = _gather_167_rule(p)) // ','.(expression ['as' star_target])+ + (_gather_172_var = _gather_172_rule(p)) // ','.(expression ['as' star_target])+ && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -19764,7 +19851,7 @@ invalid_with_stmt_indent_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' ':' NEWLINE !INDENT")); - asdl_seq * _gather_169_var; + asdl_seq * _gather_174_var; Token * _literal; Token * _literal_1; Token * _literal_2; @@ -19781,7 +19868,7 @@ invalid_with_stmt_indent_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_169_var = _gather_169_rule(p)) // ','.(expressions ['as' star_target])+ + (_gather_174_var = _gather_174_rule(p)) // ','.(expressions ['as' star_target])+ && (_opt_var_1 = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -19872,7 +19959,7 @@ invalid_try_stmt_rule(Parser *p) && (block_var = block_rule(p)) // block && - _PyPegen_lookahead(0, _tmp_171_rule, p) + _PyPegen_lookahead(0, _tmp_176_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' ':' block !('except' | 'finally')")); @@ -19930,7 +20017,7 @@ invalid_except_stmt_rule(Parser *p) && (expressions_var = expressions_rule(p)) // expressions && - (_opt_var = _tmp_172_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_177_rule(p), !p->error_indicator) // ['as' NAME] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' ) @@ -19964,7 +20051,7 @@ invalid_except_stmt_rule(Parser *p) && (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_173_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_178_rule(p), !p->error_indicator) // ['as' NAME] && (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) @@ -20094,7 +20181,7 @@ invalid_except_stmt_indent_rule(Parser *p) && (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_174_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_179_rule(p), !p->error_indicator) // ['as' NAME] && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -20478,7 +20565,7 @@ invalid_class_argument_pattern_rule(Parser *p) asdl_pattern_seq* a; asdl_seq* keyword_patterns_var; if ( - (_opt_var = _tmp_175_rule(p), !p->error_indicator) // [positional_patterns ','] + (_opt_var = _tmp_180_rule(p), !p->error_indicator) // [positional_patterns ','] && (keyword_patterns_var = keyword_patterns_rule(p)) // keyword_patterns && @@ -20912,7 +20999,7 @@ invalid_def_raw_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' && - (_opt_var_2 = _tmp_176_rule(p), !p->error_indicator) // ['->' expression] + (_opt_var_2 = _tmp_181_rule(p), !p->error_indicator) // ['->' expression] && (_literal_2 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -20968,7 +21055,7 @@ invalid_class_def_raw_rule(Parser *p) && (name_var = _PyPegen_name_token(p)) // NAME && - (_opt_var = _tmp_177_rule(p), !p->error_indicator) // ['(' arguments? ')'] + (_opt_var = _tmp_182_rule(p), !p->error_indicator) // ['(' arguments? ')'] && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -21016,11 +21103,11 @@ invalid_double_starred_kvpairs_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_double_starred_kvpairs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ',' invalid_kvpair")); - asdl_seq * _gather_178_var; + asdl_seq * _gather_183_var; Token * _literal; void *invalid_kvpair_var; if ( - (_gather_178_var = _gather_178_rule(p)) // ','.double_starred_kvpair+ + (_gather_183_var = _gather_183_rule(p)) // ','.double_starred_kvpair+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && @@ -21028,7 +21115,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) ) { D(fprintf(stderr, "%*c+ invalid_double_starred_kvpairs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ',' invalid_kvpair")); - _res = _PyPegen_dummy_name(p, _gather_178_var, _literal, invalid_kvpair_var); + _res = _PyPegen_dummy_name(p, _gather_183_var, _literal, invalid_kvpair_var); goto done; } p->mark = _mark; @@ -21081,7 +21168,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) && (a = _PyPegen_expect_token(p, 11)) // token=':' && - _PyPegen_lookahead(1, _tmp_180_rule, p) + _PyPegen_lookahead(1, _tmp_185_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_double_starred_kvpairs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' &('}' | ',')")); @@ -21998,12 +22085,12 @@ _loop1_14_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_14[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_181_var; + void *_tmp_186_var; while ( - (_tmp_181_var = _tmp_181_rule(p)) // star_targets '=' + (_tmp_186_var = _tmp_186_rule(p)) // star_targets '=' ) { - _res = _tmp_181_var; + _res = _tmp_186_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -22550,12 +22637,12 @@ _loop0_24_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_24[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); - void *_tmp_182_var; + void *_tmp_187_var; while ( - (_tmp_182_var = _tmp_182_rule(p)) // '.' | '...' + (_tmp_187_var = _tmp_187_rule(p)) // '.' | '...' ) { - _res = _tmp_182_var; + _res = _tmp_187_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -22616,12 +22703,12 @@ _loop1_25_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_25[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); - void *_tmp_183_var; + void *_tmp_188_var; while ( - (_tmp_183_var = _tmp_183_rule(p)) // '.' | '...' + (_tmp_188_var = _tmp_188_rule(p)) // '.' | '...' ) { - _res = _tmp_183_var; + _res = _tmp_188_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -23003,12 +23090,12 @@ _loop1_32_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_32[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('@' named_expression NEWLINE)")); - void *_tmp_184_var; + void *_tmp_189_var; while ( - (_tmp_184_var = _tmp_184_rule(p)) // '@' named_expression NEWLINE + (_tmp_189_var = _tmp_189_rule(p)) // '@' named_expression NEWLINE ) { - _res = _tmp_184_var; + _res = _tmp_189_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -25767,12 +25854,12 @@ _loop1_77_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_77[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' expression)")); - void *_tmp_185_var; + void *_tmp_190_var; while ( - (_tmp_185_var = _tmp_185_rule(p)) // ',' expression + (_tmp_190_var = _tmp_190_rule(p)) // ',' expression ) { - _res = _tmp_185_var; + _res = _tmp_190_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -25838,12 +25925,12 @@ _loop1_78_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_78[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_expression)")); - void *_tmp_186_var; + void *_tmp_191_var; while ( - (_tmp_186_var = _tmp_186_rule(p)) // ',' star_expression + (_tmp_191_var = _tmp_191_rule(p)) // ',' star_expression ) { - _res = _tmp_186_var; + _res = _tmp_191_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -26023,12 +26110,12 @@ _loop1_81_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_81[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('or' conjunction)")); - void *_tmp_187_var; + void *_tmp_192_var; while ( - (_tmp_187_var = _tmp_187_rule(p)) // 'or' conjunction + (_tmp_192_var = _tmp_192_rule(p)) // 'or' conjunction ) { - _res = _tmp_187_var; + _res = _tmp_192_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -26094,12 +26181,12 @@ _loop1_82_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_82[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('and' inversion)")); - void *_tmp_188_var; + void *_tmp_193_var; while ( - (_tmp_188_var = _tmp_188_rule(p)) // 'and' inversion + (_tmp_193_var = _tmp_193_rule(p)) // 'and' inversion ) { - _res = _tmp_188_var; + _res = _tmp_193_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -27974,12 +28061,12 @@ _loop0_111_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_111[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); - void *_tmp_189_var; + void *_tmp_194_var; while ( - (_tmp_189_var = _tmp_189_rule(p)) // 'if' disjunction + (_tmp_194_var = _tmp_194_rule(p)) // 'if' disjunction ) { - _res = _tmp_189_var; + _res = _tmp_194_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -28040,12 +28127,12 @@ _loop0_112_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); - void *_tmp_190_var; + void *_tmp_195_var; while ( - (_tmp_190_var = _tmp_190_rule(p)) // 'if' disjunction + (_tmp_195_var = _tmp_195_rule(p)) // 'if' disjunction ) { - _res = _tmp_190_var; + _res = _tmp_195_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -28168,7 +28255,7 @@ _loop0_115_rule(Parser *p) while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_191_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' + (elem = _tmp_196_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' ) { _res = elem; @@ -28232,7 +28319,7 @@ _gather_114_rule(Parser *p) void *elem; asdl_seq * seq; if ( - (elem = _tmp_191_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' + (elem = _tmp_196_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' && (seq = _loop0_115_rule(p)) // _loop0_115 ) @@ -28778,12 +28865,12 @@ _loop0_125_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); - void *_tmp_192_var; + void *_tmp_197_var; while ( - (_tmp_192_var = _tmp_192_rule(p)) // ',' star_target + (_tmp_197_var = _tmp_197_rule(p)) // ',' star_target ) { - _res = _tmp_192_var; + _res = _tmp_197_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -28958,12 +29045,12 @@ _loop1_128_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); - void *_tmp_193_var; + void *_tmp_198_var; while ( - (_tmp_193_var = _tmp_193_rule(p)) // ',' star_target + (_tmp_198_var = _tmp_198_rule(p)) // ',' star_target ) { - _res = _tmp_193_var; + _res = _tmp_198_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30267,12 +30354,12 @@ _loop0_150_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_194_var; + void *_tmp_199_var; while ( - (_tmp_194_var = _tmp_194_rule(p)) // star_targets '=' + (_tmp_199_var = _tmp_199_rule(p)) // star_targets '=' ) { - _res = _tmp_194_var; + _res = _tmp_199_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30333,12 +30420,12 @@ _loop0_151_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_195_var; + void *_tmp_200_var; while ( - (_tmp_195_var = _tmp_195_rule(p)) // star_targets '=' + (_tmp_200_var = _tmp_200_rule(p)) // star_targets '=' ) { - _res = _tmp_195_var; + _res = _tmp_200_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30677,9 +30764,146 @@ _loop0_156_rule(Parser *p) return _seq; } -// _loop1_157: param_with_default +// _loop0_157: param_no_default static asdl_seq * -_loop1_157_rule(Parser *p) +_loop0_157_rule(Parser *p) +{ + D(p->level++); + if (p->error_indicator) { + D(p->level--); + return NULL; + } + void *_res = NULL; + int _mark = p->mark; + int _start_mark = p->mark; + void **_children = PyMem_Malloc(sizeof(void *)); + if (!_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + Py_ssize_t _children_capacity = 1; + Py_ssize_t _n = 0; + { // param_no_default + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _loop0_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + arg_ty param_no_default_var; + while ( + (param_no_default_var = param_no_default_rule(p)) // param_no_default + ) + { + _res = param_no_default_var; + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _loop0_157[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); + } + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + 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_157_type, _seq); + D(p->level--); + return _seq; +} + +// _loop1_158: param_no_default +static asdl_seq * +_loop1_158_rule(Parser *p) +{ + D(p->level++); + if (p->error_indicator) { + D(p->level--); + return NULL; + } + void *_res = NULL; + int _mark = p->mark; + int _start_mark = p->mark; + void **_children = PyMem_Malloc(sizeof(void *)); + if (!_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + Py_ssize_t _children_capacity = 1; + Py_ssize_t _n = 0; + { // param_no_default + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _loop1_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + arg_ty param_no_default_var; + while ( + (param_no_default_var = param_no_default_rule(p)) // param_no_default + ) + { + _res = param_no_default_var; + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _loop1_158[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); + } + if (_n == 0 || p->error_indicator) { + PyMem_Free(_children); + D(p->level--); + return NULL; + } + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + 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_158_type, _seq); + D(p->level--); + return _seq; +} + +// _loop1_159: param_with_default +static asdl_seq * +_loop1_159_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30703,7 +30927,7 @@ _loop1_157_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); + D(fprintf(stderr, "%*c> _loop1_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); NameDefaultPair* param_with_default_var; while ( (param_with_default_var = param_with_default_rule(p)) // param_with_default @@ -30725,7 +30949,7 @@ _loop1_157_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_157[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_159[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -30743,14 +30967,14 @@ _loop1_157_rule(Parser *p) } 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); + _PyPegen_insert_memo(p, _start_mark, _loop1_159_type, _seq); D(p->level--); return _seq; } -// _loop0_158: lambda_param_no_default +// _loop0_160: lambda_param_no_default static asdl_seq * -_loop0_158_rule(Parser *p) +_loop0_160_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30774,7 +30998,7 @@ _loop0_158_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop0_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -30796,7 +31020,7 @@ _loop0_158_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_158[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_160[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30809,14 +31033,194 @@ _loop0_158_rule(Parser *p) } 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); + _PyPegen_insert_memo(p, _start_mark, _loop0_160_type, _seq); D(p->level--); return _seq; } -// _loop1_159: lambda_param_with_default +// _loop0_161: lambda_param_no_default static asdl_seq * -_loop1_159_rule(Parser *p) +_loop0_161_rule(Parser *p) +{ + D(p->level++); + if (p->error_indicator) { + D(p->level--); + return NULL; + } + void *_res = NULL; + int _mark = p->mark; + int _start_mark = p->mark; + void **_children = PyMem_Malloc(sizeof(void *)); + if (!_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + Py_ssize_t _children_capacity = 1; + Py_ssize_t _n = 0; + { // lambda_param_no_default + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _loop0_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + arg_ty lambda_param_no_default_var; + while ( + (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default + ) + { + _res = lambda_param_no_default_var; + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _loop0_161[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); + } + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + 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_161_type, _seq); + D(p->level--); + return _seq; +} + +// _loop0_163: ',' lambda_param +static asdl_seq * +_loop0_163_rule(Parser *p) +{ + D(p->level++); + if (p->error_indicator) { + D(p->level--); + return NULL; + } + void *_res = NULL; + int _mark = p->mark; + int _start_mark = p->mark; + void **_children = PyMem_Malloc(sizeof(void *)); + if (!_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + Py_ssize_t _children_capacity = 1; + Py_ssize_t _n = 0; + { // ',' lambda_param + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _loop0_163[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' lambda_param")); + Token * _literal; + arg_ty elem; + while ( + (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (elem = lambda_param_rule(p)) // lambda_param + ) + { + _res = elem; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + PyMem_Free(_children); + D(p->level--); + return NULL; + } + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _loop0_163[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' lambda_param")); + } + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + 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_163_type, _seq); + D(p->level--); + return _seq; +} + +// _gather_162: lambda_param _loop0_163 +static asdl_seq * +_gather_162_rule(Parser *p) +{ + D(p->level++); + if (p->error_indicator) { + D(p->level--); + return NULL; + } + asdl_seq * _res = NULL; + int _mark = p->mark; + { // lambda_param _loop0_163 + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _gather_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param _loop0_163")); + arg_ty elem; + asdl_seq * seq; + if ( + (elem = lambda_param_rule(p)) // lambda_param + && + (seq = _loop0_163_rule(p)) // _loop0_163 + ) + { + D(fprintf(stderr, "%*c+ _gather_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param _loop0_163")); + _res = _PyPegen_seq_insert_in_front(p, elem, seq); + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _gather_162[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param _loop0_163")); + } + _res = NULL; + done: + D(p->level--); + return _res; +} + +// _loop1_164: lambda_param_with_default +static asdl_seq * +_loop1_164_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30840,7 +31244,7 @@ _loop1_159_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop1_164[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -30862,7 +31266,7 @@ _loop1_159_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_159[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_164[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -30880,14 +31284,14 @@ _loop1_159_rule(Parser *p) } 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); + _PyPegen_insert_memo(p, _start_mark, _loop1_164_type, _seq); D(p->level--); return _seq; } -// _tmp_160: ')' | ',' (')' | '**') +// _tmp_165: ')' | ',' (')' | '**') static void * -_tmp_160_rule(Parser *p) +_tmp_165_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30901,18 +31305,18 @@ _tmp_160_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_165[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_165[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // ',' (')' | '**') @@ -30920,21 +31324,21 @@ _tmp_160_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); + D(fprintf(stderr, "%*c> _tmp_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); Token * _literal; - void *_tmp_196_var; + void *_tmp_201_var; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_tmp_196_var = _tmp_196_rule(p)) // ')' | '**' + (_tmp_201_var = _tmp_201_rule(p)) // ')' | '**' ) { - D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); - _res = _PyPegen_dummy_name(p, _literal, _tmp_196_var); + D(fprintf(stderr, "%*c+ _tmp_165[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); + _res = _PyPegen_dummy_name(p, _literal, _tmp_201_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_165[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (')' | '**')")); } _res = NULL; @@ -30943,9 +31347,9 @@ _tmp_160_rule(Parser *p) return _res; } -// _tmp_161: ':' | ',' (':' | '**') +// _tmp_166: ':' | ',' (':' | '**') static void * -_tmp_161_rule(Parser *p) +_tmp_166_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -30959,18 +31363,18 @@ _tmp_161_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_166[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_166[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // ',' (':' | '**') @@ -30978,21 +31382,21 @@ _tmp_161_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); + D(fprintf(stderr, "%*c> _tmp_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); Token * _literal; - void *_tmp_197_var; + void *_tmp_202_var; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_tmp_197_var = _tmp_197_rule(p)) // ':' | '**' + (_tmp_202_var = _tmp_202_rule(p)) // ':' | '**' ) { - D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); - _res = _PyPegen_dummy_name(p, _literal, _tmp_197_var); + D(fprintf(stderr, "%*c+ _tmp_166[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); + _res = _PyPegen_dummy_name(p, _literal, _tmp_202_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_166[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (':' | '**')")); } _res = NULL; @@ -31001,9 +31405,9 @@ _tmp_161_rule(Parser *p) return _res; } -// _tmp_162: ',' | ')' | ':' +// _tmp_167: ',' | ')' | ':' static void * -_tmp_162_rule(Parser *p) +_tmp_167_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31017,18 +31421,18 @@ _tmp_162_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_162[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_167[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } { // ')' @@ -31036,18 +31440,18 @@ _tmp_162_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_162[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_167[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // ':' @@ -31055,18 +31459,18 @@ _tmp_162_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_162[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_167[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } _res = NULL; @@ -31075,9 +31479,9 @@ _tmp_162_rule(Parser *p) return _res; } -// _loop0_164: ',' (expression ['as' star_target]) +// _loop0_169: ',' (expression ['as' star_target]) static asdl_seq * -_loop0_164_rule(Parser *p) +_loop0_169_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31101,13 +31505,13 @@ _loop0_164_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_164[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_198_rule(p)) // expression ['as' star_target] + (elem = _tmp_203_rule(p)) // expression ['as' star_target] ) { _res = elem; @@ -31132,7 +31536,7 @@ _loop0_164_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_164[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_169[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expression ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31145,14 +31549,14 @@ _loop0_164_rule(Parser *p) } 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); + _PyPegen_insert_memo(p, _start_mark, _loop0_169_type, _seq); D(p->level--); return _seq; } -// _gather_163: (expression ['as' star_target]) _loop0_164 +// _gather_168: (expression ['as' star_target]) _loop0_169 static asdl_seq * -_gather_163_rule(Parser *p) +_gather_168_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31161,27 +31565,27 @@ _gather_163_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expression ['as' star_target]) _loop0_164 + { // (expression ['as' star_target]) _loop0_169 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_163[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_164")); + D(fprintf(stderr, "%*c> _gather_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_169")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_198_rule(p)) // expression ['as' star_target] + (elem = _tmp_203_rule(p)) // expression ['as' star_target] && - (seq = _loop0_164_rule(p)) // _loop0_164 + (seq = _loop0_169_rule(p)) // _loop0_169 ) { - D(fprintf(stderr, "%*c+ _gather_163[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_164")); + D(fprintf(stderr, "%*c+ _gather_168[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_169")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_163[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_164")); + D(fprintf(stderr, "%*c%s _gather_168[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_169")); } _res = NULL; done: @@ -31189,9 +31593,9 @@ _gather_163_rule(Parser *p) return _res; } -// _loop0_166: ',' (expressions ['as' star_target]) +// _loop0_171: ',' (expressions ['as' star_target]) static asdl_seq * -_loop0_166_rule(Parser *p) +_loop0_171_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31215,13 +31619,13 @@ _loop0_166_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_199_rule(p)) // expressions ['as' star_target] + (elem = _tmp_204_rule(p)) // expressions ['as' star_target] ) { _res = elem; @@ -31246,7 +31650,7 @@ _loop0_166_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_166[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_171[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expressions ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31259,14 +31663,14 @@ _loop0_166_rule(Parser *p) } 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); + _PyPegen_insert_memo(p, _start_mark, _loop0_171_type, _seq); D(p->level--); return _seq; } -// _gather_165: (expressions ['as' star_target]) _loop0_166 +// _gather_170: (expressions ['as' star_target]) _loop0_171 static asdl_seq * -_gather_165_rule(Parser *p) +_gather_170_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31275,27 +31679,27 @@ _gather_165_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expressions ['as' star_target]) _loop0_166 + { // (expressions ['as' star_target]) _loop0_171 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_166")); + D(fprintf(stderr, "%*c> _gather_170[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_171")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_199_rule(p)) // expressions ['as' star_target] + (elem = _tmp_204_rule(p)) // expressions ['as' star_target] && - (seq = _loop0_166_rule(p)) // _loop0_166 + (seq = _loop0_171_rule(p)) // _loop0_171 ) { - D(fprintf(stderr, "%*c+ _gather_165[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_166")); + D(fprintf(stderr, "%*c+ _gather_170[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_171")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_165[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_166")); + D(fprintf(stderr, "%*c%s _gather_170[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_171")); } _res = NULL; done: @@ -31303,9 +31707,9 @@ _gather_165_rule(Parser *p) return _res; } -// _loop0_168: ',' (expression ['as' star_target]) +// _loop0_173: ',' (expression ['as' star_target]) static asdl_seq * -_loop0_168_rule(Parser *p) +_loop0_173_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31329,13 +31733,13 @@ _loop0_168_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_173[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_200_rule(p)) // expression ['as' star_target] + (elem = _tmp_205_rule(p)) // expression ['as' star_target] ) { _res = elem; @@ -31360,7 +31764,7 @@ _loop0_168_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_168[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_173[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expression ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31373,14 +31777,14 @@ _loop0_168_rule(Parser *p) } 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); + _PyPegen_insert_memo(p, _start_mark, _loop0_173_type, _seq); D(p->level--); return _seq; } -// _gather_167: (expression ['as' star_target]) _loop0_168 +// _gather_172: (expression ['as' star_target]) _loop0_173 static asdl_seq * -_gather_167_rule(Parser *p) +_gather_172_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31389,27 +31793,27 @@ _gather_167_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expression ['as' star_target]) _loop0_168 + { // (expression ['as' star_target]) _loop0_173 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_168")); + D(fprintf(stderr, "%*c> _gather_172[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_173")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_200_rule(p)) // expression ['as' star_target] + (elem = _tmp_205_rule(p)) // expression ['as' star_target] && - (seq = _loop0_168_rule(p)) // _loop0_168 + (seq = _loop0_173_rule(p)) // _loop0_173 ) { - D(fprintf(stderr, "%*c+ _gather_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_168")); + D(fprintf(stderr, "%*c+ _gather_172[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_173")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_167[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_168")); + D(fprintf(stderr, "%*c%s _gather_172[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_173")); } _res = NULL; done: @@ -31417,9 +31821,9 @@ _gather_167_rule(Parser *p) return _res; } -// _loop0_170: ',' (expressions ['as' star_target]) +// _loop0_175: ',' (expressions ['as' star_target]) static asdl_seq * -_loop0_170_rule(Parser *p) +_loop0_175_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31443,13 +31847,13 @@ _loop0_170_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_170[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_175[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_201_rule(p)) // expressions ['as' star_target] + (elem = _tmp_206_rule(p)) // expressions ['as' star_target] ) { _res = elem; @@ -31474,7 +31878,7 @@ _loop0_170_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_170[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_175[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expressions ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31487,14 +31891,14 @@ _loop0_170_rule(Parser *p) } 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); + _PyPegen_insert_memo(p, _start_mark, _loop0_175_type, _seq); D(p->level--); return _seq; } -// _gather_169: (expressions ['as' star_target]) _loop0_170 +// _gather_174: (expressions ['as' star_target]) _loop0_175 static asdl_seq * -_gather_169_rule(Parser *p) +_gather_174_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31503,27 +31907,27 @@ _gather_169_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expressions ['as' star_target]) _loop0_170 + { // (expressions ['as' star_target]) _loop0_175 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_170")); + D(fprintf(stderr, "%*c> _gather_174[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_175")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_201_rule(p)) // expressions ['as' star_target] + (elem = _tmp_206_rule(p)) // expressions ['as' star_target] && - (seq = _loop0_170_rule(p)) // _loop0_170 + (seq = _loop0_175_rule(p)) // _loop0_175 ) { - D(fprintf(stderr, "%*c+ _gather_169[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_170")); + D(fprintf(stderr, "%*c+ _gather_174[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_175")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_169[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_170")); + D(fprintf(stderr, "%*c%s _gather_174[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_175")); } _res = NULL; done: @@ -31531,9 +31935,9 @@ _gather_169_rule(Parser *p) return _res; } -// _tmp_171: 'except' | 'finally' +// _tmp_176: 'except' | 'finally' static void * -_tmp_171_rule(Parser *p) +_tmp_176_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31547,18 +31951,18 @@ _tmp_171_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'")); + D(fprintf(stderr, "%*c> _tmp_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 623)) // token='except' ) { - D(fprintf(stderr, "%*c+ _tmp_171[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except'")); + D(fprintf(stderr, "%*c+ _tmp_176[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_171[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_176[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except'")); } { // 'finally' @@ -31566,18 +31970,18 @@ _tmp_171_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'")); + D(fprintf(stderr, "%*c> _tmp_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 620)) // token='finally' ) { - D(fprintf(stderr, "%*c+ _tmp_171[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally'")); + D(fprintf(stderr, "%*c+ _tmp_176[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_171[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_176[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'finally'")); } _res = NULL; @@ -31586,9 +31990,9 @@ _tmp_171_rule(Parser *p) return _res; } -// _tmp_172: 'as' NAME +// _tmp_177: 'as' NAME static void * -_tmp_172_rule(Parser *p) +_tmp_177_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31602,7 +32006,7 @@ _tmp_172_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_172[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_177[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( @@ -31611,12 +32015,12 @@ _tmp_172_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_172[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_177[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_172[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_177[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -31625,9 +32029,9 @@ _tmp_172_rule(Parser *p) return _res; } -// _tmp_173: 'as' NAME +// _tmp_178: 'as' NAME static void * -_tmp_173_rule(Parser *p) +_tmp_178_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31641,7 +32045,7 @@ _tmp_173_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_173[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( @@ -31650,12 +32054,12 @@ _tmp_173_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_173[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_178[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_173[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_178[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -31664,9 +32068,9 @@ _tmp_173_rule(Parser *p) return _res; } -// _tmp_174: 'as' NAME +// _tmp_179: 'as' NAME static void * -_tmp_174_rule(Parser *p) +_tmp_179_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31680,7 +32084,7 @@ _tmp_174_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_174[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( @@ -31689,12 +32093,12 @@ _tmp_174_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_174[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_179[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_174[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_179[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -31703,9 +32107,9 @@ _tmp_174_rule(Parser *p) return _res; } -// _tmp_175: positional_patterns ',' +// _tmp_180: positional_patterns ',' static void * -_tmp_175_rule(Parser *p) +_tmp_180_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31719,7 +32123,7 @@ _tmp_175_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_175[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); + D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); Token * _literal; asdl_pattern_seq* positional_patterns_var; if ( @@ -31728,12 +32132,12 @@ _tmp_175_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_175[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); + D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); _res = _PyPegen_dummy_name(p, positional_patterns_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_175[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "positional_patterns ','")); } _res = NULL; @@ -31742,9 +32146,9 @@ _tmp_175_rule(Parser *p) return _res; } -// _tmp_176: '->' expression +// _tmp_181: '->' expression static void * -_tmp_176_rule(Parser *p) +_tmp_181_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31758,7 +32162,7 @@ _tmp_176_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); + D(fprintf(stderr, "%*c> _tmp_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); Token * _literal; expr_ty expression_var; if ( @@ -31767,12 +32171,12 @@ _tmp_176_rule(Parser *p) (expression_var = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ _tmp_176[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); + D(fprintf(stderr, "%*c+ _tmp_181[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); _res = _PyPegen_dummy_name(p, _literal, expression_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_176[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_181[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'->' expression")); } _res = NULL; @@ -31781,9 +32185,9 @@ _tmp_176_rule(Parser *p) return _res; } -// _tmp_177: '(' arguments? ')' +// _tmp_182: '(' arguments? ')' static void * -_tmp_177_rule(Parser *p) +_tmp_182_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31797,7 +32201,7 @@ _tmp_177_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_177[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); Token * _literal; Token * _literal_1; void *_opt_var; @@ -31810,12 +32214,12 @@ _tmp_177_rule(Parser *p) (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_177[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c+ _tmp_182[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); _res = _PyPegen_dummy_name(p, _literal, _opt_var, _literal_1); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_177[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_182[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' arguments? ')'")); } _res = NULL; @@ -31824,9 +32228,9 @@ _tmp_177_rule(Parser *p) return _res; } -// _loop0_179: ',' double_starred_kvpair +// _loop0_184: ',' double_starred_kvpair static asdl_seq * -_loop0_179_rule(Parser *p) +_loop0_184_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31850,7 +32254,7 @@ _loop0_179_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); + D(fprintf(stderr, "%*c> _loop0_184[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); Token * _literal; KeyValuePair* elem; while ( @@ -31881,7 +32285,7 @@ _loop0_179_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_179[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_184[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' double_starred_kvpair")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31894,14 +32298,14 @@ _loop0_179_rule(Parser *p) } 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_179_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_184_type, _seq); D(p->level--); return _seq; } -// _gather_178: double_starred_kvpair _loop0_179 +// _gather_183: double_starred_kvpair _loop0_184 static asdl_seq * -_gather_178_rule(Parser *p) +_gather_183_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31910,27 +32314,27 @@ _gather_178_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // double_starred_kvpair _loop0_179 + { // double_starred_kvpair _loop0_184 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_179")); + D(fprintf(stderr, "%*c> _gather_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_184")); KeyValuePair* elem; asdl_seq * seq; if ( (elem = double_starred_kvpair_rule(p)) // double_starred_kvpair && - (seq = _loop0_179_rule(p)) // _loop0_179 + (seq = _loop0_184_rule(p)) // _loop0_184 ) { - D(fprintf(stderr, "%*c+ _gather_178[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_179")); + D(fprintf(stderr, "%*c+ _gather_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_184")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_178[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_179")); + D(fprintf(stderr, "%*c%s _gather_183[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_184")); } _res = NULL; done: @@ -31938,9 +32342,9 @@ _gather_178_rule(Parser *p) return _res; } -// _tmp_180: '}' | ',' +// _tmp_185: '}' | ',' static void * -_tmp_180_rule(Parser *p) +_tmp_185_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -31954,18 +32358,18 @@ _tmp_180_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_185[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_185[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_185[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } { // ',' @@ -31973,18 +32377,18 @@ _tmp_180_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_185[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_185[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_185[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -31993,9 +32397,9 @@ _tmp_180_rule(Parser *p) return _res; } -// _tmp_181: star_targets '=' +// _tmp_186: star_targets '=' static void * -_tmp_181_rule(Parser *p) +_tmp_186_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32009,7 +32413,7 @@ _tmp_181_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_186[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty z; if ( @@ -32018,7 +32422,7 @@ _tmp_181_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_181[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_186[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32028,7 +32432,7 @@ _tmp_181_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_181[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_186[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; @@ -32037,9 +32441,9 @@ _tmp_181_rule(Parser *p) return _res; } -// _tmp_182: '.' | '...' +// _tmp_187: '.' | '...' static void * -_tmp_182_rule(Parser *p) +_tmp_187_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32053,18 +32457,18 @@ _tmp_182_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c> _tmp_187[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 23)) // token='.' ) { - D(fprintf(stderr, "%*c+ _tmp_182[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c+ _tmp_187[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_182[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_187[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); } { // '...' @@ -32072,18 +32476,18 @@ _tmp_182_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c> _tmp_187[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 52)) // token='...' ) { - D(fprintf(stderr, "%*c+ _tmp_182[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c+ _tmp_187[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_182[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_187[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'")); } _res = NULL; @@ -32092,9 +32496,9 @@ _tmp_182_rule(Parser *p) return _res; } -// _tmp_183: '.' | '...' +// _tmp_188: '.' | '...' static void * -_tmp_183_rule(Parser *p) +_tmp_188_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32108,18 +32512,18 @@ _tmp_183_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c> _tmp_188[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 23)) // token='.' ) { - D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c+ _tmp_188[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_188[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); } { // '...' @@ -32127,18 +32531,18 @@ _tmp_183_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c> _tmp_188[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 52)) // token='...' ) { - D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c+ _tmp_188[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_188[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'")); } _res = NULL; @@ -32147,9 +32551,9 @@ _tmp_183_rule(Parser *p) return _res; } -// _tmp_184: '@' named_expression NEWLINE +// _tmp_189: '@' named_expression NEWLINE static void * -_tmp_184_rule(Parser *p) +_tmp_189_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32163,7 +32567,7 @@ _tmp_184_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_184[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); + D(fprintf(stderr, "%*c> _tmp_189[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); Token * _literal; expr_ty f; Token * newline_var; @@ -32175,7 +32579,7 @@ _tmp_184_rule(Parser *p) (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) { - D(fprintf(stderr, "%*c+ _tmp_184[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); + D(fprintf(stderr, "%*c+ _tmp_189[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); _res = f; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32185,7 +32589,7 @@ _tmp_184_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_184[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_189[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'@' named_expression NEWLINE")); } _res = NULL; @@ -32194,9 +32598,9 @@ _tmp_184_rule(Parser *p) return _res; } -// _tmp_185: ',' expression +// _tmp_190: ',' expression static void * -_tmp_185_rule(Parser *p) +_tmp_190_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32210,7 +32614,7 @@ _tmp_185_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_185[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _tmp_190[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty c; if ( @@ -32219,7 +32623,7 @@ _tmp_185_rule(Parser *p) (c = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ _tmp_185[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c+ _tmp_190[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32229,7 +32633,7 @@ _tmp_185_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_185[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_190[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } _res = NULL; @@ -32238,9 +32642,9 @@ _tmp_185_rule(Parser *p) return _res; } -// _tmp_186: ',' star_expression +// _tmp_191: ',' star_expression static void * -_tmp_186_rule(Parser *p) +_tmp_191_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32254,7 +32658,7 @@ _tmp_186_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_186[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression")); + D(fprintf(stderr, "%*c> _tmp_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression")); Token * _literal; expr_ty c; if ( @@ -32263,7 +32667,7 @@ _tmp_186_rule(Parser *p) (c = star_expression_rule(p)) // star_expression ) { - D(fprintf(stderr, "%*c+ _tmp_186[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression")); + D(fprintf(stderr, "%*c+ _tmp_191[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32273,7 +32677,7 @@ _tmp_186_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_186[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_191[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_expression")); } _res = NULL; @@ -32282,9 +32686,9 @@ _tmp_186_rule(Parser *p) return _res; } -// _tmp_187: 'or' conjunction +// _tmp_192: 'or' conjunction static void * -_tmp_187_rule(Parser *p) +_tmp_192_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32298,7 +32702,7 @@ _tmp_187_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_187[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); + D(fprintf(stderr, "%*c> _tmp_192[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); Token * _keyword; expr_ty c; if ( @@ -32307,7 +32711,7 @@ _tmp_187_rule(Parser *p) (c = conjunction_rule(p)) // conjunction ) { - D(fprintf(stderr, "%*c+ _tmp_187[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); + D(fprintf(stderr, "%*c+ _tmp_192[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32317,7 +32721,7 @@ _tmp_187_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_187[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_192[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'or' conjunction")); } _res = NULL; @@ -32326,9 +32730,9 @@ _tmp_187_rule(Parser *p) return _res; } -// _tmp_188: 'and' inversion +// _tmp_193: 'and' inversion static void * -_tmp_188_rule(Parser *p) +_tmp_193_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32342,7 +32746,7 @@ _tmp_188_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_188[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion")); + D(fprintf(stderr, "%*c> _tmp_193[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion")); Token * _keyword; expr_ty c; if ( @@ -32351,7 +32755,7 @@ _tmp_188_rule(Parser *p) (c = inversion_rule(p)) // inversion ) { - D(fprintf(stderr, "%*c+ _tmp_188[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion")); + D(fprintf(stderr, "%*c+ _tmp_193[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32361,7 +32765,7 @@ _tmp_188_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_188[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_193[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'and' inversion")); } _res = NULL; @@ -32370,9 +32774,9 @@ _tmp_188_rule(Parser *p) return _res; } -// _tmp_189: 'if' disjunction +// _tmp_194: 'if' disjunction static void * -_tmp_189_rule(Parser *p) +_tmp_194_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32386,7 +32790,7 @@ _tmp_189_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_189[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c> _tmp_194[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); Token * _keyword; expr_ty z; if ( @@ -32395,7 +32799,7 @@ _tmp_189_rule(Parser *p) (z = disjunction_rule(p)) // disjunction ) { - D(fprintf(stderr, "%*c+ _tmp_189[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c+ _tmp_194[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32405,7 +32809,7 @@ _tmp_189_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_189[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_194[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction")); } _res = NULL; @@ -32414,9 +32818,9 @@ _tmp_189_rule(Parser *p) return _res; } -// _tmp_190: 'if' disjunction +// _tmp_195: 'if' disjunction static void * -_tmp_190_rule(Parser *p) +_tmp_195_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32430,7 +32834,7 @@ _tmp_190_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_190[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c> _tmp_195[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); Token * _keyword; expr_ty z; if ( @@ -32439,7 +32843,7 @@ _tmp_190_rule(Parser *p) (z = disjunction_rule(p)) // disjunction ) { - D(fprintf(stderr, "%*c+ _tmp_190[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c+ _tmp_195[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32449,7 +32853,7 @@ _tmp_190_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_190[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_195[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction")); } _res = NULL; @@ -32458,9 +32862,9 @@ _tmp_190_rule(Parser *p) return _res; } -// _tmp_191: starred_expression | (assignment_expression | expression !':=') !'=' +// _tmp_196: starred_expression | (assignment_expression | expression !':=') !'=' static void * -_tmp_191_rule(Parser *p) +_tmp_196_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32474,18 +32878,18 @@ _tmp_191_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c> _tmp_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); expr_ty starred_expression_var; if ( (starred_expression_var = starred_expression_rule(p)) // starred_expression ) { - D(fprintf(stderr, "%*c+ _tmp_191[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c+ _tmp_196[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); _res = starred_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_191[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_196[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression")); } { // (assignment_expression | expression !':=') !'=' @@ -32493,20 +32897,20 @@ _tmp_191_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); - void *_tmp_202_var; + D(fprintf(stderr, "%*c> _tmp_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); + void *_tmp_207_var; if ( - (_tmp_202_var = _tmp_202_rule(p)) // assignment_expression | expression !':=' + (_tmp_207_var = _tmp_207_rule(p)) // assignment_expression | expression !':=' && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_191[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); - _res = _tmp_202_var; + D(fprintf(stderr, "%*c+ _tmp_196[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); + _res = _tmp_207_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_191[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_196[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(assignment_expression | expression !':=') !'='")); } _res = NULL; @@ -32515,9 +32919,9 @@ _tmp_191_rule(Parser *p) return _res; } -// _tmp_192: ',' star_target +// _tmp_197: ',' star_target static void * -_tmp_192_rule(Parser *p) +_tmp_197_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32531,7 +32935,7 @@ _tmp_192_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_192[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _tmp_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); Token * _literal; expr_ty c; if ( @@ -32540,7 +32944,7 @@ _tmp_192_rule(Parser *p) (c = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_192[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c+ _tmp_197[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32550,7 +32954,7 @@ _tmp_192_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_192[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_197[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } _res = NULL; @@ -32559,9 +32963,9 @@ _tmp_192_rule(Parser *p) return _res; } -// _tmp_193: ',' star_target +// _tmp_198: ',' star_target static void * -_tmp_193_rule(Parser *p) +_tmp_198_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32575,7 +32979,7 @@ _tmp_193_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_193[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _tmp_198[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); Token * _literal; expr_ty c; if ( @@ -32584,7 +32988,7 @@ _tmp_193_rule(Parser *p) (c = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_193[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c+ _tmp_198[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32594,7 +32998,7 @@ _tmp_193_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_193[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_198[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } _res = NULL; @@ -32603,9 +33007,9 @@ _tmp_193_rule(Parser *p) return _res; } -// _tmp_194: star_targets '=' +// _tmp_199: star_targets '=' static void * -_tmp_194_rule(Parser *p) +_tmp_199_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32619,7 +33023,7 @@ _tmp_194_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_194[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_199[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty star_targets_var; if ( @@ -32628,12 +33032,12 @@ _tmp_194_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_194[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_199[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = _PyPegen_dummy_name(p, star_targets_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_194[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_199[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; @@ -32642,9 +33046,9 @@ _tmp_194_rule(Parser *p) return _res; } -// _tmp_195: star_targets '=' +// _tmp_200: star_targets '=' static void * -_tmp_195_rule(Parser *p) +_tmp_200_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32658,7 +33062,7 @@ _tmp_195_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_195[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_200[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty star_targets_var; if ( @@ -32667,12 +33071,12 @@ _tmp_195_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_195[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_200[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = _PyPegen_dummy_name(p, star_targets_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_195[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_200[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; @@ -32681,9 +33085,9 @@ _tmp_195_rule(Parser *p) return _res; } -// _tmp_196: ')' | '**' +// _tmp_201: ')' | '**' static void * -_tmp_196_rule(Parser *p) +_tmp_201_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32697,18 +33101,18 @@ _tmp_196_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_196[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_196[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // '**' @@ -32716,18 +33120,18 @@ _tmp_196_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_196[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_196[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } _res = NULL; @@ -32736,9 +33140,9 @@ _tmp_196_rule(Parser *p) return _res; } -// _tmp_197: ':' | '**' +// _tmp_202: ':' | '**' static void * -_tmp_197_rule(Parser *p) +_tmp_202_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32752,18 +33156,18 @@ _tmp_197_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_197[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_197[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // '**' @@ -32771,18 +33175,18 @@ _tmp_197_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_197[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_197[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } _res = NULL; @@ -32791,9 +33195,9 @@ _tmp_197_rule(Parser *p) return _res; } -// _tmp_198: expression ['as' star_target] +// _tmp_203: expression ['as' star_target] static void * -_tmp_198_rule(Parser *p) +_tmp_203_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32807,22 +33211,22 @@ _tmp_198_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_198[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_203_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_208_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_198[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_203[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); _res = _PyPegen_dummy_name(p, expression_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_198[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_203[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' star_target]")); } _res = NULL; @@ -32831,9 +33235,9 @@ _tmp_198_rule(Parser *p) return _res; } -// _tmp_199: expressions ['as' star_target] +// _tmp_204: expressions ['as' star_target] static void * -_tmp_199_rule(Parser *p) +_tmp_204_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32847,22 +33251,22 @@ _tmp_199_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_199[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_204[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expressions_var; if ( (expressions_var = expressions_rule(p)) // expressions && - (_opt_var = _tmp_204_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_209_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_199[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_204[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); _res = _PyPegen_dummy_name(p, expressions_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_199[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_204[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expressions ['as' star_target]")); } _res = NULL; @@ -32871,9 +33275,9 @@ _tmp_199_rule(Parser *p) return _res; } -// _tmp_200: expression ['as' star_target] +// _tmp_205: expression ['as' star_target] static void * -_tmp_200_rule(Parser *p) +_tmp_205_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32887,22 +33291,22 @@ _tmp_200_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_200[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_205[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_205_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_210_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_200[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_205[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); _res = _PyPegen_dummy_name(p, expression_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_200[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_205[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' star_target]")); } _res = NULL; @@ -32911,9 +33315,9 @@ _tmp_200_rule(Parser *p) return _res; } -// _tmp_201: expressions ['as' star_target] +// _tmp_206: expressions ['as' star_target] static void * -_tmp_201_rule(Parser *p) +_tmp_206_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32927,22 +33331,22 @@ _tmp_201_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_206[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expressions_var; if ( (expressions_var = expressions_rule(p)) // expressions && - (_opt_var = _tmp_206_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_211_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_206[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); _res = _PyPegen_dummy_name(p, expressions_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_206[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expressions ['as' star_target]")); } _res = NULL; @@ -32951,9 +33355,9 @@ _tmp_201_rule(Parser *p) return _res; } -// _tmp_202: assignment_expression | expression !':=' +// _tmp_207: assignment_expression | expression !':=' static void * -_tmp_202_rule(Parser *p) +_tmp_207_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -32967,18 +33371,18 @@ _tmp_202_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + D(fprintf(stderr, "%*c> _tmp_207[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); expr_ty assignment_expression_var; if ( (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression ) { - D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + D(fprintf(stderr, "%*c+ _tmp_207[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); _res = assignment_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_207[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); } { // expression !':=' @@ -32986,7 +33390,7 @@ _tmp_202_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c> _tmp_207[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression @@ -32994,12 +33398,12 @@ _tmp_202_rule(Parser *p) _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 53) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c+ _tmp_207[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); _res = expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_207[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression !':='")); } _res = NULL; @@ -33008,9 +33412,9 @@ _tmp_202_rule(Parser *p) return _res; } -// _tmp_203: 'as' star_target +// _tmp_208: 'as' star_target static void * -_tmp_203_rule(Parser *p) +_tmp_208_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -33024,7 +33428,7 @@ _tmp_203_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_208[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( @@ -33033,12 +33437,12 @@ _tmp_203_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_203[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_208[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_203[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_208[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; @@ -33047,9 +33451,9 @@ _tmp_203_rule(Parser *p) return _res; } -// _tmp_204: 'as' star_target +// _tmp_209: 'as' star_target static void * -_tmp_204_rule(Parser *p) +_tmp_209_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -33063,7 +33467,7 @@ _tmp_204_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_204[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_209[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( @@ -33072,12 +33476,12 @@ _tmp_204_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_204[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_209[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_204[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_209[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; @@ -33086,9 +33490,9 @@ _tmp_204_rule(Parser *p) return _res; } -// _tmp_205: 'as' star_target +// _tmp_210: 'as' star_target static void * -_tmp_205_rule(Parser *p) +_tmp_210_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -33102,7 +33506,7 @@ _tmp_205_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_205[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_210[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( @@ -33111,12 +33515,12 @@ _tmp_205_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_205[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_210[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_205[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_210[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; @@ -33125,9 +33529,9 @@ _tmp_205_rule(Parser *p) return _res; } -// _tmp_206: 'as' star_target +// _tmp_211: 'as' star_target static void * -_tmp_206_rule(Parser *p) +_tmp_211_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -33141,7 +33545,7 @@ _tmp_206_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_206[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_211[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( @@ -33150,12 +33554,12 @@ _tmp_206_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_206[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_211[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_206[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_211[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; From webhook-mailer at python.org Sat Nov 20 13:28:39 2021 From: webhook-mailer at python.org (pablogsal) Date: Sat, 20 Nov 2021 18:28:39 -0000 Subject: [Python-checkins] bpo-45811: Improve error message when source code contains invisible control characters (GH-29654) Message-ID: https://github.com/python/cpython/commit/81f4e116ef7d30ef6e2041c2d6cf29af511a3a02 commit: 81f4e116ef7d30ef6e2041c2d6cf29af511a3a02 branch: main author: Pablo Galindo Salgado committer: pablogsal date: 2021-11-20T18:28:28Z summary: bpo-45811: Improve error message when source code contains invisible control characters (GH-29654) files: A Misc/NEWS.d/next/Core and Builtins/2021-11-20-02-25-06.bpo-45811.B-1Gsr.rst M Lib/test/test_syntax.py M Parser/tokenizer.c diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 28414ba59493b..fc3c62954a29b 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -1566,6 +1566,9 @@ def test_error_parenthesis(self): for paren in ")]}": self._check_error(paren + "1 + 2", f"unmatched '\\{paren}'") + def test_invisible_characters(self): + self._check_error('print\x17("Hello")', "invalid non-printable character") + def test_match_call_does_not_raise_syntax_error(self): code = """ def match(x): diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-20-02-25-06.bpo-45811.B-1Gsr.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-20-02-25-06.bpo-45811.B-1Gsr.rst new file mode 100644 index 0000000000000..4b31414408150 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-20-02-25-06.bpo-45811.B-1Gsr.rst @@ -0,0 +1,2 @@ +Improve the tokenizer errors when encountering invisible control characters +in the parser. Patch by Pablo Galindo diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index f281c423d0e0c..69d2c08b43926 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -2045,6 +2045,12 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end) break; } + if (!Py_UNICODE_ISPRINTABLE(c)) { + char hex[9]; + (void)PyOS_snprintf(hex, sizeof(hex), "%04X", c); + return syntaxerror(tok, "invalid non-printable character U+%s", hex); + } + /* Punctuation character */ *p_start = tok->start; *p_end = tok->cur; From webhook-mailer at python.org Sat Nov 20 13:44:14 2021 From: webhook-mailer at python.org (miss-islington) Date: Sat, 20 Nov 2021 18:44:14 -0000 Subject: [Python-checkins] bpo-44844: Remove unresponsive web link (GH-29651) Message-ID: https://github.com/python/cpython/commit/d1855ed752ea0484101fc13622626ed0fa2c17b9 commit: d1855ed752ea0484101fc13622626ed0fa2c17b9 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-20T10:44:04-08:00 summary: bpo-44844: Remove unresponsive web link (GH-29651) Threading notes by Aahz from OSCON 2001. (cherry picked from commit 985233914504c73f14a23af1c68a3709079e6913) Co-authored-by: Terry Jan Reedy files: M Doc/faq/library.rst diff --git a/Doc/faq/library.rst b/Doc/faq/library.rst index 97058b5806a35..bfc4baecb4529 100644 --- a/Doc/faq/library.rst +++ b/Doc/faq/library.rst @@ -243,9 +243,6 @@ Be sure to use the :mod:`threading` module and not the :mod:`_thread` module. The :mod:`threading` module builds convenient abstractions on top of the low-level primitives provided by the :mod:`_thread` module. -Aahz has a set of slides from his threading tutorial that are helpful; see -http://www.pythoncraft.com/OSCON2001/. - None of my threads seem to run: why? ------------------------------------ From webhook-mailer at python.org Sat Nov 20 13:50:32 2021 From: webhook-mailer at python.org (terryjreedy) Date: Sat, 20 Nov 2021 18:50:32 -0000 Subject: [Python-checkins] bpo-45845: Remove unresponsive web link (GH-29651) (GH-29674) Message-ID: https://github.com/python/cpython/commit/edabf3904619e6be97d12e41d30402845b3ec8b8 commit: edabf3904619e6be97d12e41d30402845b3ec8b8 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: terryjreedy date: 2021-11-20T13:50:24-05:00 summary: bpo-45845: Remove unresponsive web link (GH-29651) (GH-29674) Threading notes by Aahz from OSCON 2001. (cherry picked from commit 985233914504c73f14a23af1c68a3709079e6913) Co-authored-by: Terry Jan Reedy files: M Doc/faq/library.rst diff --git a/Doc/faq/library.rst b/Doc/faq/library.rst index 45c20bd6cadb2..ebc6eaecf7d26 100644 --- a/Doc/faq/library.rst +++ b/Doc/faq/library.rst @@ -243,9 +243,6 @@ Be sure to use the :mod:`threading` module and not the :mod:`_thread` module. The :mod:`threading` module builds convenient abstractions on top of the low-level primitives provided by the :mod:`_thread` module. -Aahz has a set of slides from his threading tutorial that are helpful; see -http://www.pythoncraft.com/OSCON2001/. - None of my threads seem to run: why? ------------------------------------ From webhook-mailer at python.org Sat Nov 20 14:56:53 2021 From: webhook-mailer at python.org (terryjreedy) Date: Sat, 20 Nov 2021 19:56:53 -0000 Subject: [Python-checkins] bpo-45845: Change link for pyserial (GH-29675) Message-ID: https://github.com/python/cpython/commit/123a3527ddd7774e8db325c778927e49172e01d4 commit: 123a3527ddd7774e8db325c778927e49172e01d4 branch: main author: Terry Jan Reedy committer: terryjreedy date: 2021-11-20T14:56:42-05:00 summary: bpo-45845: Change link for pyserial (GH-29675) files: M Doc/faq/library.rst diff --git a/Doc/faq/library.rst b/Doc/faq/library.rst index 78f5a06120879..b9e541c150dc4 100644 --- a/Doc/faq/library.rst +++ b/Doc/faq/library.rst @@ -611,9 +611,9 @@ use ``p.read(n)``. How do I access the serial (RS232) port? ---------------------------------------- -For Win32, POSIX (Linux, BSD, etc.), Jython: +For Win32, OSX, Linux, BSD, Jython, IronPython: - http://pyserial.sourceforge.net + https://pypi.org/project/pyserial/ For Unix, see a Usenet post by Mitch Chapman: From webhook-mailer at python.org Sat Nov 20 15:19:51 2021 From: webhook-mailer at python.org (pitrou) Date: Sat, 20 Nov 2021 20:19:51 -0000 Subject: [Python-checkins] bpo-44733: Add max_tasks_per_child to ProcessPoolExecutor (GH-27373) Message-ID: https://github.com/python/cpython/commit/fdc0e09c3316098b038996c428e88931f0a4fcdb commit: fdc0e09c3316098b038996c428e88931f0a4fcdb branch: main author: Logan Jones committer: pitrou date: 2021-11-20T21:19:41+01:00 summary: bpo-44733: Add max_tasks_per_child to ProcessPoolExecutor (GH-27373) Co-authored-by: Antoine Pitrou files: A Misc/NEWS.d/next/Library/2021-07-26-13-33-37.bpo-44733.88LrP1.rst M Doc/library/concurrent.futures.rst M Lib/concurrent/futures/process.py M Lib/test/test_concurrent_futures.py diff --git a/Doc/library/concurrent.futures.rst b/Doc/library/concurrent.futures.rst index 897efc2f54442..b4213b451157e 100644 --- a/Doc/library/concurrent.futures.rst +++ b/Doc/library/concurrent.futures.rst @@ -231,7 +231,7 @@ that :class:`ProcessPoolExecutor` will not work in the interactive interpreter. Calling :class:`Executor` or :class:`Future` methods from a callable submitted to a :class:`ProcessPoolExecutor` will result in deadlock. -.. class:: ProcessPoolExecutor(max_workers=None, mp_context=None, initializer=None, initargs=()) +.. class:: ProcessPoolExecutor(max_workers=None, mp_context=None, initializer=None, initargs=(), max_tasks_per_child=None) An :class:`Executor` subclass that executes calls asynchronously using a pool of at most *max_workers* processes. If *max_workers* is ``None`` or not @@ -252,6 +252,11 @@ to a :class:`ProcessPoolExecutor` will result in deadlock. pending jobs will raise a :exc:`~concurrent.futures.process.BrokenProcessPool`, as well as any attempt to submit more jobs to the pool. + *max_tasks_per_child* is an optional argument that specifies the maximum + number of tasks a single process can execute before it will exit and be + replaced with a fresh worker process. The default *max_tasks_per_child* is + ``None`` which means worker processes will live as long as the pool. + .. versionchanged:: 3.3 When one of the worker processes terminates abruptly, a :exc:`BrokenProcessPool` error is now raised. Previously, behaviour @@ -264,6 +269,10 @@ to a :class:`ProcessPoolExecutor` will result in deadlock. Added the *initializer* and *initargs* arguments. + .. versionchanged:: 3.11 + The *max_tasks_per_child* argument was added to allow users to + control the lifetime of workers in the pool. + .. _processpoolexecutor-example: diff --git a/Lib/concurrent/futures/process.py b/Lib/concurrent/futures/process.py index 9904db78c5b4c..19e93a608b276 100644 --- a/Lib/concurrent/futures/process.py +++ b/Lib/concurrent/futures/process.py @@ -141,10 +141,11 @@ def __init__(self, future, fn, args, kwargs): self.kwargs = kwargs class _ResultItem(object): - def __init__(self, work_id, exception=None, result=None): + def __init__(self, work_id, exception=None, result=None, exit_pid=None): self.work_id = work_id self.exception = exception self.result = result + self.exit_pid = exit_pid class _CallItem(object): def __init__(self, work_id, fn, args, kwargs): @@ -201,17 +202,19 @@ def _process_chunk(fn, chunk): return [fn(*args) for args in chunk] -def _sendback_result(result_queue, work_id, result=None, exception=None): +def _sendback_result(result_queue, work_id, result=None, exception=None, + exit_pid=None): """Safely send back the given result or exception""" try: result_queue.put(_ResultItem(work_id, result=result, - exception=exception)) + exception=exception, exit_pid=exit_pid)) except BaseException as e: exc = _ExceptionWithTraceback(e, e.__traceback__) - result_queue.put(_ResultItem(work_id, exception=exc)) + result_queue.put(_ResultItem(work_id, exception=exc, + exit_pid=exit_pid)) -def _process_worker(call_queue, result_queue, initializer, initargs): +def _process_worker(call_queue, result_queue, initializer, initargs, max_tasks=None): """Evaluates calls from call_queue and places the results in result_queue. This worker is run in a separate process. @@ -232,25 +235,38 @@ def _process_worker(call_queue, result_queue, initializer, initargs): # The parent will notice that the process stopped and # mark the pool broken return + num_tasks = 0 + exit_pid = None while True: call_item = call_queue.get(block=True) if call_item is None: # Wake up queue management thread result_queue.put(os.getpid()) return + + if max_tasks is not None: + num_tasks += 1 + if num_tasks >= max_tasks: + exit_pid = os.getpid() + try: r = call_item.fn(*call_item.args, **call_item.kwargs) except BaseException as e: exc = _ExceptionWithTraceback(e, e.__traceback__) - _sendback_result(result_queue, call_item.work_id, exception=exc) + _sendback_result(result_queue, call_item.work_id, exception=exc, + exit_pid=exit_pid) else: - _sendback_result(result_queue, call_item.work_id, result=r) + _sendback_result(result_queue, call_item.work_id, result=r, + exit_pid=exit_pid) del r # Liberate the resource as soon as possible, to avoid holding onto # open files or shared memory that is not needed anymore del call_item + if exit_pid is not None: + return + class _ExecutorManagerThread(threading.Thread): """Manages the communication between this process and the worker processes. @@ -301,6 +317,10 @@ def weakref_cb(_, # A queue.Queue of work ids e.g. Queue([5, 6, ...]). self.work_ids_queue = executor._work_ids + # Maximum number of tasks a worker process can execute before + # exiting safely + self.max_tasks_per_child = executor._max_tasks_per_child + # A dict mapping work ids to _WorkItems e.g. # {5: <_WorkItem...>, 6: <_WorkItem...>, ...} self.pending_work_items = executor._pending_work_items @@ -320,15 +340,23 @@ def run(self): return if result_item is not None: self.process_result_item(result_item) + + process_exited = result_item.exit_pid is not None + if process_exited: + p = self.processes.pop(result_item.exit_pid) + p.join() + # Delete reference to result_item to avoid keeping references # while waiting on new results. del result_item - # attempt to increment idle process count - executor = self.executor_reference() - if executor is not None: - executor._idle_worker_semaphore.release() - del executor + if executor := self.executor_reference(): + if process_exited: + with self.shutdown_lock: + executor._adjust_process_count() + else: + executor._idle_worker_semaphore.release() + del executor if self.is_shutting_down(): self.flag_executor_shutting_down() @@ -578,7 +606,7 @@ class BrokenProcessPool(_base.BrokenExecutor): class ProcessPoolExecutor(_base.Executor): def __init__(self, max_workers=None, mp_context=None, - initializer=None, initargs=()): + initializer=None, initargs=(), *, max_tasks_per_child=None): """Initializes a new ProcessPoolExecutor instance. Args: @@ -589,6 +617,11 @@ def __init__(self, max_workers=None, mp_context=None, object should provide SimpleQueue, Queue and Process. initializer: A callable used to initialize worker processes. initargs: A tuple of arguments to pass to the initializer. + max_tasks_per_child: The maximum number of tasks a worker process can + complete before it will exit and be replaced with a fresh + worker process, to enable unused resources to be freed. The + default value is None, which means worker process will live + as long as the executor will live. """ _check_system_limits() @@ -616,6 +649,13 @@ def __init__(self, max_workers=None, mp_context=None, self._initializer = initializer self._initargs = initargs + if max_tasks_per_child is not None: + if not isinstance(max_tasks_per_child, int): + raise TypeError("max_tasks_per_child must be an integer") + elif max_tasks_per_child <= 0: + raise ValueError("max_tasks_per_child must be >= 1") + self._max_tasks_per_child = max_tasks_per_child + # Management thread self._executor_manager_thread = None @@ -678,7 +718,8 @@ def _adjust_process_count(self): args=(self._call_queue, self._result_queue, self._initializer, - self._initargs)) + self._initargs, + self._max_tasks_per_child)) p.start() self._processes[p.pid] = p diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py index 84209ca2520b8..bbb6aa1eef81f 100644 --- a/Lib/test/test_concurrent_futures.py +++ b/Lib/test/test_concurrent_futures.py @@ -49,7 +49,6 @@ def create_future(state=PENDING, exception=None, result=None): INITIALIZER_STATUS = 'uninitialized' - def mul(x, y): return x * y @@ -1038,6 +1037,36 @@ def test_idle_process_reuse_multiple(self): self.assertLessEqual(len(executor._processes), 2) executor.shutdown() + def test_max_tasks_per_child(self): + executor = self.executor_type(1, max_tasks_per_child=3) + f1 = executor.submit(os.getpid) + original_pid = f1.result() + # The worker pid remains the same as the worker could be reused + f2 = executor.submit(os.getpid) + self.assertEqual(f2.result(), original_pid) + self.assertEqual(len(executor._processes), 1) + f3 = executor.submit(os.getpid) + self.assertEqual(f3.result(), original_pid) + + # A new worker is spawned, with a statistically different pid, + # while the previous was reaped. + f4 = executor.submit(os.getpid) + new_pid = f4.result() + self.assertNotEqual(original_pid, new_pid) + self.assertEqual(len(executor._processes), 1) + + executor.shutdown() + + def test_max_tasks_early_shutdown(self): + executor = self.executor_type(3, max_tasks_per_child=1) + futures = [] + for i in range(6): + futures.append(executor.submit(mul, i, i)) + executor.shutdown() + for i, future in enumerate(futures): + self.assertEqual(future.result(), mul(i, i)) + + create_executor_tests(ProcessPoolExecutorTest, executor_mixins=(ProcessPoolForkMixin, ProcessPoolForkserverMixin, diff --git a/Misc/NEWS.d/next/Library/2021-07-26-13-33-37.bpo-44733.88LrP1.rst b/Misc/NEWS.d/next/Library/2021-07-26-13-33-37.bpo-44733.88LrP1.rst new file mode 100644 index 0000000000000..666b5f7d0a035 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-07-26-13-33-37.bpo-44733.88LrP1.rst @@ -0,0 +1,3 @@ +Add ``max_tasks_per_child`` to :class:`concurrent.futures.ProcessPoolExecutor`. +This allows users to specify the maximum number of tasks a single process +should execute before the process needs to be restarted. From webhook-mailer at python.org Sat Nov 20 15:51:32 2021 From: webhook-mailer at python.org (terryjreedy) Date: Sat, 20 Nov 2021 20:51:32 -0000 Subject: [Python-checkins] [3.10] bpo-45845: Change link for pyserial (GH-29675) Message-ID: https://github.com/python/cpython/commit/3528df12581e8ccf3fae6d25bd9687ae55424398 commit: 3528df12581e8ccf3fae6d25bd9687ae55424398 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: terryjreedy date: 2021-11-20T15:51:24-05:00 summary: [3.10] bpo-45845: Change link for pyserial (GH-29675) (cherry picked from commit 123a3527ddd7774e8db325c778927e49172e01d4) Co-authored-by: Terry Jan Reedy files: M Doc/faq/library.rst diff --git a/Doc/faq/library.rst b/Doc/faq/library.rst index ebc6eaecf7d26..faca834e96545 100644 --- a/Doc/faq/library.rst +++ b/Doc/faq/library.rst @@ -614,9 +614,9 @@ use ``p.read(n)``. How do I access the serial (RS232) port? ---------------------------------------- -For Win32, POSIX (Linux, BSD, etc.), Jython: +For Win32, OSX, Linux, BSD, Jython, IronPython: - http://pyserial.sourceforge.net + https://pypi.org/project/pyserial/ For Unix, see a Usenet post by Mitch Chapman: From webhook-mailer at python.org Sat Nov 20 15:52:12 2021 From: webhook-mailer at python.org (terryjreedy) Date: Sat, 20 Nov 2021 20:52:12 -0000 Subject: [Python-checkins] [3.9] bpo-45845: Change link for pyserial (GH-29675) Message-ID: https://github.com/python/cpython/commit/e81e1d7f8116e9bf905ca378b0bec3ca5131bc29 commit: e81e1d7f8116e9bf905ca378b0bec3ca5131bc29 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: terryjreedy date: 2021-11-20T15:52:07-05:00 summary: [3.9] bpo-45845: Change link for pyserial (GH-29675) (cherry picked from commit 123a3527ddd7774e8db325c778927e49172e01d4) Co-authored-by: Terry Jan Reedy files: M Doc/faq/library.rst diff --git a/Doc/faq/library.rst b/Doc/faq/library.rst index bfc4baecb4529..7703d48a2137a 100644 --- a/Doc/faq/library.rst +++ b/Doc/faq/library.rst @@ -614,9 +614,9 @@ use ``p.read(n)``. How do I access the serial (RS232) port? ---------------------------------------- -For Win32, POSIX (Linux, BSD, etc.), Jython: +For Win32, OSX, Linux, BSD, Jython, IronPython: - http://pyserial.sourceforge.net + https://pypi.org/project/pyserial/ For Unix, see a Usenet post by Mitch Chapman: From webhook-mailer at python.org Sat Nov 20 18:26:09 2021 From: webhook-mailer at python.org (ericvsmith) Date: Sat, 20 Nov 2021 23:26:09 -0000 Subject: [Python-checkins] Added kw_only parameter to make_dataclasses. (GH-29679) Message-ID: https://github.com/python/cpython/commit/f7638dd0f90b2afd9295ee179119f4a29859953a commit: f7638dd0f90b2afd9295ee179119f4a29859953a branch: main author: Eric V. Smith committer: ericvsmith date: 2021-11-20T18:25:56-05:00 summary: Added kw_only parameter to make_dataclasses. (GH-29679) files: A Misc/NEWS.d/next/Library/2021-11-20-17-04-25.bpo-45803.wSgFOy.rst M Lib/dataclasses.py M Lib/test/test_dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 1e98bf9b9bb97..aca60501d0e0f 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -1326,7 +1326,7 @@ def _astuple_inner(obj, tuple_factory): def make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True, repr=True, eq=True, order=False, unsafe_hash=False, - frozen=False, match_args=True, slots=False): + frozen=False, match_args=True, kw_only=False, slots=False): """Return a new dynamically created dataclass. The dataclass name will be 'cls_name'. 'fields' is an iterable @@ -1393,7 +1393,7 @@ def exec_body_callback(ns): # Apply the normal decorator. return dataclass(cls, init=init, repr=repr, eq=eq, order=order, unsafe_hash=unsafe_hash, frozen=frozen, - match_args=match_args, slots=slots) + match_args=match_args, kw_only=kw_only, slots=slots) def replace(obj, /, **changes): diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index bbbb8e6c6395b..b00d0484d387e 100644 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -3864,5 +3864,16 @@ class A: c: int = 1 d: int + def test_make_dataclass(self): + A = make_dataclass("A", ['a'], kw_only=True) + self.assertTrue(fields(A)[0].kw_only) + + B = make_dataclass("B", + ['a', ('b', int, field(kw_only=False))], + kw_only=True) + self.assertTrue(fields(B)[0].kw_only) + self.assertFalse(fields(B)[1].kw_only) + + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Library/2021-11-20-17-04-25.bpo-45803.wSgFOy.rst b/Misc/NEWS.d/next/Library/2021-11-20-17-04-25.bpo-45803.wSgFOy.rst new file mode 100644 index 0000000000000..77479d7db476b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-20-17-04-25.bpo-45803.wSgFOy.rst @@ -0,0 +1 @@ +Added missing kw_only parameter to dataclasses.make_dataclass(). From webhook-mailer at python.org Sat Nov 20 18:47:06 2021 From: webhook-mailer at python.org (miss-islington) Date: Sat, 20 Nov 2021 23:47:06 -0000 Subject: [Python-checkins] Added kw_only parameter to make_dataclasses. (GH-29679) Message-ID: https://github.com/python/cpython/commit/cf8c8788c904cce68b0ab1d39900483f50983301 commit: cf8c8788c904cce68b0ab1d39900483f50983301 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-20T15:46:56-08:00 summary: Added kw_only parameter to make_dataclasses. (GH-29679) (cherry picked from commit f7638dd0f90b2afd9295ee179119f4a29859953a) Co-authored-by: Eric V. Smith files: A Misc/NEWS.d/next/Library/2021-11-20-17-04-25.bpo-45803.wSgFOy.rst M Lib/dataclasses.py M Lib/test/test_dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index aa84f1b9533cb..4f4aa3d3487ce 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -1326,7 +1326,7 @@ def _astuple_inner(obj, tuple_factory): def make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True, repr=True, eq=True, order=False, unsafe_hash=False, - frozen=False, match_args=True, slots=False): + frozen=False, match_args=True, kw_only=False, slots=False): """Return a new dynamically created dataclass. The dataclass name will be 'cls_name'. 'fields' is an iterable @@ -1393,7 +1393,7 @@ def exec_body_callback(ns): # Apply the normal decorator. return dataclass(cls, init=init, repr=repr, eq=eq, order=order, unsafe_hash=unsafe_hash, frozen=frozen, - match_args=match_args, slots=slots) + match_args=match_args, kw_only=kw_only, slots=slots) def replace(obj, /, **changes): diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index bbbb8e6c6395b..b00d0484d387e 100644 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -3864,5 +3864,16 @@ class A: c: int = 1 d: int + def test_make_dataclass(self): + A = make_dataclass("A", ['a'], kw_only=True) + self.assertTrue(fields(A)[0].kw_only) + + B = make_dataclass("B", + ['a', ('b', int, field(kw_only=False))], + kw_only=True) + self.assertTrue(fields(B)[0].kw_only) + self.assertFalse(fields(B)[1].kw_only) + + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Library/2021-11-20-17-04-25.bpo-45803.wSgFOy.rst b/Misc/NEWS.d/next/Library/2021-11-20-17-04-25.bpo-45803.wSgFOy.rst new file mode 100644 index 0000000000000..77479d7db476b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-20-17-04-25.bpo-45803.wSgFOy.rst @@ -0,0 +1 @@ +Added missing kw_only parameter to dataclasses.make_dataclass(). From webhook-mailer at python.org Sat Nov 20 19:27:54 2021 From: webhook-mailer at python.org (rhettinger) Date: Sun, 21 Nov 2021 00:27:54 -0000 Subject: [Python-checkins] bpo-45852: Fix the Counter/iter test for statistics.mode() (GH-29667) (GH-29671) Message-ID: https://github.com/python/cpython/commit/9841ac2da5689ff765250c1abdbf5af9d3750519 commit: 9841ac2da5689ff765250c1abdbf5af9d3750519 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: rhettinger date: 2021-11-20T18:27:44-06:00 summary: bpo-45852: Fix the Counter/iter test for statistics.mode() (GH-29667) (GH-29671) Suggested by Stefan Pochmann. (cherry picked from commit 48744db70ed519c1566c22bf123a0e1f5c69253f) Co-authored-by: Raymond Hettinger Co-authored-by: Raymond Hettinger files: M Lib/test/test_statistics.py diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py index adccfad7b8ed1..2853b1b2b2f4f 100644 --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -1897,10 +1897,13 @@ def test_none_data(self): def test_counter_data(self): # Test that a Counter is treated like any other iterable. - data = collections.Counter([1, 1, 1, 2]) - # Since the keys of the counter are treated as data points, not the - # counts, this should return the first mode encountered, 1 - self.assertEqual(self.func(data), 1) + # We're making sure mode() first calls iter() on its input. + # The concern is that a Counter of a Counter returns the original + # unchanged rather than counting its keys. + c = collections.Counter(a=1, b=2) + # If iter() is called, mode(c) loops over the keys, ['a', 'b'], + # all the counts will be 1, and the first encountered mode is 'a'. + self.assertEqual(self.func(c), 'a') class TestMultiMode(unittest.TestCase): From webhook-mailer at python.org Sat Nov 20 20:09:03 2021 From: webhook-mailer at python.org (pablogsal) Date: Sun, 21 Nov 2021 01:09:03 -0000 Subject: [Python-checkins] Refactor parser compilation units into specific components (GH-29676) Message-ID: https://github.com/python/cpython/commit/c9c4444d9f11ae80c2c4cc7d40b6718419d81a97 commit: c9c4444d9f11ae80c2c4cc7d40b6718419d81a97 branch: main author: Pablo Galindo Salgado committer: pablogsal date: 2021-11-21T01:08:50Z summary: Refactor parser compilation units into specific components (GH-29676) files: A Parser/action_helpers.c A Parser/pegen_errors.c M Makefile.pre.in M PCbuild/_freeze_module.vcxproj M PCbuild/pythoncore.vcxproj M PCbuild/pythoncore.vcxproj.filters M Parser/pegen.c M Parser/pegen.h M Tools/peg_generator/Makefile M Tools/peg_generator/pegen/build.py diff --git a/Makefile.pre.in b/Makefile.pre.in index 11ffdaabc617b..fc4def8f5d12f 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -331,6 +331,8 @@ LIBFFI_INCLUDEDIR= @LIBFFI_INCLUDEDIR@ PEGEN_OBJS= \ Parser/pegen.o \ + Parser/pegen_errors.o \ + Parser/action_helpers.o \ Parser/parser.o \ Parser/string_parser.o \ Parser/peg_api.o diff --git a/PCbuild/_freeze_module.vcxproj b/PCbuild/_freeze_module.vcxproj index d33e07c54b8c9..6a91776b9d8e9 100644 --- a/PCbuild/_freeze_module.vcxproj +++ b/PCbuild/_freeze_module.vcxproj @@ -163,6 +163,8 @@ + + diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index b65998186927b..70f05563fa391 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -433,6 +433,8 @@ + + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 62aab5bccf9ef..b19f0279ec311 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -1205,6 +1205,12 @@ Parser + + Parser + + + Parser + Parser diff --git a/Parser/action_helpers.c b/Parser/action_helpers.c new file mode 100644 index 0000000000000..e5d7b667f7f5e --- /dev/null +++ b/Parser/action_helpers.c @@ -0,0 +1,1289 @@ +#include + +#include "pegen.h" +#include "string_parser.h" + +static PyObject * +_create_dummy_identifier(Parser *p) +{ + return _PyPegen_new_identifier(p, ""); +} + +void * +_PyPegen_dummy_name(Parser *p, ...) +{ + static void *cache = NULL; + + if (cache != NULL) { + return cache; + } + + PyObject *id = _create_dummy_identifier(p); + if (!id) { + return NULL; + } + cache = _PyAST_Name(id, Load, 1, 0, 1, 0, p->arena); + return cache; +} + +/* Creates a single-element asdl_seq* that contains a */ +asdl_seq * +_PyPegen_singleton_seq(Parser *p, void *a) +{ + assert(a != NULL); + asdl_seq *seq = (asdl_seq*)_Py_asdl_generic_seq_new(1, p->arena); + if (!seq) { + return NULL; + } + asdl_seq_SET_UNTYPED(seq, 0, a); + return seq; +} + +/* Creates a copy of seq and prepends a to it */ +asdl_seq * +_PyPegen_seq_insert_in_front(Parser *p, void *a, asdl_seq *seq) +{ + assert(a != NULL); + if (!seq) { + return _PyPegen_singleton_seq(p, a); + } + + asdl_seq *new_seq = (asdl_seq*)_Py_asdl_generic_seq_new(asdl_seq_LEN(seq) + 1, p->arena); + if (!new_seq) { + return NULL; + } + + asdl_seq_SET_UNTYPED(new_seq, 0, a); + for (Py_ssize_t i = 1, l = asdl_seq_LEN(new_seq); i < l; i++) { + asdl_seq_SET_UNTYPED(new_seq, i, asdl_seq_GET_UNTYPED(seq, i - 1)); + } + return new_seq; +} + +/* Creates a copy of seq and appends a to it */ +asdl_seq * +_PyPegen_seq_append_to_end(Parser *p, asdl_seq *seq, void *a) +{ + assert(a != NULL); + if (!seq) { + return _PyPegen_singleton_seq(p, a); + } + + asdl_seq *new_seq = (asdl_seq*)_Py_asdl_generic_seq_new(asdl_seq_LEN(seq) + 1, p->arena); + if (!new_seq) { + return NULL; + } + + for (Py_ssize_t i = 0, l = asdl_seq_LEN(new_seq); i + 1 < l; i++) { + asdl_seq_SET_UNTYPED(new_seq, i, asdl_seq_GET_UNTYPED(seq, i)); + } + asdl_seq_SET_UNTYPED(new_seq, asdl_seq_LEN(new_seq) - 1, a); + return new_seq; +} + +static Py_ssize_t +_get_flattened_seq_size(asdl_seq *seqs) +{ + Py_ssize_t size = 0; + for (Py_ssize_t i = 0, l = asdl_seq_LEN(seqs); i < l; i++) { + asdl_seq *inner_seq = asdl_seq_GET_UNTYPED(seqs, i); + size += asdl_seq_LEN(inner_seq); + } + return size; +} + +/* Flattens an asdl_seq* of asdl_seq*s */ +asdl_seq * +_PyPegen_seq_flatten(Parser *p, asdl_seq *seqs) +{ + Py_ssize_t flattened_seq_size = _get_flattened_seq_size(seqs); + assert(flattened_seq_size > 0); + + asdl_seq *flattened_seq = (asdl_seq*)_Py_asdl_generic_seq_new(flattened_seq_size, p->arena); + if (!flattened_seq) { + return NULL; + } + + int flattened_seq_idx = 0; + for (Py_ssize_t i = 0, l = asdl_seq_LEN(seqs); i < l; i++) { + asdl_seq *inner_seq = asdl_seq_GET_UNTYPED(seqs, i); + for (Py_ssize_t j = 0, li = asdl_seq_LEN(inner_seq); j < li; j++) { + asdl_seq_SET_UNTYPED(flattened_seq, flattened_seq_idx++, asdl_seq_GET_UNTYPED(inner_seq, j)); + } + } + assert(flattened_seq_idx == flattened_seq_size); + + return flattened_seq; +} + +void * +_PyPegen_seq_last_item(asdl_seq *seq) +{ + Py_ssize_t len = asdl_seq_LEN(seq); + return asdl_seq_GET_UNTYPED(seq, len - 1); +} + +void * +_PyPegen_seq_first_item(asdl_seq *seq) +{ + return asdl_seq_GET_UNTYPED(seq, 0); +} + +/* Creates a new name of the form . */ +expr_ty +_PyPegen_join_names_with_dot(Parser *p, expr_ty first_name, expr_ty second_name) +{ + assert(first_name != NULL && second_name != NULL); + PyObject *first_identifier = first_name->v.Name.id; + PyObject *second_identifier = second_name->v.Name.id; + + if (PyUnicode_READY(first_identifier) == -1) { + return NULL; + } + if (PyUnicode_READY(second_identifier) == -1) { + return NULL; + } + const char *first_str = PyUnicode_AsUTF8(first_identifier); + if (!first_str) { + return NULL; + } + const char *second_str = PyUnicode_AsUTF8(second_identifier); + if (!second_str) { + return NULL; + } + Py_ssize_t len = strlen(first_str) + strlen(second_str) + 1; // +1 for the dot + + PyObject *str = PyBytes_FromStringAndSize(NULL, len); + if (!str) { + return NULL; + } + + char *s = PyBytes_AS_STRING(str); + if (!s) { + return NULL; + } + + strcpy(s, first_str); + s += strlen(first_str); + *s++ = '.'; + strcpy(s, second_str); + s += strlen(second_str); + *s = '\0'; + + PyObject *uni = PyUnicode_DecodeUTF8(PyBytes_AS_STRING(str), PyBytes_GET_SIZE(str), NULL); + Py_DECREF(str); + if (!uni) { + return NULL; + } + PyUnicode_InternInPlace(&uni); + if (_PyArena_AddPyObject(p->arena, uni) < 0) { + Py_DECREF(uni); + return NULL; + } + + return _PyAST_Name(uni, Load, EXTRA_EXPR(first_name, second_name)); +} + +/* Counts the total number of dots in seq's tokens */ +int +_PyPegen_seq_count_dots(asdl_seq *seq) +{ + int number_of_dots = 0; + for (Py_ssize_t i = 0, l = asdl_seq_LEN(seq); i < l; i++) { + Token *current_expr = asdl_seq_GET_UNTYPED(seq, i); + switch (current_expr->type) { + case ELLIPSIS: + number_of_dots += 3; + break; + case DOT: + number_of_dots += 1; + break; + default: + Py_UNREACHABLE(); + } + } + + return number_of_dots; +} + +/* Creates an alias with '*' as the identifier name */ +alias_ty +_PyPegen_alias_for_star(Parser *p, int lineno, int col_offset, int end_lineno, + int end_col_offset, PyArena *arena) { + PyObject *str = PyUnicode_InternFromString("*"); + if (!str) { + return NULL; + } + if (_PyArena_AddPyObject(p->arena, str) < 0) { + Py_DECREF(str); + return NULL; + } + return _PyAST_alias(str, NULL, lineno, col_offset, end_lineno, end_col_offset, arena); +} + +/* Creates a new asdl_seq* with the identifiers of all the names in seq */ +asdl_identifier_seq * +_PyPegen_map_names_to_ids(Parser *p, asdl_expr_seq *seq) +{ + Py_ssize_t len = asdl_seq_LEN(seq); + assert(len > 0); + + asdl_identifier_seq *new_seq = _Py_asdl_identifier_seq_new(len, p->arena); + if (!new_seq) { + return NULL; + } + for (Py_ssize_t i = 0; i < len; i++) { + expr_ty e = asdl_seq_GET(seq, i); + asdl_seq_SET(new_seq, i, e->v.Name.id); + } + return new_seq; +} + +/* Constructs a CmpopExprPair */ +CmpopExprPair * +_PyPegen_cmpop_expr_pair(Parser *p, cmpop_ty cmpop, expr_ty expr) +{ + assert(expr != NULL); + CmpopExprPair *a = _PyArena_Malloc(p->arena, sizeof(CmpopExprPair)); + if (!a) { + return NULL; + } + a->cmpop = cmpop; + a->expr = expr; + return a; +} + +asdl_int_seq * +_PyPegen_get_cmpops(Parser *p, asdl_seq *seq) +{ + Py_ssize_t len = asdl_seq_LEN(seq); + assert(len > 0); + + asdl_int_seq *new_seq = _Py_asdl_int_seq_new(len, p->arena); + if (!new_seq) { + return NULL; + } + for (Py_ssize_t i = 0; i < len; i++) { + CmpopExprPair *pair = asdl_seq_GET_UNTYPED(seq, i); + asdl_seq_SET(new_seq, i, pair->cmpop); + } + return new_seq; +} + +asdl_expr_seq * +_PyPegen_get_exprs(Parser *p, asdl_seq *seq) +{ + Py_ssize_t len = asdl_seq_LEN(seq); + assert(len > 0); + + asdl_expr_seq *new_seq = _Py_asdl_expr_seq_new(len, p->arena); + if (!new_seq) { + return NULL; + } + for (Py_ssize_t i = 0; i < len; i++) { + CmpopExprPair *pair = asdl_seq_GET_UNTYPED(seq, i); + asdl_seq_SET(new_seq, i, pair->expr); + } + return new_seq; +} + +/* Creates an asdl_seq* where all the elements have been changed to have ctx as context */ +static asdl_expr_seq * +_set_seq_context(Parser *p, asdl_expr_seq *seq, expr_context_ty ctx) +{ + Py_ssize_t len = asdl_seq_LEN(seq); + if (len == 0) { + return NULL; + } + + asdl_expr_seq *new_seq = _Py_asdl_expr_seq_new(len, p->arena); + if (!new_seq) { + return NULL; + } + for (Py_ssize_t i = 0; i < len; i++) { + expr_ty e = asdl_seq_GET(seq, i); + asdl_seq_SET(new_seq, i, _PyPegen_set_expr_context(p, e, ctx)); + } + return new_seq; +} + +static expr_ty +_set_name_context(Parser *p, expr_ty e, expr_context_ty ctx) +{ + return _PyAST_Name(e->v.Name.id, ctx, EXTRA_EXPR(e, e)); +} + +static expr_ty +_set_tuple_context(Parser *p, expr_ty e, expr_context_ty ctx) +{ + return _PyAST_Tuple( + _set_seq_context(p, e->v.Tuple.elts, ctx), + ctx, + EXTRA_EXPR(e, e)); +} + +static expr_ty +_set_list_context(Parser *p, expr_ty e, expr_context_ty ctx) +{ + return _PyAST_List( + _set_seq_context(p, e->v.List.elts, ctx), + ctx, + EXTRA_EXPR(e, e)); +} + +static expr_ty +_set_subscript_context(Parser *p, expr_ty e, expr_context_ty ctx) +{ + return _PyAST_Subscript(e->v.Subscript.value, e->v.Subscript.slice, + ctx, EXTRA_EXPR(e, e)); +} + +static expr_ty +_set_attribute_context(Parser *p, expr_ty e, expr_context_ty ctx) +{ + return _PyAST_Attribute(e->v.Attribute.value, e->v.Attribute.attr, + ctx, EXTRA_EXPR(e, e)); +} + +static expr_ty +_set_starred_context(Parser *p, expr_ty e, expr_context_ty ctx) +{ + return _PyAST_Starred(_PyPegen_set_expr_context(p, e->v.Starred.value, ctx), + ctx, EXTRA_EXPR(e, e)); +} + +/* Creates an `expr_ty` equivalent to `expr` but with `ctx` as context */ +expr_ty +_PyPegen_set_expr_context(Parser *p, expr_ty expr, expr_context_ty ctx) +{ + assert(expr != NULL); + + expr_ty new = NULL; + switch (expr->kind) { + case Name_kind: + new = _set_name_context(p, expr, ctx); + break; + case Tuple_kind: + new = _set_tuple_context(p, expr, ctx); + break; + case List_kind: + new = _set_list_context(p, expr, ctx); + break; + case Subscript_kind: + new = _set_subscript_context(p, expr, ctx); + break; + case Attribute_kind: + new = _set_attribute_context(p, expr, ctx); + break; + case Starred_kind: + new = _set_starred_context(p, expr, ctx); + break; + default: + new = expr; + } + return new; +} + +/* Constructs a KeyValuePair that is used when parsing a dict's key value pairs */ +KeyValuePair * +_PyPegen_key_value_pair(Parser *p, expr_ty key, expr_ty value) +{ + KeyValuePair *a = _PyArena_Malloc(p->arena, sizeof(KeyValuePair)); + if (!a) { + return NULL; + } + a->key = key; + a->value = value; + return a; +} + +/* Extracts all keys from an asdl_seq* of KeyValuePair*'s */ +asdl_expr_seq * +_PyPegen_get_keys(Parser *p, asdl_seq *seq) +{ + Py_ssize_t len = asdl_seq_LEN(seq); + asdl_expr_seq *new_seq = _Py_asdl_expr_seq_new(len, p->arena); + if (!new_seq) { + return NULL; + } + for (Py_ssize_t i = 0; i < len; i++) { + KeyValuePair *pair = asdl_seq_GET_UNTYPED(seq, i); + asdl_seq_SET(new_seq, i, pair->key); + } + return new_seq; +} + +/* Extracts all values from an asdl_seq* of KeyValuePair*'s */ +asdl_expr_seq * +_PyPegen_get_values(Parser *p, asdl_seq *seq) +{ + Py_ssize_t len = asdl_seq_LEN(seq); + asdl_expr_seq *new_seq = _Py_asdl_expr_seq_new(len, p->arena); + if (!new_seq) { + return NULL; + } + for (Py_ssize_t i = 0; i < len; i++) { + KeyValuePair *pair = asdl_seq_GET_UNTYPED(seq, i); + asdl_seq_SET(new_seq, i, pair->value); + } + return new_seq; +} + +/* Constructs a KeyPatternPair that is used when parsing mapping & class patterns */ +KeyPatternPair * +_PyPegen_key_pattern_pair(Parser *p, expr_ty key, pattern_ty pattern) +{ + KeyPatternPair *a = _PyArena_Malloc(p->arena, sizeof(KeyPatternPair)); + if (!a) { + return NULL; + } + a->key = key; + a->pattern = pattern; + return a; +} + +/* Extracts all keys from an asdl_seq* of KeyPatternPair*'s */ +asdl_expr_seq * +_PyPegen_get_pattern_keys(Parser *p, asdl_seq *seq) +{ + Py_ssize_t len = asdl_seq_LEN(seq); + asdl_expr_seq *new_seq = _Py_asdl_expr_seq_new(len, p->arena); + if (!new_seq) { + return NULL; + } + for (Py_ssize_t i = 0; i < len; i++) { + KeyPatternPair *pair = asdl_seq_GET_UNTYPED(seq, i); + asdl_seq_SET(new_seq, i, pair->key); + } + return new_seq; +} + +/* Extracts all patterns from an asdl_seq* of KeyPatternPair*'s */ +asdl_pattern_seq * +_PyPegen_get_patterns(Parser *p, asdl_seq *seq) +{ + Py_ssize_t len = asdl_seq_LEN(seq); + asdl_pattern_seq *new_seq = _Py_asdl_pattern_seq_new(len, p->arena); + if (!new_seq) { + return NULL; + } + for (Py_ssize_t i = 0; i < len; i++) { + KeyPatternPair *pair = asdl_seq_GET_UNTYPED(seq, i); + asdl_seq_SET(new_seq, i, pair->pattern); + } + return new_seq; +} + +/* Constructs a NameDefaultPair */ +NameDefaultPair * +_PyPegen_name_default_pair(Parser *p, arg_ty arg, expr_ty value, Token *tc) +{ + NameDefaultPair *a = _PyArena_Malloc(p->arena, sizeof(NameDefaultPair)); + if (!a) { + return NULL; + } + a->arg = _PyPegen_add_type_comment_to_arg(p, arg, tc); + a->value = value; + return a; +} + +/* Constructs a SlashWithDefault */ +SlashWithDefault * +_PyPegen_slash_with_default(Parser *p, asdl_arg_seq *plain_names, asdl_seq *names_with_defaults) +{ + SlashWithDefault *a = _PyArena_Malloc(p->arena, sizeof(SlashWithDefault)); + if (!a) { + return NULL; + } + a->plain_names = plain_names; + a->names_with_defaults = names_with_defaults; + return a; +} + +/* Constructs a StarEtc */ +StarEtc * +_PyPegen_star_etc(Parser *p, arg_ty vararg, asdl_seq *kwonlyargs, arg_ty kwarg) +{ + StarEtc *a = _PyArena_Malloc(p->arena, sizeof(StarEtc)); + if (!a) { + return NULL; + } + a->vararg = vararg; + a->kwonlyargs = kwonlyargs; + a->kwarg = kwarg; + return a; +} + +asdl_seq * +_PyPegen_join_sequences(Parser *p, asdl_seq *a, asdl_seq *b) +{ + Py_ssize_t first_len = asdl_seq_LEN(a); + Py_ssize_t second_len = asdl_seq_LEN(b); + asdl_seq *new_seq = (asdl_seq*)_Py_asdl_generic_seq_new(first_len + second_len, p->arena); + if (!new_seq) { + return NULL; + } + + int k = 0; + for (Py_ssize_t i = 0; i < first_len; i++) { + asdl_seq_SET_UNTYPED(new_seq, k++, asdl_seq_GET_UNTYPED(a, i)); + } + for (Py_ssize_t i = 0; i < second_len; i++) { + asdl_seq_SET_UNTYPED(new_seq, k++, asdl_seq_GET_UNTYPED(b, i)); + } + + return new_seq; +} + +static asdl_arg_seq* +_get_names(Parser *p, asdl_seq *names_with_defaults) +{ + Py_ssize_t len = asdl_seq_LEN(names_with_defaults); + asdl_arg_seq *seq = _Py_asdl_arg_seq_new(len, p->arena); + if (!seq) { + return NULL; + } + for (Py_ssize_t i = 0; i < len; i++) { + NameDefaultPair *pair = asdl_seq_GET_UNTYPED(names_with_defaults, i); + asdl_seq_SET(seq, i, pair->arg); + } + return seq; +} + +static asdl_expr_seq * +_get_defaults(Parser *p, asdl_seq *names_with_defaults) +{ + Py_ssize_t len = asdl_seq_LEN(names_with_defaults); + asdl_expr_seq *seq = _Py_asdl_expr_seq_new(len, p->arena); + if (!seq) { + return NULL; + } + for (Py_ssize_t i = 0; i < len; i++) { + NameDefaultPair *pair = asdl_seq_GET_UNTYPED(names_with_defaults, i); + asdl_seq_SET(seq, i, pair->value); + } + return seq; +} + +static int +_make_posonlyargs(Parser *p, + asdl_arg_seq *slash_without_default, + SlashWithDefault *slash_with_default, + asdl_arg_seq **posonlyargs) { + if (slash_without_default != NULL) { + *posonlyargs = slash_without_default; + } + else if (slash_with_default != NULL) { + asdl_arg_seq *slash_with_default_names = + _get_names(p, slash_with_default->names_with_defaults); + if (!slash_with_default_names) { + return -1; + } + *posonlyargs = (asdl_arg_seq*)_PyPegen_join_sequences( + p, + (asdl_seq*)slash_with_default->plain_names, + (asdl_seq*)slash_with_default_names); + } + else { + *posonlyargs = _Py_asdl_arg_seq_new(0, p->arena); + } + return *posonlyargs == NULL ? -1 : 0; +} + +static int +_make_posargs(Parser *p, + asdl_arg_seq *plain_names, + asdl_seq *names_with_default, + asdl_arg_seq **posargs) { + if (plain_names != NULL && names_with_default != NULL) { + asdl_arg_seq *names_with_default_names = _get_names(p, names_with_default); + if (!names_with_default_names) { + return -1; + } + *posargs = (asdl_arg_seq*)_PyPegen_join_sequences( + p,(asdl_seq*)plain_names, (asdl_seq*)names_with_default_names); + } + else if (plain_names == NULL && names_with_default != NULL) { + *posargs = _get_names(p, names_with_default); + } + else if (plain_names != NULL && names_with_default == NULL) { + *posargs = plain_names; + } + else { + *posargs = _Py_asdl_arg_seq_new(0, p->arena); + } + return *posargs == NULL ? -1 : 0; +} + +static int +_make_posdefaults(Parser *p, + SlashWithDefault *slash_with_default, + asdl_seq *names_with_default, + asdl_expr_seq **posdefaults) { + if (slash_with_default != NULL && names_with_default != NULL) { + asdl_expr_seq *slash_with_default_values = + _get_defaults(p, slash_with_default->names_with_defaults); + if (!slash_with_default_values) { + return -1; + } + asdl_expr_seq *names_with_default_values = _get_defaults(p, names_with_default); + if (!names_with_default_values) { + return -1; + } + *posdefaults = (asdl_expr_seq*)_PyPegen_join_sequences( + p, + (asdl_seq*)slash_with_default_values, + (asdl_seq*)names_with_default_values); + } + else if (slash_with_default == NULL && names_with_default != NULL) { + *posdefaults = _get_defaults(p, names_with_default); + } + else if (slash_with_default != NULL && names_with_default == NULL) { + *posdefaults = _get_defaults(p, slash_with_default->names_with_defaults); + } + else { + *posdefaults = _Py_asdl_expr_seq_new(0, p->arena); + } + return *posdefaults == NULL ? -1 : 0; +} + +static int +_make_kwargs(Parser *p, StarEtc *star_etc, + asdl_arg_seq **kwonlyargs, + asdl_expr_seq **kwdefaults) { + if (star_etc != NULL && star_etc->kwonlyargs != NULL) { + *kwonlyargs = _get_names(p, star_etc->kwonlyargs); + } + else { + *kwonlyargs = _Py_asdl_arg_seq_new(0, p->arena); + } + + if (*kwonlyargs == NULL) { + return -1; + } + + if (star_etc != NULL && star_etc->kwonlyargs != NULL) { + *kwdefaults = _get_defaults(p, star_etc->kwonlyargs); + } + else { + *kwdefaults = _Py_asdl_expr_seq_new(0, p->arena); + } + + if (*kwdefaults == NULL) { + return -1; + } + + return 0; +} + +/* Constructs an arguments_ty object out of all the parsed constructs in the parameters rule */ +arguments_ty +_PyPegen_make_arguments(Parser *p, asdl_arg_seq *slash_without_default, + SlashWithDefault *slash_with_default, asdl_arg_seq *plain_names, + asdl_seq *names_with_default, StarEtc *star_etc) +{ + asdl_arg_seq *posonlyargs; + if (_make_posonlyargs(p, slash_without_default, slash_with_default, &posonlyargs) == -1) { + return NULL; + } + + asdl_arg_seq *posargs; + if (_make_posargs(p, plain_names, names_with_default, &posargs) == -1) { + return NULL; + } + + asdl_expr_seq *posdefaults; + if (_make_posdefaults(p,slash_with_default, names_with_default, &posdefaults) == -1) { + return NULL; + } + + arg_ty vararg = NULL; + if (star_etc != NULL && star_etc->vararg != NULL) { + vararg = star_etc->vararg; + } + + asdl_arg_seq *kwonlyargs; + asdl_expr_seq *kwdefaults; + if (_make_kwargs(p, star_etc, &kwonlyargs, &kwdefaults) == -1) { + return NULL; + } + + arg_ty kwarg = NULL; + if (star_etc != NULL && star_etc->kwarg != NULL) { + kwarg = star_etc->kwarg; + } + + return _PyAST_arguments(posonlyargs, posargs, vararg, kwonlyargs, + kwdefaults, kwarg, posdefaults, p->arena); +} + + +/* Constructs an empty arguments_ty object, that gets used when a function accepts no + * arguments. */ +arguments_ty +_PyPegen_empty_arguments(Parser *p) +{ + asdl_arg_seq *posonlyargs = _Py_asdl_arg_seq_new(0, p->arena); + if (!posonlyargs) { + return NULL; + } + asdl_arg_seq *posargs = _Py_asdl_arg_seq_new(0, p->arena); + if (!posargs) { + return NULL; + } + asdl_expr_seq *posdefaults = _Py_asdl_expr_seq_new(0, p->arena); + if (!posdefaults) { + return NULL; + } + asdl_arg_seq *kwonlyargs = _Py_asdl_arg_seq_new(0, p->arena); + if (!kwonlyargs) { + return NULL; + } + asdl_expr_seq *kwdefaults = _Py_asdl_expr_seq_new(0, p->arena); + if (!kwdefaults) { + return NULL; + } + + return _PyAST_arguments(posonlyargs, posargs, NULL, kwonlyargs, + kwdefaults, NULL, posdefaults, p->arena); +} + +/* Encapsulates the value of an operator_ty into an AugOperator struct */ +AugOperator * +_PyPegen_augoperator(Parser *p, operator_ty kind) +{ + AugOperator *a = _PyArena_Malloc(p->arena, sizeof(AugOperator)); + if (!a) { + return NULL; + } + a->kind = kind; + return a; +} + +/* Construct a FunctionDef equivalent to function_def, but with decorators */ +stmt_ty +_PyPegen_function_def_decorators(Parser *p, asdl_expr_seq *decorators, stmt_ty function_def) +{ + assert(function_def != NULL); + if (function_def->kind == AsyncFunctionDef_kind) { + return _PyAST_AsyncFunctionDef( + function_def->v.FunctionDef.name, function_def->v.FunctionDef.args, + function_def->v.FunctionDef.body, decorators, function_def->v.FunctionDef.returns, + function_def->v.FunctionDef.type_comment, function_def->lineno, + function_def->col_offset, function_def->end_lineno, function_def->end_col_offset, + p->arena); + } + + return _PyAST_FunctionDef( + function_def->v.FunctionDef.name, function_def->v.FunctionDef.args, + function_def->v.FunctionDef.body, decorators, + function_def->v.FunctionDef.returns, + function_def->v.FunctionDef.type_comment, function_def->lineno, + function_def->col_offset, function_def->end_lineno, + function_def->end_col_offset, p->arena); +} + +/* Construct a ClassDef equivalent to class_def, but with decorators */ +stmt_ty +_PyPegen_class_def_decorators(Parser *p, asdl_expr_seq *decorators, stmt_ty class_def) +{ + assert(class_def != NULL); + return _PyAST_ClassDef( + class_def->v.ClassDef.name, class_def->v.ClassDef.bases, + class_def->v.ClassDef.keywords, class_def->v.ClassDef.body, decorators, + class_def->lineno, class_def->col_offset, class_def->end_lineno, + class_def->end_col_offset, p->arena); +} + +/* Construct a KeywordOrStarred */ +KeywordOrStarred * +_PyPegen_keyword_or_starred(Parser *p, void *element, int is_keyword) +{ + KeywordOrStarred *a = _PyArena_Malloc(p->arena, sizeof(KeywordOrStarred)); + if (!a) { + return NULL; + } + a->element = element; + a->is_keyword = is_keyword; + return a; +} + +/* Get the number of starred expressions in an asdl_seq* of KeywordOrStarred*s */ +static int +_seq_number_of_starred_exprs(asdl_seq *seq) +{ + int n = 0; + for (Py_ssize_t i = 0, l = asdl_seq_LEN(seq); i < l; i++) { + KeywordOrStarred *k = asdl_seq_GET_UNTYPED(seq, i); + if (!k->is_keyword) { + n++; + } + } + return n; +} + +/* Extract the starred expressions of an asdl_seq* of KeywordOrStarred*s */ +asdl_expr_seq * +_PyPegen_seq_extract_starred_exprs(Parser *p, asdl_seq *kwargs) +{ + int new_len = _seq_number_of_starred_exprs(kwargs); + if (new_len == 0) { + return NULL; + } + asdl_expr_seq *new_seq = _Py_asdl_expr_seq_new(new_len, p->arena); + if (!new_seq) { + return NULL; + } + + int idx = 0; + for (Py_ssize_t i = 0, len = asdl_seq_LEN(kwargs); i < len; i++) { + KeywordOrStarred *k = asdl_seq_GET_UNTYPED(kwargs, i); + if (!k->is_keyword) { + asdl_seq_SET(new_seq, idx++, k->element); + } + } + return new_seq; +} + +/* Return a new asdl_seq* with only the keywords in kwargs */ +asdl_keyword_seq* +_PyPegen_seq_delete_starred_exprs(Parser *p, asdl_seq *kwargs) +{ + Py_ssize_t len = asdl_seq_LEN(kwargs); + Py_ssize_t new_len = len - _seq_number_of_starred_exprs(kwargs); + if (new_len == 0) { + return NULL; + } + asdl_keyword_seq *new_seq = _Py_asdl_keyword_seq_new(new_len, p->arena); + if (!new_seq) { + return NULL; + } + + int idx = 0; + for (Py_ssize_t i = 0; i < len; i++) { + KeywordOrStarred *k = asdl_seq_GET_UNTYPED(kwargs, i); + if (k->is_keyword) { + asdl_seq_SET(new_seq, idx++, k->element); + } + } + return new_seq; +} + +expr_ty +_PyPegen_concatenate_strings(Parser *p, asdl_seq *strings) +{ + Py_ssize_t len = asdl_seq_LEN(strings); + assert(len > 0); + + Token *first = asdl_seq_GET_UNTYPED(strings, 0); + Token *last = asdl_seq_GET_UNTYPED(strings, len - 1); + + int bytesmode = 0; + PyObject *bytes_str = NULL; + + FstringParser state; + _PyPegen_FstringParser_Init(&state); + + for (Py_ssize_t i = 0; i < len; i++) { + Token *t = asdl_seq_GET_UNTYPED(strings, i); + + int this_bytesmode; + int this_rawmode; + PyObject *s; + const char *fstr; + Py_ssize_t fstrlen = -1; + + if (_PyPegen_parsestr(p, &this_bytesmode, &this_rawmode, &s, &fstr, &fstrlen, t) != 0) { + goto error; + } + + /* Check that we are not mixing bytes with unicode. */ + if (i != 0 && bytesmode != this_bytesmode) { + RAISE_SYNTAX_ERROR("cannot mix bytes and nonbytes literals"); + Py_XDECREF(s); + goto error; + } + bytesmode = this_bytesmode; + + if (fstr != NULL) { + assert(s == NULL && !bytesmode); + + int result = _PyPegen_FstringParser_ConcatFstring(p, &state, &fstr, fstr + fstrlen, + this_rawmode, 0, first, t, last); + if (result < 0) { + goto error; + } + } + else { + /* String or byte string. */ + assert(s != NULL && fstr == NULL); + assert(bytesmode ? PyBytes_CheckExact(s) : PyUnicode_CheckExact(s)); + + if (bytesmode) { + if (i == 0) { + bytes_str = s; + } + else { + PyBytes_ConcatAndDel(&bytes_str, s); + if (!bytes_str) { + goto error; + } + } + } + else { + /* This is a regular string. Concatenate it. */ + if (_PyPegen_FstringParser_ConcatAndDel(&state, s) < 0) { + goto error; + } + } + } + } + + if (bytesmode) { + if (_PyArena_AddPyObject(p->arena, bytes_str) < 0) { + goto error; + } + return _PyAST_Constant(bytes_str, NULL, first->lineno, + first->col_offset, last->end_lineno, + last->end_col_offset, p->arena); + } + + return _PyPegen_FstringParser_Finish(p, &state, first, last); + +error: + Py_XDECREF(bytes_str); + _PyPegen_FstringParser_Dealloc(&state); + if (PyErr_Occurred()) { + _Pypegen_raise_decode_error(p); + } + return NULL; +} + +expr_ty +_PyPegen_ensure_imaginary(Parser *p, expr_ty exp) +{ + if (exp->kind != Constant_kind || !PyComplex_CheckExact(exp->v.Constant.value)) { + RAISE_SYNTAX_ERROR_KNOWN_LOCATION(exp, "imaginary number required in complex literal"); + return NULL; + } + return exp; +} + +expr_ty +_PyPegen_ensure_real(Parser *p, expr_ty exp) +{ + if (exp->kind != Constant_kind || PyComplex_CheckExact(exp->v.Constant.value)) { + RAISE_SYNTAX_ERROR_KNOWN_LOCATION(exp, "real number required in complex literal"); + return NULL; + } + return exp; +} + +mod_ty +_PyPegen_make_module(Parser *p, asdl_stmt_seq *a) { + asdl_type_ignore_seq *type_ignores = NULL; + Py_ssize_t num = p->type_ignore_comments.num_items; + if (num > 0) { + // Turn the raw (comment, lineno) pairs into TypeIgnore objects in the arena + type_ignores = _Py_asdl_type_ignore_seq_new(num, p->arena); + if (type_ignores == NULL) { + return NULL; + } + for (int i = 0; i < num; i++) { + PyObject *tag = _PyPegen_new_type_comment(p, p->type_ignore_comments.items[i].comment); + if (tag == NULL) { + return NULL; + } + type_ignore_ty ti = _PyAST_TypeIgnore(p->type_ignore_comments.items[i].lineno, + tag, p->arena); + if (ti == NULL) { + return NULL; + } + asdl_seq_SET(type_ignores, i, ti); + } + } + return _PyAST_Module(a, type_ignores, p->arena); +} + +PyObject * +_PyPegen_new_type_comment(Parser *p, const char *s) +{ + PyObject *res = PyUnicode_DecodeUTF8(s, strlen(s), NULL); + if (res == NULL) { + return NULL; + } + if (_PyArena_AddPyObject(p->arena, res) < 0) { + Py_DECREF(res); + return NULL; + } + return res; +} + +arg_ty +_PyPegen_add_type_comment_to_arg(Parser *p, arg_ty a, Token *tc) +{ + if (tc == NULL) { + return a; + } + const char *bytes = PyBytes_AsString(tc->bytes); + if (bytes == NULL) { + return NULL; + } + PyObject *tco = _PyPegen_new_type_comment(p, bytes); + if (tco == NULL) { + return NULL; + } + return _PyAST_arg(a->arg, a->annotation, tco, + a->lineno, a->col_offset, a->end_lineno, a->end_col_offset, + p->arena); +} + +/* Checks if the NOTEQUAL token is valid given the current parser flags +0 indicates success and nonzero indicates failure (an exception may be set) */ +int +_PyPegen_check_barry_as_flufl(Parser *p, Token* t) { + assert(t->bytes != NULL); + assert(t->type == NOTEQUAL); + + const char* tok_str = PyBytes_AS_STRING(t->bytes); + if (p->flags & PyPARSE_BARRY_AS_BDFL && strcmp(tok_str, "<>") != 0) { + RAISE_SYNTAX_ERROR("with Barry as BDFL, use '<>' instead of '!='"); + return -1; + } + if (!(p->flags & PyPARSE_BARRY_AS_BDFL)) { + return strcmp(tok_str, "!="); + } + return 0; +} + +int +_PyPegen_check_legacy_stmt(Parser *p, expr_ty name) { + if (name->kind != Name_kind) { + return 0; + } + const char* candidates[2] = {"print", "exec"}; + for (int i=0; i<2; i++) { + if (PyUnicode_CompareWithASCIIString(name->v.Name.id, candidates[i]) == 0) { + return 1; + } + } + return 0; +} + +const char * +_PyPegen_get_expr_name(expr_ty e) +{ + assert(e != NULL); + switch (e->kind) { + case Attribute_kind: + return "attribute"; + case Subscript_kind: + return "subscript"; + case Starred_kind: + return "starred"; + case Name_kind: + return "name"; + case List_kind: + return "list"; + case Tuple_kind: + return "tuple"; + case Lambda_kind: + return "lambda"; + case Call_kind: + return "function call"; + case BoolOp_kind: + case BinOp_kind: + case UnaryOp_kind: + return "expression"; + case GeneratorExp_kind: + return "generator expression"; + case Yield_kind: + case YieldFrom_kind: + return "yield expression"; + case Await_kind: + return "await expression"; + case ListComp_kind: + return "list comprehension"; + case SetComp_kind: + return "set comprehension"; + case DictComp_kind: + return "dict comprehension"; + case Dict_kind: + return "dict literal"; + case Set_kind: + return "set display"; + case JoinedStr_kind: + case FormattedValue_kind: + return "f-string expression"; + case Constant_kind: { + PyObject *value = e->v.Constant.value; + if (value == Py_None) { + return "None"; + } + if (value == Py_False) { + return "False"; + } + if (value == Py_True) { + return "True"; + } + if (value == Py_Ellipsis) { + return "ellipsis"; + } + return "literal"; + } + case Compare_kind: + return "comparison"; + case IfExp_kind: + return "conditional expression"; + case NamedExpr_kind: + return "named expression"; + default: + PyErr_Format(PyExc_SystemError, + "unexpected expression in assignment %d (line %d)", + e->kind, e->lineno); + return NULL; + } +} + +static inline expr_ty +_PyPegen_get_last_comprehension_item(comprehension_ty comprehension) { + if (comprehension->ifs == NULL || asdl_seq_LEN(comprehension->ifs) == 0) { + return comprehension->iter; + } + return PyPegen_last_item(comprehension->ifs, expr_ty); +} + +expr_ty _PyPegen_collect_call_seqs(Parser *p, asdl_expr_seq *a, asdl_seq *b, + int lineno, int col_offset, int end_lineno, + int end_col_offset, PyArena *arena) { + Py_ssize_t args_len = asdl_seq_LEN(a); + Py_ssize_t total_len = args_len; + + if (b == NULL) { + return _PyAST_Call(_PyPegen_dummy_name(p), a, NULL, lineno, col_offset, + end_lineno, end_col_offset, arena); + + } + + asdl_expr_seq *starreds = _PyPegen_seq_extract_starred_exprs(p, b); + asdl_keyword_seq *keywords = _PyPegen_seq_delete_starred_exprs(p, b); + + if (starreds) { + total_len += asdl_seq_LEN(starreds); + } + + asdl_expr_seq *args = _Py_asdl_expr_seq_new(total_len, arena); + + Py_ssize_t i = 0; + for (i = 0; i < args_len; i++) { + asdl_seq_SET(args, i, asdl_seq_GET(a, i)); + } + for (; i < total_len; i++) { + asdl_seq_SET(args, i, asdl_seq_GET(starreds, i - args_len)); + } + + return _PyAST_Call(_PyPegen_dummy_name(p), args, keywords, lineno, + col_offset, end_lineno, end_col_offset, arena); +} + +// AST Error reporting helpers + +expr_ty +_PyPegen_get_invalid_target(expr_ty e, TARGETS_TYPE targets_type) +{ + if (e == NULL) { + return NULL; + } + +#define VISIT_CONTAINER(CONTAINER, TYPE) do { \ + Py_ssize_t len = asdl_seq_LEN((CONTAINER)->v.TYPE.elts);\ + for (Py_ssize_t i = 0; i < len; i++) {\ + expr_ty other = asdl_seq_GET((CONTAINER)->v.TYPE.elts, i);\ + expr_ty child = _PyPegen_get_invalid_target(other, targets_type);\ + if (child != NULL) {\ + return child;\ + }\ + }\ + } while (0) + + // We only need to visit List and Tuple nodes recursively as those + // are the only ones that can contain valid names in targets when + // they are parsed as expressions. Any other kind of expression + // that is a container (like Sets or Dicts) is directly invalid and + // we don't need to visit it recursively. + + switch (e->kind) { + case List_kind: + VISIT_CONTAINER(e, List); + return NULL; + case Tuple_kind: + VISIT_CONTAINER(e, Tuple); + return NULL; + case Starred_kind: + if (targets_type == DEL_TARGETS) { + return e; + } + return _PyPegen_get_invalid_target(e->v.Starred.value, targets_type); + case Compare_kind: + // This is needed, because the `a in b` in `for a in b` gets parsed + // as a comparison, and so we need to search the left side of the comparison + // for invalid targets. + if (targets_type == FOR_TARGETS) { + cmpop_ty cmpop = (cmpop_ty) asdl_seq_GET(e->v.Compare.ops, 0); + if (cmpop == In) { + return _PyPegen_get_invalid_target(e->v.Compare.left, targets_type); + } + return NULL; + } + return e; + case Name_kind: + case Subscript_kind: + case Attribute_kind: + return NULL; + default: + return e; + } +} + +void *_PyPegen_arguments_parsing_error(Parser *p, expr_ty e) { + int kwarg_unpacking = 0; + for (Py_ssize_t i = 0, l = asdl_seq_LEN(e->v.Call.keywords); i < l; i++) { + keyword_ty keyword = asdl_seq_GET(e->v.Call.keywords, i); + if (!keyword->arg) { + kwarg_unpacking = 1; + } + } + + const char *msg = NULL; + if (kwarg_unpacking) { + msg = "positional argument follows keyword argument unpacking"; + } else { + msg = "positional argument follows keyword argument"; + } + + return RAISE_SYNTAX_ERROR(msg); +} + +void * +_PyPegen_nonparen_genexp_in_call(Parser *p, expr_ty args, asdl_comprehension_seq *comprehensions) +{ + /* The rule that calls this function is 'args for_if_clauses'. + For the input f(L, x for x in y), L and x are in args and + the for is parsed as a for_if_clause. We have to check if + len <= 1, so that input like dict((a, b) for a, b in x) + gets successfully parsed and then we pass the last + argument (x in the above example) as the location of the + error */ + Py_ssize_t len = asdl_seq_LEN(args->v.Call.args); + if (len <= 1) { + return NULL; + } + + comprehension_ty last_comprehension = PyPegen_last_item(comprehensions, comprehension_ty); + + return RAISE_SYNTAX_ERROR_KNOWN_RANGE( + (expr_ty) asdl_seq_GET(args->v.Call.args, len - 1), + _PyPegen_get_last_comprehension_item(last_comprehension), + "Generator expression must be parenthesized" + ); +} \ No newline at end of file diff --git a/Parser/pegen.c b/Parser/pegen.c index b760730189073..4f51c63c44353 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -1,432 +1,21 @@ #include #include "pycore_ast.h" // _PyAST_Validate(), #include -#include "tokenizer.h" +#include "tokenizer.h" #include "pegen.h" -#include "string_parser.h" - -PyObject * -_PyPegen_new_type_comment(Parser *p, const char *s) -{ - PyObject *res = PyUnicode_DecodeUTF8(s, strlen(s), NULL); - if (res == NULL) { - return NULL; - } - if (_PyArena_AddPyObject(p->arena, res) < 0) { - Py_DECREF(res); - return NULL; - } - return res; -} - -arg_ty -_PyPegen_add_type_comment_to_arg(Parser *p, arg_ty a, Token *tc) -{ - if (tc == NULL) { - return a; - } - const char *bytes = PyBytes_AsString(tc->bytes); - if (bytes == NULL) { - return NULL; - } - PyObject *tco = _PyPegen_new_type_comment(p, bytes); - if (tco == NULL) { - return NULL; - } - return _PyAST_arg(a->arg, a->annotation, tco, - a->lineno, a->col_offset, a->end_lineno, a->end_col_offset, - p->arena); -} - -static int -init_normalization(Parser *p) -{ - if (p->normalize) { - return 1; - } - PyObject *m = PyImport_ImportModuleNoBlock("unicodedata"); - if (!m) - { - return 0; - } - p->normalize = PyObject_GetAttrString(m, "normalize"); - Py_DECREF(m); - if (!p->normalize) - { - return 0; - } - return 1; -} - -/* Checks if the NOTEQUAL token is valid given the current parser flags -0 indicates success and nonzero indicates failure (an exception may be set) */ -int -_PyPegen_check_barry_as_flufl(Parser *p, Token* t) { - assert(t->bytes != NULL); - assert(t->type == NOTEQUAL); - - const char* tok_str = PyBytes_AS_STRING(t->bytes); - if (p->flags & PyPARSE_BARRY_AS_BDFL && strcmp(tok_str, "<>") != 0) { - RAISE_SYNTAX_ERROR("with Barry as BDFL, use '<>' instead of '!='"); - return -1; - } - if (!(p->flags & PyPARSE_BARRY_AS_BDFL)) { - return strcmp(tok_str, "!="); - } - return 0; -} - -int -_PyPegen_check_legacy_stmt(Parser *p, expr_ty name) { - if (name->kind != Name_kind) { - return 0; - } - const char* candidates[2] = {"print", "exec"}; - for (int i=0; i<2; i++) { - if (PyUnicode_CompareWithASCIIString(name->v.Name.id, candidates[i]) == 0) { - return 1; - } - } - return 0; -} - -PyObject * -_PyPegen_new_identifier(Parser *p, const char *n) -{ - PyObject *id = PyUnicode_DecodeUTF8(n, strlen(n), NULL); - if (!id) { - goto error; - } - /* PyUnicode_DecodeUTF8 should always return a ready string. */ - assert(PyUnicode_IS_READY(id)); - /* Check whether there are non-ASCII characters in the - identifier; if so, normalize to NFKC. */ - if (!PyUnicode_IS_ASCII(id)) - { - PyObject *id2; - if (!init_normalization(p)) - { - Py_DECREF(id); - goto error; - } - PyObject *form = PyUnicode_InternFromString("NFKC"); - if (form == NULL) - { - Py_DECREF(id); - goto error; - } - PyObject *args[2] = {form, id}; - id2 = _PyObject_FastCall(p->normalize, args, 2); - Py_DECREF(id); - Py_DECREF(form); - if (!id2) { - goto error; - } - if (!PyUnicode_Check(id2)) - { - PyErr_Format(PyExc_TypeError, - "unicodedata.normalize() must return a string, not " - "%.200s", - _PyType_Name(Py_TYPE(id2))); - Py_DECREF(id2); - goto error; - } - id = id2; - } - PyUnicode_InternInPlace(&id); - if (_PyArena_AddPyObject(p->arena, id) < 0) - { - Py_DECREF(id); - goto error; - } - return id; - -error: - p->error_indicator = 1; - return NULL; -} - -static PyObject * -_create_dummy_identifier(Parser *p) -{ - return _PyPegen_new_identifier(p, ""); -} - -const char * -_PyPegen_get_expr_name(expr_ty e) -{ - assert(e != NULL); - switch (e->kind) { - case Attribute_kind: - return "attribute"; - case Subscript_kind: - return "subscript"; - case Starred_kind: - return "starred"; - case Name_kind: - return "name"; - case List_kind: - return "list"; - case Tuple_kind: - return "tuple"; - case Lambda_kind: - return "lambda"; - case Call_kind: - return "function call"; - case BoolOp_kind: - case BinOp_kind: - case UnaryOp_kind: - return "expression"; - case GeneratorExp_kind: - return "generator expression"; - case Yield_kind: - case YieldFrom_kind: - return "yield expression"; - case Await_kind: - return "await expression"; - case ListComp_kind: - return "list comprehension"; - case SetComp_kind: - return "set comprehension"; - case DictComp_kind: - return "dict comprehension"; - case Dict_kind: - return "dict literal"; - case Set_kind: - return "set display"; - case JoinedStr_kind: - case FormattedValue_kind: - return "f-string expression"; - case Constant_kind: { - PyObject *value = e->v.Constant.value; - if (value == Py_None) { - return "None"; - } - if (value == Py_False) { - return "False"; - } - if (value == Py_True) { - return "True"; - } - if (value == Py_Ellipsis) { - return "ellipsis"; - } - return "literal"; - } - case Compare_kind: - return "comparison"; - case IfExp_kind: - return "conditional expression"; - case NamedExpr_kind: - return "named expression"; - default: - PyErr_Format(PyExc_SystemError, - "unexpected expression in assignment %d (line %d)", - e->kind, e->lineno); - return NULL; - } -} - -static int -raise_decode_error(Parser *p) -{ - assert(PyErr_Occurred()); - const char *errtype = NULL; - if (PyErr_ExceptionMatches(PyExc_UnicodeError)) { - errtype = "unicode error"; - } - else if (PyErr_ExceptionMatches(PyExc_ValueError)) { - errtype = "value error"; - } - if (errtype) { - PyObject *type; - PyObject *value; - PyObject *tback; - PyObject *errstr; - PyErr_Fetch(&type, &value, &tback); - errstr = PyObject_Str(value); - if (errstr) { - RAISE_SYNTAX_ERROR("(%s) %U", errtype, errstr); - Py_DECREF(errstr); - } - else { - PyErr_Clear(); - RAISE_SYNTAX_ERROR("(%s) unknown error", errtype); - } - Py_XDECREF(type); - Py_XDECREF(value); - Py_XDECREF(tback); - } - - return -1; -} - -static inline void -raise_unclosed_parentheses_error(Parser *p) { - int error_lineno = p->tok->parenlinenostack[p->tok->level-1]; - int error_col = p->tok->parencolstack[p->tok->level-1]; - RAISE_ERROR_KNOWN_LOCATION(p, PyExc_SyntaxError, - error_lineno, error_col, error_lineno, -1, - "'%c' was never closed", - p->tok->parenstack[p->tok->level-1]); -} - -static void -raise_tokenizer_init_error(PyObject *filename) -{ - if (!(PyErr_ExceptionMatches(PyExc_LookupError) - || PyErr_ExceptionMatches(PyExc_SyntaxError) - || PyErr_ExceptionMatches(PyExc_ValueError) - || PyErr_ExceptionMatches(PyExc_UnicodeDecodeError))) { - return; - } - PyObject *errstr = NULL; - PyObject *tuple = NULL; - PyObject *type; - PyObject *value; - PyObject *tback; - PyErr_Fetch(&type, &value, &tback); - errstr = PyObject_Str(value); - if (!errstr) { - goto error; - } - - PyObject *tmp = Py_BuildValue("(OiiO)", filename, 0, -1, Py_None); - if (!tmp) { - goto error; - } - - tuple = PyTuple_Pack(2, errstr, tmp); - Py_DECREF(tmp); - if (!value) { - goto error; - } - PyErr_SetObject(PyExc_SyntaxError, tuple); - -error: - Py_XDECREF(type); - Py_XDECREF(value); - Py_XDECREF(tback); - Py_XDECREF(errstr); - Py_XDECREF(tuple); -} - -static int -tokenizer_error(Parser *p) -{ - if (PyErr_Occurred()) { - return -1; - } - - const char *msg = NULL; - PyObject* errtype = PyExc_SyntaxError; - Py_ssize_t col_offset = -1; - switch (p->tok->done) { - case E_TOKEN: - msg = "invalid token"; - break; - case E_EOF: - if (p->tok->level) { - raise_unclosed_parentheses_error(p); - } else { - RAISE_SYNTAX_ERROR("unexpected EOF while parsing"); - } - return -1; - case E_DEDENT: - RAISE_INDENTATION_ERROR("unindent does not match any outer indentation level"); - return -1; - case E_INTR: - if (!PyErr_Occurred()) { - PyErr_SetNone(PyExc_KeyboardInterrupt); - } - return -1; - case E_NOMEM: - PyErr_NoMemory(); - return -1; - case E_TABSPACE: - errtype = PyExc_TabError; - msg = "inconsistent use of tabs and spaces in indentation"; - break; - case E_TOODEEP: - errtype = PyExc_IndentationError; - msg = "too many levels of indentation"; - break; - case E_LINECONT: { - col_offset = p->tok->cur - p->tok->buf - 1; - msg = "unexpected character after line continuation character"; - break; - } - default: - msg = "unknown parsing error"; - } - RAISE_ERROR_KNOWN_LOCATION(p, errtype, p->tok->lineno, - col_offset >= 0 ? col_offset : 0, - p->tok->lineno, -1, msg); - return -1; -} +// Internal parser functions -void * -_PyPegen_raise_error(Parser *p, PyObject *errtype, const char *errmsg, ...) +asdl_stmt_seq* +_PyPegen_interactive_exit(Parser *p) { - if (p->fill == 0) { - va_list va; - va_start(va, errmsg); - _PyPegen_raise_error_known_location(p, errtype, 0, 0, 0, -1, errmsg, va); - va_end(va); - return NULL; - } - - Token *t = p->known_err_token != NULL ? p->known_err_token : p->tokens[p->fill - 1]; - Py_ssize_t col_offset; - Py_ssize_t end_col_offset = -1; - if (t->col_offset == -1) { - if (p->tok->cur == p->tok->buf) { - col_offset = 0; - } else { - const char* start = p->tok->buf ? p->tok->line_start : p->tok->buf; - col_offset = Py_SAFE_DOWNCAST(p->tok->cur - start, intptr_t, int); - } - } else { - col_offset = t->col_offset + 1; - } - - if (t->end_col_offset != -1) { - end_col_offset = t->end_col_offset + 1; + if (p->errcode) { + *(p->errcode) = E_EOF; } - - va_list va; - va_start(va, errmsg); - _PyPegen_raise_error_known_location(p, errtype, t->lineno, col_offset, t->end_lineno, end_col_offset, errmsg, va); - va_end(va); - return NULL; } -static PyObject * -get_error_line(Parser *p, Py_ssize_t lineno) -{ - /* If the file descriptor is interactive, the source lines of the current - * (multi-line) statement are stored in p->tok->interactive_src_start. - * If not, we're parsing from a string, which means that the whole source - * is stored in p->tok->str. */ - assert(p->tok->fp == NULL || p->tok->fp == stdin); - - char *cur_line = p->tok->fp_interactive ? p->tok->interactive_src_start : p->tok->str; - assert(cur_line != NULL); - - for (int i = 0; i < lineno - 1; i++) { - cur_line = strchr(cur_line, '\n') + 1; - } - - char *next_newline; - if ((next_newline = strchr(cur_line, '\n')) == NULL) { // This is the last line - next_newline = cur_line + strlen(cur_line); - } - return PyUnicode_DecodeUTF8(cur_line, next_newline - cur_line, "replace"); -} - Py_ssize_t _PyPegen_byte_offset_to_character_offset(PyObject *line, Py_ssize_t col_offset) { @@ -448,127 +37,6 @@ _PyPegen_byte_offset_to_character_offset(PyObject *line, Py_ssize_t col_offset) return size; } -void * -_PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, - Py_ssize_t lineno, Py_ssize_t col_offset, - Py_ssize_t end_lineno, Py_ssize_t end_col_offset, - const char *errmsg, va_list va) -{ - PyObject *value = NULL; - PyObject *errstr = NULL; - PyObject *error_line = NULL; - PyObject *tmp = NULL; - p->error_indicator = 1; - - if (end_lineno == CURRENT_POS) { - end_lineno = p->tok->lineno; - } - if (end_col_offset == CURRENT_POS) { - end_col_offset = p->tok->cur - p->tok->line_start; - } - - if (p->start_rule == Py_fstring_input) { - const char *fstring_msg = "f-string: "; - Py_ssize_t len = strlen(fstring_msg) + strlen(errmsg); - - char *new_errmsg = PyMem_Malloc(len + 1); // Lengths of both strings plus NULL character - if (!new_errmsg) { - return (void *) PyErr_NoMemory(); - } - - // Copy both strings into new buffer - memcpy(new_errmsg, fstring_msg, strlen(fstring_msg)); - memcpy(new_errmsg + strlen(fstring_msg), errmsg, strlen(errmsg)); - new_errmsg[len] = 0; - errmsg = new_errmsg; - } - errstr = PyUnicode_FromFormatV(errmsg, va); - if (!errstr) { - goto error; - } - - if (p->tok->fp_interactive) { - error_line = get_error_line(p, lineno); - } - else if (p->start_rule == Py_file_input) { - error_line = _PyErr_ProgramDecodedTextObject(p->tok->filename, - (int) lineno, p->tok->encoding); - } - - if (!error_line) { - /* PyErr_ProgramTextObject was not called or returned NULL. If it was not called, - then we need to find the error line from some other source, because - p->start_rule != Py_file_input. If it returned NULL, then it either unexpectedly - failed or we're parsing from a string or the REPL. There's a third edge case where - we're actually parsing from a file, which has an E_EOF SyntaxError and in that case - `PyErr_ProgramTextObject` fails because lineno points to last_file_line + 1, which - does not physically exist */ - assert(p->tok->fp == NULL || p->tok->fp == stdin || p->tok->done == E_EOF); - - if (p->tok->lineno <= lineno && p->tok->inp > p->tok->buf) { - Py_ssize_t size = p->tok->inp - p->tok->buf; - error_line = PyUnicode_DecodeUTF8(p->tok->buf, size, "replace"); - } - else if (p->tok->fp == NULL || p->tok->fp == stdin) { - error_line = get_error_line(p, lineno); - } - else { - error_line = PyUnicode_FromStringAndSize("", 0); - } - if (!error_line) { - goto error; - } - } - - if (p->start_rule == Py_fstring_input) { - col_offset -= p->starting_col_offset; - end_col_offset -= p->starting_col_offset; - } - - Py_ssize_t col_number = col_offset; - Py_ssize_t end_col_number = end_col_offset; - - if (p->tok->encoding != NULL) { - col_number = _PyPegen_byte_offset_to_character_offset(error_line, col_offset); - if (col_number < 0) { - goto error; - } - if (end_col_number > 0) { - Py_ssize_t end_col_offset = _PyPegen_byte_offset_to_character_offset(error_line, end_col_number); - if (end_col_offset < 0) { - goto error; - } else { - end_col_number = end_col_offset; - } - } - } - tmp = Py_BuildValue("(OiiNii)", p->tok->filename, lineno, col_number, error_line, end_lineno, end_col_number); - if (!tmp) { - goto error; - } - value = PyTuple_Pack(2, errstr, tmp); - Py_DECREF(tmp); - if (!value) { - goto error; - } - PyErr_SetObject(errtype, value); - - Py_DECREF(errstr); - Py_DECREF(value); - if (p->start_rule == Py_fstring_input) { - PyMem_Free((void *)errmsg); - } - return NULL; - -error: - Py_XDECREF(errstr); - Py_XDECREF(error_line); - if (p->start_rule == Py_fstring_input) { - PyMem_Free((void *)errmsg); - } - return NULL; -} - #if 0 static const char * token_name(int type) @@ -614,39 +82,24 @@ _PyPegen_update_memo(Parser *p, int mark, int type, void *node) return _PyPegen_insert_memo(p, mark, type, node); } -// Return dummy NAME. -void * -_PyPegen_dummy_name(Parser *p, ...) +static int +init_normalization(Parser *p) { - static void *cache = NULL; - - if (cache != NULL) { - return cache; + if (p->normalize) { + return 1; } - - PyObject *id = _create_dummy_identifier(p); - if (!id) { - return NULL; + PyObject *m = PyImport_ImportModuleNoBlock("unicodedata"); + if (!m) + { + return 0; } - cache = _PyAST_Name(id, Load, 1, 0, 1, 0, p->arena); - return cache; -} - -static int -_get_keyword_or_name_type(Parser *p, const char *name, int name_len) -{ - assert(name_len > 0); - if (name_len >= p->n_keyword_lists || - p->keywords[name_len] == NULL || - p->keywords[name_len]->type == -1) { - return NAME; - } - for (KeywordToken *k = p->keywords[name_len]; k != NULL && k->type != -1; k++) { - if (strncmp(k->str, name, name_len) == 0) { - return k->type; - } + p->normalize = PyObject_GetAttrString(m, "normalize"); + Py_DECREF(m); + if (!p->normalize) + { + return 0; } - return NAME; + return 1; } static int @@ -685,6 +138,23 @@ growable_comment_array_deallocate(growable_comment_array *arr) { PyMem_Free(arr->items); } +static int +_get_keyword_or_name_type(Parser *p, const char *name, int name_len) +{ + assert(name_len > 0); + if (name_len >= p->n_keyword_lists || + p->keywords[name_len] == NULL || + p->keywords[name_len]->type == -1) { + return NAME; + } + for (KeywordToken *k = p->keywords[name_len]; k != NULL && k->type != -1; k++) { + if (strncmp(k->str, name, name_len) == 0) { + return k->type; + } + } + return NAME; +} + static int initialize_token(Parser *p, Token *token, const char *start, const char *end, int token_type) { assert(token != NULL); @@ -715,10 +185,10 @@ initialize_token(Parser *p, Token *token, const char *start, const char *end, in p->fill += 1; if (token_type == ERRORTOKEN && p->tok->done == E_DECODE) { - return raise_decode_error(p); + return _Pypegen_raise_decode_error(p); } - return (token_type == ERRORTOKEN ? tokenizer_error(p) : 0); + return (token_type == ERRORTOKEN ? _Pypegen_tokenizer_error(p) : 0); } static int @@ -791,7 +261,6 @@ _PyPegen_fill_token(Parser *p) return initialize_token(p, t, start, end, type); } - #if defined(Py_DEBUG) // Instrumentation to count the effectiveness of memoization. // The array counts the number of tokens skipped by memoization, @@ -989,6 +458,62 @@ _PyPegen_get_last_nonnwhitespace_token(Parser *p) return token; } +PyObject * +_PyPegen_new_identifier(Parser *p, const char *n) +{ + PyObject *id = PyUnicode_DecodeUTF8(n, strlen(n), NULL); + if (!id) { + goto error; + } + /* PyUnicode_DecodeUTF8 should always return a ready string. */ + assert(PyUnicode_IS_READY(id)); + /* Check whether there are non-ASCII characters in the + identifier; if so, normalize to NFKC. */ + if (!PyUnicode_IS_ASCII(id)) + { + PyObject *id2; + if (!init_normalization(p)) + { + Py_DECREF(id); + goto error; + } + PyObject *form = PyUnicode_InternFromString("NFKC"); + if (form == NULL) + { + Py_DECREF(id); + goto error; + } + PyObject *args[2] = {form, id}; + id2 = _PyObject_FastCall(p->normalize, args, 2); + Py_DECREF(id); + Py_DECREF(form); + if (!id2) { + goto error; + } + if (!PyUnicode_Check(id2)) + { + PyErr_Format(PyExc_TypeError, + "unicodedata.normalize() must return a string, not " + "%.200s", + _PyType_Name(Py_TYPE(id2))); + Py_DECREF(id2); + goto error; + } + id = id2; + } + PyUnicode_InternInPlace(&id); + if (_PyArena_AddPyObject(p->arena, id) < 0) + { + Py_DECREF(id); + goto error; + } + return id; + +error: + p->error_indicator = 1; + return NULL; +} + static expr_ty _PyPegen_name_from_token(Parser *p, Token* t) { @@ -1009,7 +534,6 @@ _PyPegen_name_from_token(Parser *p, Token* t) t->end_col_offset, p->arena); } - expr_ty _PyPegen_name_token(Parser *p) { @@ -1023,7 +547,6 @@ _PyPegen_string_token(Parser *p) return _PyPegen_expect_token(p, STRING); } - expr_ty _PyPegen_soft_keyword_token(Parser *p) { Token *t = _PyPegen_expect_token(p, NAME); if (t == NULL) { @@ -1197,18 +720,6 @@ bad_single_statement(Parser *p) } } -void -_PyPegen_Parser_Free(Parser *p) -{ - Py_XDECREF(p->normalize); - for (int i = 0; i < p->size; i++) { - PyMem_Free(p->tokens[i]); - } - PyMem_Free(p->tokens); - growable_comment_array_deallocate(&p->type_ignore_comments); - PyMem_Free(p); -} - static int compute_parser_flags(PyCompilerFlags *flags) { @@ -1234,6 +745,8 @@ compute_parser_flags(PyCompilerFlags *flags) return parser_flags; } +// Parser API + Parser * _PyPegen_Parser_New(struct tok_state *tok, int start_rule, int flags, int feature_version, int *errcode, PyArena *arena) @@ -1289,8 +802,20 @@ _PyPegen_Parser_New(struct tok_state *tok, int start_rule, int flags, return p; } +void +_PyPegen_Parser_Free(Parser *p) +{ + Py_XDECREF(p->normalize); + for (int i = 0; i < p->size; i++) { + PyMem_Free(p->tokens[i]); + } + PyMem_Free(p->tokens); + growable_comment_array_deallocate(&p->type_ignore_comments); + PyMem_Free(p); +} + static void -reset_parser_state(Parser *p) +reset_parser_state_for_error_pass(Parser *p) { for (int i = 0; i < p->fill; i++) { p->tokens[i]->memo = NULL; @@ -1302,60 +827,6 @@ reset_parser_state(Parser *p) p->tok->interactive_underflow = IUNDERFLOW_STOP; } -static int -_PyPegen_check_tokenizer_errors(Parser *p) { - // Tokenize the whole input to see if there are any tokenization - // errors such as mistmatching parentheses. These will get priority - // over generic syntax errors only if the line number of the error is - // before the one that we had for the generic error. - - // We don't want to tokenize to the end for interactive input - if (p->tok->prompt != NULL) { - return 0; - } - - PyObject *type, *value, *traceback; - PyErr_Fetch(&type, &value, &traceback); - - Token *current_token = p->known_err_token != NULL ? p->known_err_token : p->tokens[p->fill - 1]; - Py_ssize_t current_err_line = current_token->lineno; - - int ret = 0; - - for (;;) { - const char *start; - const char *end; - switch (_PyTokenizer_Get(p->tok, &start, &end)) { - case ERRORTOKEN: - if (p->tok->level != 0) { - int error_lineno = p->tok->parenlinenostack[p->tok->level-1]; - if (current_err_line > error_lineno) { - raise_unclosed_parentheses_error(p); - ret = -1; - goto exit; - } - } - break; - case ENDMARKER: - break; - default: - continue; - } - break; - } - - -exit: - if (PyErr_Occurred()) { - Py_XDECREF(value); - Py_XDECREF(type); - Py_XDECREF(traceback); - } else { - PyErr_Restore(type, value, traceback); - } - return ret; -} - void * _PyPegen_run_parser(Parser *p) { @@ -1364,46 +835,17 @@ _PyPegen_run_parser(Parser *p) if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_SyntaxError)) { return NULL; } + // Make a second parser pass. In this pass we activate heavier and slower checks + // to produce better error messages and more complete diagnostics. Extra "invalid_*" + // rules will be active during parsing. Token *last_token = p->tokens[p->fill - 1]; - reset_parser_state(p); + reset_parser_state_for_error_pass(p); _PyPegen_parse(p); - if (PyErr_Occurred()) { - // Prioritize tokenizer errors to custom syntax errors raised - // on the second phase only if the errors come from the parser. - if (p->tok->done == E_DONE && PyErr_ExceptionMatches(PyExc_SyntaxError)) { - _PyPegen_check_tokenizer_errors(p); - } - return NULL; - } - if (p->fill == 0) { - RAISE_SYNTAX_ERROR("error at start before reading any input"); - } - else if (p->tok->done == E_EOF) { - if (p->tok->level) { - raise_unclosed_parentheses_error(p); - } else { - RAISE_SYNTAX_ERROR("unexpected EOF while parsing"); - } - } - else { - if (p->tokens[p->fill-1]->type == INDENT) { - RAISE_INDENTATION_ERROR("unexpected indent"); - } - else if (p->tokens[p->fill-1]->type == DEDENT) { - RAISE_INDENTATION_ERROR("unexpected unindent"); - } - else { - // Use the last token we found on the first pass to avoid reporting - // incorrect locations for generic syntax errors just because we reached - // further away when trying to find specific syntax errors in the second - // pass. - RAISE_SYNTAX_ERROR_KNOWN_LOCATION(last_token, "invalid syntax"); - // _PyPegen_check_tokenizer_errors will override the existing - // generic SyntaxError we just raised if errors are found. - _PyPegen_check_tokenizer_errors(p); - } - } - return NULL; + + // Set SyntaxErrors accordingly depending on the parser/tokenizer status at the failure + // point. + _Pypegen_set_syntax_error(p, last_token); + return NULL; } if (p->start_rule == Py_single_input && bad_single_statement(p)) { @@ -1433,7 +875,7 @@ _PyPegen_run_parser_from_file_pointer(FILE *fp, int start_rule, PyObject *filena struct tok_state *tok = _PyTokenizer_FromFile(fp, enc, ps1, ps2); if (tok == NULL) { if (PyErr_Occurred()) { - raise_tokenizer_init_error(filename_ob); + _PyPegen_raise_tokenizer_init_error(filename_ob); return NULL; } return NULL; @@ -1478,7 +920,7 @@ _PyPegen_run_parser_from_string(const char *str, int start_rule, PyObject *filen } if (tok == NULL) { if (PyErr_Occurred()) { - raise_tokenizer_init_error(filename_ob); + _PyPegen_raise_tokenizer_init_error(filename_ob); } return NULL; } @@ -1504,1138 +946,4 @@ _PyPegen_run_parser_from_string(const char *str, int start_rule, PyObject *filen error: _PyTokenizer_Free(tok); return result; -} - -asdl_stmt_seq* -_PyPegen_interactive_exit(Parser *p) -{ - if (p->errcode) { - *(p->errcode) = E_EOF; - } - return NULL; -} - -/* Creates a single-element asdl_seq* that contains a */ -asdl_seq * -_PyPegen_singleton_seq(Parser *p, void *a) -{ - assert(a != NULL); - asdl_seq *seq = (asdl_seq*)_Py_asdl_generic_seq_new(1, p->arena); - if (!seq) { - return NULL; - } - asdl_seq_SET_UNTYPED(seq, 0, a); - return seq; -} - -/* Creates a copy of seq and prepends a to it */ -asdl_seq * -_PyPegen_seq_insert_in_front(Parser *p, void *a, asdl_seq *seq) -{ - assert(a != NULL); - if (!seq) { - return _PyPegen_singleton_seq(p, a); - } - - asdl_seq *new_seq = (asdl_seq*)_Py_asdl_generic_seq_new(asdl_seq_LEN(seq) + 1, p->arena); - if (!new_seq) { - return NULL; - } - - asdl_seq_SET_UNTYPED(new_seq, 0, a); - for (Py_ssize_t i = 1, l = asdl_seq_LEN(new_seq); i < l; i++) { - asdl_seq_SET_UNTYPED(new_seq, i, asdl_seq_GET_UNTYPED(seq, i - 1)); - } - return new_seq; -} - -/* Creates a copy of seq and appends a to it */ -asdl_seq * -_PyPegen_seq_append_to_end(Parser *p, asdl_seq *seq, void *a) -{ - assert(a != NULL); - if (!seq) { - return _PyPegen_singleton_seq(p, a); - } - - asdl_seq *new_seq = (asdl_seq*)_Py_asdl_generic_seq_new(asdl_seq_LEN(seq) + 1, p->arena); - if (!new_seq) { - return NULL; - } - - for (Py_ssize_t i = 0, l = asdl_seq_LEN(new_seq); i + 1 < l; i++) { - asdl_seq_SET_UNTYPED(new_seq, i, asdl_seq_GET_UNTYPED(seq, i)); - } - asdl_seq_SET_UNTYPED(new_seq, asdl_seq_LEN(new_seq) - 1, a); - return new_seq; -} - -static Py_ssize_t -_get_flattened_seq_size(asdl_seq *seqs) -{ - Py_ssize_t size = 0; - for (Py_ssize_t i = 0, l = asdl_seq_LEN(seqs); i < l; i++) { - asdl_seq *inner_seq = asdl_seq_GET_UNTYPED(seqs, i); - size += asdl_seq_LEN(inner_seq); - } - return size; -} - -/* Flattens an asdl_seq* of asdl_seq*s */ -asdl_seq * -_PyPegen_seq_flatten(Parser *p, asdl_seq *seqs) -{ - Py_ssize_t flattened_seq_size = _get_flattened_seq_size(seqs); - assert(flattened_seq_size > 0); - - asdl_seq *flattened_seq = (asdl_seq*)_Py_asdl_generic_seq_new(flattened_seq_size, p->arena); - if (!flattened_seq) { - return NULL; - } - - int flattened_seq_idx = 0; - for (Py_ssize_t i = 0, l = asdl_seq_LEN(seqs); i < l; i++) { - asdl_seq *inner_seq = asdl_seq_GET_UNTYPED(seqs, i); - for (Py_ssize_t j = 0, li = asdl_seq_LEN(inner_seq); j < li; j++) { - asdl_seq_SET_UNTYPED(flattened_seq, flattened_seq_idx++, asdl_seq_GET_UNTYPED(inner_seq, j)); - } - } - assert(flattened_seq_idx == flattened_seq_size); - - return flattened_seq; -} - -void * -_PyPegen_seq_last_item(asdl_seq *seq) -{ - Py_ssize_t len = asdl_seq_LEN(seq); - return asdl_seq_GET_UNTYPED(seq, len - 1); -} - -void * -_PyPegen_seq_first_item(asdl_seq *seq) -{ - return asdl_seq_GET_UNTYPED(seq, 0); -} - - -/* Creates a new name of the form . */ -expr_ty -_PyPegen_join_names_with_dot(Parser *p, expr_ty first_name, expr_ty second_name) -{ - assert(first_name != NULL && second_name != NULL); - PyObject *first_identifier = first_name->v.Name.id; - PyObject *second_identifier = second_name->v.Name.id; - - if (PyUnicode_READY(first_identifier) == -1) { - return NULL; - } - if (PyUnicode_READY(second_identifier) == -1) { - return NULL; - } - const char *first_str = PyUnicode_AsUTF8(first_identifier); - if (!first_str) { - return NULL; - } - const char *second_str = PyUnicode_AsUTF8(second_identifier); - if (!second_str) { - return NULL; - } - Py_ssize_t len = strlen(first_str) + strlen(second_str) + 1; // +1 for the dot - - PyObject *str = PyBytes_FromStringAndSize(NULL, len); - if (!str) { - return NULL; - } - - char *s = PyBytes_AS_STRING(str); - if (!s) { - return NULL; - } - - strcpy(s, first_str); - s += strlen(first_str); - *s++ = '.'; - strcpy(s, second_str); - s += strlen(second_str); - *s = '\0'; - - PyObject *uni = PyUnicode_DecodeUTF8(PyBytes_AS_STRING(str), PyBytes_GET_SIZE(str), NULL); - Py_DECREF(str); - if (!uni) { - return NULL; - } - PyUnicode_InternInPlace(&uni); - if (_PyArena_AddPyObject(p->arena, uni) < 0) { - Py_DECREF(uni); - return NULL; - } - - return _PyAST_Name(uni, Load, EXTRA_EXPR(first_name, second_name)); -} - -/* Counts the total number of dots in seq's tokens */ -int -_PyPegen_seq_count_dots(asdl_seq *seq) -{ - int number_of_dots = 0; - for (Py_ssize_t i = 0, l = asdl_seq_LEN(seq); i < l; i++) { - Token *current_expr = asdl_seq_GET_UNTYPED(seq, i); - switch (current_expr->type) { - case ELLIPSIS: - number_of_dots += 3; - break; - case DOT: - number_of_dots += 1; - break; - default: - Py_UNREACHABLE(); - } - } - - return number_of_dots; -} - -/* Creates an alias with '*' as the identifier name */ -alias_ty -_PyPegen_alias_for_star(Parser *p, int lineno, int col_offset, int end_lineno, - int end_col_offset, PyArena *arena) { - PyObject *str = PyUnicode_InternFromString("*"); - if (!str) { - return NULL; - } - if (_PyArena_AddPyObject(p->arena, str) < 0) { - Py_DECREF(str); - return NULL; - } - return _PyAST_alias(str, NULL, lineno, col_offset, end_lineno, end_col_offset, arena); -} - -/* Creates a new asdl_seq* with the identifiers of all the names in seq */ -asdl_identifier_seq * -_PyPegen_map_names_to_ids(Parser *p, asdl_expr_seq *seq) -{ - Py_ssize_t len = asdl_seq_LEN(seq); - assert(len > 0); - - asdl_identifier_seq *new_seq = _Py_asdl_identifier_seq_new(len, p->arena); - if (!new_seq) { - return NULL; - } - for (Py_ssize_t i = 0; i < len; i++) { - expr_ty e = asdl_seq_GET(seq, i); - asdl_seq_SET(new_seq, i, e->v.Name.id); - } - return new_seq; -} - -/* Constructs a CmpopExprPair */ -CmpopExprPair * -_PyPegen_cmpop_expr_pair(Parser *p, cmpop_ty cmpop, expr_ty expr) -{ - assert(expr != NULL); - CmpopExprPair *a = _PyArena_Malloc(p->arena, sizeof(CmpopExprPair)); - if (!a) { - return NULL; - } - a->cmpop = cmpop; - a->expr = expr; - return a; -} - -asdl_int_seq * -_PyPegen_get_cmpops(Parser *p, asdl_seq *seq) -{ - Py_ssize_t len = asdl_seq_LEN(seq); - assert(len > 0); - - asdl_int_seq *new_seq = _Py_asdl_int_seq_new(len, p->arena); - if (!new_seq) { - return NULL; - } - for (Py_ssize_t i = 0; i < len; i++) { - CmpopExprPair *pair = asdl_seq_GET_UNTYPED(seq, i); - asdl_seq_SET(new_seq, i, pair->cmpop); - } - return new_seq; -} - -asdl_expr_seq * -_PyPegen_get_exprs(Parser *p, asdl_seq *seq) -{ - Py_ssize_t len = asdl_seq_LEN(seq); - assert(len > 0); - - asdl_expr_seq *new_seq = _Py_asdl_expr_seq_new(len, p->arena); - if (!new_seq) { - return NULL; - } - for (Py_ssize_t i = 0; i < len; i++) { - CmpopExprPair *pair = asdl_seq_GET_UNTYPED(seq, i); - asdl_seq_SET(new_seq, i, pair->expr); - } - return new_seq; -} - -/* Creates an asdl_seq* where all the elements have been changed to have ctx as context */ -static asdl_expr_seq * -_set_seq_context(Parser *p, asdl_expr_seq *seq, expr_context_ty ctx) -{ - Py_ssize_t len = asdl_seq_LEN(seq); - if (len == 0) { - return NULL; - } - - asdl_expr_seq *new_seq = _Py_asdl_expr_seq_new(len, p->arena); - if (!new_seq) { - return NULL; - } - for (Py_ssize_t i = 0; i < len; i++) { - expr_ty e = asdl_seq_GET(seq, i); - asdl_seq_SET(new_seq, i, _PyPegen_set_expr_context(p, e, ctx)); - } - return new_seq; -} - -static expr_ty -_set_name_context(Parser *p, expr_ty e, expr_context_ty ctx) -{ - return _PyAST_Name(e->v.Name.id, ctx, EXTRA_EXPR(e, e)); -} - -static expr_ty -_set_tuple_context(Parser *p, expr_ty e, expr_context_ty ctx) -{ - return _PyAST_Tuple( - _set_seq_context(p, e->v.Tuple.elts, ctx), - ctx, - EXTRA_EXPR(e, e)); -} - -static expr_ty -_set_list_context(Parser *p, expr_ty e, expr_context_ty ctx) -{ - return _PyAST_List( - _set_seq_context(p, e->v.List.elts, ctx), - ctx, - EXTRA_EXPR(e, e)); -} - -static expr_ty -_set_subscript_context(Parser *p, expr_ty e, expr_context_ty ctx) -{ - return _PyAST_Subscript(e->v.Subscript.value, e->v.Subscript.slice, - ctx, EXTRA_EXPR(e, e)); -} - -static expr_ty -_set_attribute_context(Parser *p, expr_ty e, expr_context_ty ctx) -{ - return _PyAST_Attribute(e->v.Attribute.value, e->v.Attribute.attr, - ctx, EXTRA_EXPR(e, e)); -} - -static expr_ty -_set_starred_context(Parser *p, expr_ty e, expr_context_ty ctx) -{ - return _PyAST_Starred(_PyPegen_set_expr_context(p, e->v.Starred.value, ctx), - ctx, EXTRA_EXPR(e, e)); -} - -/* Creates an `expr_ty` equivalent to `expr` but with `ctx` as context */ -expr_ty -_PyPegen_set_expr_context(Parser *p, expr_ty expr, expr_context_ty ctx) -{ - assert(expr != NULL); - - expr_ty new = NULL; - switch (expr->kind) { - case Name_kind: - new = _set_name_context(p, expr, ctx); - break; - case Tuple_kind: - new = _set_tuple_context(p, expr, ctx); - break; - case List_kind: - new = _set_list_context(p, expr, ctx); - break; - case Subscript_kind: - new = _set_subscript_context(p, expr, ctx); - break; - case Attribute_kind: - new = _set_attribute_context(p, expr, ctx); - break; - case Starred_kind: - new = _set_starred_context(p, expr, ctx); - break; - default: - new = expr; - } - return new; -} - -/* Constructs a KeyValuePair that is used when parsing a dict's key value pairs */ -KeyValuePair * -_PyPegen_key_value_pair(Parser *p, expr_ty key, expr_ty value) -{ - KeyValuePair *a = _PyArena_Malloc(p->arena, sizeof(KeyValuePair)); - if (!a) { - return NULL; - } - a->key = key; - a->value = value; - return a; -} - -/* Extracts all keys from an asdl_seq* of KeyValuePair*'s */ -asdl_expr_seq * -_PyPegen_get_keys(Parser *p, asdl_seq *seq) -{ - Py_ssize_t len = asdl_seq_LEN(seq); - asdl_expr_seq *new_seq = _Py_asdl_expr_seq_new(len, p->arena); - if (!new_seq) { - return NULL; - } - for (Py_ssize_t i = 0; i < len; i++) { - KeyValuePair *pair = asdl_seq_GET_UNTYPED(seq, i); - asdl_seq_SET(new_seq, i, pair->key); - } - return new_seq; -} - -/* Extracts all values from an asdl_seq* of KeyValuePair*'s */ -asdl_expr_seq * -_PyPegen_get_values(Parser *p, asdl_seq *seq) -{ - Py_ssize_t len = asdl_seq_LEN(seq); - asdl_expr_seq *new_seq = _Py_asdl_expr_seq_new(len, p->arena); - if (!new_seq) { - return NULL; - } - for (Py_ssize_t i = 0; i < len; i++) { - KeyValuePair *pair = asdl_seq_GET_UNTYPED(seq, i); - asdl_seq_SET(new_seq, i, pair->value); - } - return new_seq; -} - -/* Constructs a KeyPatternPair that is used when parsing mapping & class patterns */ -KeyPatternPair * -_PyPegen_key_pattern_pair(Parser *p, expr_ty key, pattern_ty pattern) -{ - KeyPatternPair *a = _PyArena_Malloc(p->arena, sizeof(KeyPatternPair)); - if (!a) { - return NULL; - } - a->key = key; - a->pattern = pattern; - return a; -} - -/* Extracts all keys from an asdl_seq* of KeyPatternPair*'s */ -asdl_expr_seq * -_PyPegen_get_pattern_keys(Parser *p, asdl_seq *seq) -{ - Py_ssize_t len = asdl_seq_LEN(seq); - asdl_expr_seq *new_seq = _Py_asdl_expr_seq_new(len, p->arena); - if (!new_seq) { - return NULL; - } - for (Py_ssize_t i = 0; i < len; i++) { - KeyPatternPair *pair = asdl_seq_GET_UNTYPED(seq, i); - asdl_seq_SET(new_seq, i, pair->key); - } - return new_seq; -} - -/* Extracts all patterns from an asdl_seq* of KeyPatternPair*'s */ -asdl_pattern_seq * -_PyPegen_get_patterns(Parser *p, asdl_seq *seq) -{ - Py_ssize_t len = asdl_seq_LEN(seq); - asdl_pattern_seq *new_seq = _Py_asdl_pattern_seq_new(len, p->arena); - if (!new_seq) { - return NULL; - } - for (Py_ssize_t i = 0; i < len; i++) { - KeyPatternPair *pair = asdl_seq_GET_UNTYPED(seq, i); - asdl_seq_SET(new_seq, i, pair->pattern); - } - return new_seq; -} - -/* Constructs a NameDefaultPair */ -NameDefaultPair * -_PyPegen_name_default_pair(Parser *p, arg_ty arg, expr_ty value, Token *tc) -{ - NameDefaultPair *a = _PyArena_Malloc(p->arena, sizeof(NameDefaultPair)); - if (!a) { - return NULL; - } - a->arg = _PyPegen_add_type_comment_to_arg(p, arg, tc); - a->value = value; - return a; -} - -/* Constructs a SlashWithDefault */ -SlashWithDefault * -_PyPegen_slash_with_default(Parser *p, asdl_arg_seq *plain_names, asdl_seq *names_with_defaults) -{ - SlashWithDefault *a = _PyArena_Malloc(p->arena, sizeof(SlashWithDefault)); - if (!a) { - return NULL; - } - a->plain_names = plain_names; - a->names_with_defaults = names_with_defaults; - return a; -} - -/* Constructs a StarEtc */ -StarEtc * -_PyPegen_star_etc(Parser *p, arg_ty vararg, asdl_seq *kwonlyargs, arg_ty kwarg) -{ - StarEtc *a = _PyArena_Malloc(p->arena, sizeof(StarEtc)); - if (!a) { - return NULL; - } - a->vararg = vararg; - a->kwonlyargs = kwonlyargs; - a->kwarg = kwarg; - return a; -} - -asdl_seq * -_PyPegen_join_sequences(Parser *p, asdl_seq *a, asdl_seq *b) -{ - Py_ssize_t first_len = asdl_seq_LEN(a); - Py_ssize_t second_len = asdl_seq_LEN(b); - asdl_seq *new_seq = (asdl_seq*)_Py_asdl_generic_seq_new(first_len + second_len, p->arena); - if (!new_seq) { - return NULL; - } - - int k = 0; - for (Py_ssize_t i = 0; i < first_len; i++) { - asdl_seq_SET_UNTYPED(new_seq, k++, asdl_seq_GET_UNTYPED(a, i)); - } - for (Py_ssize_t i = 0; i < second_len; i++) { - asdl_seq_SET_UNTYPED(new_seq, k++, asdl_seq_GET_UNTYPED(b, i)); - } - - return new_seq; -} - -static asdl_arg_seq* -_get_names(Parser *p, asdl_seq *names_with_defaults) -{ - Py_ssize_t len = asdl_seq_LEN(names_with_defaults); - asdl_arg_seq *seq = _Py_asdl_arg_seq_new(len, p->arena); - if (!seq) { - return NULL; - } - for (Py_ssize_t i = 0; i < len; i++) { - NameDefaultPair *pair = asdl_seq_GET_UNTYPED(names_with_defaults, i); - asdl_seq_SET(seq, i, pair->arg); - } - return seq; -} - -static asdl_expr_seq * -_get_defaults(Parser *p, asdl_seq *names_with_defaults) -{ - Py_ssize_t len = asdl_seq_LEN(names_with_defaults); - asdl_expr_seq *seq = _Py_asdl_expr_seq_new(len, p->arena); - if (!seq) { - return NULL; - } - for (Py_ssize_t i = 0; i < len; i++) { - NameDefaultPair *pair = asdl_seq_GET_UNTYPED(names_with_defaults, i); - asdl_seq_SET(seq, i, pair->value); - } - return seq; -} - -static int -_make_posonlyargs(Parser *p, - asdl_arg_seq *slash_without_default, - SlashWithDefault *slash_with_default, - asdl_arg_seq **posonlyargs) { - if (slash_without_default != NULL) { - *posonlyargs = slash_without_default; - } - else if (slash_with_default != NULL) { - asdl_arg_seq *slash_with_default_names = - _get_names(p, slash_with_default->names_with_defaults); - if (!slash_with_default_names) { - return -1; - } - *posonlyargs = (asdl_arg_seq*)_PyPegen_join_sequences( - p, - (asdl_seq*)slash_with_default->plain_names, - (asdl_seq*)slash_with_default_names); - } - else { - *posonlyargs = _Py_asdl_arg_seq_new(0, p->arena); - } - return *posonlyargs == NULL ? -1 : 0; -} - -static int -_make_posargs(Parser *p, - asdl_arg_seq *plain_names, - asdl_seq *names_with_default, - asdl_arg_seq **posargs) { - if (plain_names != NULL && names_with_default != NULL) { - asdl_arg_seq *names_with_default_names = _get_names(p, names_with_default); - if (!names_with_default_names) { - return -1; - } - *posargs = (asdl_arg_seq*)_PyPegen_join_sequences( - p,(asdl_seq*)plain_names, (asdl_seq*)names_with_default_names); - } - else if (plain_names == NULL && names_with_default != NULL) { - *posargs = _get_names(p, names_with_default); - } - else if (plain_names != NULL && names_with_default == NULL) { - *posargs = plain_names; - } - else { - *posargs = _Py_asdl_arg_seq_new(0, p->arena); - } - return *posargs == NULL ? -1 : 0; -} - -static int -_make_posdefaults(Parser *p, - SlashWithDefault *slash_with_default, - asdl_seq *names_with_default, - asdl_expr_seq **posdefaults) { - if (slash_with_default != NULL && names_with_default != NULL) { - asdl_expr_seq *slash_with_default_values = - _get_defaults(p, slash_with_default->names_with_defaults); - if (!slash_with_default_values) { - return -1; - } - asdl_expr_seq *names_with_default_values = _get_defaults(p, names_with_default); - if (!names_with_default_values) { - return -1; - } - *posdefaults = (asdl_expr_seq*)_PyPegen_join_sequences( - p, - (asdl_seq*)slash_with_default_values, - (asdl_seq*)names_with_default_values); - } - else if (slash_with_default == NULL && names_with_default != NULL) { - *posdefaults = _get_defaults(p, names_with_default); - } - else if (slash_with_default != NULL && names_with_default == NULL) { - *posdefaults = _get_defaults(p, slash_with_default->names_with_defaults); - } - else { - *posdefaults = _Py_asdl_expr_seq_new(0, p->arena); - } - return *posdefaults == NULL ? -1 : 0; -} - -static int -_make_kwargs(Parser *p, StarEtc *star_etc, - asdl_arg_seq **kwonlyargs, - asdl_expr_seq **kwdefaults) { - if (star_etc != NULL && star_etc->kwonlyargs != NULL) { - *kwonlyargs = _get_names(p, star_etc->kwonlyargs); - } - else { - *kwonlyargs = _Py_asdl_arg_seq_new(0, p->arena); - } - - if (*kwonlyargs == NULL) { - return -1; - } - - if (star_etc != NULL && star_etc->kwonlyargs != NULL) { - *kwdefaults = _get_defaults(p, star_etc->kwonlyargs); - } - else { - *kwdefaults = _Py_asdl_expr_seq_new(0, p->arena); - } - - if (*kwdefaults == NULL) { - return -1; - } - - return 0; -} - -/* Constructs an arguments_ty object out of all the parsed constructs in the parameters rule */ -arguments_ty -_PyPegen_make_arguments(Parser *p, asdl_arg_seq *slash_without_default, - SlashWithDefault *slash_with_default, asdl_arg_seq *plain_names, - asdl_seq *names_with_default, StarEtc *star_etc) -{ - asdl_arg_seq *posonlyargs; - if (_make_posonlyargs(p, slash_without_default, slash_with_default, &posonlyargs) == -1) { - return NULL; - } - - asdl_arg_seq *posargs; - if (_make_posargs(p, plain_names, names_with_default, &posargs) == -1) { - return NULL; - } - - asdl_expr_seq *posdefaults; - if (_make_posdefaults(p,slash_with_default, names_with_default, &posdefaults) == -1) { - return NULL; - } - - arg_ty vararg = NULL; - if (star_etc != NULL && star_etc->vararg != NULL) { - vararg = star_etc->vararg; - } - - asdl_arg_seq *kwonlyargs; - asdl_expr_seq *kwdefaults; - if (_make_kwargs(p, star_etc, &kwonlyargs, &kwdefaults) == -1) { - return NULL; - } - - arg_ty kwarg = NULL; - if (star_etc != NULL && star_etc->kwarg != NULL) { - kwarg = star_etc->kwarg; - } - - return _PyAST_arguments(posonlyargs, posargs, vararg, kwonlyargs, - kwdefaults, kwarg, posdefaults, p->arena); -} - - -/* Constructs an empty arguments_ty object, that gets used when a function accepts no - * arguments. */ -arguments_ty -_PyPegen_empty_arguments(Parser *p) -{ - asdl_arg_seq *posonlyargs = _Py_asdl_arg_seq_new(0, p->arena); - if (!posonlyargs) { - return NULL; - } - asdl_arg_seq *posargs = _Py_asdl_arg_seq_new(0, p->arena); - if (!posargs) { - return NULL; - } - asdl_expr_seq *posdefaults = _Py_asdl_expr_seq_new(0, p->arena); - if (!posdefaults) { - return NULL; - } - asdl_arg_seq *kwonlyargs = _Py_asdl_arg_seq_new(0, p->arena); - if (!kwonlyargs) { - return NULL; - } - asdl_expr_seq *kwdefaults = _Py_asdl_expr_seq_new(0, p->arena); - if (!kwdefaults) { - return NULL; - } - - return _PyAST_arguments(posonlyargs, posargs, NULL, kwonlyargs, - kwdefaults, NULL, posdefaults, p->arena); -} - -/* Encapsulates the value of an operator_ty into an AugOperator struct */ -AugOperator * -_PyPegen_augoperator(Parser *p, operator_ty kind) -{ - AugOperator *a = _PyArena_Malloc(p->arena, sizeof(AugOperator)); - if (!a) { - return NULL; - } - a->kind = kind; - return a; -} - -/* Construct a FunctionDef equivalent to function_def, but with decorators */ -stmt_ty -_PyPegen_function_def_decorators(Parser *p, asdl_expr_seq *decorators, stmt_ty function_def) -{ - assert(function_def != NULL); - if (function_def->kind == AsyncFunctionDef_kind) { - return _PyAST_AsyncFunctionDef( - function_def->v.FunctionDef.name, function_def->v.FunctionDef.args, - function_def->v.FunctionDef.body, decorators, function_def->v.FunctionDef.returns, - function_def->v.FunctionDef.type_comment, function_def->lineno, - function_def->col_offset, function_def->end_lineno, function_def->end_col_offset, - p->arena); - } - - return _PyAST_FunctionDef( - function_def->v.FunctionDef.name, function_def->v.FunctionDef.args, - function_def->v.FunctionDef.body, decorators, - function_def->v.FunctionDef.returns, - function_def->v.FunctionDef.type_comment, function_def->lineno, - function_def->col_offset, function_def->end_lineno, - function_def->end_col_offset, p->arena); -} - -/* Construct a ClassDef equivalent to class_def, but with decorators */ -stmt_ty -_PyPegen_class_def_decorators(Parser *p, asdl_expr_seq *decorators, stmt_ty class_def) -{ - assert(class_def != NULL); - return _PyAST_ClassDef( - class_def->v.ClassDef.name, class_def->v.ClassDef.bases, - class_def->v.ClassDef.keywords, class_def->v.ClassDef.body, decorators, - class_def->lineno, class_def->col_offset, class_def->end_lineno, - class_def->end_col_offset, p->arena); -} - -/* Construct a KeywordOrStarred */ -KeywordOrStarred * -_PyPegen_keyword_or_starred(Parser *p, void *element, int is_keyword) -{ - KeywordOrStarred *a = _PyArena_Malloc(p->arena, sizeof(KeywordOrStarred)); - if (!a) { - return NULL; - } - a->element = element; - a->is_keyword = is_keyword; - return a; -} - -/* Get the number of starred expressions in an asdl_seq* of KeywordOrStarred*s */ -static int -_seq_number_of_starred_exprs(asdl_seq *seq) -{ - int n = 0; - for (Py_ssize_t i = 0, l = asdl_seq_LEN(seq); i < l; i++) { - KeywordOrStarred *k = asdl_seq_GET_UNTYPED(seq, i); - if (!k->is_keyword) { - n++; - } - } - return n; -} - -/* Extract the starred expressions of an asdl_seq* of KeywordOrStarred*s */ -asdl_expr_seq * -_PyPegen_seq_extract_starred_exprs(Parser *p, asdl_seq *kwargs) -{ - int new_len = _seq_number_of_starred_exprs(kwargs); - if (new_len == 0) { - return NULL; - } - asdl_expr_seq *new_seq = _Py_asdl_expr_seq_new(new_len, p->arena); - if (!new_seq) { - return NULL; - } - - int idx = 0; - for (Py_ssize_t i = 0, len = asdl_seq_LEN(kwargs); i < len; i++) { - KeywordOrStarred *k = asdl_seq_GET_UNTYPED(kwargs, i); - if (!k->is_keyword) { - asdl_seq_SET(new_seq, idx++, k->element); - } - } - return new_seq; -} - -/* Return a new asdl_seq* with only the keywords in kwargs */ -asdl_keyword_seq* -_PyPegen_seq_delete_starred_exprs(Parser *p, asdl_seq *kwargs) -{ - Py_ssize_t len = asdl_seq_LEN(kwargs); - Py_ssize_t new_len = len - _seq_number_of_starred_exprs(kwargs); - if (new_len == 0) { - return NULL; - } - asdl_keyword_seq *new_seq = _Py_asdl_keyword_seq_new(new_len, p->arena); - if (!new_seq) { - return NULL; - } - - int idx = 0; - for (Py_ssize_t i = 0; i < len; i++) { - KeywordOrStarred *k = asdl_seq_GET_UNTYPED(kwargs, i); - if (k->is_keyword) { - asdl_seq_SET(new_seq, idx++, k->element); - } - } - return new_seq; -} - -expr_ty -_PyPegen_concatenate_strings(Parser *p, asdl_seq *strings) -{ - Py_ssize_t len = asdl_seq_LEN(strings); - assert(len > 0); - - Token *first = asdl_seq_GET_UNTYPED(strings, 0); - Token *last = asdl_seq_GET_UNTYPED(strings, len - 1); - - int bytesmode = 0; - PyObject *bytes_str = NULL; - - FstringParser state; - _PyPegen_FstringParser_Init(&state); - - for (Py_ssize_t i = 0; i < len; i++) { - Token *t = asdl_seq_GET_UNTYPED(strings, i); - - int this_bytesmode; - int this_rawmode; - PyObject *s; - const char *fstr; - Py_ssize_t fstrlen = -1; - - if (_PyPegen_parsestr(p, &this_bytesmode, &this_rawmode, &s, &fstr, &fstrlen, t) != 0) { - goto error; - } - - /* Check that we are not mixing bytes with unicode. */ - if (i != 0 && bytesmode != this_bytesmode) { - RAISE_SYNTAX_ERROR("cannot mix bytes and nonbytes literals"); - Py_XDECREF(s); - goto error; - } - bytesmode = this_bytesmode; - - if (fstr != NULL) { - assert(s == NULL && !bytesmode); - - int result = _PyPegen_FstringParser_ConcatFstring(p, &state, &fstr, fstr + fstrlen, - this_rawmode, 0, first, t, last); - if (result < 0) { - goto error; - } - } - else { - /* String or byte string. */ - assert(s != NULL && fstr == NULL); - assert(bytesmode ? PyBytes_CheckExact(s) : PyUnicode_CheckExact(s)); - - if (bytesmode) { - if (i == 0) { - bytes_str = s; - } - else { - PyBytes_ConcatAndDel(&bytes_str, s); - if (!bytes_str) { - goto error; - } - } - } - else { - /* This is a regular string. Concatenate it. */ - if (_PyPegen_FstringParser_ConcatAndDel(&state, s) < 0) { - goto error; - } - } - } - } - - if (bytesmode) { - if (_PyArena_AddPyObject(p->arena, bytes_str) < 0) { - goto error; - } - return _PyAST_Constant(bytes_str, NULL, first->lineno, - first->col_offset, last->end_lineno, - last->end_col_offset, p->arena); - } - - return _PyPegen_FstringParser_Finish(p, &state, first, last); - -error: - Py_XDECREF(bytes_str); - _PyPegen_FstringParser_Dealloc(&state); - if (PyErr_Occurred()) { - raise_decode_error(p); - } - return NULL; -} - -expr_ty -_PyPegen_ensure_imaginary(Parser *p, expr_ty exp) -{ - if (exp->kind != Constant_kind || !PyComplex_CheckExact(exp->v.Constant.value)) { - RAISE_SYNTAX_ERROR_KNOWN_LOCATION(exp, "imaginary number required in complex literal"); - return NULL; - } - return exp; -} - -expr_ty -_PyPegen_ensure_real(Parser *p, expr_ty exp) -{ - if (exp->kind != Constant_kind || PyComplex_CheckExact(exp->v.Constant.value)) { - RAISE_SYNTAX_ERROR_KNOWN_LOCATION(exp, "real number required in complex literal"); - return NULL; - } - return exp; -} - -mod_ty -_PyPegen_make_module(Parser *p, asdl_stmt_seq *a) { - asdl_type_ignore_seq *type_ignores = NULL; - Py_ssize_t num = p->type_ignore_comments.num_items; - if (num > 0) { - // Turn the raw (comment, lineno) pairs into TypeIgnore objects in the arena - type_ignores = _Py_asdl_type_ignore_seq_new(num, p->arena); - if (type_ignores == NULL) { - return NULL; - } - for (int i = 0; i < num; i++) { - PyObject *tag = _PyPegen_new_type_comment(p, p->type_ignore_comments.items[i].comment); - if (tag == NULL) { - return NULL; - } - type_ignore_ty ti = _PyAST_TypeIgnore(p->type_ignore_comments.items[i].lineno, - tag, p->arena); - if (ti == NULL) { - return NULL; - } - asdl_seq_SET(type_ignores, i, ti); - } - } - return _PyAST_Module(a, type_ignores, p->arena); -} - -// Error reporting helpers - -expr_ty -_PyPegen_get_invalid_target(expr_ty e, TARGETS_TYPE targets_type) -{ - if (e == NULL) { - return NULL; - } - -#define VISIT_CONTAINER(CONTAINER, TYPE) do { \ - Py_ssize_t len = asdl_seq_LEN((CONTAINER)->v.TYPE.elts);\ - for (Py_ssize_t i = 0; i < len; i++) {\ - expr_ty other = asdl_seq_GET((CONTAINER)->v.TYPE.elts, i);\ - expr_ty child = _PyPegen_get_invalid_target(other, targets_type);\ - if (child != NULL) {\ - return child;\ - }\ - }\ - } while (0) - - // We only need to visit List and Tuple nodes recursively as those - // are the only ones that can contain valid names in targets when - // they are parsed as expressions. Any other kind of expression - // that is a container (like Sets or Dicts) is directly invalid and - // we don't need to visit it recursively. - - switch (e->kind) { - case List_kind: - VISIT_CONTAINER(e, List); - return NULL; - case Tuple_kind: - VISIT_CONTAINER(e, Tuple); - return NULL; - case Starred_kind: - if (targets_type == DEL_TARGETS) { - return e; - } - return _PyPegen_get_invalid_target(e->v.Starred.value, targets_type); - case Compare_kind: - // This is needed, because the `a in b` in `for a in b` gets parsed - // as a comparison, and so we need to search the left side of the comparison - // for invalid targets. - if (targets_type == FOR_TARGETS) { - cmpop_ty cmpop = (cmpop_ty) asdl_seq_GET(e->v.Compare.ops, 0); - if (cmpop == In) { - return _PyPegen_get_invalid_target(e->v.Compare.left, targets_type); - } - return NULL; - } - return e; - case Name_kind: - case Subscript_kind: - case Attribute_kind: - return NULL; - default: - return e; - } -} - -void *_PyPegen_arguments_parsing_error(Parser *p, expr_ty e) { - int kwarg_unpacking = 0; - for (Py_ssize_t i = 0, l = asdl_seq_LEN(e->v.Call.keywords); i < l; i++) { - keyword_ty keyword = asdl_seq_GET(e->v.Call.keywords, i); - if (!keyword->arg) { - kwarg_unpacking = 1; - } - } - - const char *msg = NULL; - if (kwarg_unpacking) { - msg = "positional argument follows keyword argument unpacking"; - } else { - msg = "positional argument follows keyword argument"; - } - - return RAISE_SYNTAX_ERROR(msg); -} - - -static inline expr_ty -_PyPegen_get_last_comprehension_item(comprehension_ty comprehension) { - if (comprehension->ifs == NULL || asdl_seq_LEN(comprehension->ifs) == 0) { - return comprehension->iter; - } - return PyPegen_last_item(comprehension->ifs, expr_ty); -} - -void * -_PyPegen_nonparen_genexp_in_call(Parser *p, expr_ty args, asdl_comprehension_seq *comprehensions) -{ - /* The rule that calls this function is 'args for_if_clauses'. - For the input f(L, x for x in y), L and x are in args and - the for is parsed as a for_if_clause. We have to check if - len <= 1, so that input like dict((a, b) for a, b in x) - gets successfully parsed and then we pass the last - argument (x in the above example) as the location of the - error */ - Py_ssize_t len = asdl_seq_LEN(args->v.Call.args); - if (len <= 1) { - return NULL; - } - - comprehension_ty last_comprehension = PyPegen_last_item(comprehensions, comprehension_ty); - - return RAISE_SYNTAX_ERROR_KNOWN_RANGE( - (expr_ty) asdl_seq_GET(args->v.Call.args, len - 1), - _PyPegen_get_last_comprehension_item(last_comprehension), - "Generator expression must be parenthesized" - ); -} - - -expr_ty _PyPegen_collect_call_seqs(Parser *p, asdl_expr_seq *a, asdl_seq *b, - int lineno, int col_offset, int end_lineno, - int end_col_offset, PyArena *arena) { - Py_ssize_t args_len = asdl_seq_LEN(a); - Py_ssize_t total_len = args_len; - - if (b == NULL) { - return _PyAST_Call(_PyPegen_dummy_name(p), a, NULL, lineno, col_offset, - end_lineno, end_col_offset, arena); - - } - - asdl_expr_seq *starreds = _PyPegen_seq_extract_starred_exprs(p, b); - asdl_keyword_seq *keywords = _PyPegen_seq_delete_starred_exprs(p, b); - - if (starreds) { - total_len += asdl_seq_LEN(starreds); - } - - asdl_expr_seq *args = _Py_asdl_expr_seq_new(total_len, arena); - - Py_ssize_t i = 0; - for (i = 0; i < args_len; i++) { - asdl_seq_SET(args, i, asdl_seq_GET(a, i)); - } - for (; i < total_len; i++) { - asdl_seq_SET(args, i, asdl_seq_GET(starreds, i - args_len)); - } - - return _PyAST_Call(_PyPegen_dummy_name(p), args, keywords, lineno, - col_offset, end_lineno, end_col_offset, arena); -} +} \ No newline at end of file diff --git a/Parser/pegen.h b/Parser/pegen.h index 8721d7e891005..e5e712ab26b87 100644 --- a/Parser/pegen.h +++ b/Parser/pegen.h @@ -23,6 +23,8 @@ #define PyPARSE_TYPE_COMMENTS 0x0040 #define PyPARSE_ASYNC_HACKS 0x0080 +#define CURRENT_POS (-5) + typedef struct _memo { int type; void *node; @@ -114,6 +116,7 @@ typedef struct { int is_keyword; } KeywordOrStarred; +// Internal parser functions #if defined(Py_DEBUG) void _PyPegen_clear_memo_statistics(void); PyObject *_PyPegen_get_memo_statistics(void); @@ -123,7 +126,6 @@ int _PyPegen_insert_memo(Parser *p, int mark, int type, void *node); int _PyPegen_update_memo(Parser *p, int mark, int type, void *node); int _PyPegen_is_memoized(Parser *p, int type, void *pres); - int _PyPegen_lookahead_with_name(int, expr_ty (func)(Parser *), Parser *); int _PyPegen_lookahead_with_int(int, Token *(func)(Parser *, int), Parser *, int); int _PyPegen_lookahead_with_string(int , expr_ty (func)(Parser *, const char*), Parser *, const char*); @@ -139,23 +141,24 @@ int _PyPegen_fill_token(Parser *p); expr_ty _PyPegen_name_token(Parser *p); expr_ty _PyPegen_number_token(Parser *p); void *_PyPegen_string_token(Parser *p); -const char *_PyPegen_get_expr_name(expr_ty); Py_ssize_t _PyPegen_byte_offset_to_character_offset(PyObject *line, Py_ssize_t col_offset); + +// Error handling functions and APIs +typedef enum { + STAR_TARGETS, + DEL_TARGETS, + FOR_TARGETS +} TARGETS_TYPE; + +int _Pypegen_raise_decode_error(Parser *p); +void _PyPegen_raise_tokenizer_init_error(PyObject *filename); +int _Pypegen_tokenizer_error(Parser *p); void *_PyPegen_raise_error(Parser *p, PyObject *errtype, const char *errmsg, ...); void *_PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, Py_ssize_t lineno, Py_ssize_t col_offset, Py_ssize_t end_lineno, Py_ssize_t end_col_offset, const char *errmsg, va_list va); -void *_PyPegen_dummy_name(Parser *p, ...); - -void * _PyPegen_seq_last_item(asdl_seq *seq); -#define PyPegen_last_item(seq, type) ((type)_PyPegen_seq_last_item((asdl_seq*)seq)) - -void * _PyPegen_seq_first_item(asdl_seq *seq); -#define PyPegen_first_item(seq, type) ((type)_PyPegen_seq_first_item((asdl_seq*)seq)) - -#define CURRENT_POS (-5) - +void _Pypegen_set_syntax_error(Parser* p, Token* last_token); Py_LOCAL_INLINE(void *) RAISE_ERROR_KNOWN_LOCATION(Parser *p, PyObject *errtype, Py_ssize_t lineno, Py_ssize_t col_offset, @@ -170,10 +173,6 @@ RAISE_ERROR_KNOWN_LOCATION(Parser *p, PyObject *errtype, va_end(va); return NULL; } - -#define UNUSED(expr) do { (void)(expr); } while (0) -#define EXTRA_EXPR(head, tail) head->lineno, (head)->col_offset, (tail)->end_lineno, (tail)->end_col_offset, p->arena -#define EXTRA _start_lineno, _start_col_offset, _end_lineno, _end_col_offset, p->arena #define RAISE_SYNTAX_ERROR(msg, ...) _PyPegen_raise_error(p, PyExc_SyntaxError, msg, ##__VA_ARGS__) #define RAISE_INDENTATION_ERROR(msg, ...) _PyPegen_raise_error(p, PyExc_IndentationError, msg, ##__VA_ARGS__) #define RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, msg, ...) \ @@ -182,6 +181,7 @@ RAISE_ERROR_KNOWN_LOCATION(Parser *p, PyObject *errtype, RAISE_ERROR_KNOWN_LOCATION(p, PyExc_SyntaxError, (a)->lineno, (a)->col_offset, (a)->end_lineno, (a)->end_col_offset, msg, ##__VA_ARGS__) #define RAISE_SYNTAX_ERROR_STARTING_FROM(a, msg, ...) \ RAISE_ERROR_KNOWN_LOCATION(p, PyExc_SyntaxError, (a)->lineno, (a)->col_offset, CURRENT_POS, CURRENT_POS, msg, ##__VA_ARGS__) +#define RAISE_SYNTAX_ERROR_INVALID_TARGET(type, e) _RAISE_SYNTAX_ERROR_INVALID_TARGET(p, type, e) Py_LOCAL_INLINE(void *) CHECK_CALL(Parser *p, void *result) @@ -207,6 +207,39 @@ CHECK_CALL_NULL_ALLOWED(Parser *p, void *result) #define CHECK(type, result) ((type) CHECK_CALL(p, result)) #define CHECK_NULL_ALLOWED(type, result) ((type) CHECK_CALL_NULL_ALLOWED(p, result)) +expr_ty _PyPegen_get_invalid_target(expr_ty e, TARGETS_TYPE targets_type); +const char *_PyPegen_get_expr_name(expr_ty); +Py_LOCAL_INLINE(void *) +_RAISE_SYNTAX_ERROR_INVALID_TARGET(Parser *p, TARGETS_TYPE type, void *e) +{ + expr_ty invalid_target = CHECK_NULL_ALLOWED(expr_ty, _PyPegen_get_invalid_target(e, type)); + if (invalid_target != NULL) { + const char *msg; + if (type == STAR_TARGETS || type == FOR_TARGETS) { + msg = "cannot assign to %s"; + } + else { + msg = "cannot delete %s"; + } + return RAISE_SYNTAX_ERROR_KNOWN_LOCATION( + invalid_target, + msg, + _PyPegen_get_expr_name(invalid_target) + ); + } + return RAISE_SYNTAX_ERROR("invalid syntax"); +} + +// Action utility functions + +void *_PyPegen_dummy_name(Parser *p, ...); +void * _PyPegen_seq_last_item(asdl_seq *seq); +#define PyPegen_last_item(seq, type) ((type)_PyPegen_seq_last_item((asdl_seq*)seq)) +void * _PyPegen_seq_first_item(asdl_seq *seq); +#define PyPegen_first_item(seq, type) ((type)_PyPegen_seq_first_item((asdl_seq*)seq)) +#define UNUSED(expr) do { (void)(expr); } while (0) +#define EXTRA_EXPR(head, tail) head->lineno, (head)->col_offset, (tail)->end_lineno, (tail)->end_col_offset, p->arena +#define EXTRA _start_lineno, _start_col_offset, _end_lineno, _end_col_offset, p->arena PyObject *_PyPegen_new_type_comment(Parser *, const char *); Py_LOCAL_INLINE(PyObject *) @@ -248,13 +281,6 @@ INVALID_VERSION_CHECK(Parser *p, int version, char *msg, void *node) arg_ty _PyPegen_add_type_comment_to_arg(Parser *, arg_ty, Token *); PyObject *_PyPegen_new_identifier(Parser *, const char *); -Parser *_PyPegen_Parser_New(struct tok_state *, int, int, int, int *, PyArena *); -void _PyPegen_Parser_Free(Parser *); -mod_ty _PyPegen_run_parser_from_file_pointer(FILE *, int, PyObject *, const char *, - const char *, const char *, PyCompilerFlags *, int *, PyArena *); -void *_PyPegen_run_parser(Parser *); -mod_ty _PyPegen_run_parser_from_string(const char *, int, PyObject *, PyCompilerFlags *, PyArena *); -asdl_stmt_seq *_PyPegen_interactive_exit(Parser *); asdl_seq *_PyPegen_singleton_seq(Parser *, void *); asdl_seq *_PyPegen_seq_insert_in_front(Parser *, void *, asdl_seq *); asdl_seq *_PyPegen_seq_append_to_end(Parser *, asdl_seq *, void *); @@ -295,40 +321,18 @@ asdl_seq *_PyPegen_join_sequences(Parser *, asdl_seq *, asdl_seq *); int _PyPegen_check_barry_as_flufl(Parser *, Token *); int _PyPegen_check_legacy_stmt(Parser *p, expr_ty t); mod_ty _PyPegen_make_module(Parser *, asdl_stmt_seq *); - -// Error reporting helpers -typedef enum { - STAR_TARGETS, - DEL_TARGETS, - FOR_TARGETS -} TARGETS_TYPE; -expr_ty _PyPegen_get_invalid_target(expr_ty e, TARGETS_TYPE targets_type); -#define RAISE_SYNTAX_ERROR_INVALID_TARGET(type, e) _RAISE_SYNTAX_ERROR_INVALID_TARGET(p, type, e) - -Py_LOCAL_INLINE(void *) -_RAISE_SYNTAX_ERROR_INVALID_TARGET(Parser *p, TARGETS_TYPE type, void *e) -{ - expr_ty invalid_target = CHECK_NULL_ALLOWED(expr_ty, _PyPegen_get_invalid_target(e, type)); - if (invalid_target != NULL) { - const char *msg; - if (type == STAR_TARGETS || type == FOR_TARGETS) { - msg = "cannot assign to %s"; - } - else { - msg = "cannot delete %s"; - } - return RAISE_SYNTAX_ERROR_KNOWN_LOCATION( - invalid_target, - msg, - _PyPegen_get_expr_name(invalid_target) - ); - } - return RAISE_SYNTAX_ERROR("invalid syntax"); -} - void *_PyPegen_arguments_parsing_error(Parser *, expr_ty); void *_PyPegen_nonparen_genexp_in_call(Parser *p, expr_ty args, asdl_comprehension_seq *comprehensions); +// Parser API + +Parser *_PyPegen_Parser_New(struct tok_state *, int, int, int, int *, PyArena *); +void _PyPegen_Parser_Free(Parser *); +mod_ty _PyPegen_run_parser_from_file_pointer(FILE *, int, PyObject *, const char *, + const char *, const char *, PyCompilerFlags *, int *, PyArena *); +void *_PyPegen_run_parser(Parser *); +mod_ty _PyPegen_run_parser_from_string(const char *, int, PyObject *, PyCompilerFlags *, PyArena *); +asdl_stmt_seq *_PyPegen_interactive_exit(Parser *); // Generated function in parse.c - function definition in python.gram void *_PyPegen_parse(Parser *); diff --git a/Parser/pegen_errors.c b/Parser/pegen_errors.c new file mode 100644 index 0000000000000..6eeab0a97226f --- /dev/null +++ b/Parser/pegen_errors.c @@ -0,0 +1,425 @@ +#include +#include + +#include "tokenizer.h" +#include "pegen.h" + +// TOKENIZER ERRORS + +void +_PyPegen_raise_tokenizer_init_error(PyObject *filename) +{ + if (!(PyErr_ExceptionMatches(PyExc_LookupError) + || PyErr_ExceptionMatches(PyExc_SyntaxError) + || PyErr_ExceptionMatches(PyExc_ValueError) + || PyErr_ExceptionMatches(PyExc_UnicodeDecodeError))) { + return; + } + PyObject *errstr = NULL; + PyObject *tuple = NULL; + PyObject *type; + PyObject *value; + PyObject *tback; + PyErr_Fetch(&type, &value, &tback); + errstr = PyObject_Str(value); + if (!errstr) { + goto error; + } + + PyObject *tmp = Py_BuildValue("(OiiO)", filename, 0, -1, Py_None); + if (!tmp) { + goto error; + } + + tuple = PyTuple_Pack(2, errstr, tmp); + Py_DECREF(tmp); + if (!value) { + goto error; + } + PyErr_SetObject(PyExc_SyntaxError, tuple); + +error: + Py_XDECREF(type); + Py_XDECREF(value); + Py_XDECREF(tback); + Py_XDECREF(errstr); + Py_XDECREF(tuple); +} + +static inline void +raise_unclosed_parentheses_error(Parser *p) { + int error_lineno = p->tok->parenlinenostack[p->tok->level-1]; + int error_col = p->tok->parencolstack[p->tok->level-1]; + RAISE_ERROR_KNOWN_LOCATION(p, PyExc_SyntaxError, + error_lineno, error_col, error_lineno, -1, + "'%c' was never closed", + p->tok->parenstack[p->tok->level-1]); +} + +int +_Pypegen_tokenizer_error(Parser *p) +{ + if (PyErr_Occurred()) { + return -1; + } + + const char *msg = NULL; + PyObject* errtype = PyExc_SyntaxError; + Py_ssize_t col_offset = -1; + switch (p->tok->done) { + case E_TOKEN: + msg = "invalid token"; + break; + case E_EOF: + if (p->tok->level) { + raise_unclosed_parentheses_error(p); + } else { + RAISE_SYNTAX_ERROR("unexpected EOF while parsing"); + } + return -1; + case E_DEDENT: + RAISE_INDENTATION_ERROR("unindent does not match any outer indentation level"); + return -1; + case E_INTR: + if (!PyErr_Occurred()) { + PyErr_SetNone(PyExc_KeyboardInterrupt); + } + return -1; + case E_NOMEM: + PyErr_NoMemory(); + return -1; + case E_TABSPACE: + errtype = PyExc_TabError; + msg = "inconsistent use of tabs and spaces in indentation"; + break; + case E_TOODEEP: + errtype = PyExc_IndentationError; + msg = "too many levels of indentation"; + break; + case E_LINECONT: { + col_offset = p->tok->cur - p->tok->buf - 1; + msg = "unexpected character after line continuation character"; + break; + } + default: + msg = "unknown parsing error"; + } + + RAISE_ERROR_KNOWN_LOCATION(p, errtype, p->tok->lineno, + col_offset >= 0 ? col_offset : 0, + p->tok->lineno, -1, msg); + return -1; +} + +int +_Pypegen_raise_decode_error(Parser *p) +{ + assert(PyErr_Occurred()); + const char *errtype = NULL; + if (PyErr_ExceptionMatches(PyExc_UnicodeError)) { + errtype = "unicode error"; + } + else if (PyErr_ExceptionMatches(PyExc_ValueError)) { + errtype = "value error"; + } + if (errtype) { + PyObject *type; + PyObject *value; + PyObject *tback; + PyObject *errstr; + PyErr_Fetch(&type, &value, &tback); + errstr = PyObject_Str(value); + if (errstr) { + RAISE_SYNTAX_ERROR("(%s) %U", errtype, errstr); + Py_DECREF(errstr); + } + else { + PyErr_Clear(); + RAISE_SYNTAX_ERROR("(%s) unknown error", errtype); + } + Py_XDECREF(type); + Py_XDECREF(value); + Py_XDECREF(tback); + } + + return -1; +} + +static int +_PyPegen_tokenize_full_source_to_check_for_errors(Parser *p) { + // Tokenize the whole input to see if there are any tokenization + // errors such as mistmatching parentheses. These will get priority + // over generic syntax errors only if the line number of the error is + // before the one that we had for the generic error. + + // We don't want to tokenize to the end for interactive input + if (p->tok->prompt != NULL) { + return 0; + } + + PyObject *type, *value, *traceback; + PyErr_Fetch(&type, &value, &traceback); + + Token *current_token = p->known_err_token != NULL ? p->known_err_token : p->tokens[p->fill - 1]; + Py_ssize_t current_err_line = current_token->lineno; + + int ret = 0; + + for (;;) { + const char *start; + const char *end; + switch (_PyTokenizer_Get(p->tok, &start, &end)) { + case ERRORTOKEN: + if (p->tok->level != 0) { + int error_lineno = p->tok->parenlinenostack[p->tok->level-1]; + if (current_err_line > error_lineno) { + raise_unclosed_parentheses_error(p); + ret = -1; + goto exit; + } + } + break; + case ENDMARKER: + break; + default: + continue; + } + break; + } + + +exit: + if (PyErr_Occurred()) { + Py_XDECREF(value); + Py_XDECREF(type); + Py_XDECREF(traceback); + } else { + PyErr_Restore(type, value, traceback); + } + return ret; +} + +// PARSER ERRORS + +void * +_PyPegen_raise_error(Parser *p, PyObject *errtype, const char *errmsg, ...) +{ + if (p->fill == 0) { + va_list va; + va_start(va, errmsg); + _PyPegen_raise_error_known_location(p, errtype, 0, 0, 0, -1, errmsg, va); + va_end(va); + return NULL; + } + + Token *t = p->known_err_token != NULL ? p->known_err_token : p->tokens[p->fill - 1]; + Py_ssize_t col_offset; + Py_ssize_t end_col_offset = -1; + if (t->col_offset == -1) { + if (p->tok->cur == p->tok->buf) { + col_offset = 0; + } else { + const char* start = p->tok->buf ? p->tok->line_start : p->tok->buf; + col_offset = Py_SAFE_DOWNCAST(p->tok->cur - start, intptr_t, int); + } + } else { + col_offset = t->col_offset + 1; + } + + if (t->end_col_offset != -1) { + end_col_offset = t->end_col_offset + 1; + } + + va_list va; + va_start(va, errmsg); + _PyPegen_raise_error_known_location(p, errtype, t->lineno, col_offset, t->end_lineno, end_col_offset, errmsg, va); + va_end(va); + + return NULL; +} + +static PyObject * +get_error_line_from_tokenizer_buffers(Parser *p, Py_ssize_t lineno) +{ + /* If the file descriptor is interactive, the source lines of the current + * (multi-line) statement are stored in p->tok->interactive_src_start. + * If not, we're parsing from a string, which means that the whole source + * is stored in p->tok->str. */ + assert(p->tok->fp == NULL || p->tok->fp == stdin); + + char *cur_line = p->tok->fp_interactive ? p->tok->interactive_src_start : p->tok->str; + assert(cur_line != NULL); + + for (int i = 0; i < lineno - 1; i++) { + cur_line = strchr(cur_line, '\n') + 1; + } + + char *next_newline; + if ((next_newline = strchr(cur_line, '\n')) == NULL) { // This is the last line + next_newline = cur_line + strlen(cur_line); + } + return PyUnicode_DecodeUTF8(cur_line, next_newline - cur_line, "replace"); +} + +void * +_PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, + Py_ssize_t lineno, Py_ssize_t col_offset, + Py_ssize_t end_lineno, Py_ssize_t end_col_offset, + const char *errmsg, va_list va) +{ + PyObject *value = NULL; + PyObject *errstr = NULL; + PyObject *error_line = NULL; + PyObject *tmp = NULL; + p->error_indicator = 1; + + if (end_lineno == CURRENT_POS) { + end_lineno = p->tok->lineno; + } + if (end_col_offset == CURRENT_POS) { + end_col_offset = p->tok->cur - p->tok->line_start; + } + + if (p->start_rule == Py_fstring_input) { + const char *fstring_msg = "f-string: "; + Py_ssize_t len = strlen(fstring_msg) + strlen(errmsg); + + char *new_errmsg = PyMem_Malloc(len + 1); // Lengths of both strings plus NULL character + if (!new_errmsg) { + return (void *) PyErr_NoMemory(); + } + + // Copy both strings into new buffer + memcpy(new_errmsg, fstring_msg, strlen(fstring_msg)); + memcpy(new_errmsg + strlen(fstring_msg), errmsg, strlen(errmsg)); + new_errmsg[len] = 0; + errmsg = new_errmsg; + } + errstr = PyUnicode_FromFormatV(errmsg, va); + if (!errstr) { + goto error; + } + + if (p->tok->fp_interactive) { + error_line = get_error_line_from_tokenizer_buffers(p, lineno); + } + else if (p->start_rule == Py_file_input) { + error_line = _PyErr_ProgramDecodedTextObject(p->tok->filename, + (int) lineno, p->tok->encoding); + } + + if (!error_line) { + /* PyErr_ProgramTextObject was not called or returned NULL. If it was not called, + then we need to find the error line from some other source, because + p->start_rule != Py_file_input. If it returned NULL, then it either unexpectedly + failed or we're parsing from a string or the REPL. There's a third edge case where + we're actually parsing from a file, which has an E_EOF SyntaxError and in that case + `PyErr_ProgramTextObject` fails because lineno points to last_file_line + 1, which + does not physically exist */ + assert(p->tok->fp == NULL || p->tok->fp == stdin || p->tok->done == E_EOF); + + if (p->tok->lineno <= lineno && p->tok->inp > p->tok->buf) { + Py_ssize_t size = p->tok->inp - p->tok->buf; + error_line = PyUnicode_DecodeUTF8(p->tok->buf, size, "replace"); + } + else if (p->tok->fp == NULL || p->tok->fp == stdin) { + error_line = get_error_line_from_tokenizer_buffers(p, lineno); + } + else { + error_line = PyUnicode_FromStringAndSize("", 0); + } + if (!error_line) { + goto error; + } + } + + if (p->start_rule == Py_fstring_input) { + col_offset -= p->starting_col_offset; + end_col_offset -= p->starting_col_offset; + } + + Py_ssize_t col_number = col_offset; + Py_ssize_t end_col_number = end_col_offset; + + if (p->tok->encoding != NULL) { + col_number = _PyPegen_byte_offset_to_character_offset(error_line, col_offset); + if (col_number < 0) { + goto error; + } + if (end_col_number > 0) { + Py_ssize_t end_col_offset = _PyPegen_byte_offset_to_character_offset(error_line, end_col_number); + if (end_col_offset < 0) { + goto error; + } else { + end_col_number = end_col_offset; + } + } + } + tmp = Py_BuildValue("(OiiNii)", p->tok->filename, lineno, col_number, error_line, end_lineno, end_col_number); + if (!tmp) { + goto error; + } + value = PyTuple_Pack(2, errstr, tmp); + Py_DECREF(tmp); + if (!value) { + goto error; + } + PyErr_SetObject(errtype, value); + + Py_DECREF(errstr); + Py_DECREF(value); + if (p->start_rule == Py_fstring_input) { + PyMem_Free((void *)errmsg); + } + return NULL; + +error: + Py_XDECREF(errstr); + Py_XDECREF(error_line); + if (p->start_rule == Py_fstring_input) { + PyMem_Free((void *)errmsg); + } + return NULL; +} + +void +_Pypegen_set_syntax_error(Parser* p, Token* last_token) { + // Existing sintax error + if (PyErr_Occurred()) { + // Prioritize tokenizer errors to custom syntax errors raised + // on the second phase only if the errors come from the parser. + if (p->tok->done == E_DONE && PyErr_ExceptionMatches(PyExc_SyntaxError)) { + _PyPegen_tokenize_full_source_to_check_for_errors(p); + } + // Propagate the existing syntax error. + return; + } + // Initialization error + if (p->fill == 0) { + RAISE_SYNTAX_ERROR("error at start before reading any input"); + } + // Parser encountered EOF (End of File) unexpectedtly + if (p->tok->done == E_EOF) { + if (p->tok->level) { + raise_unclosed_parentheses_error(p); + } else { + RAISE_SYNTAX_ERROR("unexpected EOF while parsing"); + } + return; + } + // Indentation error in the tokenizer + if (last_token->type == INDENT || last_token->type == DEDENT) { + RAISE_INDENTATION_ERROR(last_token->type == INDENT ? "unexpected indent" : "unexpected unindent"); + return; + } + // Unknown error (generic case) + + // Use the last token we found on the first pass to avoid reporting + // incorrect locations for generic syntax errors just because we reached + // further away when trying to find specific syntax errors in the second + // pass. + RAISE_SYNTAX_ERROR_KNOWN_LOCATION(last_token, "invalid syntax"); + // _PyPegen_tokenize_full_source_to_check_for_errors will override the existing + // generic SyntaxError we just raised if errors are found. + _PyPegen_tokenize_full_source_to_check_for_errors(p); +} \ No newline at end of file diff --git a/Tools/peg_generator/Makefile b/Tools/peg_generator/Makefile index 6ad9c91b985cb..d010f19d58892 100644 --- a/Tools/peg_generator/Makefile +++ b/Tools/peg_generator/Makefile @@ -22,7 +22,7 @@ data/xxl.py: build: peg_extension/parse.c -peg_extension/parse.c: $(GRAMMAR) $(TOKENS) pegen/*.py peg_extension/peg_extension.c ../../Parser/pegen.c ../../Parser/string_parser.c ../../Parser/*.h pegen/grammar_parser.py +peg_extension/parse.c: $(GRAMMAR) $(TOKENS) pegen/*.py peg_extension/peg_extension.c ../../Parser/pegen.c ../../Parser/pegen_errors.c ../../Parser/string_parser.c ../../Parser/action_helpers.c ../../Parser/*.h pegen/grammar_parser.py $(PYTHON) -m pegen -q c $(GRAMMAR) $(TOKENS) -o peg_extension/parse.c --compile-extension clean: diff --git a/Tools/peg_generator/pegen/build.py b/Tools/peg_generator/pegen/build.py index bf01078ff0b4a..c69e5c9a5f26a 100644 --- a/Tools/peg_generator/pegen/build.py +++ b/Tools/peg_generator/pegen/build.py @@ -69,6 +69,8 @@ def compile_c_extension( str(MOD_DIR.parent.parent.parent / "Python" / "asdl.c"), str(MOD_DIR.parent.parent.parent / "Parser" / "tokenizer.c"), str(MOD_DIR.parent.parent.parent / "Parser" / "pegen.c"), + str(MOD_DIR.parent.parent.parent / "Parser" / "pegen_errors.c"), + str(MOD_DIR.parent.parent.parent / "Parser" / "action_helpers.c"), str(MOD_DIR.parent.parent.parent / "Parser" / "string_parser.c"), str(MOD_DIR.parent / "peg_extension" / "peg_extension.c"), generated_source_path, From webhook-mailer at python.org Sat Nov 20 21:06:26 2021 From: webhook-mailer at python.org (pablogsal) Date: Sun, 21 Nov 2021 02:06:26 -0000 Subject: [Python-checkins] Reactivate primary mechanism to retrieve frames in the gdb helpers (GH-29682) Message-ID: https://github.com/python/cpython/commit/4cf65240ae3fbd0e85d8b1e1a9e35f4065843c8c commit: 4cf65240ae3fbd0e85d8b1e1a9e35f4065843c8c branch: main author: Pablo Galindo Salgado committer: pablogsal date: 2021-11-21T02:06:16Z summary: Reactivate primary mechanism to retrieve frames in the gdb helpers (GH-29682) files: M Tools/gdb/libpython.py diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py index 71c99b516b34f..a105e58b4af90 100755 --- a/Tools/gdb/libpython.py +++ b/Tools/gdb/libpython.py @@ -1797,10 +1797,10 @@ def is_gc_collect(self): def get_pyop(self): try: - # frame = self._gdbframe.read_var('frame') - # frame = PyFramePtr(frame) - # if not frame.is_optimized_out(): - # return frame + frame = self._gdbframe.read_var('frame') + frame = PyFramePtr(frame) + if not frame.is_optimized_out(): + return frame cframe = self._gdbframe.read_var('cframe') if cframe is None: return None @@ -1865,6 +1865,7 @@ def print_summary(self): break else: sys.stdout.write('#%i (unable to read python frame information)\n' % self.get_index()) + break interp_frame = interp_frame.previous() else: info = self.is_other_python_frame() @@ -1887,6 +1888,7 @@ def print_traceback(self): break else: sys.stdout.write(' (unable to read python frame information)\n') + break interp_frame = interp_frame.previous() else: info = self.is_other_python_frame() From webhook-mailer at python.org Sat Nov 20 21:06:44 2021 From: webhook-mailer at python.org (pablogsal) Date: Sun, 21 Nov 2021 02:06:44 -0000 Subject: [Python-checkins] Ensure the str member of the tokenizer is always initialised (GH-29681) Message-ID: https://github.com/python/cpython/commit/4f006a789a35f5d1a7ef142bd1304ce167392457 commit: 4f006a789a35f5d1a7ef142bd1304ce167392457 branch: main author: Pablo Galindo Salgado committer: pablogsal date: 2021-11-21T02:06:39Z summary: Ensure the str member of the tokenizer is always initialised (GH-29681) files: M Parser/pegen_errors.c M Parser/tokenizer.c M Parser/tokenizer.h diff --git a/Parser/pegen_errors.c b/Parser/pegen_errors.c index 6eeab0a97226f..694184a03b075 100644 --- a/Parser/pegen_errors.c +++ b/Parser/pegen_errors.c @@ -245,7 +245,7 @@ get_error_line_from_tokenizer_buffers(Parser *p, Py_ssize_t lineno) * (multi-line) statement are stored in p->tok->interactive_src_start. * If not, we're parsing from a string, which means that the whole source * is stored in p->tok->str. */ - assert(p->tok->fp == NULL || p->tok->fp == stdin); + assert((p->tok->fp == NULL && p->tok->str != NULL) || p->tok->fp == stdin); char *cur_line = p->tok->fp_interactive ? p->tok->interactive_src_start : p->tok->str; assert(cur_line != NULL); diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index 69d2c08b43926..6358cdf654e18 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -87,7 +87,7 @@ tok_new(void) tok->async_def_indent = 0; tok->async_def_nl = 0; tok->interactive_underflow = IUNDERFLOW_NORMAL; - + tok->str = NULL; return tok; } diff --git a/Parser/tokenizer.h b/Parser/tokenizer.h index 1d1cfd639d9d5..0cb665104b2b8 100644 --- a/Parser/tokenizer.h +++ b/Parser/tokenizer.h @@ -71,7 +71,7 @@ struct tok_state { PyObject *decoding_readline; /* open(...).readline */ PyObject *decoding_buffer; const char* enc; /* Encoding for the current str. */ - char* str; + char* str; /* Source string being tokenized (if tokenizing from a string)*/ char* input; /* Tokenizer's newline translated copy of the string. */ int type_comments; /* Whether to look for type comments */ From webhook-mailer at python.org Sat Nov 20 23:15:26 2021 From: webhook-mailer at python.org (pablogsal) Date: Sun, 21 Nov 2021 04:15:26 -0000 Subject: [Python-checkins] [3.10] Ensure the str member of the tokenizer is always initialised (GH-29681). (GH-29683) Message-ID: https://github.com/python/cpython/commit/07cf66fd03e161c09279346da4e76705cf42d535 commit: 07cf66fd03e161c09279346da4e76705cf42d535 branch: 3.10 author: Pablo Galindo Salgado committer: pablogsal date: 2021-11-21T04:15:22Z summary: [3.10] Ensure the str member of the tokenizer is always initialised (GH-29681). (GH-29683) (cherry picked from commit 4f006a789a35f5d1a7ef142bd1304ce167392457) Co-authored-by: Pablo Galindo Salgado files: A Parser/pegen_errors.c M Parser/pegen.c M Parser/tokenizer.c M Parser/tokenizer.h diff --git a/Parser/pegen.c b/Parser/pegen.c index 464a902173dfb..8946aa33145b8 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -432,7 +432,7 @@ get_error_line(Parser *p, Py_ssize_t lineno) * (multi-line) statement are stored in p->tok->interactive_src_start. * If not, we're parsing from a string, which means that the whole source * is stored in p->tok->str. */ - assert(p->tok->fp == NULL || p->tok->fp == stdin); + assert((p->tok->fp == NULL && p->tok->str != NULL) || p->tok->fp == stdin); char *cur_line = p->tok->fp_interactive ? p->tok->interactive_src_start : p->tok->str; assert(cur_line != NULL); diff --git a/Parser/pegen_errors.c b/Parser/pegen_errors.c new file mode 100644 index 0000000000000..694184a03b075 --- /dev/null +++ b/Parser/pegen_errors.c @@ -0,0 +1,425 @@ +#include +#include + +#include "tokenizer.h" +#include "pegen.h" + +// TOKENIZER ERRORS + +void +_PyPegen_raise_tokenizer_init_error(PyObject *filename) +{ + if (!(PyErr_ExceptionMatches(PyExc_LookupError) + || PyErr_ExceptionMatches(PyExc_SyntaxError) + || PyErr_ExceptionMatches(PyExc_ValueError) + || PyErr_ExceptionMatches(PyExc_UnicodeDecodeError))) { + return; + } + PyObject *errstr = NULL; + PyObject *tuple = NULL; + PyObject *type; + PyObject *value; + PyObject *tback; + PyErr_Fetch(&type, &value, &tback); + errstr = PyObject_Str(value); + if (!errstr) { + goto error; + } + + PyObject *tmp = Py_BuildValue("(OiiO)", filename, 0, -1, Py_None); + if (!tmp) { + goto error; + } + + tuple = PyTuple_Pack(2, errstr, tmp); + Py_DECREF(tmp); + if (!value) { + goto error; + } + PyErr_SetObject(PyExc_SyntaxError, tuple); + +error: + Py_XDECREF(type); + Py_XDECREF(value); + Py_XDECREF(tback); + Py_XDECREF(errstr); + Py_XDECREF(tuple); +} + +static inline void +raise_unclosed_parentheses_error(Parser *p) { + int error_lineno = p->tok->parenlinenostack[p->tok->level-1]; + int error_col = p->tok->parencolstack[p->tok->level-1]; + RAISE_ERROR_KNOWN_LOCATION(p, PyExc_SyntaxError, + error_lineno, error_col, error_lineno, -1, + "'%c' was never closed", + p->tok->parenstack[p->tok->level-1]); +} + +int +_Pypegen_tokenizer_error(Parser *p) +{ + if (PyErr_Occurred()) { + return -1; + } + + const char *msg = NULL; + PyObject* errtype = PyExc_SyntaxError; + Py_ssize_t col_offset = -1; + switch (p->tok->done) { + case E_TOKEN: + msg = "invalid token"; + break; + case E_EOF: + if (p->tok->level) { + raise_unclosed_parentheses_error(p); + } else { + RAISE_SYNTAX_ERROR("unexpected EOF while parsing"); + } + return -1; + case E_DEDENT: + RAISE_INDENTATION_ERROR("unindent does not match any outer indentation level"); + return -1; + case E_INTR: + if (!PyErr_Occurred()) { + PyErr_SetNone(PyExc_KeyboardInterrupt); + } + return -1; + case E_NOMEM: + PyErr_NoMemory(); + return -1; + case E_TABSPACE: + errtype = PyExc_TabError; + msg = "inconsistent use of tabs and spaces in indentation"; + break; + case E_TOODEEP: + errtype = PyExc_IndentationError; + msg = "too many levels of indentation"; + break; + case E_LINECONT: { + col_offset = p->tok->cur - p->tok->buf - 1; + msg = "unexpected character after line continuation character"; + break; + } + default: + msg = "unknown parsing error"; + } + + RAISE_ERROR_KNOWN_LOCATION(p, errtype, p->tok->lineno, + col_offset >= 0 ? col_offset : 0, + p->tok->lineno, -1, msg); + return -1; +} + +int +_Pypegen_raise_decode_error(Parser *p) +{ + assert(PyErr_Occurred()); + const char *errtype = NULL; + if (PyErr_ExceptionMatches(PyExc_UnicodeError)) { + errtype = "unicode error"; + } + else if (PyErr_ExceptionMatches(PyExc_ValueError)) { + errtype = "value error"; + } + if (errtype) { + PyObject *type; + PyObject *value; + PyObject *tback; + PyObject *errstr; + PyErr_Fetch(&type, &value, &tback); + errstr = PyObject_Str(value); + if (errstr) { + RAISE_SYNTAX_ERROR("(%s) %U", errtype, errstr); + Py_DECREF(errstr); + } + else { + PyErr_Clear(); + RAISE_SYNTAX_ERROR("(%s) unknown error", errtype); + } + Py_XDECREF(type); + Py_XDECREF(value); + Py_XDECREF(tback); + } + + return -1; +} + +static int +_PyPegen_tokenize_full_source_to_check_for_errors(Parser *p) { + // Tokenize the whole input to see if there are any tokenization + // errors such as mistmatching parentheses. These will get priority + // over generic syntax errors only if the line number of the error is + // before the one that we had for the generic error. + + // We don't want to tokenize to the end for interactive input + if (p->tok->prompt != NULL) { + return 0; + } + + PyObject *type, *value, *traceback; + PyErr_Fetch(&type, &value, &traceback); + + Token *current_token = p->known_err_token != NULL ? p->known_err_token : p->tokens[p->fill - 1]; + Py_ssize_t current_err_line = current_token->lineno; + + int ret = 0; + + for (;;) { + const char *start; + const char *end; + switch (_PyTokenizer_Get(p->tok, &start, &end)) { + case ERRORTOKEN: + if (p->tok->level != 0) { + int error_lineno = p->tok->parenlinenostack[p->tok->level-1]; + if (current_err_line > error_lineno) { + raise_unclosed_parentheses_error(p); + ret = -1; + goto exit; + } + } + break; + case ENDMARKER: + break; + default: + continue; + } + break; + } + + +exit: + if (PyErr_Occurred()) { + Py_XDECREF(value); + Py_XDECREF(type); + Py_XDECREF(traceback); + } else { + PyErr_Restore(type, value, traceback); + } + return ret; +} + +// PARSER ERRORS + +void * +_PyPegen_raise_error(Parser *p, PyObject *errtype, const char *errmsg, ...) +{ + if (p->fill == 0) { + va_list va; + va_start(va, errmsg); + _PyPegen_raise_error_known_location(p, errtype, 0, 0, 0, -1, errmsg, va); + va_end(va); + return NULL; + } + + Token *t = p->known_err_token != NULL ? p->known_err_token : p->tokens[p->fill - 1]; + Py_ssize_t col_offset; + Py_ssize_t end_col_offset = -1; + if (t->col_offset == -1) { + if (p->tok->cur == p->tok->buf) { + col_offset = 0; + } else { + const char* start = p->tok->buf ? p->tok->line_start : p->tok->buf; + col_offset = Py_SAFE_DOWNCAST(p->tok->cur - start, intptr_t, int); + } + } else { + col_offset = t->col_offset + 1; + } + + if (t->end_col_offset != -1) { + end_col_offset = t->end_col_offset + 1; + } + + va_list va; + va_start(va, errmsg); + _PyPegen_raise_error_known_location(p, errtype, t->lineno, col_offset, t->end_lineno, end_col_offset, errmsg, va); + va_end(va); + + return NULL; +} + +static PyObject * +get_error_line_from_tokenizer_buffers(Parser *p, Py_ssize_t lineno) +{ + /* If the file descriptor is interactive, the source lines of the current + * (multi-line) statement are stored in p->tok->interactive_src_start. + * If not, we're parsing from a string, which means that the whole source + * is stored in p->tok->str. */ + assert((p->tok->fp == NULL && p->tok->str != NULL) || p->tok->fp == stdin); + + char *cur_line = p->tok->fp_interactive ? p->tok->interactive_src_start : p->tok->str; + assert(cur_line != NULL); + + for (int i = 0; i < lineno - 1; i++) { + cur_line = strchr(cur_line, '\n') + 1; + } + + char *next_newline; + if ((next_newline = strchr(cur_line, '\n')) == NULL) { // This is the last line + next_newline = cur_line + strlen(cur_line); + } + return PyUnicode_DecodeUTF8(cur_line, next_newline - cur_line, "replace"); +} + +void * +_PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, + Py_ssize_t lineno, Py_ssize_t col_offset, + Py_ssize_t end_lineno, Py_ssize_t end_col_offset, + const char *errmsg, va_list va) +{ + PyObject *value = NULL; + PyObject *errstr = NULL; + PyObject *error_line = NULL; + PyObject *tmp = NULL; + p->error_indicator = 1; + + if (end_lineno == CURRENT_POS) { + end_lineno = p->tok->lineno; + } + if (end_col_offset == CURRENT_POS) { + end_col_offset = p->tok->cur - p->tok->line_start; + } + + if (p->start_rule == Py_fstring_input) { + const char *fstring_msg = "f-string: "; + Py_ssize_t len = strlen(fstring_msg) + strlen(errmsg); + + char *new_errmsg = PyMem_Malloc(len + 1); // Lengths of both strings plus NULL character + if (!new_errmsg) { + return (void *) PyErr_NoMemory(); + } + + // Copy both strings into new buffer + memcpy(new_errmsg, fstring_msg, strlen(fstring_msg)); + memcpy(new_errmsg + strlen(fstring_msg), errmsg, strlen(errmsg)); + new_errmsg[len] = 0; + errmsg = new_errmsg; + } + errstr = PyUnicode_FromFormatV(errmsg, va); + if (!errstr) { + goto error; + } + + if (p->tok->fp_interactive) { + error_line = get_error_line_from_tokenizer_buffers(p, lineno); + } + else if (p->start_rule == Py_file_input) { + error_line = _PyErr_ProgramDecodedTextObject(p->tok->filename, + (int) lineno, p->tok->encoding); + } + + if (!error_line) { + /* PyErr_ProgramTextObject was not called or returned NULL. If it was not called, + then we need to find the error line from some other source, because + p->start_rule != Py_file_input. If it returned NULL, then it either unexpectedly + failed or we're parsing from a string or the REPL. There's a third edge case where + we're actually parsing from a file, which has an E_EOF SyntaxError and in that case + `PyErr_ProgramTextObject` fails because lineno points to last_file_line + 1, which + does not physically exist */ + assert(p->tok->fp == NULL || p->tok->fp == stdin || p->tok->done == E_EOF); + + if (p->tok->lineno <= lineno && p->tok->inp > p->tok->buf) { + Py_ssize_t size = p->tok->inp - p->tok->buf; + error_line = PyUnicode_DecodeUTF8(p->tok->buf, size, "replace"); + } + else if (p->tok->fp == NULL || p->tok->fp == stdin) { + error_line = get_error_line_from_tokenizer_buffers(p, lineno); + } + else { + error_line = PyUnicode_FromStringAndSize("", 0); + } + if (!error_line) { + goto error; + } + } + + if (p->start_rule == Py_fstring_input) { + col_offset -= p->starting_col_offset; + end_col_offset -= p->starting_col_offset; + } + + Py_ssize_t col_number = col_offset; + Py_ssize_t end_col_number = end_col_offset; + + if (p->tok->encoding != NULL) { + col_number = _PyPegen_byte_offset_to_character_offset(error_line, col_offset); + if (col_number < 0) { + goto error; + } + if (end_col_number > 0) { + Py_ssize_t end_col_offset = _PyPegen_byte_offset_to_character_offset(error_line, end_col_number); + if (end_col_offset < 0) { + goto error; + } else { + end_col_number = end_col_offset; + } + } + } + tmp = Py_BuildValue("(OiiNii)", p->tok->filename, lineno, col_number, error_line, end_lineno, end_col_number); + if (!tmp) { + goto error; + } + value = PyTuple_Pack(2, errstr, tmp); + Py_DECREF(tmp); + if (!value) { + goto error; + } + PyErr_SetObject(errtype, value); + + Py_DECREF(errstr); + Py_DECREF(value); + if (p->start_rule == Py_fstring_input) { + PyMem_Free((void *)errmsg); + } + return NULL; + +error: + Py_XDECREF(errstr); + Py_XDECREF(error_line); + if (p->start_rule == Py_fstring_input) { + PyMem_Free((void *)errmsg); + } + return NULL; +} + +void +_Pypegen_set_syntax_error(Parser* p, Token* last_token) { + // Existing sintax error + if (PyErr_Occurred()) { + // Prioritize tokenizer errors to custom syntax errors raised + // on the second phase only if the errors come from the parser. + if (p->tok->done == E_DONE && PyErr_ExceptionMatches(PyExc_SyntaxError)) { + _PyPegen_tokenize_full_source_to_check_for_errors(p); + } + // Propagate the existing syntax error. + return; + } + // Initialization error + if (p->fill == 0) { + RAISE_SYNTAX_ERROR("error at start before reading any input"); + } + // Parser encountered EOF (End of File) unexpectedtly + if (p->tok->done == E_EOF) { + if (p->tok->level) { + raise_unclosed_parentheses_error(p); + } else { + RAISE_SYNTAX_ERROR("unexpected EOF while parsing"); + } + return; + } + // Indentation error in the tokenizer + if (last_token->type == INDENT || last_token->type == DEDENT) { + RAISE_INDENTATION_ERROR(last_token->type == INDENT ? "unexpected indent" : "unexpected unindent"); + return; + } + // Unknown error (generic case) + + // Use the last token we found on the first pass to avoid reporting + // incorrect locations for generic syntax errors just because we reached + // further away when trying to find specific syntax errors in the second + // pass. + RAISE_SYNTAX_ERROR_KNOWN_LOCATION(last_token, "invalid syntax"); + // _PyPegen_tokenize_full_source_to_check_for_errors will override the existing + // generic SyntaxError we just raised if errors are found. + _PyPegen_tokenize_full_source_to_check_for_errors(p); +} \ No newline at end of file diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index 76a22dab65994..672fdb92ec86f 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -86,7 +86,7 @@ tok_new(void) tok->async_def_indent = 0; tok->async_def_nl = 0; tok->interactive_underflow = IUNDERFLOW_NORMAL; - + tok->str = NULL; return tok; } diff --git a/Parser/tokenizer.h b/Parser/tokenizer.h index 677f9dba490be..61f0a6138f676 100644 --- a/Parser/tokenizer.h +++ b/Parser/tokenizer.h @@ -71,7 +71,7 @@ struct tok_state { PyObject *decoding_readline; /* open(...).readline */ PyObject *decoding_buffer; const char* enc; /* Encoding for the current str. */ - char* str; + char* str; /* Source string being tokenized (if tokenizing from a string)*/ char* input; /* Tokenizer's newline translated copy of the string. */ int type_comments; /* Whether to look for type comments */ From webhook-mailer at python.org Sun Nov 21 04:45:36 2021 From: webhook-mailer at python.org (tiran) Date: Sun, 21 Nov 2021 09:45:36 -0000 Subject: [Python-checkins] bpo-45847: Port grp, spwd, termios, resource, syslog to PY_STDLIB_MOD (GH-29668) Message-ID: https://github.com/python/cpython/commit/f201d261cf53365b5769a434ca2bb21a892bd23f commit: f201d261cf53365b5769a434ca2bb21a892bd23f branch: main author: Christian Heimes committer: tiran date: 2021-11-21T10:45:31+01:00 summary: bpo-45847: Port grp, spwd, termios, resource, syslog to PY_STDLIB_MOD (GH-29668) files: M Modules/Setup.stdlib.in M configure M configure.ac M pyconfig.h.in M setup.py diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index fa553fb524f56..495cfb47ac231 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -61,8 +61,14 @@ # Modules with some UNIX dependencies # -# Linux and FreeBSD, needs sys/soundcard.h or linux/soundcard.h + at MODULE_GRP_TRUE@grp grpmodule.c +# needs sys/soundcard.h or linux/soundcard.h (Linux, FreeBSD) @MODULE_OSSAUDIODEV_TRUE at ossaudiodev ossaudiodev.c + at MODULE_RESOURCE_TRUE@resource resource.c +# AIX has shadow passwords, but does not provide getspent API + at MODULE_SPWD_TRUE@spwd spwdmodule.c + at MODULE_SYSLOG_TRUE@syslog syslogmodule.c + at MODULE_TERMIOS_TRUE@termios termios.c ############################################################################ diff --git a/configure b/configure index 7d2ef8f912073..45c6eb4b845ab 100755 --- a/configure +++ b/configure @@ -658,10 +658,20 @@ MODULE__ELEMENTTREE_FALSE MODULE__ELEMENTTREE_TRUE MODULE_PYEXPAT_FALSE MODULE_PYEXPAT_TRUE +MODULE_TERMIOS_FALSE +MODULE_TERMIOS_TRUE +MODULE_SYSLOG_FALSE +MODULE_SYSLOG_TRUE +MODULE_SPWD_FALSE +MODULE_SPWD_TRUE MODULE__SCPROXY_FALSE MODULE__SCPROXY_TRUE +MODULE_RESOURCE_FALSE +MODULE_RESOURCE_TRUE MODULE_OSSAUDIODEV_FALSE MODULE_OSSAUDIODEV_TRUE +MODULE_GRP_FALSE +MODULE_GRP_TRUE MODULE__DATETIME_FALSE MODULE__DATETIME_TRUE MODULE_TIME_FALSE @@ -8196,7 +8206,7 @@ sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h \ libutil.h sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \ linux/tipc.h linux/random.h spawn.h util.h alloca.h endian.h \ sys/endian.h sys/sysmacros.h linux/memfd.h linux/wait.h sys/memfd.h \ -sys/mman.h sys/eventfd.h linux/soundcard.h sys/soundcard.h +sys/mman.h sys/eventfd.h linux/soundcard.h sys/soundcard.h syslog.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" @@ -12658,7 +12668,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \ explicit_memset faccessat fchmod fchmodat fchown fchownat \ fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \ futimens futimes gai_strerror getentropy \ - getgrgid_r getgrnam_r \ + getgrgid getgrgid_r getgrnam_r \ getgrouplist getgroups getlogin getloadavg getpeername getpgid getpid \ getpriority getresuid getresgid getpwent getpwnam_r getpwuid_r getspnam getspent getsid getwd \ if_nameindex \ @@ -19551,6 +19561,45 @@ fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module grp" >&5 +$as_echo_n "checking for stdlib extension module grp... " >&6; } + case $py_stdlib_not_available in #( + *grp*) : + py_cv_module_grp=n/a ;; #( + *) : + + if true; then : + if test "$ac_cv_func_getgrgid" = yes -o "$ac_cv_func_getgrgid_r" = yes; then : + py_cv_module_grp=yes +else + py_cv_module_grp=missing +fi +else + py_cv_module_grp=disabled + +fi + + ;; +esac + as_fn_append MODULE_BLOCK "MODULE_GRP=$py_cv_module_grp$as_nl" + if test "x$py_cv_module_grp" = xyes; then : + + + + +fi + if test "$py_cv_module_grp" = yes; then + MODULE_GRP_TRUE= + MODULE_GRP_FALSE='#' +else + MODULE_GRP_TRUE='#' + MODULE_GRP_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module_grp" >&5 +$as_echo "$py_cv_module_grp" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module ossaudiodev" >&5 $as_echo_n "checking for stdlib extension module ossaudiodev... " >&6; } case $py_stdlib_not_available in #( @@ -19590,6 +19639,45 @@ fi $as_echo "$py_cv_module_ossaudiodev" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module resource" >&5 +$as_echo_n "checking for stdlib extension module resource... " >&6; } + case $py_stdlib_not_available in #( + *resource*) : + py_cv_module_resource=n/a ;; #( + *) : + + if true; then : + if test "$ac_cv_header_sys_resource_h" = yes; then : + py_cv_module_resource=yes +else + py_cv_module_resource=missing +fi +else + py_cv_module_resource=disabled + +fi + + ;; +esac + as_fn_append MODULE_BLOCK "MODULE_RESOURCE=$py_cv_module_resource$as_nl" + if test "x$py_cv_module_resource" = xyes; then : + + + + +fi + if test "$py_cv_module_resource" = yes; then + MODULE_RESOURCE_TRUE= + MODULE_RESOURCE_FALSE='#' +else + MODULE_RESOURCE_TRUE='#' + MODULE_RESOURCE_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module_resource" >&5 +$as_echo "$py_cv_module_resource" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _scproxy" >&5 $as_echo_n "checking for stdlib extension module _scproxy... " >&6; } case $py_stdlib_not_available in #( @@ -19629,6 +19717,123 @@ fi $as_echo "$py_cv_module__scproxy" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module spwd" >&5 +$as_echo_n "checking for stdlib extension module spwd... " >&6; } + case $py_stdlib_not_available in #( + *spwd*) : + py_cv_module_spwd=n/a ;; #( + *) : + + if true; then : + if test "$ac_cv_func_getspent" = yes -o "$ac_cv_func_getspnam" = yes; then : + py_cv_module_spwd=yes +else + py_cv_module_spwd=missing +fi +else + py_cv_module_spwd=disabled + +fi + + ;; +esac + as_fn_append MODULE_BLOCK "MODULE_SPWD=$py_cv_module_spwd$as_nl" + if test "x$py_cv_module_spwd" = xyes; then : + + + + +fi + if test "$py_cv_module_spwd" = yes; then + MODULE_SPWD_TRUE= + MODULE_SPWD_FALSE='#' +else + MODULE_SPWD_TRUE='#' + MODULE_SPWD_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module_spwd" >&5 +$as_echo "$py_cv_module_spwd" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module syslog" >&5 +$as_echo_n "checking for stdlib extension module syslog... " >&6; } + case $py_stdlib_not_available in #( + *syslog*) : + py_cv_module_syslog=n/a ;; #( + *) : + + if true; then : + if test "$ac_cv_header_syslog_h" = yes; then : + py_cv_module_syslog=yes +else + py_cv_module_syslog=missing +fi +else + py_cv_module_syslog=disabled + +fi + + ;; +esac + as_fn_append MODULE_BLOCK "MODULE_SYSLOG=$py_cv_module_syslog$as_nl" + if test "x$py_cv_module_syslog" = xyes; then : + + + + +fi + if test "$py_cv_module_syslog" = yes; then + MODULE_SYSLOG_TRUE= + MODULE_SYSLOG_FALSE='#' +else + MODULE_SYSLOG_TRUE='#' + MODULE_SYSLOG_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module_syslog" >&5 +$as_echo "$py_cv_module_syslog" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module termios" >&5 +$as_echo_n "checking for stdlib extension module termios... " >&6; } + case $py_stdlib_not_available in #( + *termios*) : + py_cv_module_termios=n/a ;; #( + *) : + + if true; then : + if test "$ac_cv_header_termios_h" = yes; then : + py_cv_module_termios=yes +else + py_cv_module_termios=missing +fi +else + py_cv_module_termios=disabled + +fi + + ;; +esac + as_fn_append MODULE_BLOCK "MODULE_TERMIOS=$py_cv_module_termios$as_nl" + if test "x$py_cv_module_termios" = xyes; then : + + + + +fi + if test "$py_cv_module_termios" = yes; then + MODULE_TERMIOS_TRUE= + MODULE_TERMIOS_FALSE='#' +else + MODULE_TERMIOS_TRUE='#' + MODULE_TERMIOS_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module_termios" >&5 +$as_echo "$py_cv_module_termios" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module pyexpat" >&5 $as_echo_n "checking for stdlib extension module pyexpat... " >&6; } @@ -20428,14 +20633,34 @@ if test -z "${MODULE__DATETIME_TRUE}" && test -z "${MODULE__DATETIME_FALSE}"; th as_fn_error $? "conditional \"MODULE__DATETIME\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE_GRP_TRUE}" && test -z "${MODULE_GRP_FALSE}"; then + as_fn_error $? "conditional \"MODULE_GRP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE_OSSAUDIODEV_TRUE}" && test -z "${MODULE_OSSAUDIODEV_FALSE}"; then as_fn_error $? "conditional \"MODULE_OSSAUDIODEV\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE_RESOURCE_TRUE}" && test -z "${MODULE_RESOURCE_FALSE}"; then + as_fn_error $? "conditional \"MODULE_RESOURCE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__SCPROXY_TRUE}" && test -z "${MODULE__SCPROXY_FALSE}"; then as_fn_error $? "conditional \"MODULE__SCPROXY\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE_SPWD_TRUE}" && test -z "${MODULE_SPWD_FALSE}"; then + as_fn_error $? "conditional \"MODULE_SPWD\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE_SYSLOG_TRUE}" && test -z "${MODULE_SYSLOG_FALSE}"; then + as_fn_error $? "conditional \"MODULE_SYSLOG\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE_TERMIOS_TRUE}" && test -z "${MODULE_TERMIOS_FALSE}"; then + as_fn_error $? "conditional \"MODULE_TERMIOS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE_PYEXPAT_TRUE}" && test -z "${MODULE_PYEXPAT_FALSE}"; then as_fn_error $? "conditional \"MODULE_PYEXPAT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index 6c24a278595a6..3d6233f31d9cb 100644 --- a/configure.ac +++ b/configure.ac @@ -2162,7 +2162,7 @@ sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h \ libutil.h sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \ linux/tipc.h linux/random.h spawn.h util.h alloca.h endian.h \ sys/endian.h sys/sysmacros.h linux/memfd.h linux/wait.h sys/memfd.h \ -sys/mman.h sys/eventfd.h linux/soundcard.h sys/soundcard.h) +sys/mman.h sys/eventfd.h linux/soundcard.h sys/soundcard.h syslog.h) AC_HEADER_DIRENT AC_HEADER_MAJOR @@ -3854,7 +3854,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \ explicit_memset faccessat fchmod fchmodat fchown fchownat \ fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \ futimens futimes gai_strerror getentropy \ - getgrgid_r getgrnam_r \ + getgrgid getgrgid_r getgrnam_r \ getgrouplist getgroups getlogin getloadavg getpeername getpgid getpid \ getpriority getresuid getresgid getpwent getpwnam_r getpwuid_r getspnam getspent getsid getwd \ if_nameindex \ @@ -6060,11 +6060,16 @@ dnl always enabled extension modules PY_STDLIB_MOD_SIMPLE([_datetime], [], [$TIMEMODULE_LIB $LIBM]) dnl platform specific extensions +PY_STDLIB_MOD([grp], [], [test "$ac_cv_func_getgrgid" = yes -o "$ac_cv_func_getgrgid_r" = yes]) PY_STDLIB_MOD([ossaudiodev], [], [test "$ac_cv_header_linux_soundcard_h" = yes -o "$ac_cv_header_sys_soundcard_h" = yes]) +PY_STDLIB_MOD([resource], [], [test "$ac_cv_header_sys_resource_h" = yes]) PY_STDLIB_MOD([_scproxy], [test "$ac_sys_system" = "Darwin"], [], [], [-framework SystemConfiguration -framework CoreFoundation]) +PY_STDLIB_MOD([spwd], [], [test "$ac_cv_func_getspent" = yes -o "$ac_cv_func_getspnam" = yes]) +PY_STDLIB_MOD([syslog], [], [test "$ac_cv_header_syslog_h" = yes]) +PY_STDLIB_MOD([termios], [], [test "$ac_cv_header_termios_h" = yes]) dnl _elementtree loads libexpat via CAPI hook in pyexpat PY_STDLIB_MOD([pyexpat], [], [], [$LIBEXPAT_CFLAGS], [$LIBEXPAT_LDFLAGS]) diff --git a/pyconfig.h.in b/pyconfig.h.in index b8f63955e3139..afd3ebe35bc0d 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -441,6 +441,9 @@ /* Define to 1 if you have the `getentropy' function. */ #undef HAVE_GETENTROPY +/* Define to 1 if you have the `getgrgid' function. */ +#undef HAVE_GETGRGID + /* Define to 1 if you have the `getgrgid_r' function. */ #undef HAVE_GETGRGID_R @@ -1143,6 +1146,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYSEXITS_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYSLOG_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_AUDIOIO_H diff --git a/setup.py b/setup.py index d01cc4f7169ec..9ff5969c29613 100644 --- a/setup.py +++ b/setup.py @@ -1046,16 +1046,8 @@ def detect_simple_extensions(self): self.add(Extension('fcntl', ['fcntlmodule.c'], libraries=libs)) # grp(3) - if not VXWORKS: - self.add(Extension('grp', ['grpmodule.c'])) - # spwd, shadow passwords - if (self.config_h_vars.get('HAVE_GETSPNAM', False) or - self.config_h_vars.get('HAVE_GETSPENT', False)): - self.add(Extension('spwd', ['spwdmodule.c'])) - # AIX has shadow passwords, but access is not via getspent(), etc. - # module support is not expected so it not 'missing' - elif not AIX: - self.missing.append('spwd') + self.addext(Extension('grp', ['grpmodule.c'])) + self.addext(Extension('spwd', ['spwdmodule.c'])) # select(2); not on ancient System V self.add(Extension('select', ['selectmodule.c'])) @@ -1065,7 +1057,7 @@ def detect_simple_extensions(self): # Lance Ellinghaus's syslog module # syslog daemon interface - self.add(Extension('syslog', ['syslogmodule.c'])) + self.addext(Extension('syslog', ['syslogmodule.c'])) # Python interface to subinterpreter C-API. self.add(Extension('_xxsubinterpreters', ['_xxsubinterpretersmodule.c'])) @@ -1375,15 +1367,10 @@ def detect_sqlite(self): def detect_platform_specific_exts(self): # Unix-only modules - if not MS_WINDOWS: - if not VXWORKS: - # Steen Lumholt's termios module - self.add(Extension('termios', ['termios.c'])) - # Jeremy Hylton's rlimit interface - self.add(Extension('resource', ['resource.c'])) - else: - self.missing.extend(['resource', 'termios']) - + # Steen Lumholt's termios module + self.addext(Extension('termios', ['termios.c'])) + # Jeremy Hylton's rlimit interface + self.addext(Extension('resource', ['resource.c'])) # linux/soundcard.h or sys/soundcard.h self.addext(Extension('ossaudiodev', ['ossaudiodev.c'])) From webhook-mailer at python.org Sun Nov 21 08:08:56 2021 From: webhook-mailer at python.org (tiran) Date: Sun, 21 Nov 2021 13:08:56 -0000 Subject: [Python-checkins] bpo-45847: Port codecs and unicodedata to PY_STDLIB_MOD (GH-29685) Message-ID: https://github.com/python/cpython/commit/2afa1a12669e1812a9fe8130c8f60052c4ad8bf8 commit: 2afa1a12669e1812a9fe8130c8f60052c4ad8bf8 branch: main author: Christian Heimes committer: tiran date: 2021-11-21T14:08:47+01:00 summary: bpo-45847: Port codecs and unicodedata to PY_STDLIB_MOD (GH-29685) files: M Modules/Setup.stdlib.in M configure M configure.ac M setup.py diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 495cfb47ac231..42755c952f972 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -56,6 +56,14 @@ # _elementtree libexpat via CAPI hook in pyexpat. @MODULE__ELEMENTTREE_TRUE at _elementtree _elementtree.c + at MODULE__CODECS_CN_TRUE@_codecs_cn cjkcodecs/_codecs_cn.c + at MODULE__CODECS_HK_TRUE@_codecs_hk cjkcodecs/_codecs_hk.c + at MODULE__CODECS_ISO2022_TRUE@_codecs_iso2022 cjkcodecs/_codecs_iso2022.c + at MODULE__CODECS_JP_TRUE@_codecs_jp cjkcodecs/_codecs_jp.c + at MODULE__CODECS_KR_TRUE@_codecs_kr cjkcodecs/_codecs_kr.c + at MODULE__CODECS_TW_TRUE@_codecs_tw cjkcodecs/_codecs_tw.c + at MODULE__MULTIBYTECODEC_TRUE@_multibytecodec cjkcodecs/multibytecodec.c + at MODULE_UNICODEDATA_TRUE@unicodedata unicodedata.c ############################################################################ # Modules with some UNIX dependencies diff --git a/configure b/configure index 45c6eb4b845ab..7bf2cfb257f5f 100755 --- a/configure +++ b/configure @@ -654,6 +654,22 @@ MODULE__SHA1_FALSE MODULE__SHA1_TRUE MODULE__MD5_FALSE MODULE__MD5_TRUE +MODULE_UNICODEDATA_FALSE +MODULE_UNICODEDATA_TRUE +MODULE__MULTIBYTECODEC_FALSE +MODULE__MULTIBYTECODEC_TRUE +MODULE__CODECS_TW_FALSE +MODULE__CODECS_TW_TRUE +MODULE__CODECS_KR_FALSE +MODULE__CODECS_KR_TRUE +MODULE__CODECS_JP_FALSE +MODULE__CODECS_JP_TRUE +MODULE__CODECS_ISO2022_FALSE +MODULE__CODECS_ISO2022_TRUE +MODULE__CODECS_HK_FALSE +MODULE__CODECS_HK_TRUE +MODULE__CODECS_CN_FALSE +MODULE__CODECS_CN_TRUE MODULE__ELEMENTTREE_FALSE MODULE__ELEMENTTREE_TRUE MODULE_PYEXPAT_FALSE @@ -19913,6 +19929,102 @@ fi $as_echo "$py_cv_module__elementtree" >&6; } + if true; then + MODULE__CODECS_CN_TRUE= + MODULE__CODECS_CN_FALSE='#' +else + MODULE__CODECS_CN_TRUE='#' + MODULE__CODECS_CN_FALSE= +fi + + + + + + if true; then + MODULE__CODECS_HK_TRUE= + MODULE__CODECS_HK_FALSE='#' +else + MODULE__CODECS_HK_TRUE='#' + MODULE__CODECS_HK_FALSE= +fi + + + + + + if true; then + MODULE__CODECS_ISO2022_TRUE= + MODULE__CODECS_ISO2022_FALSE='#' +else + MODULE__CODECS_ISO2022_TRUE='#' + MODULE__CODECS_ISO2022_FALSE= +fi + + + + + + if true; then + MODULE__CODECS_JP_TRUE= + MODULE__CODECS_JP_FALSE='#' +else + MODULE__CODECS_JP_TRUE='#' + MODULE__CODECS_JP_FALSE= +fi + + + + + + if true; then + MODULE__CODECS_KR_TRUE= + MODULE__CODECS_KR_FALSE='#' +else + MODULE__CODECS_KR_TRUE='#' + MODULE__CODECS_KR_FALSE= +fi + + + + + + if true; then + MODULE__CODECS_TW_TRUE= + MODULE__CODECS_TW_FALSE='#' +else + MODULE__CODECS_TW_TRUE='#' + MODULE__CODECS_TW_FALSE= +fi + + + + + + if true; then + MODULE__MULTIBYTECODEC_TRUE= + MODULE__MULTIBYTECODEC_FALSE='#' +else + MODULE__MULTIBYTECODEC_TRUE='#' + MODULE__MULTIBYTECODEC_FALSE= +fi + + + + + + if true; then + MODULE_UNICODEDATA_TRUE= + MODULE_UNICODEDATA_FALSE='#' +else + MODULE_UNICODEDATA_TRUE='#' + MODULE_UNICODEDATA_FALSE= +fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _md5" >&5 $as_echo_n "checking for stdlib extension module _md5... " >&6; } @@ -20669,6 +20781,38 @@ if test -z "${MODULE__ELEMENTTREE_TRUE}" && test -z "${MODULE__ELEMENTTREE_FALSE as_fn_error $? "conditional \"MODULE__ELEMENTTREE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__CODECS_CN_TRUE}" && test -z "${MODULE__CODECS_CN_FALSE}"; then + as_fn_error $? "conditional \"MODULE__CODECS_CN\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__CODECS_HK_TRUE}" && test -z "${MODULE__CODECS_HK_FALSE}"; then + as_fn_error $? "conditional \"MODULE__CODECS_HK\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__CODECS_ISO2022_TRUE}" && test -z "${MODULE__CODECS_ISO2022_FALSE}"; then + as_fn_error $? "conditional \"MODULE__CODECS_ISO2022\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__CODECS_JP_TRUE}" && test -z "${MODULE__CODECS_JP_FALSE}"; then + as_fn_error $? "conditional \"MODULE__CODECS_JP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__CODECS_KR_TRUE}" && test -z "${MODULE__CODECS_KR_FALSE}"; then + as_fn_error $? "conditional \"MODULE__CODECS_KR\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__CODECS_TW_TRUE}" && test -z "${MODULE__CODECS_TW_FALSE}"; then + as_fn_error $? "conditional \"MODULE__CODECS_TW\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__MULTIBYTECODEC_TRUE}" && test -z "${MODULE__MULTIBYTECODEC_FALSE}"; then + as_fn_error $? "conditional \"MODULE__MULTIBYTECODEC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE_UNICODEDATA_TRUE}" && test -z "${MODULE_UNICODEDATA_FALSE}"; then + as_fn_error $? "conditional \"MODULE_UNICODEDATA\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__MD5_TRUE}" && test -z "${MODULE__MD5_FALSE}"; then as_fn_error $? "conditional \"MODULE__MD5\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index 3d6233f31d9cb..e263993640e4c 100644 --- a/configure.ac +++ b/configure.ac @@ -6074,6 +6074,14 @@ PY_STDLIB_MOD([termios], [], [test "$ac_cv_header_termios_h" = yes]) dnl _elementtree loads libexpat via CAPI hook in pyexpat PY_STDLIB_MOD([pyexpat], [], [], [$LIBEXPAT_CFLAGS], [$LIBEXPAT_LDFLAGS]) PY_STDLIB_MOD([_elementtree], [], [], [$LIBEXPAT_CFLAGS], []) +PY_STDLIB_MOD_SIMPLE([_codecs_cn]) +PY_STDLIB_MOD_SIMPLE([_codecs_hk]) +PY_STDLIB_MOD_SIMPLE([_codecs_iso2022]) +PY_STDLIB_MOD_SIMPLE([_codecs_jp]) +PY_STDLIB_MOD_SIMPLE([_codecs_kr]) +PY_STDLIB_MOD_SIMPLE([_codecs_tw]) +PY_STDLIB_MOD_SIMPLE([_multibytecodec]) +PY_STDLIB_MOD_SIMPLE([unicodedata]) dnl By default we always compile these even when OpenSSL is available dnl (issue #14693). The modules are small. diff --git a/setup.py b/setup.py index 9ff5969c29613..13ed636b13f0c 100644 --- a/setup.py +++ b/setup.py @@ -1022,7 +1022,7 @@ def detect_simple_extensions(self): # profiler (_lsprof is for cProfile.py) self.add(Extension('_lsprof', ['_lsprof.c', 'rotatingtree.c'])) # static Unicode character database - self.add(Extension('unicodedata', ['unicodedata.c'])) + self.addext(Extension('unicodedata', ['unicodedata.c'])) # _opcode module self.add(Extension('_opcode', ['_opcode.c'])) # asyncio speedups @@ -1432,11 +1432,12 @@ def detect_expat_elementtree(self): def detect_multibytecodecs(self): # Hye-Shik Chang's CJKCodecs modules. - self.add(Extension('_multibytecodec', - ['cjkcodecs/multibytecodec.c'])) + self.addext(Extension('_multibytecodec', + ['cjkcodecs/multibytecodec.c'])) for loc in ('kr', 'jp', 'cn', 'tw', 'hk', 'iso2022'): - self.add(Extension('_codecs_%s' % loc, - ['cjkcodecs/_codecs_%s.c' % loc])) + self.addext(Extension( + f'_codecs_{loc}', [f'cjkcodecs/_codecs_{loc}.c'] + )) def detect_multiprocessing(self): # Richard Oudkerk's multiprocessing module From webhook-mailer at python.org Sun Nov 21 09:39:30 2021 From: webhook-mailer at python.org (rhettinger) Date: Sun, 21 Nov 2021 14:39:30 -0000 Subject: [Python-checkins] bpo-45766: Add direct proportion option to linear_regression(). (#29490) Message-ID: https://github.com/python/cpython/commit/d2b55b07d2b503dcd3b5c0e2753efa835cff8e8f commit: d2b55b07d2b503dcd3b5c0e2753efa835cff8e8f branch: main author: Raymond Hettinger committer: rhettinger date: 2021-11-21T08:39:26-06:00 summary: bpo-45766: Add direct proportion option to linear_regression(). (#29490) * bpo-45766: Add direct proportion option to linear_regression(). * Update 2021-11-09-09-18-06.bpo-45766.dvbcMf.rst * Use ellipsis to avoid round-off issues. * Update Misc/NEWS.d/next/Library/2021-11-09-09-18-06.bpo-45766.dvbcMf.rst Co-authored-by: Erlend Egeberg Aasland * Update signature in main docs * Fix missing comma Co-authored-by: Erlend Egeberg Aasland files: A Misc/NEWS.d/next/Library/2021-11-09-09-18-06.bpo-45766.dvbcMf.rst M Doc/library/statistics.rst M Lib/statistics.py M Lib/test/test_statistics.py diff --git a/Doc/library/statistics.rst b/Doc/library/statistics.rst index bb03a2ce6ee97..8638abfb697b8 100644 --- a/Doc/library/statistics.rst +++ b/Doc/library/statistics.rst @@ -643,7 +643,7 @@ However, for reading convenience, most of the examples show sorted sequences. .. versionadded:: 3.10 -.. function:: linear_regression(x, y, /) +.. function:: linear_regression(x, y, /, *, proportional=False) Return the slope and intercept of `simple linear regression `_ @@ -677,8 +677,18 @@ However, for reading convenience, most of the examples show sorted sequences. >>> round(slope * 2019 + intercept) 16 + If *proportional* is true, the independent variable *x* and the + dependent variable *y* are assumed to be directly proportional. + The data is fit to a line passing through the origin. + Since the *intercept* will always be 0.0, the underlying linear + function simplifies to: + + *y = slope \* x + noise* + .. versionadded:: 3.10 + .. versionchanged:: 3.11 + Added support for *proportional*. Exceptions ---------- diff --git a/Lib/statistics.py b/Lib/statistics.py index 4f3ab49b40219..5c3f77df1549d 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -937,13 +937,13 @@ def correlation(x, y, /): LinearRegression = namedtuple('LinearRegression', ('slope', 'intercept')) -def linear_regression(x, y, /): +def linear_regression(x, y, /, *, proportional=False): """Slope and intercept for simple linear regression. Return the slope and intercept of simple linear regression parameters estimated using ordinary least squares. Simple linear regression describes relationship between an independent variable - *x* and a dependent variable *y* in terms of linear function: + *x* and a dependent variable *y* in terms of a linear function: y = slope * x + intercept + noise @@ -961,21 +961,38 @@ def linear_regression(x, y, /): >>> linear_regression(x, y) #doctest: +ELLIPSIS LinearRegression(slope=3.09078914170..., intercept=1.75684970486...) + If *proportional* is true, the independent variable *x* and the + dependent variable *y* are assumed to be directly proportional. + The data is fit to a line passing through the origin. + + Since the *intercept* will always be 0.0, the underlying linear + function simplifies to: + + y = slope * x + noise + + >>> y = [3 * x[i] + noise[i] for i in range(5)] + >>> linear_regression(x, y, proportional=True) #doctest: +ELLIPSIS + LinearRegression(slope=3.02447542484..., intercept=0.0) + """ n = len(x) if len(y) != n: raise StatisticsError('linear regression requires that both inputs have same number of data points') if n < 2: raise StatisticsError('linear regression requires at least two data points') - xbar = fsum(x) / n - ybar = fsum(y) / n - sxy = fsum((xi - xbar) * (yi - ybar) for xi, yi in zip(x, y)) - sxx = fsum((d := xi - xbar) * d for xi in x) + if proportional: + sxy = fsum(xi * yi for xi, yi in zip(x, y)) + sxx = fsum(xi * xi for xi in x) + else: + xbar = fsum(x) / n + ybar = fsum(y) / n + sxy = fsum((xi - xbar) * (yi - ybar) for xi, yi in zip(x, y)) + sxx = fsum((d := xi - xbar) * d for xi in x) try: slope = sxy / sxx # equivalent to: covariance(x, y) / variance(x) except ZeroDivisionError: raise StatisticsError('x is constant') - intercept = ybar - slope * xbar + intercept = 0.0 if proportional else ybar - slope * xbar return LinearRegression(slope=slope, intercept=intercept) diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py index fbc6a071cfd34..c0e427d9355f2 100644 --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -2527,6 +2527,12 @@ def test_results(self): self.assertAlmostEqual(intercept, true_intercept) self.assertAlmostEqual(slope, true_slope) + def test_proportional(self): + x = [10, 20, 30, 40] + y = [180, 398, 610, 799] + slope, intercept = statistics.linear_regression(x, y, proportional=True) + self.assertAlmostEqual(slope, 20 + 1/150) + self.assertEqual(intercept, 0.0) class TestNormalDist: diff --git a/Misc/NEWS.d/next/Library/2021-11-09-09-18-06.bpo-45766.dvbcMf.rst b/Misc/NEWS.d/next/Library/2021-11-09-09-18-06.bpo-45766.dvbcMf.rst new file mode 100644 index 0000000000000..b2e9c7e2f0460 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-09-09-18-06.bpo-45766.dvbcMf.rst @@ -0,0 +1 @@ +Added *proportional* option to :meth:`statistics.linear_regression`. From webhook-mailer at python.org Mon Nov 22 03:05:16 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 22 Nov 2021 08:05:16 -0000 Subject: [Python-checkins] bpo-45723: Add helpers for save/restore env (GH-29637) Message-ID: https://github.com/python/cpython/commit/db2277a114463d30a58d9066f2b47f7a53a1488c commit: db2277a114463d30a58d9066f2b47f7a53a1488c branch: main author: Erlend Egeberg Aasland committer: tiran date: 2021-11-22T09:05:06+01:00 summary: bpo-45723: Add helpers for save/restore env (GH-29637) files: A Misc/NEWS.d/next/Build/2021-11-19-15-42-27.bpo-45723.vwIJWI.rst M configure M configure.ac diff --git a/Misc/NEWS.d/next/Build/2021-11-19-15-42-27.bpo-45723.vwIJWI.rst b/Misc/NEWS.d/next/Build/2021-11-19-15-42-27.bpo-45723.vwIJWI.rst new file mode 100644 index 0000000000000..51e7735d9ca32 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-19-15-42-27.bpo-45723.vwIJWI.rst @@ -0,0 +1,10 @@ +Add ``autoconf`` helpers for saving and restoring environment variables: + +* ``SAVE_ENV``: Save ``$CFLAGS``, ``$LDFLAGS``, ``$LIBS``, and + ``$CPPFLAGS``. +* ``RESTORE_ENV``: Restore ``$CFLAGS``, ``$LDFLAGS``, ``$LIBS``, and + ``$CPPFLAGS``. +* ``WITH_SAVE_ENV([SCRIPT])``: Run ``SCRIPT`` wrapped with ``SAVE_ENV`` and + ``RESTORE_ENV``. + +Patch by Erlend E. Aasland. diff --git a/configure b/configure index 7bf2cfb257f5f..fd75c52ab3d62 100755 --- a/configure +++ b/configure @@ -2866,6 +2866,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu + if test "$srcdir" != . -a "$srcdir" != "$(pwd)"; then # If we're building out-of-tree, we need to make sure the following # resources get picked up before their $srcdir counterparts. @@ -11085,13 +11086,14 @@ save_CFLAGS=$CFLAGS save_CPPFLAGS=$CPPFLAGS save_LDFLAGS=$LDFLAGS save_LIBS=$LIBS -CPPFLAGS="$LIBSQLITE3_CFLAGS $CFLAGS" -LDFLAGS="$LIBSQLITE3_LIBS $LDFLAGS" -ac_fn_c_check_header_mongrel "$LINENO" "sqlite3.h" "ac_cv_header_sqlite3_h" "$ac_includes_default" + CPPFLAGS="$LIBSQLITE3_CFLAGS $CFLAGS" + LDFLAGS="$LIBSQLITE3_LIBS $LDFLAGS" + + ac_fn_c_check_header_mongrel "$LINENO" "sqlite3.h" "ac_cv_header_sqlite3_h" "$ac_includes_default" if test "x$ac_cv_header_sqlite3_h" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sqlite3_open_v2 in -lsqlite3" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sqlite3_open_v2 in -lsqlite3" >&5 $as_echo_n "checking for sqlite3_open_v2 in -lsqlite3... " >&6; } if ${ac_cv_lib_sqlite3_sqlite3_open_v2+:} false; then : $as_echo_n "(cached) " >&6 @@ -11129,15 +11131,15 @@ fi $as_echo "$ac_cv_lib_sqlite3_sqlite3_open_v2" >&6; } if test "x$ac_cv_lib_sqlite3_sqlite3_open_v2" = xyes; then : - have_sqlite3=yes - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + have_sqlite3=yes + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #include - #if SQLITE_VERSION_NUMBER < 3007015 - # error "SQLite 3.7.15 or higher required" - #endif + #include + #if SQLITE_VERSION_NUMBER < 3007015 + # error "SQLite 3.7.15 or higher required" + #endif int main () @@ -11159,7 +11161,7 @@ else have_sqlite3=no fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sqlite3_load_extension in -lsqlite3" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sqlite3_load_extension in -lsqlite3" >&5 $as_echo_n "checking for sqlite3_load_extension in -lsqlite3... " >&6; } if ${ac_cv_lib_sqlite3_sqlite3_load_extension+:} false; then : $as_echo_n "(cached) " >&6 @@ -11211,6 +11213,8 @@ CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS + + # Check for support for loadable sqlite extensions { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --enable-loadable-sqlite-extensions" >&5 $as_echo_n "checking for --enable-loadable-sqlite-extensions... " >&6; } diff --git a/configure.ac b/configure.ac index e263993640e4c..63df5188d3890 100644 --- a/configure.ac +++ b/configure.ac @@ -23,6 +23,32 @@ m4_ifdef( [AC_MSG_ERROR([Please install pkgconf's m4 macro package and re-run autoreconf])] )dnl +dnl Helpers for saving and restoring environment variables: +dnl - _SAVE_VAR([VAR]) Helper for SAVE_ENV; stores VAR as save_VAR +dnl - _RESTORE_VAR([VAR]) Helper for RESTORE_ENV; restores VAR from save_VAR +dnl - SAVE_ENV Saves CFLAGS, LDFLAGS, LIBS, and CPPFLAGS +dnl - RESTORE_ENV Restores CFLAGS, LDFLAGS, LIBS, and CPPFLAGS +dnl - WITH_SAVE_ENV([SCRIPT]) Runs SCRIPT wrapped with SAVE_ENV/RESTORE_ENV +AC_DEFUN([_SAVE_VAR], [AS_VAR_COPY([save_][$1], [$1])])dnl +AC_DEFUN([_RESTORE_VAR], [AS_VAR_COPY([$1], [save_][$1])])dnl +AC_DEFUN([SAVE_ENV], +[_SAVE_VAR([CFLAGS])] +[_SAVE_VAR([CPPFLAGS])] +[_SAVE_VAR([LDFLAGS])] +[_SAVE_VAR([LIBS])] +)dnl +AC_DEFUN([RESTORE_ENV], +[_RESTORE_VAR([CFLAGS])] +[_RESTORE_VAR([CPPFLAGS])] +[_RESTORE_VAR([LDFLAGS])] +[_RESTORE_VAR([LIBS])] +)dnl +AC_DEFUN([WITH_SAVE_ENV], +[SAVE_ENV] +[$1] +[RESTORE_ENV] +)dnl + AC_SUBST(BASECPPFLAGS) if test "$srcdir" != . -a "$srcdir" != "$(pwd)"; then # If we're building out-of-tree, we need to make sure the following @@ -3174,37 +3200,29 @@ PKG_CHECK_MODULES( ) AS_VAR_APPEND([LIBSQLITE3_CFLAGS], [' -I$(srcdir)/Modules/_sqlite']) +WITH_SAVE_ENV( dnl bpo-45774/GH-29507: The CPP check in AC_CHECK_HEADER can fail on FreeBSD, -dnl hence CPPFLAGS instead of CFLAGS. We still need to save CFLAGS, because it -dnl is touched by AC_CHECK_HEADER. -AS_VAR_COPY([save_CFLAGS], [CFLAGS]) -AS_VAR_COPY([save_CPPFLAGS], [CPPFLAGS]) -AS_VAR_COPY([save_LDFLAGS], [LDFLAGS]) -AS_VAR_COPY([save_LIBS], [LIBS]) -CPPFLAGS="$LIBSQLITE3_CFLAGS $CFLAGS" -LDFLAGS="$LIBSQLITE3_LIBS $LDFLAGS" - -AC_CHECK_HEADER([sqlite3.h], [ - AC_CHECK_LIB([sqlite3], [sqlite3_open_v2], [ - have_sqlite3=yes - AC_COMPILE_IFELSE([ - AC_LANG_PROGRAM([ - #include - #if SQLITE_VERSION_NUMBER < 3007015 - # error "SQLite 3.7.15 or higher required" - #endif - ], []) - ], [have_supported_sqlite3=yes], [have_supported_sqlite3=no]) - ], [have_sqlite3=no]) - AC_CHECK_LIB([sqlite3], [sqlite3_load_extension], - [have_sqlite3_load_extension=yes], - [have_sqlite3_load_extension=no]) -]) - -AS_VAR_COPY([CFLAGS], [save_CFLAGS]) -AS_VAR_COPY([CPPFLAGS], [save_CPPFLAGS]) -AS_VAR_COPY([LDFLAGS], [save_LDFLAGS]) -AS_VAR_COPY([LIBS], [save_LIBS]) +dnl hence CPPFLAGS instead of CFLAGS. + CPPFLAGS="$LIBSQLITE3_CFLAGS $CFLAGS" + LDFLAGS="$LIBSQLITE3_LIBS $LDFLAGS" + + AC_CHECK_HEADER([sqlite3.h], [ + AC_CHECK_LIB([sqlite3], [sqlite3_open_v2], [ + have_sqlite3=yes + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([ + #include + #if SQLITE_VERSION_NUMBER < 3007015 + # error "SQLite 3.7.15 or higher required" + #endif + ], []) + ], [have_supported_sqlite3=yes], [have_supported_sqlite3=no]) + ], [have_sqlite3=no]) + AC_CHECK_LIB([sqlite3], [sqlite3_load_extension], + [have_sqlite3_load_extension=yes], + [have_sqlite3_load_extension=no]) + ]) +) # Check for support for loadable sqlite extensions AC_MSG_CHECKING(for --enable-loadable-sqlite-extensions) From webhook-mailer at python.org Mon Nov 22 03:05:41 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 22 Nov 2021 08:05:41 -0000 Subject: [Python-checkins] bpo-45847: Port array, _contextvars, math, and cmath to PY_STDLIB_MOD_SIMPLE (GH-29688) Message-ID: https://github.com/python/cpython/commit/133c65a870e8bdcce7cd6a2bc6bd0cefbb2fa9f3 commit: 133c65a870e8bdcce7cd6a2bc6bd0cefbb2fa9f3 branch: main author: Erlend Egeberg Aasland committer: tiran date: 2021-11-22T09:05:36+01:00 summary: bpo-45847: Port array, _contextvars, math, and cmath to PY_STDLIB_MOD_SIMPLE (GH-29688) files: M Modules/Setup.stdlib.in M configure M configure.ac M setup.py diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 42755c952f972..b22a956f0c404 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -28,6 +28,12 @@ ############################################################################ # Modules that should always be present (POSIX and Windows): + at MODULE_ARRAY_TRUE@array arraymodule.c + at MODULE__CONTEXTVARS_TRUE@_contextvars _contextvarsmodule.c + +# needs libm + at MODULE_MATH_TRUE@math mathmodule.c + at MODULE_CMATH_TRUE@cmath cmathmodule.c # needs libm and on some platforms librt @MODULE__DATETIME_TRUE at _datetime _datetimemodule.c diff --git a/configure b/configure index fd75c52ab3d62..72285a6eeae72 100755 --- a/configure +++ b/configure @@ -688,8 +688,16 @@ MODULE_OSSAUDIODEV_FALSE MODULE_OSSAUDIODEV_TRUE MODULE_GRP_FALSE MODULE_GRP_TRUE +MODULE_CMATH_FALSE +MODULE_CMATH_TRUE +MODULE_MATH_FALSE +MODULE_MATH_TRUE MODULE__DATETIME_FALSE MODULE__DATETIME_TRUE +MODULE__CONTEXTVARS_FALSE +MODULE__CONTEXTVARS_TRUE +MODULE_ARRAY_FALSE +MODULE_ARRAY_TRUE MODULE_TIME_FALSE MODULE_TIME_TRUE MODULE__IO_FALSE @@ -19566,6 +19574,30 @@ fi + if true; then + MODULE_ARRAY_TRUE= + MODULE_ARRAY_FALSE='#' +else + MODULE_ARRAY_TRUE='#' + MODULE_ARRAY_FALSE= +fi + + + + + + if true; then + MODULE__CONTEXTVARS_TRUE= + MODULE__CONTEXTVARS_FALSE='#' +else + MODULE__CONTEXTVARS_TRUE='#' + MODULE__CONTEXTVARS_FALSE= +fi + + + + + if true; then MODULE__DATETIME_TRUE= MODULE__DATETIME_FALSE='#' @@ -19580,6 +19612,34 @@ fi + if true; then + MODULE_MATH_TRUE= + MODULE_MATH_FALSE='#' +else + MODULE_MATH_TRUE='#' + MODULE_MATH_FALSE= +fi + + + + as_fn_append MODULE_BLOCK "MODULE_MATH_LDFLAGS=$LIBM$as_nl" + + + + if true; then + MODULE_CMATH_TRUE= + MODULE_CMATH_FALSE='#' +else + MODULE_CMATH_TRUE='#' + MODULE_CMATH_FALSE= +fi + + + + as_fn_append MODULE_BLOCK "MODULE_CMATH_LDFLAGS=$LIBM$as_nl" + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module grp" >&5 $as_echo_n "checking for stdlib extension module grp... " >&6; } @@ -20745,10 +20805,26 @@ if test -z "${MODULE_TIME_TRUE}" && test -z "${MODULE_TIME_FALSE}"; then as_fn_error $? "conditional \"MODULE_TIME\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE_ARRAY_TRUE}" && test -z "${MODULE_ARRAY_FALSE}"; then + as_fn_error $? "conditional \"MODULE_ARRAY\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__CONTEXTVARS_TRUE}" && test -z "${MODULE__CONTEXTVARS_FALSE}"; then + as_fn_error $? "conditional \"MODULE__CONTEXTVARS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__DATETIME_TRUE}" && test -z "${MODULE__DATETIME_FALSE}"; then as_fn_error $? "conditional \"MODULE__DATETIME\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE_MATH_TRUE}" && test -z "${MODULE_MATH_FALSE}"; then + as_fn_error $? "conditional \"MODULE_MATH\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE_CMATH_TRUE}" && test -z "${MODULE_CMATH_FALSE}"; then + as_fn_error $? "conditional \"MODULE_CMATH\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE_GRP_TRUE}" && test -z "${MODULE_GRP_FALSE}"; then as_fn_error $? "conditional \"MODULE_GRP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index 63df5188d3890..e0013c71ac8c1 100644 --- a/configure.ac +++ b/configure.ac @@ -6075,7 +6075,11 @@ PY_STDLIB_MOD_SIMPLE([_io], [-I\$(srcdir)/Modules/_io], []) PY_STDLIB_MOD_SIMPLE([time], [], [$TIMEMODULE_LIB]) dnl always enabled extension modules +PY_STDLIB_MOD_SIMPLE([array]) +PY_STDLIB_MOD_SIMPLE([_contextvars]) PY_STDLIB_MOD_SIMPLE([_datetime], [], [$TIMEMODULE_LIB $LIBM]) +PY_STDLIB_MOD_SIMPLE([math], [], [$LIBM]) +PY_STDLIB_MOD_SIMPLE([cmath], [], [$LIBM]) dnl platform specific extensions PY_STDLIB_MOD([grp], [], [test "$ac_cv_func_getgrgid" = yes -o "$ac_cv_func_getgrgid_r" = yes]) diff --git a/setup.py b/setup.py index 13ed636b13f0c..b2a3f4eb7140d 100644 --- a/setup.py +++ b/setup.py @@ -984,18 +984,16 @@ def detect_simple_extensions(self): # # array objects - self.add(Extension('array', ['arraymodule.c'])) + self.addext(Extension('array', ['arraymodule.c'])) # Context Variables - self.add(Extension('_contextvars', ['_contextvarsmodule.c'])) + self.addext(Extension('_contextvars', ['_contextvarsmodule.c'])) # math library functions, e.g. sin() - self.add(Extension('math', ['mathmodule.c'], - libraries=['m'])) + self.addext(Extension('math', ['mathmodule.c'])) # complex math library functions - self.add(Extension('cmath', ['cmathmodule.c'], - libraries=['m'])) + self.addext(Extension('cmath', ['cmathmodule.c'])) # time libraries: librt may be needed for clock_gettime() time_libs = [] From webhook-mailer at python.org Mon Nov 22 03:45:50 2021 From: webhook-mailer at python.org (miss-islington) Date: Mon, 22 Nov 2021 08:45:50 -0000 Subject: [Python-checkins] bpo-45847: Port _bisect, _heapq, _json, _pickle, _random, and _zoneinfo to PY_STDLIB_MOD_SIMPLE (GH-29689) Message-ID: https://github.com/python/cpython/commit/718cee08cc082ece590f5a012253a405422da03d commit: 718cee08cc082ece590f5a012253a405422da03d branch: main author: Erlend Egeberg Aasland committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-22T00:45:41-08:00 summary: bpo-45847: Port _bisect, _heapq, _json, _pickle, _random, and _zoneinfo to PY_STDLIB_MOD_SIMPLE (GH-29689) Automerge-Triggered-By: GH:tiran files: M Modules/Setup.stdlib.in M configure M configure.ac M setup.py diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index b22a956f0c404..bf414410d4b76 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -29,7 +29,13 @@ ############################################################################ # Modules that should always be present (POSIX and Windows): @MODULE_ARRAY_TRUE at array arraymodule.c + at MODULE__BISECT_TRUE@_bisect _bisectmodule.c @MODULE__CONTEXTVARS_TRUE at _contextvars _contextvarsmodule.c + at MODULE__HEAPQ_TRUE@_heapq _heapqmodule.c + at MODULE__JSON_TRUE@_json _json.c + at MODULE__PICKLE_TRUE@_pickle _pickle.c + at MODULE__RANDOM_TRUE@_random _randommodule.c + at MODULE__ZONEINFO_TRUE@_zoneinfo _zoneinfo.c # needs libm @MODULE_MATH_TRUE at math mathmodule.c diff --git a/configure b/configure index 72285a6eeae72..6aea5b6b77e56 100755 --- a/configure +++ b/configure @@ -688,14 +688,26 @@ MODULE_OSSAUDIODEV_FALSE MODULE_OSSAUDIODEV_TRUE MODULE_GRP_FALSE MODULE_GRP_TRUE -MODULE_CMATH_FALSE -MODULE_CMATH_TRUE +MODULE__ZONEINFO_FALSE +MODULE__ZONEINFO_TRUE +MODULE__RANDOM_FALSE +MODULE__RANDOM_TRUE +MODULE__PICKLE_FALSE +MODULE__PICKLE_TRUE MODULE_MATH_FALSE MODULE_MATH_TRUE +MODULE__JSON_FALSE +MODULE__JSON_TRUE +MODULE__HEAPQ_FALSE +MODULE__HEAPQ_TRUE MODULE__DATETIME_FALSE MODULE__DATETIME_TRUE MODULE__CONTEXTVARS_FALSE MODULE__CONTEXTVARS_TRUE +MODULE_CMATH_FALSE +MODULE_CMATH_TRUE +MODULE__BISECT_FALSE +MODULE__BISECT_TRUE MODULE_ARRAY_FALSE MODULE_ARRAY_TRUE MODULE_TIME_FALSE @@ -19586,6 +19598,32 @@ fi + if true; then + MODULE__BISECT_TRUE= + MODULE__BISECT_FALSE='#' +else + MODULE__BISECT_TRUE='#' + MODULE__BISECT_FALSE= +fi + + + + + + if true; then + MODULE_CMATH_TRUE= + MODULE_CMATH_FALSE='#' +else + MODULE_CMATH_TRUE='#' + MODULE_CMATH_FALSE= +fi + + + + as_fn_append MODULE_BLOCK "MODULE_CMATH_LDFLAGS=$LIBM$as_nl" + + + if true; then MODULE__CONTEXTVARS_TRUE= MODULE__CONTEXTVARS_FALSE='#' @@ -19612,6 +19650,30 @@ fi + if true; then + MODULE__HEAPQ_TRUE= + MODULE__HEAPQ_FALSE='#' +else + MODULE__HEAPQ_TRUE='#' + MODULE__HEAPQ_FALSE= +fi + + + + + + if true; then + MODULE__JSON_TRUE= + MODULE__JSON_FALSE='#' +else + MODULE__JSON_TRUE='#' + MODULE__JSON_FALSE= +fi + + + + + if true; then MODULE_MATH_TRUE= MODULE_MATH_FALSE='#' @@ -19627,16 +19689,38 @@ fi if true; then - MODULE_CMATH_TRUE= - MODULE_CMATH_FALSE='#' + MODULE__PICKLE_TRUE= + MODULE__PICKLE_FALSE='#' else - MODULE_CMATH_TRUE='#' - MODULE_CMATH_FALSE= + MODULE__PICKLE_TRUE='#' + MODULE__PICKLE_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE_CMATH_LDFLAGS=$LIBM$as_nl" + + + if true; then + MODULE__RANDOM_TRUE= + MODULE__RANDOM_FALSE='#' +else + MODULE__RANDOM_TRUE='#' + MODULE__RANDOM_FALSE= +fi + + + + + + if true; then + MODULE__ZONEINFO_TRUE= + MODULE__ZONEINFO_FALSE='#' +else + MODULE__ZONEINFO_TRUE='#' + MODULE__ZONEINFO_FALSE= +fi + + @@ -20809,6 +20893,14 @@ if test -z "${MODULE_ARRAY_TRUE}" && test -z "${MODULE_ARRAY_FALSE}"; then as_fn_error $? "conditional \"MODULE_ARRAY\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__BISECT_TRUE}" && test -z "${MODULE__BISECT_FALSE}"; then + as_fn_error $? "conditional \"MODULE__BISECT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE_CMATH_TRUE}" && test -z "${MODULE_CMATH_FALSE}"; then + as_fn_error $? "conditional \"MODULE_CMATH\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__CONTEXTVARS_TRUE}" && test -z "${MODULE__CONTEXTVARS_FALSE}"; then as_fn_error $? "conditional \"MODULE__CONTEXTVARS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -20817,12 +20909,28 @@ if test -z "${MODULE__DATETIME_TRUE}" && test -z "${MODULE__DATETIME_FALSE}"; th as_fn_error $? "conditional \"MODULE__DATETIME\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__HEAPQ_TRUE}" && test -z "${MODULE__HEAPQ_FALSE}"; then + as_fn_error $? "conditional \"MODULE__HEAPQ\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__JSON_TRUE}" && test -z "${MODULE__JSON_FALSE}"; then + as_fn_error $? "conditional \"MODULE__JSON\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE_MATH_TRUE}" && test -z "${MODULE_MATH_FALSE}"; then as_fn_error $? "conditional \"MODULE_MATH\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${MODULE_CMATH_TRUE}" && test -z "${MODULE_CMATH_FALSE}"; then - as_fn_error $? "conditional \"MODULE_CMATH\" was never defined. +if test -z "${MODULE__PICKLE_TRUE}" && test -z "${MODULE__PICKLE_FALSE}"; then + as_fn_error $? "conditional \"MODULE__PICKLE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__RANDOM_TRUE}" && test -z "${MODULE__RANDOM_FALSE}"; then + as_fn_error $? "conditional \"MODULE__RANDOM\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__ZONEINFO_TRUE}" && test -z "${MODULE__ZONEINFO_FALSE}"; then + as_fn_error $? "conditional \"MODULE__ZONEINFO\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${MODULE_GRP_TRUE}" && test -z "${MODULE_GRP_FALSE}"; then diff --git a/configure.ac b/configure.ac index e0013c71ac8c1..925d7f9f575c8 100644 --- a/configure.ac +++ b/configure.ac @@ -6076,10 +6076,16 @@ PY_STDLIB_MOD_SIMPLE([time], [], [$TIMEMODULE_LIB]) dnl always enabled extension modules PY_STDLIB_MOD_SIMPLE([array]) +PY_STDLIB_MOD_SIMPLE([_bisect]) +PY_STDLIB_MOD_SIMPLE([cmath], [], [$LIBM]) PY_STDLIB_MOD_SIMPLE([_contextvars]) PY_STDLIB_MOD_SIMPLE([_datetime], [], [$TIMEMODULE_LIB $LIBM]) +PY_STDLIB_MOD_SIMPLE([_heapq]) +PY_STDLIB_MOD_SIMPLE([_json]) PY_STDLIB_MOD_SIMPLE([math], [], [$LIBM]) -PY_STDLIB_MOD_SIMPLE([cmath], [], [$LIBM]) +PY_STDLIB_MOD_SIMPLE([_pickle]) +PY_STDLIB_MOD_SIMPLE([_random]) +PY_STDLIB_MOD_SIMPLE([_zoneinfo]) dnl platform specific extensions PY_STDLIB_MOD([grp], [], [test "$ac_cv_func_getgrgid" = yes -o "$ac_cv_func_getgrgid_r" = yes]) diff --git a/setup.py b/setup.py index b2a3f4eb7140d..a76df82c1b742 100644 --- a/setup.py +++ b/setup.py @@ -1004,18 +1004,15 @@ def detect_simple_extensions(self): # libm is needed by delta_new() that uses round() and by accum() that # uses modf(). self.addext(Extension('_datetime', ['_datetimemodule.c'])) - # zoneinfo module - self.add(Extension('_zoneinfo', ['_zoneinfo.c'])) + self.addext(Extension('_zoneinfo', ['_zoneinfo.c'])) # random number generator implemented in C - self.add(Extension("_random", ["_randommodule.c"])) - # bisect - self.add(Extension("_bisect", ["_bisectmodule.c"])) - # heapq - self.add(Extension("_heapq", ["_heapqmodule.c"])) + self.addext(Extension("_random", ["_randommodule.c"])) + self.addext(Extension("_bisect", ["_bisectmodule.c"])) + self.addext(Extension("_heapq", ["_heapqmodule.c"])) # C-optimized pickle replacement - self.add(Extension("_pickle", ["_pickle.c"])) + self.addext(Extension("_pickle", ["_pickle.c"])) # _json speedups - self.add(Extension("_json", ["_json.c"])) + self.addext(Extension("_json", ["_json.c"])) # profiler (_lsprof is for cProfile.py) self.add(Extension('_lsprof', ['_lsprof.c', 'rotatingtree.c'])) From webhook-mailer at python.org Mon Nov 22 04:51:02 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 22 Nov 2021 09:51:02 -0000 Subject: [Python-checkins] Fix out-of-tree build support for multissltest (GH-29694) Message-ID: https://github.com/python/cpython/commit/512dbf6f56364d359e16988b3fd7e766edfaebf9 commit: 512dbf6f56364d359e16988b3fd7e766edfaebf9 branch: main author: Christian Heimes committer: tiran date: 2021-11-22T10:50:53+01:00 summary: Fix out-of-tree build support for multissltest (GH-29694) files: M Makefile.pre.in M Tools/ssl/multissltests.py diff --git a/Makefile.pre.in b/Makefile.pre.in index fc4def8f5d12f..d52f73620795c 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1709,10 +1709,10 @@ quicktest: @DEF_MAKE_RULE@ platform # SSL tests .PHONY: multisslcompile multissltest multisslcompile: build_all - $(RUNSHARED) ./$(BUILDPYTHON) Tools/ssl/multissltests.py --steps=modules + $(RUNSHARED) ./$(BUILDPYTHON) $(srcdir)/Tools/ssl/multissltests.py --steps=modules multissltest: build_all - $(RUNSHARED) ./$(BUILDPYTHON) Tools/ssl/multissltests.py + $(RUNSHARED) ./$(BUILDPYTHON) $(srcdir)/Tools/ssl/multissltests.py install: @FRAMEWORKINSTALLFIRST@ commoninstall bininstall maninstall @FRAMEWORKINSTALLLAST@ if test "x$(ENSUREPIP)" != "xno" ; then \ diff --git a/Tools/ssl/multissltests.py b/Tools/ssl/multissltests.py index 7bdfd0b92bacf..ba2663e9a399b 100755 --- a/Tools/ssl/multissltests.py +++ b/Tools/ssl/multissltests.py @@ -153,8 +153,10 @@ class AbstractBuilder(object): install_target = 'install' jobs = os.cpu_count() - module_files = ("Modules/_ssl.c", - "Modules/_hashopenssl.c") + module_files = ( + os.path.join(PYTHONROOT, "Modules/_ssl.c"), + os.path.join(PYTHONROOT, "Modules/_hashopenssl.c"), + ) module_libs = ("_ssl", "_hashlib") def __init__(self, version, args): @@ -357,7 +359,7 @@ def recompile_pymods(self): env["LD_RUN_PATH"] = self.lib_dir log.info("Rebuilding Python modules") - cmd = [sys.executable, "setup.py", "build"] + cmd = [sys.executable, os.path.join(PYTHONROOT, "setup.py"), "build"] self._subprocess_call(cmd, env=env) self.check_imports() @@ -372,7 +374,11 @@ def check_pyssl(self): def run_python_tests(self, tests, network=True): if not tests: - cmd = [sys.executable, 'Lib/test/ssltests.py', '-j0'] + cmd = [ + sys.executable, + os.path.join(PYTHONROOT, 'Lib/test/ssltests.py'), + '-j0' + ] elif sys.version_info < (3, 3): cmd = [sys.executable, '-m', 'test.regrtest'] else: From webhook-mailer at python.org Mon Nov 22 04:57:58 2021 From: webhook-mailer at python.org (miss-islington) Date: Mon, 22 Nov 2021 09:57:58 -0000 Subject: [Python-checkins] bpo-45847: Port _lfprof, _opcode, _asyncio, _queue, _statistics, and _typing to PY_STDLIB_MOD_SIMPLE (GH-29690) Message-ID: https://github.com/python/cpython/commit/39f7d2ff01eb03f1dd87a019472a32cde6250e84 commit: 39f7d2ff01eb03f1dd87a019472a32cde6250e84 branch: main author: Erlend Egeberg Aasland committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-22T01:57:50-08:00 summary: bpo-45847: Port _lfprof, _opcode, _asyncio, _queue, _statistics, and _typing to PY_STDLIB_MOD_SIMPLE (GH-29690) Automerge-Triggered-By: GH:tiran files: M Modules/Setup.stdlib.in M configure M configure.ac M setup.py diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index bf414410d4b76..5e28a72d7a162 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -29,17 +29,23 @@ ############################################################################ # Modules that should always be present (POSIX and Windows): @MODULE_ARRAY_TRUE at array arraymodule.c + at MODULE__ASYNCIO_TRUE@_asyncio _asynciomodule.c @MODULE__BISECT_TRUE at _bisect _bisectmodule.c @MODULE__CONTEXTVARS_TRUE at _contextvars _contextvarsmodule.c @MODULE__HEAPQ_TRUE at _heapq _heapqmodule.c @MODULE__JSON_TRUE at _json _json.c + at MODULE__LSPROF_TRUE@_lsprof _lsprof.c rotatingtree.c + at MODULE__OPCODE_TRUE@_opcode _opcode.c @MODULE__PICKLE_TRUE at _pickle _pickle.c + at MODULE__QUEUE_TRUE@_queue _queuemodule.c @MODULE__RANDOM_TRUE at _random _randommodule.c + at MODULE__TYPING_TRUE@_typing _typingmodule.c @MODULE__ZONEINFO_TRUE at _zoneinfo _zoneinfo.c # needs libm @MODULE_MATH_TRUE at math mathmodule.c @MODULE_CMATH_TRUE at cmath cmathmodule.c + at MODULE__STATISTICS_TRUE@_statistics _statisticsmodule.c # needs libm and on some platforms librt @MODULE__DATETIME_TRUE at _datetime _datetimemodule.c diff --git a/configure b/configure index 6aea5b6b77e56..2cdc899082bfa 100755 --- a/configure +++ b/configure @@ -688,26 +688,38 @@ MODULE_OSSAUDIODEV_FALSE MODULE_OSSAUDIODEV_TRUE MODULE_GRP_FALSE MODULE_GRP_TRUE +MODULE__DATETIME_FALSE +MODULE__DATETIME_TRUE +MODULE_MATH_FALSE +MODULE_MATH_TRUE +MODULE_CMATH_FALSE +MODULE_CMATH_TRUE +MODULE__STATISTICS_FALSE +MODULE__STATISTICS_TRUE MODULE__ZONEINFO_FALSE MODULE__ZONEINFO_TRUE +MODULE__TYPING_FALSE +MODULE__TYPING_TRUE MODULE__RANDOM_FALSE MODULE__RANDOM_TRUE +MODULE__QUEUE_FALSE +MODULE__QUEUE_TRUE MODULE__PICKLE_FALSE MODULE__PICKLE_TRUE -MODULE_MATH_FALSE -MODULE_MATH_TRUE +MODULE__OPCODE_FALSE +MODULE__OPCODE_TRUE +MODULE__LSPROF_FALSE +MODULE__LSPROF_TRUE MODULE__JSON_FALSE MODULE__JSON_TRUE MODULE__HEAPQ_FALSE MODULE__HEAPQ_TRUE -MODULE__DATETIME_FALSE -MODULE__DATETIME_TRUE MODULE__CONTEXTVARS_FALSE MODULE__CONTEXTVARS_TRUE -MODULE_CMATH_FALSE -MODULE_CMATH_TRUE MODULE__BISECT_FALSE MODULE__BISECT_TRUE +MODULE__ASYNCIO_FALSE +MODULE__ASYNCIO_TRUE MODULE_ARRAY_FALSE MODULE_ARRAY_TRUE MODULE_TIME_FALSE @@ -19599,11 +19611,11 @@ fi if true; then - MODULE__BISECT_TRUE= - MODULE__BISECT_FALSE='#' + MODULE__ASYNCIO_TRUE= + MODULE__ASYNCIO_FALSE='#' else - MODULE__BISECT_TRUE='#' - MODULE__BISECT_FALSE= + MODULE__ASYNCIO_TRUE='#' + MODULE__ASYNCIO_FALSE= fi @@ -19611,17 +19623,15 @@ fi if true; then - MODULE_CMATH_TRUE= - MODULE_CMATH_FALSE='#' + MODULE__BISECT_TRUE= + MODULE__BISECT_FALSE='#' else - MODULE_CMATH_TRUE='#' - MODULE_CMATH_FALSE= + MODULE__BISECT_TRUE='#' + MODULE__BISECT_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE_CMATH_LDFLAGS=$LIBM$as_nl" - if true; then @@ -19636,20 +19646,6 @@ fi - if true; then - MODULE__DATETIME_TRUE= - MODULE__DATETIME_FALSE='#' -else - MODULE__DATETIME_TRUE='#' - MODULE__DATETIME_FALSE= -fi - - - - as_fn_append MODULE_BLOCK "MODULE__DATETIME_LDFLAGS=$TIMEMODULE_LIB $LIBM$as_nl" - - - if true; then MODULE__HEAPQ_TRUE= MODULE__HEAPQ_FALSE='#' @@ -19675,16 +19671,26 @@ fi if true; then - MODULE_MATH_TRUE= - MODULE_MATH_FALSE='#' + MODULE__LSPROF_TRUE= + MODULE__LSPROF_FALSE='#' else - MODULE_MATH_TRUE='#' - MODULE_MATH_FALSE= + MODULE__LSPROF_TRUE='#' + MODULE__LSPROF_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE_MATH_LDFLAGS=$LIBM$as_nl" + + + if true; then + MODULE__OPCODE_TRUE= + MODULE__OPCODE_FALSE='#' +else + MODULE__OPCODE_TRUE='#' + MODULE__OPCODE_FALSE= +fi + + @@ -19700,6 +19706,18 @@ fi + if true; then + MODULE__QUEUE_TRUE= + MODULE__QUEUE_FALSE='#' +else + MODULE__QUEUE_TRUE='#' + MODULE__QUEUE_FALSE= +fi + + + + + if true; then MODULE__RANDOM_TRUE= MODULE__RANDOM_FALSE='#' @@ -19712,6 +19730,18 @@ fi + if true; then + MODULE__TYPING_TRUE= + MODULE__TYPING_FALSE='#' +else + MODULE__TYPING_TRUE='#' + MODULE__TYPING_FALSE= +fi + + + + + if true; then MODULE__ZONEINFO_TRUE= MODULE__ZONEINFO_FALSE='#' @@ -19725,6 +19755,64 @@ fi + if true; then + MODULE__STATISTICS_TRUE= + MODULE__STATISTICS_FALSE='#' +else + MODULE__STATISTICS_TRUE='#' + MODULE__STATISTICS_FALSE= +fi + + + + as_fn_append MODULE_BLOCK "MODULE__STATISTICS_LDFLAGS=$LIBM$as_nl" + + + + if true; then + MODULE_CMATH_TRUE= + MODULE_CMATH_FALSE='#' +else + MODULE_CMATH_TRUE='#' + MODULE_CMATH_FALSE= +fi + + + + as_fn_append MODULE_BLOCK "MODULE_CMATH_LDFLAGS=$LIBM$as_nl" + + + + if true; then + MODULE_MATH_TRUE= + MODULE_MATH_FALSE='#' +else + MODULE_MATH_TRUE='#' + MODULE_MATH_FALSE= +fi + + + + as_fn_append MODULE_BLOCK "MODULE_MATH_LDFLAGS=$LIBM$as_nl" + + + + + if true; then + MODULE__DATETIME_TRUE= + MODULE__DATETIME_FALSE='#' +else + MODULE__DATETIME_TRUE='#' + MODULE__DATETIME_FALSE= +fi + + + + as_fn_append MODULE_BLOCK "MODULE__DATETIME_LDFLAGS=$TIMEMODULE_LIB $LIBM$as_nl" + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module grp" >&5 $as_echo_n "checking for stdlib extension module grp... " >&6; } case $py_stdlib_not_available in #( @@ -20893,22 +20981,18 @@ if test -z "${MODULE_ARRAY_TRUE}" && test -z "${MODULE_ARRAY_FALSE}"; then as_fn_error $? "conditional \"MODULE_ARRAY\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${MODULE__BISECT_TRUE}" && test -z "${MODULE__BISECT_FALSE}"; then - as_fn_error $? "conditional \"MODULE__BISECT\" was never defined. +if test -z "${MODULE__ASYNCIO_TRUE}" && test -z "${MODULE__ASYNCIO_FALSE}"; then + as_fn_error $? "conditional \"MODULE__ASYNCIO\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${MODULE_CMATH_TRUE}" && test -z "${MODULE_CMATH_FALSE}"; then - as_fn_error $? "conditional \"MODULE_CMATH\" was never defined. +if test -z "${MODULE__BISECT_TRUE}" && test -z "${MODULE__BISECT_FALSE}"; then + as_fn_error $? "conditional \"MODULE__BISECT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${MODULE__CONTEXTVARS_TRUE}" && test -z "${MODULE__CONTEXTVARS_FALSE}"; then as_fn_error $? "conditional \"MODULE__CONTEXTVARS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${MODULE__DATETIME_TRUE}" && test -z "${MODULE__DATETIME_FALSE}"; then - as_fn_error $? "conditional \"MODULE__DATETIME\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${MODULE__HEAPQ_TRUE}" && test -z "${MODULE__HEAPQ_FALSE}"; then as_fn_error $? "conditional \"MODULE__HEAPQ\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -20917,22 +21001,50 @@ if test -z "${MODULE__JSON_TRUE}" && test -z "${MODULE__JSON_FALSE}"; then as_fn_error $? "conditional \"MODULE__JSON\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${MODULE_MATH_TRUE}" && test -z "${MODULE_MATH_FALSE}"; then - as_fn_error $? "conditional \"MODULE_MATH\" was never defined. +if test -z "${MODULE__LSPROF_TRUE}" && test -z "${MODULE__LSPROF_FALSE}"; then + as_fn_error $? "conditional \"MODULE__LSPROF\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__OPCODE_TRUE}" && test -z "${MODULE__OPCODE_FALSE}"; then + as_fn_error $? "conditional \"MODULE__OPCODE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${MODULE__PICKLE_TRUE}" && test -z "${MODULE__PICKLE_FALSE}"; then as_fn_error $? "conditional \"MODULE__PICKLE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__QUEUE_TRUE}" && test -z "${MODULE__QUEUE_FALSE}"; then + as_fn_error $? "conditional \"MODULE__QUEUE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__RANDOM_TRUE}" && test -z "${MODULE__RANDOM_FALSE}"; then as_fn_error $? "conditional \"MODULE__RANDOM\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__TYPING_TRUE}" && test -z "${MODULE__TYPING_FALSE}"; then + as_fn_error $? "conditional \"MODULE__TYPING\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__ZONEINFO_TRUE}" && test -z "${MODULE__ZONEINFO_FALSE}"; then as_fn_error $? "conditional \"MODULE__ZONEINFO\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__STATISTICS_TRUE}" && test -z "${MODULE__STATISTICS_FALSE}"; then + as_fn_error $? "conditional \"MODULE__STATISTICS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE_CMATH_TRUE}" && test -z "${MODULE_CMATH_FALSE}"; then + as_fn_error $? "conditional \"MODULE_CMATH\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE_MATH_TRUE}" && test -z "${MODULE_MATH_FALSE}"; then + as_fn_error $? "conditional \"MODULE_MATH\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__DATETIME_TRUE}" && test -z "${MODULE__DATETIME_FALSE}"; then + as_fn_error $? "conditional \"MODULE__DATETIME\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE_GRP_TRUE}" && test -z "${MODULE_GRP_FALSE}"; then as_fn_error $? "conditional \"MODULE_GRP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index 925d7f9f575c8..ee379b71417c7 100644 --- a/configure.ac +++ b/configure.ac @@ -6076,17 +6076,27 @@ PY_STDLIB_MOD_SIMPLE([time], [], [$TIMEMODULE_LIB]) dnl always enabled extension modules PY_STDLIB_MOD_SIMPLE([array]) +PY_STDLIB_MOD_SIMPLE([_asyncio]) PY_STDLIB_MOD_SIMPLE([_bisect]) -PY_STDLIB_MOD_SIMPLE([cmath], [], [$LIBM]) PY_STDLIB_MOD_SIMPLE([_contextvars]) -PY_STDLIB_MOD_SIMPLE([_datetime], [], [$TIMEMODULE_LIB $LIBM]) PY_STDLIB_MOD_SIMPLE([_heapq]) PY_STDLIB_MOD_SIMPLE([_json]) -PY_STDLIB_MOD_SIMPLE([math], [], [$LIBM]) +PY_STDLIB_MOD_SIMPLE([_lsprof]) +PY_STDLIB_MOD_SIMPLE([_opcode]) PY_STDLIB_MOD_SIMPLE([_pickle]) +PY_STDLIB_MOD_SIMPLE([_queue]) PY_STDLIB_MOD_SIMPLE([_random]) +PY_STDLIB_MOD_SIMPLE([_typing]) PY_STDLIB_MOD_SIMPLE([_zoneinfo]) +dnl needs libm +PY_STDLIB_MOD_SIMPLE([_statistics], [], [$LIBM]) +PY_STDLIB_MOD_SIMPLE([cmath], [], [$LIBM]) +PY_STDLIB_MOD_SIMPLE([math], [], [$LIBM]) + +dnl needs libm and on some platforms librt +PY_STDLIB_MOD_SIMPLE([_datetime], [], [$TIMEMODULE_LIB $LIBM]) + dnl platform specific extensions PY_STDLIB_MOD([grp], [], [test "$ac_cv_func_getgrgid" = yes -o "$ac_cv_func_getgrgid_r" = yes]) PY_STDLIB_MOD([ossaudiodev], diff --git a/setup.py b/setup.py index a76df82c1b742..91040171a494b 100644 --- a/setup.py +++ b/setup.py @@ -1015,19 +1015,17 @@ def detect_simple_extensions(self): self.addext(Extension("_json", ["_json.c"])) # profiler (_lsprof is for cProfile.py) - self.add(Extension('_lsprof', ['_lsprof.c', 'rotatingtree.c'])) + self.addext(Extension('_lsprof', ['_lsprof.c', 'rotatingtree.c'])) # static Unicode character database self.addext(Extension('unicodedata', ['unicodedata.c'])) - # _opcode module - self.add(Extension('_opcode', ['_opcode.c'])) + self.addext(Extension('_opcode', ['_opcode.c'])) + # asyncio speedups - self.add(Extension("_asyncio", ["_asynciomodule.c"])) - # _queue module - self.add(Extension("_queue", ["_queuemodule.c"])) - # _statistics module - self.add(Extension("_statistics", ["_statisticsmodule.c"])) - # _typing module - self.add(Extension("_typing", ["_typingmodule.c"])) + self.addext(Extension("_asyncio", ["_asynciomodule.c"])) + + self.addext(Extension("_queue", ["_queuemodule.c"])) + self.addext(Extension("_statistics", ["_statisticsmodule.c"])) + self.addext(Extension("_typing", ["_typingmodule.c"])) # Modules with some UNIX dependencies -- on by default: # (If you have a really backward UNIX, select and socket may not be From webhook-mailer at python.org Mon Nov 22 05:14:43 2021 From: webhook-mailer at python.org (miss-islington) Date: Mon, 22 Nov 2021 10:14:43 -0000 Subject: [Python-checkins] Fix out-of-tree build support for multissltest (GH-29694) Message-ID: https://github.com/python/cpython/commit/9e7a2e492052956d511d753a276a4bdf6eb47072 commit: 9e7a2e492052956d511d753a276a4bdf6eb47072 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-22T02:14:28-08:00 summary: Fix out-of-tree build support for multissltest (GH-29694) (cherry picked from commit 512dbf6f56364d359e16988b3fd7e766edfaebf9) Co-authored-by: Christian Heimes files: M Makefile.pre.in M Tools/ssl/multissltests.py diff --git a/Makefile.pre.in b/Makefile.pre.in index 673e6efbf1e4f..ae6555c8e2fe1 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1259,10 +1259,10 @@ quicktest: @DEF_MAKE_RULE@ platform # SSL tests .PHONY: multisslcompile multissltest multisslcompile: build_all - $(RUNSHARED) ./$(BUILDPYTHON) Tools/ssl/multissltests.py --steps=modules + $(RUNSHARED) ./$(BUILDPYTHON) $(srcdir)/Tools/ssl/multissltests.py --steps=modules multissltest: build_all - $(RUNSHARED) ./$(BUILDPYTHON) Tools/ssl/multissltests.py + $(RUNSHARED) ./$(BUILDPYTHON) $(srcdir)/Tools/ssl/multissltests.py install: @FRAMEWORKINSTALLFIRST@ commoninstall bininstall maninstall @FRAMEWORKINSTALLLAST@ if test "x$(ENSUREPIP)" != "xno" ; then \ diff --git a/Tools/ssl/multissltests.py b/Tools/ssl/multissltests.py index 7bdfd0b92bacf..ba2663e9a399b 100755 --- a/Tools/ssl/multissltests.py +++ b/Tools/ssl/multissltests.py @@ -153,8 +153,10 @@ class AbstractBuilder(object): install_target = 'install' jobs = os.cpu_count() - module_files = ("Modules/_ssl.c", - "Modules/_hashopenssl.c") + module_files = ( + os.path.join(PYTHONROOT, "Modules/_ssl.c"), + os.path.join(PYTHONROOT, "Modules/_hashopenssl.c"), + ) module_libs = ("_ssl", "_hashlib") def __init__(self, version, args): @@ -357,7 +359,7 @@ def recompile_pymods(self): env["LD_RUN_PATH"] = self.lib_dir log.info("Rebuilding Python modules") - cmd = [sys.executable, "setup.py", "build"] + cmd = [sys.executable, os.path.join(PYTHONROOT, "setup.py"), "build"] self._subprocess_call(cmd, env=env) self.check_imports() @@ -372,7 +374,11 @@ def check_pyssl(self): def run_python_tests(self, tests, network=True): if not tests: - cmd = [sys.executable, 'Lib/test/ssltests.py', '-j0'] + cmd = [ + sys.executable, + os.path.join(PYTHONROOT, 'Lib/test/ssltests.py'), + '-j0' + ] elif sys.version_info < (3, 3): cmd = [sys.executable, '-m', 'test.regrtest'] else: From webhook-mailer at python.org Mon Nov 22 06:09:22 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 22 Nov 2021 11:09:22 -0000 Subject: [Python-checkins] bpo-45847: Various PY_STDLIB_MOD cleanups (GH-29697) Message-ID: https://github.com/python/cpython/commit/29699a2a2aa2f0d6e790beeae55967fc2f35fe50 commit: 29699a2a2aa2f0d6e790beeae55967fc2f35fe50 branch: main author: Christian Heimes committer: tiran date: 2021-11-22T12:09:14+01:00 summary: bpo-45847: Various PY_STDLIB_MOD cleanups (GH-29697) files: M configure M configure.ac M setup.py diff --git a/configure b/configure index 2cdc899082bfa..9bd659efbf923 100755 --- a/configure +++ b/configure @@ -19576,13 +19576,10 @@ else MODULE__IO_TRUE='#' MODULE__IO_FALSE= fi - - + as_fn_append MODULE_BLOCK "MODULE__IO=yes$as_nl" as_fn_append MODULE_BLOCK "MODULE__IO_CFLAGS=-I\$(srcdir)/Modules/_io$as_nl" - - if true; then MODULE_TIME_TRUE= MODULE_TIME_FALSE='#' @@ -19590,14 +19587,11 @@ else MODULE_TIME_TRUE='#' MODULE_TIME_FALSE= fi - - - + as_fn_append MODULE_BLOCK "MODULE_TIME=yes$as_nl" as_fn_append MODULE_BLOCK "MODULE_TIME_LDFLAGS=$TIMEMODULE_LIB$as_nl" - if true; then MODULE_ARRAY_TRUE= MODULE_ARRAY_FALSE='#' @@ -19605,10 +19599,7 @@ else MODULE_ARRAY_TRUE='#' MODULE_ARRAY_FALSE= fi - - - - + as_fn_append MODULE_BLOCK "MODULE_ARRAY=yes$as_nl" if true; then MODULE__ASYNCIO_TRUE= @@ -19617,10 +19608,7 @@ else MODULE__ASYNCIO_TRUE='#' MODULE__ASYNCIO_FALSE= fi - - - - + as_fn_append MODULE_BLOCK "MODULE__ASYNCIO=yes$as_nl" if true; then MODULE__BISECT_TRUE= @@ -19629,10 +19617,7 @@ else MODULE__BISECT_TRUE='#' MODULE__BISECT_FALSE= fi - - - - + as_fn_append MODULE_BLOCK "MODULE__BISECT=yes$as_nl" if true; then MODULE__CONTEXTVARS_TRUE= @@ -19641,10 +19626,7 @@ else MODULE__CONTEXTVARS_TRUE='#' MODULE__CONTEXTVARS_FALSE= fi - - - - + as_fn_append MODULE_BLOCK "MODULE__CONTEXTVARS=yes$as_nl" if true; then MODULE__HEAPQ_TRUE= @@ -19653,10 +19635,7 @@ else MODULE__HEAPQ_TRUE='#' MODULE__HEAPQ_FALSE= fi - - - - + as_fn_append MODULE_BLOCK "MODULE__HEAPQ=yes$as_nl" if true; then MODULE__JSON_TRUE= @@ -19665,10 +19644,7 @@ else MODULE__JSON_TRUE='#' MODULE__JSON_FALSE= fi - - - - + as_fn_append MODULE_BLOCK "MODULE__JSON=yes$as_nl" if true; then MODULE__LSPROF_TRUE= @@ -19677,10 +19653,7 @@ else MODULE__LSPROF_TRUE='#' MODULE__LSPROF_FALSE= fi - - - - + as_fn_append MODULE_BLOCK "MODULE__LSPROF=yes$as_nl" if true; then MODULE__OPCODE_TRUE= @@ -19689,10 +19662,7 @@ else MODULE__OPCODE_TRUE='#' MODULE__OPCODE_FALSE= fi - - - - + as_fn_append MODULE_BLOCK "MODULE__OPCODE=yes$as_nl" if true; then MODULE__PICKLE_TRUE= @@ -19701,10 +19671,7 @@ else MODULE__PICKLE_TRUE='#' MODULE__PICKLE_FALSE= fi - - - - + as_fn_append MODULE_BLOCK "MODULE__PICKLE=yes$as_nl" if true; then MODULE__QUEUE_TRUE= @@ -19713,10 +19680,7 @@ else MODULE__QUEUE_TRUE='#' MODULE__QUEUE_FALSE= fi - - - - + as_fn_append MODULE_BLOCK "MODULE__QUEUE=yes$as_nl" if true; then MODULE__RANDOM_TRUE= @@ -19725,10 +19689,7 @@ else MODULE__RANDOM_TRUE='#' MODULE__RANDOM_FALSE= fi - - - - + as_fn_append MODULE_BLOCK "MODULE__RANDOM=yes$as_nl" if true; then MODULE__TYPING_TRUE= @@ -19737,10 +19698,7 @@ else MODULE__TYPING_TRUE='#' MODULE__TYPING_FALSE= fi - - - - + as_fn_append MODULE_BLOCK "MODULE__TYPING=yes$as_nl" if true; then MODULE__ZONEINFO_TRUE= @@ -19749,10 +19707,7 @@ else MODULE__ZONEINFO_TRUE='#' MODULE__ZONEINFO_FALSE= fi - - - - + as_fn_append MODULE_BLOCK "MODULE__ZONEINFO=yes$as_nl" if true; then @@ -19762,13 +19717,10 @@ else MODULE__STATISTICS_TRUE='#' MODULE__STATISTICS_FALSE= fi - - - + as_fn_append MODULE_BLOCK "MODULE__STATISTICS=yes$as_nl" as_fn_append MODULE_BLOCK "MODULE__STATISTICS_LDFLAGS=$LIBM$as_nl" - if true; then MODULE_CMATH_TRUE= MODULE_CMATH_FALSE='#' @@ -19776,13 +19728,10 @@ else MODULE_CMATH_TRUE='#' MODULE_CMATH_FALSE= fi - - - + as_fn_append MODULE_BLOCK "MODULE_CMATH=yes$as_nl" as_fn_append MODULE_BLOCK "MODULE_CMATH_LDFLAGS=$LIBM$as_nl" - if true; then MODULE_MATH_TRUE= MODULE_MATH_FALSE='#' @@ -19790,14 +19739,11 @@ else MODULE_MATH_TRUE='#' MODULE_MATH_FALSE= fi - - - + as_fn_append MODULE_BLOCK "MODULE_MATH=yes$as_nl" as_fn_append MODULE_BLOCK "MODULE_MATH_LDFLAGS=$LIBM$as_nl" - if true; then MODULE__DATETIME_TRUE= MODULE__DATETIME_FALSE='#' @@ -19805,22 +19751,18 @@ else MODULE__DATETIME_TRUE='#' MODULE__DATETIME_FALSE= fi - - - + as_fn_append MODULE_BLOCK "MODULE__DATETIME=yes$as_nl" as_fn_append MODULE_BLOCK "MODULE__DATETIME_LDFLAGS=$TIMEMODULE_LIB $LIBM$as_nl" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module grp" >&5 $as_echo_n "checking for stdlib extension module grp... " >&6; } case $py_stdlib_not_available in #( *grp*) : py_cv_module_grp=n/a ;; #( *) : - - if true; then : + if true; then : if test "$ac_cv_func_getgrgid" = yes -o "$ac_cv_func_getgrgid_r" = yes; then : py_cv_module_grp=yes else @@ -19828,9 +19770,7 @@ else fi else py_cv_module_grp=disabled - fi - ;; esac as_fn_append MODULE_BLOCK "MODULE_GRP=$py_cv_module_grp$as_nl" @@ -19858,8 +19798,7 @@ $as_echo_n "checking for stdlib extension module ossaudiodev... " >&6; } *ossaudiodev*) : py_cv_module_ossaudiodev=n/a ;; #( *) : - - if true; then : + if true; then : if test "$ac_cv_header_linux_soundcard_h" = yes -o "$ac_cv_header_sys_soundcard_h" = yes; then : py_cv_module_ossaudiodev=yes else @@ -19867,9 +19806,7 @@ else fi else py_cv_module_ossaudiodev=disabled - fi - ;; esac as_fn_append MODULE_BLOCK "MODULE_OSSAUDIODEV=$py_cv_module_ossaudiodev$as_nl" @@ -19897,8 +19834,7 @@ $as_echo_n "checking for stdlib extension module resource... " >&6; } *resource*) : py_cv_module_resource=n/a ;; #( *) : - - if true; then : + if true; then : if test "$ac_cv_header_sys_resource_h" = yes; then : py_cv_module_resource=yes else @@ -19906,9 +19842,7 @@ else fi else py_cv_module_resource=disabled - fi - ;; esac as_fn_append MODULE_BLOCK "MODULE_RESOURCE=$py_cv_module_resource$as_nl" @@ -19936,8 +19870,7 @@ $as_echo_n "checking for stdlib extension module _scproxy... " >&6; } *_scproxy*) : py_cv_module__scproxy=n/a ;; #( *) : - - if test "$ac_sys_system" = "Darwin"; then : + if test "$ac_sys_system" = "Darwin"; then : if true; then : py_cv_module__scproxy=yes else @@ -19945,9 +19878,7 @@ else fi else py_cv_module__scproxy=disabled - fi - ;; esac as_fn_append MODULE_BLOCK "MODULE__SCPROXY=$py_cv_module__scproxy$as_nl" @@ -19975,8 +19906,7 @@ $as_echo_n "checking for stdlib extension module spwd... " >&6; } *spwd*) : py_cv_module_spwd=n/a ;; #( *) : - - if true; then : + if true; then : if test "$ac_cv_func_getspent" = yes -o "$ac_cv_func_getspnam" = yes; then : py_cv_module_spwd=yes else @@ -19984,9 +19914,7 @@ else fi else py_cv_module_spwd=disabled - fi - ;; esac as_fn_append MODULE_BLOCK "MODULE_SPWD=$py_cv_module_spwd$as_nl" @@ -20014,8 +19942,7 @@ $as_echo_n "checking for stdlib extension module syslog... " >&6; } *syslog*) : py_cv_module_syslog=n/a ;; #( *) : - - if true; then : + if true; then : if test "$ac_cv_header_syslog_h" = yes; then : py_cv_module_syslog=yes else @@ -20023,9 +19950,7 @@ else fi else py_cv_module_syslog=disabled - fi - ;; esac as_fn_append MODULE_BLOCK "MODULE_SYSLOG=$py_cv_module_syslog$as_nl" @@ -20053,8 +19978,7 @@ $as_echo_n "checking for stdlib extension module termios... " >&6; } *termios*) : py_cv_module_termios=n/a ;; #( *) : - - if true; then : + if true; then : if test "$ac_cv_header_termios_h" = yes; then : py_cv_module_termios=yes else @@ -20062,9 +19986,7 @@ else fi else py_cv_module_termios=disabled - fi - ;; esac as_fn_append MODULE_BLOCK "MODULE_TERMIOS=$py_cv_module_termios$as_nl" @@ -20093,8 +20015,7 @@ $as_echo_n "checking for stdlib extension module pyexpat... " >&6; } *pyexpat*) : py_cv_module_pyexpat=n/a ;; #( *) : - - if true; then : + if true; then : if true; then : py_cv_module_pyexpat=yes else @@ -20102,9 +20023,7 @@ else fi else py_cv_module_pyexpat=disabled - fi - ;; esac as_fn_append MODULE_BLOCK "MODULE_PYEXPAT=$py_cv_module_pyexpat$as_nl" @@ -20132,8 +20051,7 @@ $as_echo_n "checking for stdlib extension module _elementtree... " >&6; } *_elementtree*) : py_cv_module__elementtree=n/a ;; #( *) : - - if true; then : + if true; then : if true; then : py_cv_module__elementtree=yes else @@ -20141,9 +20059,7 @@ else fi else py_cv_module__elementtree=disabled - fi - ;; esac as_fn_append MODULE_BLOCK "MODULE__ELEMENTTREE=$py_cv_module__elementtree$as_nl" @@ -20172,10 +20088,7 @@ else MODULE__CODECS_CN_TRUE='#' MODULE__CODECS_CN_FALSE= fi - - - - + as_fn_append MODULE_BLOCK "MODULE__CODECS_CN=yes$as_nl" if true; then MODULE__CODECS_HK_TRUE= @@ -20184,10 +20097,7 @@ else MODULE__CODECS_HK_TRUE='#' MODULE__CODECS_HK_FALSE= fi - - - - + as_fn_append MODULE_BLOCK "MODULE__CODECS_HK=yes$as_nl" if true; then MODULE__CODECS_ISO2022_TRUE= @@ -20196,10 +20106,7 @@ else MODULE__CODECS_ISO2022_TRUE='#' MODULE__CODECS_ISO2022_FALSE= fi - - - - + as_fn_append MODULE_BLOCK "MODULE__CODECS_ISO2022=yes$as_nl" if true; then MODULE__CODECS_JP_TRUE= @@ -20208,10 +20115,7 @@ else MODULE__CODECS_JP_TRUE='#' MODULE__CODECS_JP_FALSE= fi - - - - + as_fn_append MODULE_BLOCK "MODULE__CODECS_JP=yes$as_nl" if true; then MODULE__CODECS_KR_TRUE= @@ -20220,10 +20124,7 @@ else MODULE__CODECS_KR_TRUE='#' MODULE__CODECS_KR_FALSE= fi - - - - + as_fn_append MODULE_BLOCK "MODULE__CODECS_KR=yes$as_nl" if true; then MODULE__CODECS_TW_TRUE= @@ -20232,10 +20133,7 @@ else MODULE__CODECS_TW_TRUE='#' MODULE__CODECS_TW_FALSE= fi - - - - + as_fn_append MODULE_BLOCK "MODULE__CODECS_TW=yes$as_nl" if true; then MODULE__MULTIBYTECODEC_TRUE= @@ -20244,10 +20142,7 @@ else MODULE__MULTIBYTECODEC_TRUE='#' MODULE__MULTIBYTECODEC_FALSE= fi - - - - + as_fn_append MODULE_BLOCK "MODULE__MULTIBYTECODEC=yes$as_nl" if true; then MODULE_UNICODEDATA_TRUE= @@ -20256,10 +20151,7 @@ else MODULE_UNICODEDATA_TRUE='#' MODULE_UNICODEDATA_FALSE= fi - - - - + as_fn_append MODULE_BLOCK "MODULE_UNICODEDATA=yes$as_nl" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _md5" >&5 @@ -20268,8 +20160,7 @@ $as_echo_n "checking for stdlib extension module _md5... " >&6; } *_md5*) : py_cv_module__md5=n/a ;; #( *) : - - if test "$with_builtin_md5" = yes; then : + if test "$with_builtin_md5" = yes; then : if true; then : py_cv_module__md5=yes else @@ -20277,9 +20168,7 @@ else fi else py_cv_module__md5=disabled - fi - ;; esac as_fn_append MODULE_BLOCK "MODULE__MD5=$py_cv_module__md5$as_nl" @@ -20307,8 +20196,7 @@ $as_echo_n "checking for stdlib extension module _sha1... " >&6; } *_sha1*) : py_cv_module__sha1=n/a ;; #( *) : - - if test "$with_builtin_sha1" = yes; then : + if test "$with_builtin_sha1" = yes; then : if true; then : py_cv_module__sha1=yes else @@ -20316,9 +20204,7 @@ else fi else py_cv_module__sha1=disabled - fi - ;; esac as_fn_append MODULE_BLOCK "MODULE__SHA1=$py_cv_module__sha1$as_nl" @@ -20346,8 +20232,7 @@ $as_echo_n "checking for stdlib extension module _sha256... " >&6; } *_sha256*) : py_cv_module__sha256=n/a ;; #( *) : - - if test "$with_builtin_sha256" = yes; then : + if test "$with_builtin_sha256" = yes; then : if true; then : py_cv_module__sha256=yes else @@ -20355,9 +20240,7 @@ else fi else py_cv_module__sha256=disabled - fi - ;; esac as_fn_append MODULE_BLOCK "MODULE__SHA256=$py_cv_module__sha256$as_nl" @@ -20385,8 +20268,7 @@ $as_echo_n "checking for stdlib extension module _sha512... " >&6; } *_sha512*) : py_cv_module__sha512=n/a ;; #( *) : - - if test "$with_builtin_sha512" = yes; then : + if test "$with_builtin_sha512" = yes; then : if true; then : py_cv_module__sha512=yes else @@ -20394,9 +20276,7 @@ else fi else py_cv_module__sha512=disabled - fi - ;; esac as_fn_append MODULE_BLOCK "MODULE__SHA512=$py_cv_module__sha512$as_nl" @@ -20424,8 +20304,7 @@ $as_echo_n "checking for stdlib extension module _sha3... " >&6; } *_sha3*) : py_cv_module__sha3=n/a ;; #( *) : - - if test "$with_builtin_sha3" = yes; then : + if test "$with_builtin_sha3" = yes; then : if true; then : py_cv_module__sha3=yes else @@ -20433,9 +20312,7 @@ else fi else py_cv_module__sha3=disabled - fi - ;; esac as_fn_append MODULE_BLOCK "MODULE__SHA3=$py_cv_module__sha3$as_nl" @@ -20463,8 +20340,7 @@ $as_echo_n "checking for stdlib extension module _blake2... " >&6; } *_blake2*) : py_cv_module__blake2=n/a ;; #( *) : - - if test "$with_builtin_blake2" = yes; then : + if test "$with_builtin_blake2" = yes; then : if true; then : py_cv_module__blake2=yes else @@ -20472,9 +20348,7 @@ else fi else py_cv_module__blake2=disabled - fi - ;; esac as_fn_append MODULE_BLOCK "MODULE__BLAKE2=$py_cv_module__blake2$as_nl" @@ -20503,8 +20377,7 @@ $as_echo_n "checking for stdlib extension module _decimal... " >&6; } *_decimal*) : py_cv_module__decimal=n/a ;; #( *) : - - if true; then : + if true; then : if true; then : py_cv_module__decimal=yes else @@ -20512,9 +20385,7 @@ else fi else py_cv_module__decimal=disabled - fi - ;; esac as_fn_append MODULE_BLOCK "MODULE__DECIMAL=$py_cv_module__decimal$as_nl" @@ -20542,8 +20413,7 @@ $as_echo_n "checking for stdlib extension module _sqlite3... " >&6; } *_sqlite3*) : py_cv_module__sqlite3=n/a ;; #( *) : - - if test "$have_sqlite3" = "yes"; then : + if test "$have_sqlite3" = "yes"; then : if test "$have_supported_sqlite3" = "yes"; then : py_cv_module__sqlite3=yes else @@ -20551,9 +20421,7 @@ else fi else py_cv_module__sqlite3=disabled - fi - ;; esac as_fn_append MODULE_BLOCK "MODULE__SQLITE3=$py_cv_module__sqlite3$as_nl" @@ -20582,8 +20450,7 @@ $as_echo_n "checking for stdlib extension module _testcapi... " >&6; } *_testcapi*) : py_cv_module__testcapi=n/a ;; #( *) : - - if test "$TEST_MODULES" = yes; then : + if test "$TEST_MODULES" = yes; then : if true; then : py_cv_module__testcapi=yes else @@ -20591,9 +20458,7 @@ else fi else py_cv_module__testcapi=disabled - fi - ;; esac as_fn_append MODULE_BLOCK "MODULE__TESTCAPI=$py_cv_module__testcapi$as_nl" @@ -20621,8 +20486,7 @@ $as_echo_n "checking for stdlib extension module _testinternalcapi... " >&6; } *_testinternalcapi*) : py_cv_module__testinternalcapi=n/a ;; #( *) : - - if test "$TEST_MODULES" = yes; then : + if test "$TEST_MODULES" = yes; then : if true; then : py_cv_module__testinternalcapi=yes else @@ -20630,9 +20494,7 @@ else fi else py_cv_module__testinternalcapi=disabled - fi - ;; esac as_fn_append MODULE_BLOCK "MODULE__TESTINTERNALCAPI=$py_cv_module__testinternalcapi$as_nl" @@ -20660,8 +20522,7 @@ $as_echo_n "checking for stdlib extension module _testbuffer... " >&6; } *_testbuffer*) : py_cv_module__testbuffer=n/a ;; #( *) : - - if test "$TEST_MODULES" = yes; then : + if test "$TEST_MODULES" = yes; then : if true; then : py_cv_module__testbuffer=yes else @@ -20669,9 +20530,7 @@ else fi else py_cv_module__testbuffer=disabled - fi - ;; esac as_fn_append MODULE_BLOCK "MODULE__TESTBUFFER=$py_cv_module__testbuffer$as_nl" @@ -20699,8 +20558,7 @@ $as_echo_n "checking for stdlib extension module _testimportmultiple... " >&6; } *_testimportmultiple*) : py_cv_module__testimportmultiple=n/a ;; #( *) : - - if test "$TEST_MODULES" = yes; then : + if test "$TEST_MODULES" = yes; then : if true; then : py_cv_module__testimportmultiple=yes else @@ -20708,9 +20566,7 @@ else fi else py_cv_module__testimportmultiple=disabled - fi - ;; esac as_fn_append MODULE_BLOCK "MODULE__TESTIMPORTMULTIPLE=$py_cv_module__testimportmultiple$as_nl" @@ -20738,8 +20594,7 @@ $as_echo_n "checking for stdlib extension module _testmultiphase... " >&6; } *_testmultiphase*) : py_cv_module__testmultiphase=n/a ;; #( *) : - - if test "$TEST_MODULES" = yes; then : + if test "$TEST_MODULES" = yes; then : if true; then : py_cv_module__testmultiphase=yes else @@ -20747,9 +20602,7 @@ else fi else py_cv_module__testmultiphase=disabled - fi - ;; esac as_fn_append MODULE_BLOCK "MODULE__TESTMULTIPHASE=$py_cv_module__testmultiphase$as_nl" @@ -20777,8 +20630,7 @@ $as_echo_n "checking for stdlib extension module _xxtestfuzz... " >&6; } *_xxtestfuzz*) : py_cv_module__xxtestfuzz=n/a ;; #( *) : - - if test "$TEST_MODULES" = yes; then : + if test "$TEST_MODULES" = yes; then : if true; then : py_cv_module__xxtestfuzz=yes else @@ -20786,9 +20638,7 @@ else fi else py_cv_module__xxtestfuzz=disabled - fi - ;; esac as_fn_append MODULE_BLOCK "MODULE__XXTESTFUZZ=$py_cv_module__xxtestfuzz$as_nl" @@ -20816,8 +20666,7 @@ $as_echo_n "checking for stdlib extension module _ctypes_test... " >&6; } *_ctypes_test*) : py_cv_module__ctypes_test=n/a ;; #( *) : - - if test "$TEST_MODULES" = yes; then : + if test "$TEST_MODULES" = yes; then : if true; then : py_cv_module__ctypes_test=yes else @@ -20825,9 +20674,7 @@ else fi else py_cv_module__ctypes_test=disabled - fi - ;; esac as_fn_append MODULE_BLOCK "MODULE__CTYPES_TEST=$py_cv_module__ctypes_test$as_nl" diff --git a/configure.ac b/configure.ac index ee379b71417c7..3b00735648b5c 100644 --- a/configure.ac +++ b/configure.ac @@ -6037,12 +6037,9 @@ AC_DEFUN([PY_STDLIB_MOD], [ m4_pushdef([modstate], [py_cv_module_$1])dnl AS_CASE([$py_stdlib_not_available], [*$1*], [modstate=n/a], - [ - AS_IF(m4_ifblank([$2], [true], [$2]), + [AS_IF(m4_ifblank([$2], [true], [$2]), [AS_IF([m4_ifblank([$3], [true], [$3])], [modstate=yes], [modstate=missing])], - [modstate=disabled] - ) - ] + [modstate=disabled])] ) _MODULE_BLOCK_ADD(modcond, [$modstate]) AS_VAR_IF([modstate], [yes], [ @@ -6060,13 +6057,14 @@ dnl PY_STDLIB_MOD_SIMPLE([NAME], [CFLAGS], [LDFLAGS]) dnl cflags and ldflags are optional AC_DEFUN([PY_STDLIB_MOD_SIMPLE], [ m4_pushdef([modcond], [MODULE_]m4_toupper([$1]))dnl - AM_CONDITIONAL(modcond, [true]) + AM_CONDITIONAL(modcond, [true])dnl + _MODULE_BLOCK_ADD(modcond, [yes])dnl m4_ifval([$2], [ _MODULE_BLOCK_ADD([MODULE_]m4_toupper([$1])[_CFLAGS], [$2]) - ]) + ])dnl m4_ifval([$3], [ _MODULE_BLOCK_ADD([MODULE_]m4_toupper([$1])[_LDFLAGS], [$3]) - ]) + ])dnl m4_popdef([modcond])dnl ]) diff --git a/setup.py b/setup.py index 91040171a494b..6374ec24518ae 100644 --- a/setup.py +++ b/setup.py @@ -397,6 +397,10 @@ def addext(self, ext, *, update_flags=True): pass else: # not migrated to MODULE_{name} yet. + self.announce( + f'WARNING: Makefile is missing module variable for "{ext.name}"', + level=2 + ) self.extensions.append(ext) def update_extension_flags(self, ext): @@ -995,12 +999,6 @@ def detect_simple_extensions(self): # complex math library functions self.addext(Extension('cmath', ['cmathmodule.c'])) - # time libraries: librt may be needed for clock_gettime() - time_libs = [] - lib = sysconfig.get_config_var('TIMEMODULE_LIB') - if lib: - time_libs.append(lib) - # libm is needed by delta_new() that uses round() and by accum() that # uses modf(). self.addext(Extension('_datetime', ['_datetimemodule.c'])) From webhook-mailer at python.org Mon Nov 22 08:02:41 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 22 Nov 2021 13:02:41 -0000 Subject: [Python-checkins] bpo-45847: Port fcntl to Py_STDLIB_MOD (GH-29696) Message-ID: https://github.com/python/cpython/commit/5b946cadaa1175a5caae98bd2d309840bea52a58 commit: 5b946cadaa1175a5caae98bd2d309840bea52a58 branch: main author: Erlend Egeberg Aasland committer: tiran date: 2021-11-22T14:02:27+01:00 summary: bpo-45847: Port fcntl to Py_STDLIB_MOD (GH-29696) Co-authored-by: Christian Heimes files: M Modules/Setup.stdlib.in M configure M configure.ac M pyconfig.h.in M setup.py diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 5e28a72d7a162..e1ddc137354b7 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -87,6 +87,7 @@ # Modules with some UNIX dependencies # + at MODULE_FCNTL_TRUE@fcntl fcntlmodule.c @MODULE_GRP_TRUE at grp grpmodule.c # needs sys/soundcard.h or linux/soundcard.h (Linux, FreeBSD) @MODULE_OSSAUDIODEV_TRUE at ossaudiodev ossaudiodev.c diff --git a/configure b/configure index 9bd659efbf923..c725d0f92ce4c 100755 --- a/configure +++ b/configure @@ -688,6 +688,8 @@ MODULE_OSSAUDIODEV_FALSE MODULE_OSSAUDIODEV_TRUE MODULE_GRP_FALSE MODULE_GRP_TRUE +MODULE_FCNTL_FALSE +MODULE_FCNTL_TRUE MODULE__DATETIME_FALSE MODULE__DATETIME_TRUE MODULE_MATH_FALSE @@ -13343,7 +13345,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_flock_decl" >&5 $as_echo "$ac_cv_flock_decl" >&6; } -if test "x${ac_cv_flock_decl}" = xyes; then +if test "x$ac_cv_flock_decl" = xyes; then : for ac_func in flock do : ac_fn_c_check_func "$LINENO" "flock" "ac_cv_func_flock" @@ -13352,7 +13354,9 @@ if test "x$ac_cv_func_flock" = xyes; then : #define HAVE_FLOCK 1 _ACEOF -else +fi +done + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for flock in -lbsd" >&5 $as_echo_n "checking for flock in -lbsd... " >&6; } if ${ac_cv_lib_bsd_flock+:} false; then : @@ -13390,18 +13394,10 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_flock" >&5 $as_echo "$ac_cv_lib_bsd_flock" >&6; } if test "x$ac_cv_lib_bsd_flock" = xyes; then : - $as_echo "#define HAVE_FLOCK 1" >>confdefs.h - - -$as_echo "#define FLOCK_NEEDS_LIBBSD 1" >>confdefs.h - - + FCNTL_LIBS="-lbsd" fi -fi -done - fi @@ -19756,6 +19752,43 @@ fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module fcntl" >&5 +$as_echo_n "checking for stdlib extension module fcntl... " >&6; } + case $py_stdlib_not_available in #( + *fcntl*) : + py_cv_module_fcntl=n/a ;; #( + *) : + if true; then : + if test "$ac_cv_header_sys_ioctl_h" = "yes" -a "$ac_cv_header_fcntl_h" = "yes"; then : + py_cv_module_fcntl=yes +else + py_cv_module_fcntl=missing +fi +else + py_cv_module_fcntl=disabled +fi + ;; +esac + as_fn_append MODULE_BLOCK "MODULE_FCNTL=$py_cv_module_fcntl$as_nl" + if test "x$py_cv_module_fcntl" = xyes; then : + + + as_fn_append MODULE_BLOCK "MODULE_FCNTL_LDFLAGS=$FCNTL_LIBS$as_nl" + +fi + if test "$py_cv_module_fcntl" = yes; then + MODULE_FCNTL_TRUE= + MODULE_FCNTL_FALSE='#' +else + MODULE_FCNTL_TRUE='#' + MODULE_FCNTL_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module_fcntl" >&5 +$as_echo "$py_cv_module_fcntl" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module grp" >&5 $as_echo_n "checking for stdlib extension module grp... " >&6; } case $py_stdlib_not_available in #( @@ -20892,6 +20925,10 @@ if test -z "${MODULE__DATETIME_TRUE}" && test -z "${MODULE__DATETIME_FALSE}"; th as_fn_error $? "conditional \"MODULE__DATETIME\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE_FCNTL_TRUE}" && test -z "${MODULE_FCNTL_FALSE}"; then + as_fn_error $? "conditional \"MODULE_FCNTL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE_GRP_TRUE}" && test -z "${MODULE_GRP_FALSE}"; then as_fn_error $? "conditional \"MODULE_GRP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index 3b00735648b5c..25d210bf7eb13 100644 --- a/configure.ac +++ b/configure.ac @@ -3980,14 +3980,11 @@ AC_CACHE_CHECK([for flock declaration], [ac_cv_flock_decl], [ac_cv_flock_decl=no] ) ]) -if test "x${ac_cv_flock_decl}" = xyes; then - AC_CHECK_FUNCS(flock,, - AC_CHECK_LIB(bsd,flock, - [AC_DEFINE(HAVE_FLOCK) - AC_DEFINE(FLOCK_NEEDS_LIBBSD, 1, Define if flock needs to be linked with bsd library.) - ]) - ) -fi +dnl Linking with libbsd may be necessary on AIX for flock function. +AS_VAR_IF([ac_cv_flock_decl], [yes], + AC_CHECK_FUNCS([flock]) + AC_CHECK_LIB([bsd], [flock], [FCNTL_LIBS="-lbsd"]) +) PY_CHECK_FUNC([getpagesize], [#include ]) @@ -6095,6 +6092,11 @@ PY_STDLIB_MOD_SIMPLE([math], [], [$LIBM]) dnl needs libm and on some platforms librt PY_STDLIB_MOD_SIMPLE([_datetime], [], [$TIMEMODULE_LIB $LIBM]) +dnl needs libbsd on some platforms +PY_STDLIB_MOD([fcntl], + [], [test "$ac_cv_header_sys_ioctl_h" = "yes" -a "$ac_cv_header_fcntl_h" = "yes"], + [], [$FCNTL_LIBS]) + dnl platform specific extensions PY_STDLIB_MOD([grp], [], [test "$ac_cv_func_getgrgid" = yes -o "$ac_cv_func_getgrgid_r" = yes]) PY_STDLIB_MOD([ossaudiodev], diff --git a/pyconfig.h.in b/pyconfig.h.in index afd3ebe35bc0d..6f3adb2314ab7 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -51,9 +51,6 @@ significant word first */ #undef FLOAT_WORDS_BIGENDIAN -/* Define if flock needs to be linked with bsd library. */ -#undef FLOCK_NEEDS_LIBBSD - /* Define if getpgrp() must be called as getpgrp(0). */ #undef GETPGRP_HAVE_ARG diff --git a/setup.py b/setup.py index 6374ec24518ae..28fd6da383a68 100644 --- a/setup.py +++ b/setup.py @@ -1030,12 +1030,7 @@ def detect_simple_extensions(self): # supported...) # fcntl(2) and ioctl(2) - libs = [] - if (self.config_h_vars.get('FLOCK_NEEDS_LIBBSD', False)): - # May be necessary on AIX for flock function - libs = ['bsd'] - self.add(Extension('fcntl', ['fcntlmodule.c'], - libraries=libs)) + self.addext(Extension('fcntl', ['fcntlmodule.c'])) # grp(3) self.addext(Extension('grp', ['grpmodule.c'])) self.addext(Extension('spwd', ['spwdmodule.c'])) From webhook-mailer at python.org Mon Nov 22 08:26:21 2021 From: webhook-mailer at python.org (ericvsmith) Date: Mon, 22 Nov 2021 13:26:21 -0000 Subject: [Python-checkins] bpo-44649: Fix dataclasses(slots=True) with a field with a default, but init=False (GH-29692) Message-ID: https://github.com/python/cpython/commit/d3062f672c92855b7e9e962ad4bf1a67abd4589b commit: d3062f672c92855b7e9e962ad4bf1a67abd4589b branch: main author: Eric V. Smith committer: ericvsmith date: 2021-11-22T08:26:12-05:00 summary: bpo-44649: Fix dataclasses(slots=True) with a field with a default, but init=False (GH-29692) Special handling is needed, because for non-slots dataclasses the instance attributes are not set: reading from a field just references the class's attribute of the same name, which contains the default value. But this doesn't work for classes using __slots__: they don't read the class's attribute. So in that case (and that case only), initialize the instance attribute. Handle this for both normal defaults, and for fields using default_factory. files: A Misc/NEWS.d/next/Library/2021-11-21-20-50-42.bpo-44649.E8M936.rst M Lib/dataclasses.py M Lib/test/test_dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index aca60501d0e0f..8643589077a4a 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -447,7 +447,7 @@ def _field_assign(frozen, name, value, self_name): return f'{self_name}.{name}={value}' -def _field_init(f, frozen, globals, self_name): +def _field_init(f, frozen, globals, self_name, slots): # Return the text of the line in the body of __init__ that will # initialize this field. @@ -487,9 +487,15 @@ def _field_init(f, frozen, globals, self_name): globals[default_name] = f.default value = f.name else: - # This field does not need initialization. Signify that - # to the caller by returning None. - return None + # If the class has slots, then initialize this field. + if slots and f.default is not MISSING: + globals[default_name] = f.default + value = default_name + else: + # This field does not need initialization: reading from it will + # just use the class attribute that contains the default. + # Signify that to the caller by returning None. + return None # Only test this now, so that we can create variables for the # default. However, return None to signify that we're not going @@ -521,7 +527,7 @@ def _init_param(f): def _init_fn(fields, std_fields, kw_only_fields, frozen, has_post_init, - self_name, globals): + self_name, globals, slots): # fields contains both real fields and InitVar pseudo-fields. # Make sure we don't have fields without defaults following fields @@ -548,7 +554,7 @@ def _init_fn(fields, std_fields, kw_only_fields, frozen, has_post_init, body_lines = [] for f in fields: - line = _field_init(f, frozen, locals, self_name) + line = _field_init(f, frozen, locals, self_name, slots) # line is None means that this field doesn't require # initialization (it's a pseudo-field). Just skip it. if line: @@ -1027,6 +1033,7 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen, '__dataclass_self__' if 'self' in fields else 'self', globals, + slots, )) # Get the fields as a list, and include only real fields. This is diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index b00d0484d387e..bcd004f4ec3aa 100644 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -2880,6 +2880,28 @@ def test_frozen_pickle(self): self.assertIsNot(obj, p) self.assertEqual(obj, p) + def test_slots_with_default_no_init(self): + # Originally reported in bpo-44649. + @dataclass(slots=True) + class A: + a: str + b: str = field(default='b', init=False) + + obj = A("a") + self.assertEqual(obj.a, 'a') + self.assertEqual(obj.b, 'b') + + def test_slots_with_default_factory_no_init(self): + # Originally reported in bpo-44649. + @dataclass(slots=True) + class A: + a: str + b: str = field(default_factory=lambda:'b', init=False) + + obj = A("a") + self.assertEqual(obj.a, 'a') + self.assertEqual(obj.b, 'b') + class TestDescriptors(unittest.TestCase): def test_set_name(self): # See bpo-33141. diff --git a/Misc/NEWS.d/next/Library/2021-11-21-20-50-42.bpo-44649.E8M936.rst b/Misc/NEWS.d/next/Library/2021-11-21-20-50-42.bpo-44649.E8M936.rst new file mode 100644 index 0000000000000..f6391a915a821 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-21-20-50-42.bpo-44649.E8M936.rst @@ -0,0 +1,2 @@ +Handle dataclass(slots=True) with a field that has default a default value, +but for which init=False. From webhook-mailer at python.org Mon Nov 22 08:47:50 2021 From: webhook-mailer at python.org (miss-islington) Date: Mon, 22 Nov 2021 13:47:50 -0000 Subject: [Python-checkins] bpo-44649: Fix dataclasses(slots=True) with a field with a default, but init=False (GH-29692) Message-ID: https://github.com/python/cpython/commit/10343bd98390ef15909e3a19f26a6178162996fd commit: 10343bd98390ef15909e3a19f26a6178162996fd branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-22T05:47:41-08:00 summary: bpo-44649: Fix dataclasses(slots=True) with a field with a default, but init=False (GH-29692) Special handling is needed, because for non-slots dataclasses the instance attributes are not set: reading from a field just references the class's attribute of the same name, which contains the default value. But this doesn't work for classes using __slots__: they don't read the class's attribute. So in that case (and that case only), initialize the instance attribute. Handle this for both normal defaults, and for fields using default_factory. (cherry picked from commit d3062f672c92855b7e9e962ad4bf1a67abd4589b) Co-authored-by: Eric V. Smith files: A Misc/NEWS.d/next/Library/2021-11-21-20-50-42.bpo-44649.E8M936.rst M Lib/dataclasses.py M Lib/test/test_dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 4f4aa3d3487ce..b3a9194d9d068 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -447,7 +447,7 @@ def _field_assign(frozen, name, value, self_name): return f'{self_name}.{name}={value}' -def _field_init(f, frozen, globals, self_name): +def _field_init(f, frozen, globals, self_name, slots): # Return the text of the line in the body of __init__ that will # initialize this field. @@ -487,9 +487,15 @@ def _field_init(f, frozen, globals, self_name): globals[default_name] = f.default value = f.name else: - # This field does not need initialization. Signify that - # to the caller by returning None. - return None + # If the class has slots, then initialize this field. + if slots and f.default is not MISSING: + globals[default_name] = f.default + value = default_name + else: + # This field does not need initialization: reading from it will + # just use the class attribute that contains the default. + # Signify that to the caller by returning None. + return None # Only test this now, so that we can create variables for the # default. However, return None to signify that we're not going @@ -521,7 +527,7 @@ def _init_param(f): def _init_fn(fields, std_fields, kw_only_fields, frozen, has_post_init, - self_name, globals): + self_name, globals, slots): # fields contains both real fields and InitVar pseudo-fields. # Make sure we don't have fields without defaults following fields @@ -548,7 +554,7 @@ def _init_fn(fields, std_fields, kw_only_fields, frozen, has_post_init, body_lines = [] for f in fields: - line = _field_init(f, frozen, locals, self_name) + line = _field_init(f, frozen, locals, self_name, slots) # line is None means that this field doesn't require # initialization (it's a pseudo-field). Just skip it. if line: @@ -1027,6 +1033,7 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen, '__dataclass_self__' if 'self' in fields else 'self', globals, + slots, )) # Get the fields as a list, and include only real fields. This is diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index b00d0484d387e..bcd004f4ec3aa 100644 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -2880,6 +2880,28 @@ def test_frozen_pickle(self): self.assertIsNot(obj, p) self.assertEqual(obj, p) + def test_slots_with_default_no_init(self): + # Originally reported in bpo-44649. + @dataclass(slots=True) + class A: + a: str + b: str = field(default='b', init=False) + + obj = A("a") + self.assertEqual(obj.a, 'a') + self.assertEqual(obj.b, 'b') + + def test_slots_with_default_factory_no_init(self): + # Originally reported in bpo-44649. + @dataclass(slots=True) + class A: + a: str + b: str = field(default_factory=lambda:'b', init=False) + + obj = A("a") + self.assertEqual(obj.a, 'a') + self.assertEqual(obj.b, 'b') + class TestDescriptors(unittest.TestCase): def test_set_name(self): # See bpo-33141. diff --git a/Misc/NEWS.d/next/Library/2021-11-21-20-50-42.bpo-44649.E8M936.rst b/Misc/NEWS.d/next/Library/2021-11-21-20-50-42.bpo-44649.E8M936.rst new file mode 100644 index 0000000000000..f6391a915a821 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-21-20-50-42.bpo-44649.E8M936.rst @@ -0,0 +1,2 @@ +Handle dataclass(slots=True) with a field that has default a default value, +but for which init=False. From webhook-mailer at python.org Mon Nov 22 08:50:09 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 22 Nov 2021 13:50:09 -0000 Subject: [Python-checkins] bpo-45847: Port mmap, select, and _xxsubinterpreters to Py_STDLIB_MOD (GH-29703) Message-ID: https://github.com/python/cpython/commit/b451673f93465a27ee61e408190ee61cb9dbd5b6 commit: b451673f93465a27ee61e408190ee61cb9dbd5b6 branch: main author: Erlend Egeberg Aasland committer: tiran date: 2021-11-22T14:49:58+01:00 summary: bpo-45847: Port mmap, select, and _xxsubinterpreters to Py_STDLIB_MOD (GH-29703) files: M Modules/Setup.stdlib.in M configure M configure.ac M setup.py diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index e1ddc137354b7..339a32416d820 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -40,6 +40,7 @@ @MODULE__QUEUE_TRUE at _queue _queuemodule.c @MODULE__RANDOM_TRUE at _random _randommodule.c @MODULE__TYPING_TRUE at _typing _typingmodule.c + at MODULE__XXSUBINTERPRETERS_TRUE@_xxsubinterpreters __xxsubinterpretersmodule.c @MODULE__ZONEINFO_TRUE at _zoneinfo _zoneinfo.c # needs libm @@ -89,9 +90,11 @@ @MODULE_FCNTL_TRUE at fcntl fcntlmodule.c @MODULE_GRP_TRUE at grp grpmodule.c + at MODULE_MMAP_TRUE@mmap mmapmodule.c # needs sys/soundcard.h or linux/soundcard.h (Linux, FreeBSD) @MODULE_OSSAUDIODEV_TRUE at ossaudiodev ossaudiodev.c @MODULE_RESOURCE_TRUE at resource resource.c + at MODULE_SELECT_TRUE@select selectmodule.c # AIX has shadow passwords, but does not provide getspent API @MODULE_SPWD_TRUE at spwd spwdmodule.c @MODULE_SYSLOG_TRUE at syslog syslogmodule.c diff --git a/configure b/configure index c725d0f92ce4c..f3c33614e4faf 100755 --- a/configure +++ b/configure @@ -688,6 +688,8 @@ MODULE_OSSAUDIODEV_FALSE MODULE_OSSAUDIODEV_TRUE MODULE_GRP_FALSE MODULE_GRP_TRUE +MODULE_MMAP_FALSE +MODULE_MMAP_TRUE MODULE_FCNTL_FALSE MODULE_FCNTL_TRUE MODULE__DATETIME_FALSE @@ -700,8 +702,12 @@ MODULE__STATISTICS_FALSE MODULE__STATISTICS_TRUE MODULE__ZONEINFO_FALSE MODULE__ZONEINFO_TRUE +MODULE__XXSUBINTERPRETERS_FALSE +MODULE__XXSUBINTERPRETERS_TRUE MODULE__TYPING_FALSE MODULE__TYPING_TRUE +MODULE_SELECT_FALSE +MODULE_SELECT_TRUE MODULE__RANDOM_FALSE MODULE__RANDOM_TRUE MODULE__QUEUE_FALSE @@ -19687,6 +19693,15 @@ else fi as_fn_append MODULE_BLOCK "MODULE__RANDOM=yes$as_nl" + if true; then + MODULE_SELECT_TRUE= + MODULE_SELECT_FALSE='#' +else + MODULE_SELECT_TRUE='#' + MODULE_SELECT_FALSE= +fi + as_fn_append MODULE_BLOCK "MODULE_SELECT=yes$as_nl" + if true; then MODULE__TYPING_TRUE= MODULE__TYPING_FALSE='#' @@ -19696,6 +19711,15 @@ else fi as_fn_append MODULE_BLOCK "MODULE__TYPING=yes$as_nl" + if true; then + MODULE__XXSUBINTERPRETERS_TRUE= + MODULE__XXSUBINTERPRETERS_FALSE='#' +else + MODULE__XXSUBINTERPRETERS_TRUE='#' + MODULE__XXSUBINTERPRETERS_FALSE= +fi + as_fn_append MODULE_BLOCK "MODULE__XXSUBINTERPRETERS=yes$as_nl" + if true; then MODULE__ZONEINFO_TRUE= MODULE__ZONEINFO_FALSE='#' @@ -19788,6 +19812,42 @@ fi $as_echo "$py_cv_module_fcntl" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module mmap" >&5 +$as_echo_n "checking for stdlib extension module mmap... " >&6; } + case $py_stdlib_not_available in #( + *mmap*) : + py_cv_module_mmap=n/a ;; #( + *) : + if true; then : + if test "$ac_cv_header_sys_mman_h" = "yes" -a "$ac_cv_header_sys_stat_h" = "yes"; then : + py_cv_module_mmap=yes +else + py_cv_module_mmap=missing +fi +else + py_cv_module_mmap=disabled +fi + ;; +esac + as_fn_append MODULE_BLOCK "MODULE_MMAP=$py_cv_module_mmap$as_nl" + if test "x$py_cv_module_mmap" = xyes; then : + + + + +fi + if test "$py_cv_module_mmap" = yes; then + MODULE_MMAP_TRUE= + MODULE_MMAP_FALSE='#' +else + MODULE_MMAP_TRUE='#' + MODULE_MMAP_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module_mmap" >&5 +$as_echo "$py_cv_module_mmap" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module grp" >&5 $as_echo_n "checking for stdlib extension module grp... " >&6; } @@ -20901,10 +20961,18 @@ if test -z "${MODULE__RANDOM_TRUE}" && test -z "${MODULE__RANDOM_FALSE}"; then as_fn_error $? "conditional \"MODULE__RANDOM\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE_SELECT_TRUE}" && test -z "${MODULE_SELECT_FALSE}"; then + as_fn_error $? "conditional \"MODULE_SELECT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__TYPING_TRUE}" && test -z "${MODULE__TYPING_FALSE}"; then as_fn_error $? "conditional \"MODULE__TYPING\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__XXSUBINTERPRETERS_TRUE}" && test -z "${MODULE__XXSUBINTERPRETERS_FALSE}"; then + as_fn_error $? "conditional \"MODULE__XXSUBINTERPRETERS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__ZONEINFO_TRUE}" && test -z "${MODULE__ZONEINFO_FALSE}"; then as_fn_error $? "conditional \"MODULE__ZONEINFO\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -20929,6 +20997,10 @@ if test -z "${MODULE_FCNTL_TRUE}" && test -z "${MODULE_FCNTL_FALSE}"; then as_fn_error $? "conditional \"MODULE_FCNTL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE_MMAP_TRUE}" && test -z "${MODULE_MMAP_FALSE}"; then + as_fn_error $? "conditional \"MODULE_MMAP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE_GRP_TRUE}" && test -z "${MODULE_GRP_FALSE}"; then as_fn_error $? "conditional \"MODULE_GRP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index 25d210bf7eb13..224a9b959d4f9 100644 --- a/configure.ac +++ b/configure.ac @@ -6081,7 +6081,9 @@ PY_STDLIB_MOD_SIMPLE([_opcode]) PY_STDLIB_MOD_SIMPLE([_pickle]) PY_STDLIB_MOD_SIMPLE([_queue]) PY_STDLIB_MOD_SIMPLE([_random]) +PY_STDLIB_MOD_SIMPLE([select]) PY_STDLIB_MOD_SIMPLE([_typing]) +PY_STDLIB_MOD_SIMPLE([_xxsubinterpreters]) PY_STDLIB_MOD_SIMPLE([_zoneinfo]) dnl needs libm @@ -6092,10 +6094,12 @@ PY_STDLIB_MOD_SIMPLE([math], [], [$LIBM]) dnl needs libm and on some platforms librt PY_STDLIB_MOD_SIMPLE([_datetime], [], [$TIMEMODULE_LIB $LIBM]) -dnl needs libbsd on some platforms +dnl modules with some unix dependencies PY_STDLIB_MOD([fcntl], [], [test "$ac_cv_header_sys_ioctl_h" = "yes" -a "$ac_cv_header_fcntl_h" = "yes"], [], [$FCNTL_LIBS]) +PY_STDLIB_MOD([mmap], + [], [test "$ac_cv_header_sys_mman_h" = "yes" -a "$ac_cv_header_sys_stat_h" = "yes"]) dnl platform specific extensions PY_STDLIB_MOD([grp], [], [test "$ac_cv_func_getgrgid" = yes -o "$ac_cv_func_getgrgid_r" = yes]) diff --git a/setup.py b/setup.py index 28fd6da383a68..d4eff363d24ef 100644 --- a/setup.py +++ b/setup.py @@ -1036,17 +1036,17 @@ def detect_simple_extensions(self): self.addext(Extension('spwd', ['spwdmodule.c'])) # select(2); not on ancient System V - self.add(Extension('select', ['selectmodule.c'])) + self.addext(Extension('select', ['selectmodule.c'])) # Memory-mapped files (also works on Win32). - self.add(Extension('mmap', ['mmapmodule.c'])) + self.addext(Extension('mmap', ['mmapmodule.c'])) # Lance Ellinghaus's syslog module # syslog daemon interface self.addext(Extension('syslog', ['syslogmodule.c'])) # Python interface to subinterpreter C-API. - self.add(Extension('_xxsubinterpreters', ['_xxsubinterpretersmodule.c'])) + self.addext(Extension('_xxsubinterpreters', ['_xxsubinterpretersmodule.c'])) # # Here ends the simple stuff. From here on, modules need certain From webhook-mailer at python.org Mon Nov 22 08:52:38 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 22 Nov 2021 13:52:38 -0000 Subject: [Python-checkins] bpo-45847: Port compression libs to PY_STDLIB_MOD (GH-29702) Message-ID: https://github.com/python/cpython/commit/d9cedabeba0d87799f99c0717e81743a1c2d34ce commit: d9cedabeba0d87799f99c0717e81743a1c2d34ce branch: main author: Christian Heimes committer: tiran date: 2021-11-22T14:52:29+01:00 summary: bpo-45847: Port compression libs to PY_STDLIB_MOD (GH-29702) files: M Modules/Setup.stdlib.in M configure M configure.ac M pyconfig.h.in M setup.py diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 339a32416d820..fdd20d4d6217b 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -56,6 +56,13 @@ # with ./configure --with-system-libmpdec @MODULE__DECIMAL_TRUE at _decimal _decimal/_decimal.c +# compression libs and binascii (optional CRC32 from zlib) +# bindings need -lbz2, -lz, or -llzma, respectively + at MODULE_BINASCII_TRUE@binascii binascii.c + at MODULE__BZ2_TRUE@_bz2 _bz2module.c + at MODULE__LZMA_TRUE@_lzma _lzmamodule.c + at MODULE_ZLIB_TRUE@zlib zlibmodule.c + # hashing builtins, can be disabled with --without-builtin-hashlib-hashes @MODULE__MD5_TRUE at _md5 md5module.c @MODULE__SHA1_TRUE at _sha1 sha1module.c diff --git a/configure b/configure index f3c33614e4faf..0840727058042 100755 --- a/configure +++ b/configure @@ -638,6 +638,14 @@ MODULE__TESTINTERNALCAPI_FALSE MODULE__TESTINTERNALCAPI_TRUE MODULE__TESTCAPI_FALSE MODULE__TESTCAPI_TRUE +MODULE__LZMA_FALSE +MODULE__LZMA_TRUE +MODULE__BZ2_FALSE +MODULE__BZ2_TRUE +MODULE_BINASCII_FALSE +MODULE_BINASCII_TRUE +MODULE_ZLIB_FALSE +MODULE_ZLIB_TRUE MODULE__SQLITE3_FALSE MODULE__SQLITE3_TRUE MODULE__DECIMAL_FALSE @@ -761,6 +769,12 @@ HAVE_GETHOSTBYNAME_R_3_ARG HAVE_GETHOSTBYNAME_R_5_ARG HAVE_GETHOSTBYNAME_R_6_ARG LIBOBJS +LIBLZMA_LIBS +LIBLZMA_CFLAGS +BZIP2_LIBS +BZIP2_CFLAGS +ZLIB_LIBS +ZLIB_CFLAGS TRUE MACHDEP_OBJS DYNLOADFILE @@ -1001,7 +1015,13 @@ CPPFLAGS CPP PROFILE_TASK LIBSQLITE3_CFLAGS -LIBSQLITE3_LIBS' +LIBSQLITE3_LIBS +ZLIB_CFLAGS +ZLIB_LIBS +BZIP2_CFLAGS +BZIP2_LIBS +LIBLZMA_CFLAGS +LIBLZMA_LIBS' # Initialize some variables set by options. @@ -1779,6 +1799,15 @@ Some influential environment variables: C compiler flags for LIBSQLITE3, overriding pkg-config LIBSQLITE3_LIBS linker flags for LIBSQLITE3, overriding pkg-config + ZLIB_CFLAGS C compiler flags for ZLIB, overriding pkg-config + ZLIB_LIBS linker flags for ZLIB, overriding pkg-config + BZIP2_CFLAGS + C compiler flags for BZIP2, overriding pkg-config + BZIP2_LIBS linker flags for BZIP2, overriding pkg-config + LIBLZMA_CFLAGS + C compiler flags for LIBLZMA, overriding pkg-config + LIBLZMA_LIBS + linker flags for LIBLZMA, overriding pkg-config Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. @@ -13710,7 +13739,69 @@ $as_echo "#define HAVE_LCHFLAGS 1" >>confdefs.h fi -for ac_header in zlib.h + + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ZLIB" >&5 +$as_echo_n "checking for ZLIB... " >&6; } + +if test -n "$ZLIB_CFLAGS"; then + pkg_cv_ZLIB_CFLAGS="$ZLIB_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"zlib >= 1.2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "zlib >= 1.2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_ZLIB_CFLAGS=`$PKG_CONFIG --cflags "zlib >= 1.2.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$ZLIB_LIBS"; then + pkg_cv_ZLIB_LIBS="$ZLIB_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"zlib >= 1.2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "zlib >= 1.2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_ZLIB_LIBS=`$PKG_CONFIG --libs "zlib >= 1.2.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + ZLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "zlib >= 1.2.0" 2>&1` + else + ZLIB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "zlib >= 1.2.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$ZLIB_PKG_ERRORS" >&5 + + + for ac_header in zlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" if test "x$ac_cv_header_zlib_h" = xyes; then : @@ -13718,8 +13809,13 @@ if test "x$ac_cv_header_zlib_h" = xyes; then : #define HAVE_ZLIB_H 1 _ACEOF - save_LIBS="$LIBS" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gzread in -lz" >&5 + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gzread in -lz" >&5 $as_echo_n "checking for gzread in -lz... " >&6; } if ${ac_cv_lib_z_gzread+:} false; then : $as_echo_n "(cached) " >&6 @@ -13756,16 +13852,11 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_gzread" >&5 $as_echo "$ac_cv_lib_z_gzread" >&6; } if test "x$ac_cv_lib_z_gzread" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBZ 1 -_ACEOF - - LIBS="-lz $LIBS" -fi - - LIBS="$save_LIBS" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflateCopy in -lz" >&5 + have_zlib=yes + ZLIB_CFLAGS= + ZLIB_LIBS=-lz + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflateCopy in -lz" >&5 $as_echo_n "checking for inflateCopy in -lz... " >&6; } if ${ac_cv_lib_z_inflateCopy+:} false; then : $as_echo_n "(cached) " >&6 @@ -13802,34 +13893,57 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_inflateCopy" >&5 $as_echo "$ac_cv_lib_z_inflateCopy" >&6; } if test "x$ac_cv_lib_z_inflateCopy" = xyes; then : + $as_echo "#define HAVE_ZLIB_COPY 1" >>confdefs.h + +fi -$as_echo "#define HAVE_ZLIB_COPY 1" >>confdefs.h + +else + + have_zlib=no fi - LIBS="$save_LIBS" +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS + + + +else + have_zlib=no fi done -for ac_header in bzlib.h +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + for ac_header in zlib.h do : - ac_fn_c_check_header_mongrel "$LINENO" "bzlib.h" "ac_cv_header_bzlib_h" "$ac_includes_default" -if test "x$ac_cv_header_bzlib_h" = xyes; then : + ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" +if test "x$ac_cv_header_zlib_h" = xyes; then : cat >>confdefs.h <<_ACEOF -#define HAVE_BZLIB_H 1 +#define HAVE_ZLIB_H 1 _ACEOF - save_LIBS="$LIBS" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BZ2_bzCompress in -lbz2" >&5 -$as_echo_n "checking for BZ2_bzCompress in -lbz2... " >&6; } -if ${ac_cv_lib_bz2_BZ2_bzCompress+:} false; then : + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gzread in -lz" >&5 +$as_echo_n "checking for gzread in -lz... " >&6; } +if ${ac_cv_lib_z_gzread+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS -LIBS="-lbz2 $LIBS" +LIBS="-lz $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -13839,58 +13953,38 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext #ifdef __cplusplus extern "C" #endif -char BZ2_bzCompress (); +char gzread (); int main () { -return BZ2_bzCompress (); +return gzread (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_bz2_BZ2_bzCompress=yes + ac_cv_lib_z_gzread=yes else - ac_cv_lib_bz2_BZ2_bzCompress=no + ac_cv_lib_z_gzread=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bz2_BZ2_bzCompress" >&5 -$as_echo "$ac_cv_lib_bz2_BZ2_bzCompress" >&6; } -if test "x$ac_cv_lib_bz2_BZ2_bzCompress" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBBZ2 1 -_ACEOF - - LIBS="-lbz2 $LIBS" - -fi - - LIBS="$save_LIBS" - -fi - -done - - -for ac_header in lzma.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "lzma.h" "ac_cv_header_lzma_h" "$ac_includes_default" -if test "x$ac_cv_header_lzma_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LZMA_H 1 -_ACEOF +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_gzread" >&5 +$as_echo "$ac_cv_lib_z_gzread" >&6; } +if test "x$ac_cv_lib_z_gzread" = xyes; then : - save_LIBS="$LIBS" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lzma_easy_encoder in -llzma" >&5 -$as_echo_n "checking for lzma_easy_encoder in -llzma... " >&6; } -if ${ac_cv_lib_lzma_lzma_easy_encoder+:} false; then : + have_zlib=yes + ZLIB_CFLAGS= + ZLIB_LIBS=-lz + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflateCopy in -lz" >&5 +$as_echo_n "checking for inflateCopy in -lz... " >&6; } +if ${ac_cv_lib_z_inflateCopy+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS -LIBS="-llzma $LIBS" +LIBS="-lz $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -13900,128 +13994,602 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext #ifdef __cplusplus extern "C" #endif -char lzma_easy_encoder (); +char inflateCopy (); int main () { -return lzma_easy_encoder (); +return inflateCopy (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_lzma_lzma_easy_encoder=yes + ac_cv_lib_z_inflateCopy=yes else - ac_cv_lib_lzma_lzma_easy_encoder=no + ac_cv_lib_z_inflateCopy=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lzma_lzma_easy_encoder" >&5 -$as_echo "$ac_cv_lib_lzma_lzma_easy_encoder" >&6; } -if test "x$ac_cv_lib_lzma_lzma_easy_encoder" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBLZMA 1 -_ACEOF - - LIBS="-llzma $LIBS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_inflateCopy" >&5 +$as_echo "$ac_cv_lib_z_inflateCopy" >&6; } +if test "x$ac_cv_lib_z_inflateCopy" = xyes; then : + $as_echo "#define HAVE_ZLIB_COPY 1" >>confdefs.h fi - LIBS="$save_LIBS" + +else + + have_zlib=no fi -done +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for hstrerror" >&5 -$as_echo_n "checking for hstrerror... " >&6; } -if ${ac_cv_func_hstrerror+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ -void *x=hstrerror - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_func_hstrerror=yes else - ac_cv_func_hstrerror=no + have_zlib=no fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_hstrerror" >&5 -$as_echo "$ac_cv_func_hstrerror" >&6; } - if test "x$ac_cv_func_hstrerror" = xyes; then : +done -$as_echo "#define HAVE_HSTRERROR 1" >>confdefs.h -fi +else + ZLIB_CFLAGS=$pkg_cv_ZLIB_CFLAGS + ZLIB_LIBS=$pkg_cv_ZLIB_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_zlib=yes + $as_echo "#define HAVE_ZLIB_COPY 1" >>confdefs.h +fi +if test "x$have_zlib" = xyes; then : + BINASCII_CFLAGS="-DUSE_ZLIB_CRC32 $ZLIB_CFLAGS" + BINASCII_LIBS="$ZLIB_LIBS" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_aton" >&5 -$as_echo_n "checking for inet_aton... " >&6; } -if ${ac_cv_func_inet_aton+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ +fi -#include -#include -#include -#include -int -main () -{ -void *x=inet_aton - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_func_inet_aton=yes +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BZIP2" >&5 +$as_echo_n "checking for BZIP2... " >&6; } + +if test -n "$BZIP2_CFLAGS"; then + pkg_cv_BZIP2_CFLAGS="$BZIP2_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"bzip2\""; } >&5 + ($PKG_CONFIG --exists --print-errors "bzip2") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_BZIP2_CFLAGS=`$PKG_CONFIG --cflags "bzip2" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes else - ac_cv_func_inet_aton=no + pkg_failed=yes fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - + else + pkg_failed=untried fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_inet_aton" >&5 -$as_echo "$ac_cv_func_inet_aton" >&6; } - if test "x$ac_cv_func_inet_aton" = xyes; then : - -$as_echo "#define HAVE_INET_ATON 1" >>confdefs.h - +if test -n "$BZIP2_LIBS"; then + pkg_cv_BZIP2_LIBS="$BZIP2_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"bzip2\""; } >&5 + ($PKG_CONFIG --exists --print-errors "bzip2") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_BZIP2_LIBS=`$PKG_CONFIG --libs "bzip2" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried fi +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + BZIP2_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "bzip2" 2>&1` + else + BZIP2_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "bzip2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$BZIP2_PKG_ERRORS" >&5 - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_pton" >&5 -$as_echo_n "checking for inet_pton... " >&6; } -if ${ac_cv_func_inet_pton+:} false; then : - $as_echo_n "(cached) " >&6 -else + for ac_header in bzlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "bzlib.h" "ac_cv_header_bzlib_h" "$ac_includes_default" +if test "x$ac_cv_header_bzlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_BZLIB_H 1 +_ACEOF + + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BZ2_bzCompress in -lbz2" >&5 +$as_echo_n "checking for BZ2_bzCompress in -lbz2... " >&6; } +if ${ac_cv_lib_bz2_BZ2_bzCompress+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbz2 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char BZ2_bzCompress (); +int +main () +{ +return BZ2_bzCompress (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_bz2_BZ2_bzCompress=yes +else + ac_cv_lib_bz2_BZ2_bzCompress=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bz2_BZ2_bzCompress" >&5 +$as_echo "$ac_cv_lib_bz2_BZ2_bzCompress" >&6; } +if test "x$ac_cv_lib_bz2_BZ2_bzCompress" = xyes; then : + + have_bzip2=yes + BZIP2_CFLAGS= + BZIP2_LIBS=-lbz2 + +else + have_bzip2=no +fi + + +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS + + + +else + have_bzip2=no +fi + +done + + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + for ac_header in bzlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "bzlib.h" "ac_cv_header_bzlib_h" "$ac_includes_default" +if test "x$ac_cv_header_bzlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_BZLIB_H 1 +_ACEOF + + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BZ2_bzCompress in -lbz2" >&5 +$as_echo_n "checking for BZ2_bzCompress in -lbz2... " >&6; } +if ${ac_cv_lib_bz2_BZ2_bzCompress+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbz2 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char BZ2_bzCompress (); +int +main () +{ +return BZ2_bzCompress (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_bz2_BZ2_bzCompress=yes +else + ac_cv_lib_bz2_BZ2_bzCompress=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bz2_BZ2_bzCompress" >&5 +$as_echo "$ac_cv_lib_bz2_BZ2_bzCompress" >&6; } +if test "x$ac_cv_lib_bz2_BZ2_bzCompress" = xyes; then : + + have_bzip2=yes + BZIP2_CFLAGS= + BZIP2_LIBS=-lbz2 + +else + have_bzip2=no +fi + + +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS + + + +else + have_bzip2=no +fi + +done + + +else + BZIP2_CFLAGS=$pkg_cv_BZIP2_CFLAGS + BZIP2_LIBS=$pkg_cv_BZIP2_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_bzip2=yes +fi + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBLZMA" >&5 +$as_echo_n "checking for LIBLZMA... " >&6; } + +if test -n "$LIBLZMA_CFLAGS"; then + pkg_cv_LIBLZMA_CFLAGS="$LIBLZMA_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"liblzma\""; } >&5 + ($PKG_CONFIG --exists --print-errors "liblzma") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBLZMA_CFLAGS=`$PKG_CONFIG --cflags "liblzma" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LIBLZMA_LIBS"; then + pkg_cv_LIBLZMA_LIBS="$LIBLZMA_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"liblzma\""; } >&5 + ($PKG_CONFIG --exists --print-errors "liblzma") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBLZMA_LIBS=`$PKG_CONFIG --libs "liblzma" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LIBLZMA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "liblzma" 2>&1` + else + LIBLZMA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "liblzma" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LIBLZMA_PKG_ERRORS" >&5 + + + for ac_header in lzma.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "lzma.h" "ac_cv_header_lzma_h" "$ac_includes_default" +if test "x$ac_cv_header_lzma_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LZMA_H 1 +_ACEOF + + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lzma_easy_encoder in -llzma" >&5 +$as_echo_n "checking for lzma_easy_encoder in -llzma... " >&6; } +if ${ac_cv_lib_lzma_lzma_easy_encoder+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-llzma $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char lzma_easy_encoder (); +int +main () +{ +return lzma_easy_encoder (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_lzma_lzma_easy_encoder=yes +else + ac_cv_lib_lzma_lzma_easy_encoder=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lzma_lzma_easy_encoder" >&5 +$as_echo "$ac_cv_lib_lzma_lzma_easy_encoder" >&6; } +if test "x$ac_cv_lib_lzma_lzma_easy_encoder" = xyes; then : + + have_liblzma=yes + LIBLZMA_CFLAGS= + LIBLZMA_LIBS=-llzma + +else + have_liblzma=no +fi + + +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS + + + +else + have_liblzma=no +fi + +done + + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + for ac_header in lzma.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "lzma.h" "ac_cv_header_lzma_h" "$ac_includes_default" +if test "x$ac_cv_header_lzma_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LZMA_H 1 +_ACEOF + + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lzma_easy_encoder in -llzma" >&5 +$as_echo_n "checking for lzma_easy_encoder in -llzma... " >&6; } +if ${ac_cv_lib_lzma_lzma_easy_encoder+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-llzma $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char lzma_easy_encoder (); +int +main () +{ +return lzma_easy_encoder (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_lzma_lzma_easy_encoder=yes +else + ac_cv_lib_lzma_lzma_easy_encoder=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lzma_lzma_easy_encoder" >&5 +$as_echo "$ac_cv_lib_lzma_lzma_easy_encoder" >&6; } +if test "x$ac_cv_lib_lzma_lzma_easy_encoder" = xyes; then : + + have_liblzma=yes + LIBLZMA_CFLAGS= + LIBLZMA_LIBS=-llzma + +else + have_liblzma=no +fi + + +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS + + + +else + have_liblzma=no +fi + +done + + +else + LIBLZMA_CFLAGS=$pkg_cv_LIBLZMA_CFLAGS + LIBLZMA_LIBS=$pkg_cv_LIBLZMA_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_liblzma=yes +fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for hstrerror" >&5 +$as_echo_n "checking for hstrerror... " >&6; } +if ${ac_cv_func_hstrerror+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +void *x=hstrerror + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_hstrerror=yes +else + ac_cv_func_hstrerror=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_hstrerror" >&5 +$as_echo "$ac_cv_func_hstrerror" >&6; } + if test "x$ac_cv_func_hstrerror" = xyes; then : + +$as_echo "#define HAVE_HSTRERROR 1" >>confdefs.h + +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_aton" >&5 +$as_echo_n "checking for inet_aton... " >&6; } +if ${ac_cv_func_inet_aton+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +#include +#include + +int +main () +{ +void *x=inet_aton + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_inet_aton=yes +else + ac_cv_func_inet_aton=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_inet_aton" >&5 +$as_echo "$ac_cv_func_inet_aton" >&6; } + if test "x$ac_cv_func_inet_aton" = xyes; then : + +$as_echo "#define HAVE_INET_ATON 1" >>confdefs.h + +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_pton" >&5 +$as_echo_n "checking for inet_pton... " >&6; } +if ${ac_cv_func_inet_pton+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -20537,6 +21105,128 @@ $as_echo "$py_cv_module__sqlite3" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module zlib" >&5 +$as_echo_n "checking for stdlib extension module zlib... " >&6; } + case $py_stdlib_not_available in #( + *zlib*) : + py_cv_module_zlib=n/a ;; #( + *) : + if true; then : + if test "$have_zlib" = yes; then : + py_cv_module_zlib=yes +else + py_cv_module_zlib=missing +fi +else + py_cv_module_zlib=disabled +fi + ;; +esac + as_fn_append MODULE_BLOCK "MODULE_ZLIB=$py_cv_module_zlib$as_nl" + if test "x$py_cv_module_zlib" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE_ZLIB_CFLAGS=$ZLIB_CFLAGS$as_nl" + as_fn_append MODULE_BLOCK "MODULE_ZLIB_LDFLAGS=$ZLIB_LIBS$as_nl" + +fi + if test "$py_cv_module_zlib" = yes; then + MODULE_ZLIB_TRUE= + MODULE_ZLIB_FALSE='#' +else + MODULE_ZLIB_TRUE='#' + MODULE_ZLIB_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module_zlib" >&5 +$as_echo "$py_cv_module_zlib" >&6; } + + + if true; then + MODULE_BINASCII_TRUE= + MODULE_BINASCII_FALSE='#' +else + MODULE_BINASCII_TRUE='#' + MODULE_BINASCII_FALSE= +fi + as_fn_append MODULE_BLOCK "MODULE_BINASCII=yes$as_nl" + as_fn_append MODULE_BLOCK "MODULE_BINASCII_CFLAGS=$BINASCII_CFLAGS$as_nl" + + as_fn_append MODULE_BLOCK "MODULE_BINASCII_LDFLAGS=$BINASCII_LIBS$as_nl" + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _bz2" >&5 +$as_echo_n "checking for stdlib extension module _bz2... " >&6; } + case $py_stdlib_not_available in #( + *_bz2*) : + py_cv_module__bz2=n/a ;; #( + *) : + if true; then : + if test "$have_bzip2" = yes; then : + py_cv_module__bz2=yes +else + py_cv_module__bz2=missing +fi +else + py_cv_module__bz2=disabled +fi + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__BZ2=$py_cv_module__bz2$as_nl" + if test "x$py_cv_module__bz2" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE__BZ2_CFLAGS=$BZIP2_CFLAGS$as_nl" + as_fn_append MODULE_BLOCK "MODULE__BZ2_LDFLAGS=$BZIP2_LIBS$as_nl" + +fi + if test "$py_cv_module__bz2" = yes; then + MODULE__BZ2_TRUE= + MODULE__BZ2_FALSE='#' +else + MODULE__BZ2_TRUE='#' + MODULE__BZ2_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__bz2" >&5 +$as_echo "$py_cv_module__bz2" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _lzma" >&5 +$as_echo_n "checking for stdlib extension module _lzma... " >&6; } + case $py_stdlib_not_available in #( + *_lzma*) : + py_cv_module__lzma=n/a ;; #( + *) : + if true; then : + if test "$have_liblzma" = yes; then : + py_cv_module__lzma=yes +else + py_cv_module__lzma=missing +fi +else + py_cv_module__lzma=disabled +fi + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__LZMA=$py_cv_module__lzma$as_nl" + if test "x$py_cv_module__lzma" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE__LZMA_CFLAGS=$LIBLZMA_CFLAGS$as_nl" + as_fn_append MODULE_BLOCK "MODULE__LZMA_LDFLAGS=$LIBLZMA_LIBS$as_nl" + +fi + if test "$py_cv_module__lzma" = yes; then + MODULE__LZMA_TRUE= + MODULE__LZMA_FALSE='#' +else + MODULE__LZMA_TRUE='#' + MODULE__LZMA_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__lzma" >&5 +$as_echo "$py_cv_module__lzma" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _testcapi" >&5 $as_echo_n "checking for stdlib extension module _testcapi... " >&6; } case $py_stdlib_not_available in #( @@ -21101,6 +21791,22 @@ if test -z "${MODULE__SQLITE3_TRUE}" && test -z "${MODULE__SQLITE3_FALSE}"; then as_fn_error $? "conditional \"MODULE__SQLITE3\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE_ZLIB_TRUE}" && test -z "${MODULE_ZLIB_FALSE}"; then + as_fn_error $? "conditional \"MODULE_ZLIB\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE_BINASCII_TRUE}" && test -z "${MODULE_BINASCII_FALSE}"; then + as_fn_error $? "conditional \"MODULE_BINASCII\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__BZ2_TRUE}" && test -z "${MODULE__BZ2_FALSE}"; then + as_fn_error $? "conditional \"MODULE__BZ2\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__LZMA_TRUE}" && test -z "${MODULE__LZMA_FALSE}"; then + as_fn_error $? "conditional \"MODULE__LZMA\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__TESTCAPI_TRUE}" && test -z "${MODULE__TESTCAPI_FALSE}"; then as_fn_error $? "conditional \"MODULE__TESTCAPI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index 224a9b959d4f9..05992dc28f4d1 100644 --- a/configure.ac +++ b/configure.ac @@ -4054,24 +4054,55 @@ if test "$ac_cv_have_lchflags" = yes ; then fi dnl Check for compression libraries -AC_CHECK_HEADERS([zlib.h], [ - save_LIBS="$LIBS" - AC_CHECK_LIB([z], [gzread]) - LIBS="$save_LIBS" - AC_CHECK_LIB([z], [inflateCopy], [AC_DEFINE(HAVE_ZLIB_COPY, 1, [Define if the zlib library has inflateCopy])]) - LIBS="$save_LIBS" +AH_TEMPLATE([HAVE_ZLIB_COPY], [Define if the zlib library has inflateCopy]) + +PKG_CHECK_MODULES([ZLIB], [zlib >= 1.2.0], [ + have_zlib=yes + dnl zlib 1.2.0 (2003) added inflateCopy + AC_DEFINE([HAVE_ZLIB_COPY], [1]) +], [ + AC_CHECK_HEADERS([zlib.h], [ + WITH_SAVE_ENV([ + AC_CHECK_LIB([z], [gzread], [ + have_zlib=yes + ZLIB_CFLAGS= + ZLIB_LIBS=-lz + AC_CHECK_LIB([z], [inflateCopy], [AC_DEFINE([HAVE_ZLIB_COPY], [1])]) + ], [ + have_zlib=no + ]) + ]) + ], [have_zlib=no]) ]) -AC_CHECK_HEADERS([bzlib.h], [ - save_LIBS="$LIBS" - AC_CHECK_LIB([bz2], [BZ2_bzCompress]) - LIBS="$save_LIBS" +dnl binascii can use zlib for optimized crc32. +AS_VAR_IF([have_zlib], [yes], [ + BINASCII_CFLAGS="-DUSE_ZLIB_CRC32 $ZLIB_CFLAGS" + BINASCII_LIBS="$ZLIB_LIBS" ]) -AC_CHECK_HEADERS([lzma.h], [ - save_LIBS="$LIBS" - AC_CHECK_LIB([lzma], [lzma_easy_encoder]) - LIBS="$save_LIBS" +PKG_CHECK_MODULES([BZIP2], [bzip2], [have_bzip2=yes], [ + AC_CHECK_HEADERS([bzlib.h], [ + WITH_SAVE_ENV([ + AC_CHECK_LIB([bz2], [BZ2_bzCompress], [ + have_bzip2=yes + BZIP2_CFLAGS= + BZIP2_LIBS=-lbz2 + ], [have_bzip2=no]) + ]) + ], [have_bzip2=no]) +]) + +PKG_CHECK_MODULES([LIBLZMA], [liblzma], [have_liblzma=yes], [ + AC_CHECK_HEADERS([lzma.h], [ + WITH_SAVE_ENV([ + AC_CHECK_LIB([lzma], [lzma_easy_encoder], [ + have_liblzma=yes + LIBLZMA_CFLAGS= + LIBLZMA_LIBS=-llzma + ], [have_liblzma=no]) + ]) + ], [have_liblzma=no]) ]) PY_CHECK_FUNC([hstrerror], [#include ]) @@ -6140,6 +6171,16 @@ PY_STDLIB_MOD([_sqlite3], [test "$have_supported_sqlite3" = "yes"], [$LIBSQLITE3_CFLAGS], [$LIBSQLITE3_LIBS]) +dnl compression libs +PY_STDLIB_MOD([zlib], [], [test "$have_zlib" = yes], + [$ZLIB_CFLAGS], [$ZLIB_LIBS]) +dnl binascii can use zlib for optimized crc32. +PY_STDLIB_MOD_SIMPLE([binascii], [$BINASCII_CFLAGS], [$BINASCII_LIBS]) +PY_STDLIB_MOD([_bz2], [], [test "$have_bzip2" = yes], + [$BZIP2_CFLAGS], [$BZIP2_LIBS]) +PY_STDLIB_MOD([_lzma], [], [test "$have_liblzma" = yes], + [$LIBLZMA_CFLAGS], [$LIBLZMA_LIBS]) + dnl test modules PY_STDLIB_MOD([_testcapi], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_testinternalcapi], [test "$TEST_MODULES" = yes]) diff --git a/pyconfig.h.in b/pyconfig.h.in index 6f3adb2314ab7..6672344437cdd 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -595,9 +595,6 @@ /* Define to 1 if you have the `lchown' function. */ #undef HAVE_LCHOWN -/* Define to 1 if you have the `bz2' library (-lbz2). */ -#undef HAVE_LIBBZ2 - /* Define to 1 if you have the `db' library (-ldb). */ #undef HAVE_LIBDB @@ -619,9 +616,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LIBINTL_H -/* Define to 1 if you have the `lzma' library (-llzma). */ -#undef HAVE_LIBLZMA - /* Define to 1 if you have the `ndbm' library (-lndbm). */ #undef HAVE_LIBNDBM @@ -640,9 +634,6 @@ /* Define to 1 if you have the `uuid' library (-luuid). */ #undef HAVE_LIBUUID -/* Define to 1 if you have the `z' library (-lz). */ -#undef HAVE_LIBZ - /* Define if you have the 'link' function. */ #undef HAVE_LINK diff --git a/setup.py b/setup.py index d4eff363d24ef..b9b48b2f74ba0 100644 --- a/setup.py +++ b/setup.py @@ -1365,38 +1365,17 @@ def detect_platform_specific_exts(self): def detect_compress_exts(self): # Andrew Kuchling's zlib module. - have_zlib = sysconfig.get_config_var("HAVE_LIBZ") - if have_zlib: - self.add(Extension('zlib', ['zlibmodule.c'], - libraries=['z'])) - else: - self.missing.append('zlib') + self.addext(Extension('zlib', ['zlibmodule.c'])) # Helper module for various ascii-encoders. Uses zlib for an optimized # crc32 if we have it. Otherwise binascii uses its own. - if have_zlib: - define_macros = [('USE_ZLIB_CRC32', None)] - libraries = ['z'] - else: - define_macros = None - libraries = [] - self.add(Extension('binascii', ['binascii.c'], - define_macros=define_macros, - libraries=libraries)) + self.addext(Extension('binascii', ['binascii.c'])) # Gustavo Niemeyer's bz2 module. - if sysconfig.get_config_var("HAVE_LIBBZ2"): - self.add(Extension('_bz2', ['_bz2module.c'], - libraries=['bz2'])) - else: - self.missing.append('_bz2') + self.addext(Extension('_bz2', ['_bz2module.c'])) # LZMA compression support. - if sysconfig.get_config_var("HAVE_LIBLZMA"): - self.add(Extension('_lzma', ['_lzmamodule.c'], - libraries=['lzma'])) - else: - self.missing.append('_lzma') + self.addext(Extension('_lzma', ['_lzmamodule.c'])) def detect_expat_elementtree(self): # Interface to the Expat XML parser From webhook-mailer at python.org Mon Nov 22 09:01:32 2021 From: webhook-mailer at python.org (markshannon) Date: Mon, 22 Nov 2021 14:01:32 -0000 Subject: [Python-checkins] bpo-45813: Make sure that frame->generator is NULLed when generator is deallocated. (GH-29700) Message-ID: https://github.com/python/cpython/commit/7fd92a8b7ee5bed28c2681fa38e0a1e76200dd8e commit: 7fd92a8b7ee5bed28c2681fa38e0a1e76200dd8e branch: main author: Mark Shannon committer: markshannon date: 2021-11-22T14:01:23Z summary: bpo-45813: Make sure that frame->generator is NULLed when generator is deallocated. (GH-29700) files: A Misc/NEWS.d/next/Core and Builtins/2021-11-22-11-28-13.bpo-45813.ZMaWE2.rst M Lib/test/test_coroutines.py M Objects/genobject.c M Python/frame.c diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py index 4350e185a247f..fc8b8bc9541eb 100644 --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -2191,6 +2191,13 @@ async def run_gen(): return 'end' self.assertEqual(run_async(run_gen()), ([], 'end')) + def test_bpo_45813(self): + 'This would crash the interpreter in 3.11a2' + async def f(): + pass + frame = f().cr_frame + frame.clear() + class CoroAsyncIOCompatTest(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-22-11-28-13.bpo-45813.ZMaWE2.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-22-11-28-13.bpo-45813.ZMaWE2.rst new file mode 100644 index 0000000000000..65f64b11de0f7 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-22-11-28-13.bpo-45813.ZMaWE2.rst @@ -0,0 +1 @@ +Fix crash when calling coro.cr_frame.clear() after coroutine has been freed. diff --git a/Objects/genobject.c b/Objects/genobject.c index efd255d33f9be..c899ed6a82e30 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -134,6 +134,7 @@ gen_dealloc(PyGenObject *gen) InterpreterFrame *frame = gen->gi_xframe; if (frame != NULL) { gen->gi_xframe = NULL; + frame->generator = NULL; frame->previous = NULL; _PyFrame_Clear(frame, 1); } diff --git a/Python/frame.c b/Python/frame.c index 3d2415fee7097..a5c93eaaa5f37 100644 --- a/Python/frame.c +++ b/Python/frame.c @@ -99,6 +99,9 @@ take_ownership(PyFrameObject *f, InterpreterFrame *frame) int _PyFrame_Clear(InterpreterFrame * frame, int take) { + /* It is the responsibility of the owning generator/coroutine + * to have cleared the generator pointer */ + assert(frame->generator == NULL); if (frame->frame_obj) { PyFrameObject *f = frame->frame_obj; frame->frame_obj = NULL; From webhook-mailer at python.org Mon Nov 22 09:18:49 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 22 Nov 2021 14:18:49 -0000 Subject: [Python-checkins] bpo-45847: Port nis module to PY_STDLIB_MOD (GH-29699) Message-ID: https://github.com/python/cpython/commit/c6dec7e27a82cba33539d07ef8d7346e0a232421 commit: c6dec7e27a82cba33539d07ef8d7346e0a232421 branch: main author: Christian Heimes committer: tiran date: 2021-11-22T15:18:41+01:00 summary: bpo-45847: Port nis module to PY_STDLIB_MOD (GH-29699) files: M Modules/Setup.stdlib.in M configure M configure.ac M pyconfig.h.in M setup.py diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index fdd20d4d6217b..8ab93704765a5 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -40,7 +40,7 @@ @MODULE__QUEUE_TRUE at _queue _queuemodule.c @MODULE__RANDOM_TRUE at _random _randommodule.c @MODULE__TYPING_TRUE at _typing _typingmodule.c - at MODULE__XXSUBINTERPRETERS_TRUE@_xxsubinterpreters __xxsubinterpretersmodule.c + at MODULE__XXSUBINTERPRETERS_TRUE@_xxsubinterpreters _xxsubinterpretersmodule.c @MODULE__ZONEINFO_TRUE at _zoneinfo _zoneinfo.c # needs libm @@ -98,6 +98,9 @@ @MODULE_FCNTL_TRUE at fcntl fcntlmodule.c @MODULE_GRP_TRUE at grp grpmodule.c @MODULE_MMAP_TRUE at mmap mmapmodule.c +# FreeBSD: nis/yp APIs are in libc +# Linux: glibc has deprecated SUN RPC, APIs are in libnsl and libtirpc (bpo-32521) + at MODULE_NIS_TRUE@nis nismodule.c # needs sys/soundcard.h or linux/soundcard.h (Linux, FreeBSD) @MODULE_OSSAUDIODEV_TRUE at ossaudiodev ossaudiodev.c @MODULE_RESOURCE_TRUE at resource resource.c diff --git a/configure b/configure index 0840727058042..dd2e3b8ff4d76 100755 --- a/configure +++ b/configure @@ -648,6 +648,8 @@ MODULE_ZLIB_FALSE MODULE_ZLIB_TRUE MODULE__SQLITE3_FALSE MODULE__SQLITE3_TRUE +MODULE_NIS_FALSE +MODULE_NIS_TRUE MODULE__DECIMAL_FALSE MODULE__DECIMAL_TRUE MODULE__BLAKE2_FALSE @@ -787,6 +789,8 @@ TCLTK_LIBS TCLTK_INCLUDES LIBSQLITE3_LIBS LIBSQLITE3_CFLAGS +LIBNSL_LIBS +LIBNSL_CFLAGS LIBMPDEC_INTERNAL LIBMPDEC_LDFLAGS LIBMPDEC_CFLAGS @@ -1014,6 +1018,8 @@ LIBS CPPFLAGS CPP PROFILE_TASK +LIBNSL_CFLAGS +LIBNSL_LIBS LIBSQLITE3_CFLAGS LIBSQLITE3_LIBS ZLIB_CFLAGS @@ -1795,6 +1801,9 @@ Some influential environment variables: CPP C preprocessor PROFILE_TASK Python args for PGO generation task + LIBNSL_CFLAGS + C compiler flags for LIBNSL, overriding pkg-config + LIBNSL_LIBS linker flags for LIBNSL, overriding pkg-config LIBSQLITE3_CFLAGS C compiler flags for LIBSQLITE3, overriding pkg-config LIBSQLITE3_LIBS @@ -11071,6 +11080,274 @@ if test "$have_glibc_memmove_bug" = yes; then fi + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBNSL" >&5 +$as_echo_n "checking for LIBNSL... " >&6; } + +if test -n "$LIBNSL_CFLAGS"; then + pkg_cv_LIBNSL_CFLAGS="$LIBNSL_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnsl\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libnsl") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBNSL_CFLAGS=`$PKG_CONFIG --cflags "libnsl" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LIBNSL_LIBS"; then + pkg_cv_LIBNSL_LIBS="$LIBNSL_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnsl\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libnsl") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBNSL_LIBS=`$PKG_CONFIG --libs "libnsl" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LIBNSL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libnsl" 2>&1` + else + LIBNSL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libnsl" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LIBNSL_PKG_ERRORS" >&5 + + + LIBNSL_CFLAGS= + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing yp_match" >&5 +$as_echo_n "checking for library containing yp_match... " >&6; } +if ${ac_cv_search_yp_match+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char yp_match (); +int +main () +{ +return yp_match (); + ; + return 0; +} +_ACEOF +for ac_lib in '' nsl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_yp_match=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_yp_match+:} false; then : + break +fi +done +if ${ac_cv_search_yp_match+:} false; then : + +else + ac_cv_search_yp_match=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_yp_match" >&5 +$as_echo "$ac_cv_search_yp_match" >&6; } +ac_res=$ac_cv_search_yp_match +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + have_nis=yes +else + have_nis=no +fi + + +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS + + + case $ac_cv_search_yp_match in #( + no) : + LIBNSL_LIBS= ;; #( + "none required") : + LIBNSL_LIBS= ;; #( + *) : + LIBNSL_LIBS=$ac_cv_search_yp_match + ;; +esac + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + LIBNSL_CFLAGS= + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing yp_match" >&5 +$as_echo_n "checking for library containing yp_match... " >&6; } +if ${ac_cv_search_yp_match+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char yp_match (); +int +main () +{ +return yp_match (); + ; + return 0; +} +_ACEOF +for ac_lib in '' nsl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_yp_match=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_yp_match+:} false; then : + break +fi +done +if ${ac_cv_search_yp_match+:} false; then : + +else + ac_cv_search_yp_match=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_yp_match" >&5 +$as_echo "$ac_cv_search_yp_match" >&6; } +ac_res=$ac_cv_search_yp_match +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + have_nis=yes +else + have_nis=no +fi + + +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS + + + case $ac_cv_search_yp_match in #( + no) : + LIBNSL_LIBS= ;; #( + "none required") : + LIBNSL_LIBS= ;; #( + *) : + LIBNSL_LIBS=$ac_cv_search_yp_match + ;; +esac + +else + LIBNSL_CFLAGS=$pkg_cv_LIBNSL_CFLAGS + LIBNSL_LIBS=$pkg_cv_LIBNSL_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_nis=yes +fi + +if test "x$have_nis" = xyes; then : + + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + CPPFLAGS="$LIBNSL_CFLAGS $CFLAGS" + for ac_header in rpc/rpc.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "rpc/rpc.h" "ac_cv_header_rpc_rpc_h" "$ac_includes_default" +if test "x$ac_cv_header_rpc_rpc_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_RPC_RPC_H 1 +_ACEOF + +fi + +done + + +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS + + + +fi + + pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBSQLITE3" >&5 $as_echo_n "checking for LIBSQLITE3... " >&6; } @@ -21068,6 +21345,42 @@ fi $as_echo "$py_cv_module__decimal" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module nis" >&5 +$as_echo_n "checking for stdlib extension module nis... " >&6; } + case $py_stdlib_not_available in #( + *nis*) : + py_cv_module_nis=n/a ;; #( + *) : + if true; then : + if test "$have_nis" = yes -a "$ac_cv_header_rpc_rpc_h" = yes; then : + py_cv_module_nis=yes +else + py_cv_module_nis=missing +fi +else + py_cv_module_nis=disabled +fi + ;; +esac + as_fn_append MODULE_BLOCK "MODULE_NIS=$py_cv_module_nis$as_nl" + if test "x$py_cv_module_nis" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE_NIS_CFLAGS=$LIBNSL_CFLAGS$as_nl" + as_fn_append MODULE_BLOCK "MODULE_NIS_LDFLAGS=$LIBNSL_LIBS$as_nl" + +fi + if test "$py_cv_module_nis" = yes; then + MODULE_NIS_TRUE= + MODULE_NIS_FALSE='#' +else + MODULE_NIS_TRUE='#' + MODULE_NIS_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module_nis" >&5 +$as_echo "$py_cv_module_nis" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _sqlite3" >&5 $as_echo_n "checking for stdlib extension module _sqlite3... " >&6; } case $py_stdlib_not_available in #( @@ -21787,6 +22100,10 @@ if test -z "${MODULE__DECIMAL_TRUE}" && test -z "${MODULE__DECIMAL_FALSE}"; then as_fn_error $? "conditional \"MODULE__DECIMAL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE_NIS_TRUE}" && test -z "${MODULE_NIS_FALSE}"; then + as_fn_error $? "conditional \"MODULE_NIS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__SQLITE3_TRUE}" && test -z "${MODULE__SQLITE3_FALSE}"; then as_fn_error $? "conditional \"MODULE__SQLITE3\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index 05992dc28f4d1..72f2def9b11af 100644 --- a/configure.ac +++ b/configure.ac @@ -3191,6 +3191,28 @@ if test "$have_glibc_memmove_bug" = yes; then AS_VAR_APPEND([LIBMPDEC_CFLAGS], [" -U_FORTIFY_SOURCE"]) fi + +dnl check for NIS / libnsl dependencies +dnl libnsl dependencies include tirpc includes and lib +PKG_CHECK_MODULES([LIBNSL], [libnsl], [have_nis=yes], [ + LIBNSL_CFLAGS= + WITH_SAVE_ENV([ + AC_SEARCH_LIBS([yp_match], [nsl], [have_nis=yes], [have_nis=no]) + ]) + AS_CASE([$ac_cv_search_yp_match], + [no], [LIBNSL_LIBS=], + ["none required"], [LIBNSL_LIBS=], + [LIBNSL_LIBS=$ac_cv_search_yp_match] + ) +]) + +AS_VAR_IF([have_nis], [yes], [ + WITH_SAVE_ENV([ + CPPFLAGS="$LIBNSL_CFLAGS $CFLAGS" + AC_CHECK_HEADERS([rpc/rpc.h]) + ]) +]) + dnl Check for SQLite library. Use pkg-config if available. PKG_CHECK_MODULES( [LIBSQLITE3], [sqlite3 >= 3.7.15], [], [ @@ -6166,6 +6188,9 @@ PY_STDLIB_MOD([_sha3], [test "$with_builtin_sha3" = yes]) PY_STDLIB_MOD([_blake2], [test "$with_builtin_blake2" = yes]) PY_STDLIB_MOD([_decimal], [], [], [$LIBMPDEC_CFLAGS], [$LIBMPDEC_LDFLAGS]) +PY_STDLIB_MOD([nis], + [], [test "$have_nis" = yes -a "$ac_cv_header_rpc_rpc_h" = yes], + [$LIBNSL_CFLAGS], [$LIBNSL_LIBS]) PY_STDLIB_MOD([_sqlite3], [test "$have_sqlite3" = "yes"], [test "$have_supported_sqlite3" = "yes"], diff --git a/pyconfig.h.in b/pyconfig.h.in index 6672344437cdd..c9c58656f58ac 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -896,6 +896,9 @@ /* Define if you have readline 4.0 */ #undef HAVE_RL_RESIZE_TERMINAL +/* Define to 1 if you have the header file. */ +#undef HAVE_RPC_RPC_H + /* Define to 1 if you have the `rtpSpawn' function. */ #undef HAVE_RTPSPAWN diff --git a/setup.py b/setup.py index b9b48b2f74ba0..dd1a3df60bfdf 100644 --- a/setup.py +++ b/setup.py @@ -1993,49 +1993,7 @@ def detect_hash_builtins(self): )) def detect_nis(self): - if MS_WINDOWS or CYGWIN or HOST_PLATFORM == 'qnx6': - self.missing.append('nis') - return - - libs = [] - library_dirs = [] - includes_dirs = [] - - # bpo-32521: glibc has deprecated Sun RPC for some time. Fedora 28 - # moved headers and libraries to libtirpc and libnsl. The headers - # are in tircp and nsl sub directories. - rpcsvc_inc = find_file( - 'rpcsvc/yp_prot.h', self.inc_dirs, - [os.path.join(inc_dir, 'nsl') for inc_dir in self.inc_dirs] - ) - rpc_inc = find_file( - 'rpc/rpc.h', self.inc_dirs, - [os.path.join(inc_dir, 'tirpc') for inc_dir in self.inc_dirs] - ) - if rpcsvc_inc is None or rpc_inc is None: - # not found - self.missing.append('nis') - return - includes_dirs.extend(rpcsvc_inc) - includes_dirs.extend(rpc_inc) - - if self.compiler.find_library_file(self.lib_dirs, 'nsl'): - libs.append('nsl') - else: - # libnsl-devel: check for libnsl in nsl/ subdirectory - nsl_dirs = [os.path.join(lib_dir, 'nsl') for lib_dir in self.lib_dirs] - libnsl = self.compiler.find_library_file(nsl_dirs, 'nsl') - if libnsl is not None: - library_dirs.append(os.path.dirname(libnsl)) - libs.append('nsl') - - if self.compiler.find_library_file(self.lib_dirs, 'tirpc'): - libs.append('tirpc') - - self.add(Extension('nis', ['nismodule.c'], - libraries=libs, - library_dirs=library_dirs, - include_dirs=includes_dirs)) + self.addext(Extension('nis', ['nismodule.c'])) class PyBuildInstall(install): From webhook-mailer at python.org Mon Nov 22 09:37:34 2021 From: webhook-mailer at python.org (miss-islington) Date: Mon, 22 Nov 2021 14:37:34 -0000 Subject: [Python-checkins] bpo-45847: Port audioop, _csv, and _posixsubprocess to PY_STDLIB_MOD_SIMPLE (GH-29705) Message-ID: https://github.com/python/cpython/commit/eee683cbde499e62fc90ad366f7c45625fe92150 commit: eee683cbde499e62fc90ad366f7c45625fe92150 branch: main author: Erlend Egeberg Aasland committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-22T06:37:25-08:00 summary: bpo-45847: Port audioop, _csv, and _posixsubprocess to PY_STDLIB_MOD_SIMPLE (GH-29705) Automerge-Triggered-By: GH:tiran files: M Modules/Setup.stdlib.in M configure M configure.ac M setup.py diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 8ab93704765a5..0688c350db238 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -32,6 +32,7 @@ @MODULE__ASYNCIO_TRUE at _asyncio _asynciomodule.c @MODULE__BISECT_TRUE at _bisect _bisectmodule.c @MODULE__CONTEXTVARS_TRUE at _contextvars _contextvarsmodule.c + at MODULE__CSV_TRUE@_csv _csv.c @MODULE__HEAPQ_TRUE at _heapq _heapqmodule.c @MODULE__JSON_TRUE at _json _json.c @MODULE__LSPROF_TRUE at _lsprof _lsprof.c rotatingtree.c @@ -44,6 +45,7 @@ @MODULE__ZONEINFO_TRUE at _zoneinfo _zoneinfo.c # needs libm + at MODULE_AUDIOOP_TRUE@audioop audioop.c @MODULE_MATH_TRUE at math mathmodule.c @MODULE_CMATH_TRUE at cmath cmathmodule.c @MODULE__STATISTICS_TRUE at _statistics _statisticsmodule.c @@ -103,6 +105,7 @@ @MODULE_NIS_TRUE at nis nismodule.c # needs sys/soundcard.h or linux/soundcard.h (Linux, FreeBSD) @MODULE_OSSAUDIODEV_TRUE at ossaudiodev ossaudiodev.c + at MODULE__POSIXSUBPROCESS_TRUE@_posixsubprocess _posixsubprocess.c @MODULE_RESOURCE_TRUE at resource resource.c @MODULE_SELECT_TRUE at select selectmodule.c # AIX has shadow passwords, but does not provide getspent API diff --git a/configure b/configure index dd2e3b8ff4d76..193d6b9179b75 100755 --- a/configure +++ b/configure @@ -710,6 +710,8 @@ MODULE_CMATH_FALSE MODULE_CMATH_TRUE MODULE__STATISTICS_FALSE MODULE__STATISTICS_TRUE +MODULE_AUDIOOP_FALSE +MODULE_AUDIOOP_TRUE MODULE__ZONEINFO_FALSE MODULE__ZONEINFO_TRUE MODULE__XXSUBINTERPRETERS_FALSE @@ -722,6 +724,8 @@ MODULE__RANDOM_FALSE MODULE__RANDOM_TRUE MODULE__QUEUE_FALSE MODULE__QUEUE_TRUE +MODULE__POSIXSUBPROCESS_FALSE +MODULE__POSIXSUBPROCESS_TRUE MODULE__PICKLE_FALSE MODULE__PICKLE_TRUE MODULE__OPCODE_FALSE @@ -732,6 +736,8 @@ MODULE__JSON_FALSE MODULE__JSON_TRUE MODULE__HEAPQ_FALSE MODULE__HEAPQ_TRUE +MODULE__CSV_FALSE +MODULE__CSV_TRUE MODULE__CONTEXTVARS_FALSE MODULE__CONTEXTVARS_TRUE MODULE__BISECT_FALSE @@ -20475,6 +20481,15 @@ else fi as_fn_append MODULE_BLOCK "MODULE__CONTEXTVARS=yes$as_nl" + if true; then + MODULE__CSV_TRUE= + MODULE__CSV_FALSE='#' +else + MODULE__CSV_TRUE='#' + MODULE__CSV_FALSE= +fi + as_fn_append MODULE_BLOCK "MODULE__CSV=yes$as_nl" + if true; then MODULE__HEAPQ_TRUE= MODULE__HEAPQ_FALSE='#' @@ -20520,6 +20535,15 @@ else fi as_fn_append MODULE_BLOCK "MODULE__PICKLE=yes$as_nl" + if true; then + MODULE__POSIXSUBPROCESS_TRUE= + MODULE__POSIXSUBPROCESS_FALSE='#' +else + MODULE__POSIXSUBPROCESS_TRUE='#' + MODULE__POSIXSUBPROCESS_FALSE= +fi + as_fn_append MODULE_BLOCK "MODULE__POSIXSUBPROCESS=yes$as_nl" + if true; then MODULE__QUEUE_TRUE= MODULE__QUEUE_FALSE='#' @@ -20575,6 +20599,17 @@ fi as_fn_append MODULE_BLOCK "MODULE__ZONEINFO=yes$as_nl" + if true; then + MODULE_AUDIOOP_TRUE= + MODULE_AUDIOOP_FALSE='#' +else + MODULE_AUDIOOP_TRUE='#' + MODULE_AUDIOOP_FALSE= +fi + as_fn_append MODULE_BLOCK "MODULE_AUDIOOP=yes$as_nl" + as_fn_append MODULE_BLOCK "MODULE_AUDIOOP_LDFLAGS=$LIBM$as_nl" + + if true; then MODULE__STATISTICS_TRUE= MODULE__STATISTICS_FALSE='#' @@ -21936,6 +21971,10 @@ if test -z "${MODULE__CONTEXTVARS_TRUE}" && test -z "${MODULE__CONTEXTVARS_FALSE as_fn_error $? "conditional \"MODULE__CONTEXTVARS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__CSV_TRUE}" && test -z "${MODULE__CSV_FALSE}"; then + as_fn_error $? "conditional \"MODULE__CSV\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__HEAPQ_TRUE}" && test -z "${MODULE__HEAPQ_FALSE}"; then as_fn_error $? "conditional \"MODULE__HEAPQ\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -21956,6 +21995,10 @@ if test -z "${MODULE__PICKLE_TRUE}" && test -z "${MODULE__PICKLE_FALSE}"; then as_fn_error $? "conditional \"MODULE__PICKLE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__POSIXSUBPROCESS_TRUE}" && test -z "${MODULE__POSIXSUBPROCESS_FALSE}"; then + as_fn_error $? "conditional \"MODULE__POSIXSUBPROCESS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__QUEUE_TRUE}" && test -z "${MODULE__QUEUE_FALSE}"; then as_fn_error $? "conditional \"MODULE__QUEUE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -21980,6 +22023,10 @@ if test -z "${MODULE__ZONEINFO_TRUE}" && test -z "${MODULE__ZONEINFO_FALSE}"; th as_fn_error $? "conditional \"MODULE__ZONEINFO\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE_AUDIOOP_TRUE}" && test -z "${MODULE_AUDIOOP_FALSE}"; then + as_fn_error $? "conditional \"MODULE_AUDIOOP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__STATISTICS_TRUE}" && test -z "${MODULE__STATISTICS_FALSE}"; then as_fn_error $? "conditional \"MODULE__STATISTICS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index 72f2def9b11af..b48fa56d3998e 100644 --- a/configure.ac +++ b/configure.ac @@ -6127,11 +6127,13 @@ PY_STDLIB_MOD_SIMPLE([array]) PY_STDLIB_MOD_SIMPLE([_asyncio]) PY_STDLIB_MOD_SIMPLE([_bisect]) PY_STDLIB_MOD_SIMPLE([_contextvars]) +PY_STDLIB_MOD_SIMPLE([_csv]) PY_STDLIB_MOD_SIMPLE([_heapq]) PY_STDLIB_MOD_SIMPLE([_json]) PY_STDLIB_MOD_SIMPLE([_lsprof]) PY_STDLIB_MOD_SIMPLE([_opcode]) PY_STDLIB_MOD_SIMPLE([_pickle]) +PY_STDLIB_MOD_SIMPLE([_posixsubprocess]) PY_STDLIB_MOD_SIMPLE([_queue]) PY_STDLIB_MOD_SIMPLE([_random]) PY_STDLIB_MOD_SIMPLE([select]) @@ -6140,6 +6142,7 @@ PY_STDLIB_MOD_SIMPLE([_xxsubinterpreters]) PY_STDLIB_MOD_SIMPLE([_zoneinfo]) dnl needs libm +PY_STDLIB_MOD_SIMPLE([audioop], [], [$LIBM]) PY_STDLIB_MOD_SIMPLE([_statistics], [], [$LIBM]) PY_STDLIB_MOD_SIMPLE([cmath], [], [$LIBM]) PY_STDLIB_MOD_SIMPLE([math], [], [$LIBM]) diff --git a/setup.py b/setup.py index dd1a3df60bfdf..139847c87ecec 100644 --- a/setup.py +++ b/setup.py @@ -1062,14 +1062,13 @@ def detect_simple_extensions(self): # 64-bit platforms. # # audioop needs libm for floor() in multiple functions. - self.add(Extension('audioop', ['audioop.c'], - libraries=['m'])) + self.addext(Extension('audioop', ['audioop.c'])) # CSV files - self.add(Extension('_csv', ['_csv.c'])) + self.addext(Extension('_csv', ['_csv.c'])) # POSIX subprocess module helper. - self.add(Extension('_posixsubprocess', ['_posixsubprocess.c'])) + self.addext(Extension('_posixsubprocess', ['_posixsubprocess.c'])) def detect_test_extensions(self): # Python C API test module From webhook-mailer at python.org Mon Nov 22 09:45:02 2021 From: webhook-mailer at python.org (rhettinger) Date: Mon, 22 Nov 2021 14:45:02 -0000 Subject: [Python-checkins] bpo-45859: Mark test_field_descriptor in test_collections as CPython-only (GH-29691) Message-ID: https://github.com/python/cpython/commit/4fad314246399b69ef0c57ba8527d9efade99069 commit: 4fad314246399b69ef0c57ba8527d9efade99069 branch: main author: Carl Friedrich Bolz-Tereick committer: rhettinger date: 2021-11-22T08:44:57-06:00 summary: bpo-45859: Mark test_field_descriptor in test_collections as CPython-only (GH-29691) files: M Lib/test/test_collections.py diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py index 1bfd44f954788..48327bf50ea42 100644 --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -668,6 +668,7 @@ class Point(namedtuple('_Point', ['x', 'y'])): a.w = 5 self.assertEqual(a.__dict__, {'w': 5}) + @support.cpython_only def test_field_descriptor(self): Point = namedtuple('Point', 'x y') p = Point(11, 22) From webhook-mailer at python.org Mon Nov 22 09:58:54 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 22 Nov 2021 14:58:54 -0000 Subject: [Python-checkins] bpo-45847: port _struct to PY_STDLIB_MOD (GH-29706) Message-ID: https://github.com/python/cpython/commit/0e1c2f3ef84572b79fa7d8498a69bc5a56ff0d8d commit: 0e1c2f3ef84572b79fa7d8498a69bc5a56ff0d8d branch: main author: Christian Heimes committer: tiran date: 2021-11-22T15:58:43+01:00 summary: bpo-45847: port _struct to PY_STDLIB_MOD (GH-29706) files: M Modules/Setup.stdlib.in M configure M configure.ac M setup.py diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 0688c350db238..b12ae9db5e9b2 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -40,6 +40,7 @@ @MODULE__PICKLE_TRUE at _pickle _pickle.c @MODULE__QUEUE_TRUE at _queue _queuemodule.c @MODULE__RANDOM_TRUE at _random _randommodule.c + at MODULE__STRUCT_TRUE@_struct _struct.c @MODULE__TYPING_TRUE at _typing _typingmodule.c @MODULE__XXSUBINTERPRETERS_TRUE at _xxsubinterpreters _xxsubinterpretersmodule.c @MODULE__ZONEINFO_TRUE at _zoneinfo _zoneinfo.c diff --git a/configure b/configure index 193d6b9179b75..a1fc09fc04854 100755 --- a/configure +++ b/configure @@ -718,6 +718,8 @@ MODULE__XXSUBINTERPRETERS_FALSE MODULE__XXSUBINTERPRETERS_TRUE MODULE__TYPING_FALSE MODULE__TYPING_TRUE +MODULE__STRUCT_FALSE +MODULE__STRUCT_TRUE MODULE_SELECT_FALSE MODULE_SELECT_TRUE MODULE__RANDOM_FALSE @@ -20571,6 +20573,15 @@ else fi as_fn_append MODULE_BLOCK "MODULE_SELECT=yes$as_nl" + if true; then + MODULE__STRUCT_TRUE= + MODULE__STRUCT_FALSE='#' +else + MODULE__STRUCT_TRUE='#' + MODULE__STRUCT_FALSE= +fi + as_fn_append MODULE_BLOCK "MODULE__STRUCT=yes$as_nl" + if true; then MODULE__TYPING_TRUE= MODULE__TYPING_FALSE='#' @@ -22011,6 +22022,10 @@ if test -z "${MODULE_SELECT_TRUE}" && test -z "${MODULE_SELECT_FALSE}"; then as_fn_error $? "conditional \"MODULE_SELECT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__STRUCT_TRUE}" && test -z "${MODULE__STRUCT_FALSE}"; then + as_fn_error $? "conditional \"MODULE__STRUCT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__TYPING_TRUE}" && test -z "${MODULE__TYPING_FALSE}"; then as_fn_error $? "conditional \"MODULE__TYPING\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index b48fa56d3998e..5757c3b2586bc 100644 --- a/configure.ac +++ b/configure.ac @@ -6137,6 +6137,7 @@ PY_STDLIB_MOD_SIMPLE([_posixsubprocess]) PY_STDLIB_MOD_SIMPLE([_queue]) PY_STDLIB_MOD_SIMPLE([_random]) PY_STDLIB_MOD_SIMPLE([select]) +PY_STDLIB_MOD_SIMPLE([_struct]) PY_STDLIB_MOD_SIMPLE([_typing]) PY_STDLIB_MOD_SIMPLE([_xxsubinterpreters]) PY_STDLIB_MOD_SIMPLE([_zoneinfo]) diff --git a/setup.py b/setup.py index 139847c87ecec..a3aa787a1b708 100644 --- a/setup.py +++ b/setup.py @@ -1023,6 +1023,7 @@ def detect_simple_extensions(self): self.addext(Extension("_queue", ["_queuemodule.c"])) self.addext(Extension("_statistics", ["_statisticsmodule.c"])) + self.addext(Extension("_struct", ["_struct.c"])) self.addext(Extension("_typing", ["_typingmodule.c"])) # Modules with some UNIX dependencies -- on by default: @@ -1446,6 +1447,9 @@ def detect_uuid(self): self.missing.append('_uuid') def detect_modules(self): + # remove dummy extension + self.extensions = [] + self.configure_compiler() self.init_inc_lib_dirs() @@ -2100,9 +2104,9 @@ class DummyProcess: 'build_scripts': PyBuildScripts, 'install': PyBuildInstall, 'install_lib': PyBuildInstallLib}, - # The struct module is defined here, because build_ext won't be + # A dummy module is defined here, because build_ext won't be # called unless there's at least one extension module defined. - ext_modules=[Extension('_struct', ['_struct.c'])], + ext_modules=[Extension('_dummy', ['_dummy.c'])], # If you change the scripts installed here, you also need to # check the PyBuildScripts command above, and change the links From webhook-mailer at python.org Mon Nov 22 10:06:03 2021 From: webhook-mailer at python.org (rhettinger) Date: Mon, 22 Nov 2021 15:06:03 -0000 Subject: [Python-checkins] bpo-45859: Mark test_field_descriptor in test_collections as CPython-only (GH-29691) (GH-29708) Message-ID: https://github.com/python/cpython/commit/56b5cd52ab58d8f2f11f253ec1bb3e6000d2dbd2 commit: 56b5cd52ab58d8f2f11f253ec1bb3e6000d2dbd2 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: rhettinger date: 2021-11-22T09:05:54-06:00 summary: bpo-45859: Mark test_field_descriptor in test_collections as CPython-only (GH-29691) (GH-29708) (cherry picked from commit 4fad314246399b69ef0c57ba8527d9efade99069) Co-authored-by: Carl Friedrich Bolz-Tereick Co-authored-by: Carl Friedrich Bolz-Tereick files: M Lib/test/test_collections.py diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py index 75af29b2dc72d..3404b8ad1bcf7 100644 --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -668,6 +668,7 @@ class Point(namedtuple('_Point', ['x', 'y'])): a.w = 5 self.assertEqual(a.__dict__, {'w': 5}) + @support.cpython_only def test_field_descriptor(self): Point = namedtuple('Point', 'x y') p = Point(11, 22) From webhook-mailer at python.org Mon Nov 22 11:36:43 2021 From: webhook-mailer at python.org (rhettinger) Date: Mon, 22 Nov 2021 16:36:43 -0000 Subject: [Python-checkins] bpo-45859: Mark test_field_descriptor in test_collections as CPython-only (GH-29691) (GH-29709) Message-ID: https://github.com/python/cpython/commit/455ed45d7c30c5f2a31c524b015c48ac85f3d27c commit: 455ed45d7c30c5f2a31c524b015c48ac85f3d27c branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: rhettinger date: 2021-11-22T10:36:28-06:00 summary: bpo-45859: Mark test_field_descriptor in test_collections as CPython-only (GH-29691) (GH-29709) files: M Lib/test/test_collections.py diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py index 9e1174743591c..e320ef3732b21 100644 --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -663,6 +663,7 @@ class Point(namedtuple('_Point', ['x', 'y'])): a.w = 5 self.assertEqual(a.__dict__, {'w': 5}) + @support.cpython_only def test_field_descriptor(self): Point = namedtuple('Point', 'x y') p = Point(11, 22) From webhook-mailer at python.org Mon Nov 22 11:56:31 2021 From: webhook-mailer at python.org (markshannon) Date: Mon, 22 Nov 2021 16:56:31 -0000 Subject: [Python-checkins] bpo-45871: Refactor except matcher validation into a separate function so that it can be reused. Add missing unit test. (GH-29711) Message-ID: https://github.com/python/cpython/commit/4d6c0c0cce05befa06e0cad7351b1303ac048277 commit: 4d6c0c0cce05befa06e0cad7351b1303ac048277 branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: markshannon date: 2021-11-22T16:56:23Z summary: bpo-45871: Refactor except matcher validation into a separate function so that it can be reused. Add missing unit test. (GH-29711) files: M Lib/test/test_exceptions.py M Python/ceval.c diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 4c18a59f6e92c..eee178c8ca2af 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -2401,6 +2401,21 @@ def test_incorrect_constructor(self): self.assertRaises(TypeError, SyntaxError, "bad bad", args) +class TestInvalidExceptionMatcher(unittest.TestCase): + def test_except_star_invalid_exception_type(self): + with self.assertRaises(TypeError): + try: + raise ValueError + except 42: + pass + + with self.assertRaises(TypeError): + try: + raise ValueError + except (ValueError, 42): + pass + + class PEP626Tests(unittest.TestCase): def lineno_after_raise(self, f, *expected): diff --git a/Python/ceval.c b/Python/ceval.c index 9e56b50ee844b..1d69708576fa4 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -93,6 +93,7 @@ static int import_all_from(PyThreadState *, PyObject *, PyObject *); static void format_exc_check_arg(PyThreadState *, PyObject *, const char *, PyObject *); static void format_exc_unbound(PyThreadState *tstate, PyCodeObject *co, int oparg); static int check_args_iterable(PyThreadState *, PyObject *func, PyObject *vararg); +static int check_except_type_valid(PyThreadState *tstate, PyObject* right); static void format_kwargs_error(PyThreadState *, PyObject *func, PyObject *kwargs); static void format_awaitable_error(PyThreadState *, PyTypeObject *, int, int); static int get_exception_handler(PyCodeObject *, int, int*, int*, int*); @@ -3715,31 +3716,11 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } TARGET(JUMP_IF_NOT_EXC_MATCH) { - const char *cannot_catch_msg = "catching classes that do not " - "inherit from BaseException is not " - "allowed"; PyObject *right = POP(); PyObject *left = TOP(); - if (PyTuple_Check(right)) { - Py_ssize_t i, length; - length = PyTuple_GET_SIZE(right); - for (i = 0; i < length; i++) { - PyObject *exc = PyTuple_GET_ITEM(right, i); - if (!PyExceptionClass_Check(exc)) { - _PyErr_SetString(tstate, PyExc_TypeError, - cannot_catch_msg); - Py_DECREF(right); - goto error; - } - } - } - else { - if (!PyExceptionClass_Check(right)) { - _PyErr_SetString(tstate, PyExc_TypeError, - cannot_catch_msg); - Py_DECREF(right); - goto error; - } + if (check_except_type_valid(tstate, right) < 0) { + Py_DECREF(right); + goto error; } int res = PyErr_GivenExceptionMatches(left, right); Py_DECREF(right); @@ -6892,6 +6873,35 @@ import_all_from(PyThreadState *tstate, PyObject *locals, PyObject *v) return err; } + +#define CANNOT_CATCH_MSG "catching classes that do not inherit from "\ + "BaseException is not allowed" + +static int +check_except_type_valid(PyThreadState *tstate, PyObject* right) +{ + if (PyTuple_Check(right)) { + Py_ssize_t i, length; + length = PyTuple_GET_SIZE(right); + for (i = 0; i < length; i++) { + PyObject *exc = PyTuple_GET_ITEM(right, i); + if (!PyExceptionClass_Check(exc)) { + _PyErr_SetString(tstate, PyExc_TypeError, + CANNOT_CATCH_MSG); + return -1; + } + } + } + else { + if (!PyExceptionClass_Check(right)) { + _PyErr_SetString(tstate, PyExc_TypeError, + CANNOT_CATCH_MSG); + return -1; + } + } + return 0; +} + static int check_args_iterable(PyThreadState *tstate, PyObject *func, PyObject *args) { From webhook-mailer at python.org Mon Nov 22 13:09:57 2021 From: webhook-mailer at python.org (gvanrossum) Date: Mon, 22 Nov 2021 18:09:57 -0000 Subject: [Python-checkins] bpo-45850: Implement deep-freeze on Windows (#29648) Message-ID: https://github.com/python/cpython/commit/1037ca5a8ea001bfa2a198e08655620234e9befd commit: 1037ca5a8ea001bfa2a198e08655620234e9befd branch: main author: Guido van Rossum committer: gvanrossum date: 2021-11-22T10:09:48-08:00 summary: bpo-45850: Implement deep-freeze on Windows (#29648) Implement changes to build with deep-frozen modules on Windows. Note that we now require Python 3.10 as the "bootstrap" or "host" Python. This causes a modest startup speed (around 7%) on Windows. files: A Misc/NEWS.d/next/Windows/2021-11-20-00-06-59.bpo-45850.q9lofz.rst A Tools/scripts/startuptime.py A Tools/scripts/umarshal.py M PCbuild/_freeze_module.vcxproj M PCbuild/find_python.bat M PCbuild/pythoncore.vcxproj M Python/frozen.c M Tools/scripts/deepfreeze.py M Tools/scripts/freeze_modules.py diff --git a/Misc/NEWS.d/next/Windows/2021-11-20-00-06-59.bpo-45850.q9lofz.rst b/Misc/NEWS.d/next/Windows/2021-11-20-00-06-59.bpo-45850.q9lofz.rst new file mode 100644 index 0000000000000..a84e1feb75025 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2021-11-20-00-06-59.bpo-45850.q9lofz.rst @@ -0,0 +1,2 @@ +Implement changes to build with deep-frozen modules on Windows. +Note that we now require Python 3.10 as the "bootstrap" or "host" Python. diff --git a/PCbuild/_freeze_module.vcxproj b/PCbuild/_freeze_module.vcxproj index 6a91776b9d8e9..54fef9ca629b1 100644 --- a/PCbuild/_freeze_module.vcxproj +++ b/PCbuild/_freeze_module.vcxproj @@ -236,101 +236,141 @@ importlib._bootstrap $(IntDir)importlib._bootstrap.g.h $(PySourcePath)Python\frozen_modules\importlib._bootstrap.h + $(IntDir)importlib._bootstrap.g.c + $(PySourcePath)Python\deepfreeze\df.importlib._bootstrap.c importlib._bootstrap_external $(IntDir)importlib._bootstrap_external.g.h $(PySourcePath)Python\frozen_modules\importlib._bootstrap_external.h + $(IntDir)importlib._bootstrap_external.g.c + $(PySourcePath)Python\deepfreeze\df.importlib._bootstrap_external.c zipimport $(IntDir)zipimport.g.h $(PySourcePath)Python\frozen_modules\zipimport.h + $(IntDir)zipimport.g.c + $(PySourcePath)Python\deepfreeze\df.zipimport.c abc $(IntDir)abc.g.h $(PySourcePath)Python\frozen_modules\abc.h + $(IntDir)abc.g.c + $(PySourcePath)Python\deepfreeze\df.abc.c codecs $(IntDir)codecs.g.h $(PySourcePath)Python\frozen_modules\codecs.h + $(IntDir)codecs.g.c + $(PySourcePath)Python\deepfreeze\df.codecs.c io $(IntDir)io.g.h $(PySourcePath)Python\frozen_modules\io.h + $(IntDir)io.g.c + $(PySourcePath)Python\deepfreeze\df.io.c _collections_abc $(IntDir)_collections_abc.g.h $(PySourcePath)Python\frozen_modules\_collections_abc.h + $(IntDir)_collections_abc.g.c + $(PySourcePath)Python\deepfreeze\df._collections_abc.c _sitebuiltins $(IntDir)_sitebuiltins.g.h $(PySourcePath)Python\frozen_modules\_sitebuiltins.h + $(IntDir)_sitebuiltins.g.c + $(PySourcePath)Python\deepfreeze\df._sitebuiltins.c genericpath $(IntDir)genericpath.g.h $(PySourcePath)Python\frozen_modules\genericpath.h + $(IntDir)genericpath.g.c + $(PySourcePath)Python\deepfreeze\df.genericpath.c ntpath $(IntDir)ntpath.g.h $(PySourcePath)Python\frozen_modules\ntpath.h + $(IntDir)ntpath.g.c + $(PySourcePath)Python\deepfreeze\df.ntpath.c posixpath $(IntDir)posixpath.g.h $(PySourcePath)Python\frozen_modules\posixpath.h + $(IntDir)posixpath.g.c + $(PySourcePath)Python\deepfreeze\df.posixpath.c os $(IntDir)os.g.h $(PySourcePath)Python\frozen_modules\os.h + $(IntDir)os.g.c + $(PySourcePath)Python\deepfreeze\df.os.c site $(IntDir)site.g.h $(PySourcePath)Python\frozen_modules\site.h + $(IntDir)site.g.c + $(PySourcePath)Python\deepfreeze\df.site.c stat $(IntDir)stat.g.h $(PySourcePath)Python\frozen_modules\stat.h + $(IntDir)stat.g.c + $(PySourcePath)Python\deepfreeze\df.stat.c __hello__ $(IntDir)__hello__.g.h $(PySourcePath)Python\frozen_modules\__hello__.h + $(IntDir)__hello__.g.c + $(PySourcePath)Python\deepfreeze\df.__hello__.c __phello__ $(IntDir)__phello__.g.h $(PySourcePath)Python\frozen_modules\__phello__.h + $(IntDir)__phello__.g.c + $(PySourcePath)Python\deepfreeze\df.__phello__.c __phello__.ham $(IntDir)__phello__.ham.g.h $(PySourcePath)Python\frozen_modules\__phello__.ham.h + $(IntDir)__phello__.ham.g.c + $(PySourcePath)Python\deepfreeze\df.__phello__.ham.c __phello__.ham.eggs $(IntDir)__phello__.ham.eggs.g.h $(PySourcePath)Python\frozen_modules\__phello__.ham.eggs.h + $(IntDir)__phello__.ham.eggs.g.c + $(PySourcePath)Python\deepfreeze\df.__phello__.ham.eggs.c __phello__.spam $(IntDir)__phello__.spam.g.h $(PySourcePath)Python\frozen_modules\__phello__.spam.h + $(IntDir)__phello__.spam.g.c + $(PySourcePath)Python\deepfreeze\df.__phello__.spam.c frozen_only $(IntDir)frozen_only.g.h $(PySourcePath)Python\frozen_modules\frozen_only.h + $(IntDir)frozen_only.g.c + $(PySourcePath)Python\deepfreeze\df.frozen_only.c @@ -338,17 +378,29 @@ - + - + Condition="!Exists(%(None.OutFile)) or (Exists(%(None.DeepIntFile)) and '$([System.IO.File]::ReadAllText(%(None.OutFile)).Replace(` `, ` `))' != '$([System.IO.File]::ReadAllText(%(None.DeepIntFile)).Replace(` `, ` `))')"> + + + + + + + + + diff --git a/PCbuild/find_python.bat b/PCbuild/find_python.bat index d0e4a86b01fd0..a9f14c5277ffa 100644 --- a/PCbuild/find_python.bat +++ b/PCbuild/find_python.bat @@ -31,13 +31,13 @@ @if "%_Py_EXTERNALS_DIR%"=="" (set _Py_EXTERNALS_DIR=%~dp0\..\externals) @rem If we have Python in externals, use that one - at if exist "%_Py_EXTERNALS_DIR%\pythonx86\tools\python.exe" (set PYTHON="%_Py_EXTERNALS_DIR%\pythonx86\tools\python.exe") & (set _Py_Python_Source=found in externals directory) & goto :found + at if exist "%_Py_EXTERNALS_DIR%\pythonx86\tools\python.exe" ("%_Py_EXTERNALS_DIR%\pythonx86\tools\python.exe" -Ec "import sys; assert sys.version_info[:2] >= (3, 10)" >nul 2>nul) && (set PYTHON="%_Py_EXTERNALS_DIR%\pythonx86\tools\python.exe") && (set _Py_Python_Source=found in externals directory) && goto :found || rmdir /Q /S "%_Py_EXTERNALS_DIR%\pythonx86" @rem If HOST_PYTHON is recent enough, use that - at if NOT "%HOST_PYTHON%"=="" @%HOST_PYTHON% -Ec "import sys; assert sys.version_info[:2] >= (3, 8)" >nul 2>nul && (set PYTHON="%HOST_PYTHON%") && (set _Py_Python_Source=found as HOST_PYTHON) && goto :found + at if NOT "%HOST_PYTHON%"=="" @%HOST_PYTHON% -Ec "import sys; assert sys.version_info[:2] >= (3, 10)" >nul 2>nul && (set PYTHON="%HOST_PYTHON%") && (set _Py_Python_Source=found as HOST_PYTHON) && goto :found @rem If py.exe finds a recent enough version, use that one - at for %%p in (3.9 3.8) do @py -%%p -EV >nul 2>&1 && (set PYTHON=py -%%p) && (set _Py_Python_Source=found %%p with py.exe) && goto :found + at for %%p in (3.10) do @py -%%p -EV >nul 2>&1 && (set PYTHON=py -%%p) && (set _Py_Python_Source=found %%p with py.exe) && goto :found @if NOT exist "%_Py_EXTERNALS_DIR%" mkdir "%_Py_EXTERNALS_DIR%" @set _Py_NUGET=%NUGET% diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 70f05563fa391..e1d59de7bc8f2 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -502,6 +502,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Python/frozen.c b/Python/frozen.c index 1565c9a3d73f7..9f43db70886f7 100644 --- a/Python/frozen.c +++ b/Python/frozen.c @@ -61,12 +61,7 @@ #include "frozen_modules/frozen_only.h" /* End includes */ -#ifdef MS_WINDOWS -/* Deepfreeze isn't supported on Windows yet. */ -#define GET_CODE(name) NULL -#else #define GET_CODE(name) _Py_get_##name##_toplevel -#endif /* Start extern declarations */ extern PyObject *_Py_get_importlib__bootstrap_toplevel(void); diff --git a/Tools/scripts/deepfreeze.py b/Tools/scripts/deepfreeze.py index 074127f949298..b6d52b7454965 100644 --- a/Tools/scripts/deepfreeze.py +++ b/Tools/scripts/deepfreeze.py @@ -1,13 +1,16 @@ import argparse +import ast import builtins import collections import contextlib import os -import sys +import re import time import types import typing +import umarshal + verbose = False @@ -55,7 +58,8 @@ def get_localsplus_counts(code: types.CodeType, nplaincellvars += 1 elif kind & CO_FAST_FREE: nfreevars += 1 - assert nlocals == len(code.co_varnames) == code.co_nlocals + assert nlocals == len(code.co_varnames) == code.co_nlocals, \ + (nlocals, len(code.co_varnames), code.co_nlocals) assert ncellvars == len(code.co_cellvars) assert nfreevars == len(code.co_freevars) assert len(names) == nlocals + nplaincellvars + nfreevars @@ -274,14 +278,7 @@ def generate_tuple(self, name: str, t: tuple[object, ...]) -> str: self.write(item + ",") return f"& {name}._object.ob_base.ob_base" - def generate_int(self, name: str, i: int) -> str: - maxint = sys.maxsize - if maxint == 2**31 - 1: - digit = 2**15 - elif maxint == 2**63 - 1: - digit = 2**30 - else: - assert False, f"What int size is this system?!? {maxint=}" + def _generate_int_for_bits(self, name: str, i: int, digit: int) -> None: sign = -1 if i < 0 else 0 if i == 0 else +1 i = abs(i) digits: list[int] = [] @@ -298,6 +295,20 @@ def generate_int(self, name: str, i: int) -> str: if digits: ds = ", ".join(map(str, digits)) self.write(f".ob_digit = {{ {ds} }},") + + def generate_int(self, name: str, i: int) -> str: + if abs(i) < 2**15: + self._generate_int_for_bits(name, i, 2**15) + else: + connective = "if" + for bits_in_digit in 15, 30: + self.write(f"#{connective} PYLONG_BITS_IN_DIGIT == {bits_in_digit}") + self._generate_int_for_bits(name, i, 2**bits_in_digit) + connective = "elif" + self.write("#else") + self.write('#error "PYLONG_BITS_IN_DIGIT should be 15 or 30"') + self.write("#endif") + # If neither clause applies, it won't compile return f"& {name}.ob_base.ob_base" def generate_float(self, name: str, x: float) -> str: @@ -326,7 +337,7 @@ def generate(self, name: str, obj: object) -> str: return self.cache[key] self.misses += 1 match obj: - case types.CodeType() as code: + case types.CodeType() | umarshal.Code() as code: val = self.generate_code(name, code) case tuple(t): val = self.generate_tuple(name, t) @@ -367,8 +378,31 @@ def generate(self, name: str, obj: object) -> str: } """ +FROZEN_COMMENT = "/* Auto-generated by Programs/_freeze_module.c */" + +FROZEN_DATA_LINE = r"\s*(\d+,\s*)+\s*" + + +def is_frozen_header(source: str) -> bool: + return source.startswith(FROZEN_COMMENT) + + +def decode_frozen_data(source: str) -> types.CodeType: + lines = source.splitlines() + while lines and re.match(FROZEN_DATA_LINE, lines[0]) is None: + del lines[0] + while lines and re.match(FROZEN_DATA_LINE, lines[-1]) is None: + del lines[-1] + values: tuple[int, ...] = ast.literal_eval("".join(lines)) + data = bytes(values) + return umarshal.loads(data) + + def generate(source: str, filename: str, modname: str, file: typing.TextIO) -> None: - code = compile(source, filename, "exec") + if is_frozen_header(source): + code = decode_frozen_data(source) + else: + code = compile(source, filename, "exec") printer = Printer(file) printer.generate("toplevel", code) printer.write("") diff --git a/Tools/scripts/freeze_modules.py b/Tools/scripts/freeze_modules.py index ccea4e11ab6ca..61ccae61e4f96 100644 --- a/Tools/scripts/freeze_modules.py +++ b/Tools/scripts/freeze_modules.py @@ -11,7 +11,6 @@ import platform import subprocess import sys -import textwrap import time from update_file import updating_file_with_tmpfile, update_file_with_tmpfile @@ -55,6 +54,7 @@ def find_tool(): MAKEFILE = os.path.join(ROOT_DIR, 'Makefile.pre.in') PCBUILD_PROJECT = os.path.join(ROOT_DIR, 'PCbuild', '_freeze_module.vcxproj') PCBUILD_FILTERS = os.path.join(ROOT_DIR, 'PCbuild', '_freeze_module.vcxproj.filters') +PCBUILD_PYTHONCORE = os.path.join(ROOT_DIR, 'PCbuild', 'pythoncore.vcxproj') OS_PATH = 'ntpath' if os.name == 'nt' else 'posixpath' @@ -717,20 +717,28 @@ def regen_makefile(modules): def regen_pcbuild(modules): projlines = [] filterlines = [] + corelines = [] for src in _iter_sources(modules): pyfile = relpath_for_windows_display(src.pyfile, ROOT_DIR) header = relpath_for_windows_display(src.frozenfile, ROOT_DIR) + deepbase = "df." + src.id + deepoutfile = f"Python\\deepfreeze\\{deepbase}.c" intfile = ntpath.splitext(ntpath.basename(header))[0] + '.g.h' + deepintfile = ntpath.splitext(ntpath.basename(header))[0] + '.g.c' projlines.append(f' ') projlines.append(f' {src.frozenid}') projlines.append(f' $(IntDir){intfile}') projlines.append(f' $(PySourcePath){header}') + projlines.append(f' $(IntDir){deepintfile}') + projlines.append(f' $(PySourcePath){deepoutfile}') projlines.append(f' ') filterlines.append(f' ') filterlines.append(' Python Files') filterlines.append(' ') + corelines.append(f' ') + print(f'# Updating {os.path.relpath(PCBUILD_PROJECT)}') with updating_file_with_tmpfile(PCBUILD_PROJECT) as (infile, outfile): lines = infile.readlines() @@ -753,6 +761,17 @@ def regen_pcbuild(modules): PCBUILD_FILTERS, ) outfile.writelines(lines) + print(f'# Updating {os.path.relpath(PCBUILD_PYTHONCORE)}') + with updating_file_with_tmpfile(PCBUILD_PYTHONCORE) as (infile, outfile): + lines = infile.readlines() + lines = replace_block( + lines, + '', + '', + corelines, + PCBUILD_FILTERS, + ) + outfile.writelines(lines) ####################################### diff --git a/Tools/scripts/startuptime.py b/Tools/scripts/startuptime.py new file mode 100644 index 0000000000000..1bb5b208f66e0 --- /dev/null +++ b/Tools/scripts/startuptime.py @@ -0,0 +1,22 @@ +# Quick script to time startup for various binaries + +import subprocess +import sys +import time + +NREPS = 100 + + +def main(): + binaries = sys.argv[1:] + for bin in binaries: + t0 = time.time() + for _ in range(NREPS): + result = subprocess.run([bin, "-c", "pass"]) + result.check_returncode() + t1 = time.time() + print(f"{(t1-t0)/NREPS:6.3f} {bin}") + + +if __name__ == "__main__": + main() diff --git a/Tools/scripts/umarshal.py b/Tools/scripts/umarshal.py new file mode 100644 index 0000000000000..e0d18c89e7531 --- /dev/null +++ b/Tools/scripts/umarshal.py @@ -0,0 +1,328 @@ +# Implementat marshal.loads() in pure Python + +import ast + +from typing import Any + + +class Type: + # Adapted from marshal.c + NULL = ord('0') + NONE = ord('N') + FALSE = ord('F') + TRUE = ord('T') + STOPITER = ord('S') + ELLIPSIS = ord('.') + INT = ord('i') + INT64 = ord('I') + FLOAT = ord('f') + BINARY_FLOAT = ord('g') + COMPLEX = ord('x') + BINARY_COMPLEX = ord('y') + LONG = ord('l') + STRING = ord('s') + INTERNED = ord('t') + REF = ord('r') + TUPLE = ord('(') + LIST = ord('[') + DICT = ord('{') + CODE = ord('c') + UNICODE = ord('u') + UNKNOWN = ord('?') + SET = ord('<') + FROZENSET = ord('>') + ASCII = ord('a') + ASCII_INTERNED = ord('A') + SMALL_TUPLE = ord(')') + SHORT_ASCII = ord('z') + SHORT_ASCII_INTERNED = ord('Z') + + +FLAG_REF = 0x80 # with a type, add obj to index + +NULL = object() # marker + +# Cell kinds +CO_FAST_LOCAL = 0x20 +CO_FAST_CELL = 0x40 +CO_FAST_FREE = 0x80 + + +class Code: + def __init__(self, **kwds: Any): + self.__dict__.update(kwds) + + def __repr__(self) -> str: + return f"Code(**{self.__dict__})" + + co_localsplusnames: tuple[str] + co_localspluskinds: tuple[int] + + def get_localsplus_names(self, select_kind: int) -> tuple[str, ...]: + varnames: list[str] = [] + for name, kind in zip(self.co_localsplusnames, + self.co_localspluskinds): + if kind & select_kind: + varnames.append(name) + return tuple(varnames) + + @property + def co_varnames(self) -> tuple[str, ...]: + return self.get_localsplus_names(CO_FAST_LOCAL) + + @property + def co_cellvars(self) -> tuple[str, ...]: + return self.get_localsplus_names(CO_FAST_CELL) + + @property + def co_freevars(self) -> tuple[str, ...]: + return self.get_localsplus_names(CO_FAST_FREE) + + @property + def co_nlocals(self) -> int: + return len(self.co_varnames) + + +class Reader: + # A fairly literal translation of the marshal reader. + + def __init__(self, data: bytes): + self.data: bytes = data + self.end: int = len(self.data) + self.pos: int = 0 + self.refs: list[Any] = [] + self.level: int = 0 + + def r_string(self, n: int) -> bytes: + assert 0 <= n <= self.end - self.pos + buf = self.data[self.pos : self.pos + n] + self.pos += n + return buf + + def r_byte(self) -> int: + buf = self.r_string(1) + return buf[0] + + def r_short(self) -> int: + buf = self.r_string(2) + x = buf[0] + x |= buf[1] << 8 + x |= -(x & (1<<15)) # Sign-extend + return x + + def r_long(self) -> int: + buf = self.r_string(4) + x = buf[0] + x |= buf[1] << 8 + x |= buf[2] << 16 + x |= buf[3] << 24 + x |= -(x & (1<<31)) # Sign-extend + return x + + def r_long64(self) -> int: + buf = self.r_string(8) + x = buf[0] + x |= buf[1] << 8 + x |= buf[2] << 16 + x |= buf[3] << 24 + x |= buf[1] << 32 + x |= buf[1] << 40 + x |= buf[1] << 48 + x |= buf[1] << 56 + x |= -(x & (1<<63)) # Sign-extend + return x + + def r_PyLong(self) -> int: + n = self.r_long() + size = abs(n) + x = 0 + # Pray this is right + for i in range(size): + x |= self.r_short() << i*15 + if n < 0: + x = -x + return x + + def r_float_bin(self) -> float: + buf = self.r_string(8) + import struct # Lazy import to avoid breaking UNIX build + return struct.unpack("d", buf)[0] + + def r_float_str(self) -> float: + n = self.r_byte() + buf = self.r_string(n) + return ast.literal_eval(buf.decode("ascii")) + + def r_ref_reserve(self, flag: int) -> int: + if flag: + idx = len(self.refs) + self.refs.append(None) + return idx + else: + return 0 + + def r_ref_insert(self, obj: Any, idx: int, flag: int) -> Any: + if flag: + self.refs[idx] = obj + return obj + + def r_ref(self, obj: Any, flag: int) -> Any: + assert flag & FLAG_REF + self.refs.append(obj) + return obj + + def r_object(self) -> Any: + old_level = self.level + try: + return self._r_object() + finally: + self.level = old_level + + def _r_object(self) -> Any: + code = self.r_byte() + flag = code & FLAG_REF + type = code & ~FLAG_REF + # print(" "*self.level + f"{code} {flag} {type} {chr(type)!r}") + self.level += 1 + + def R_REF(obj: Any) -> Any: + if flag: + obj = self.r_ref(obj, flag) + return obj + + match type: + case Type.NULL: + return NULL + case Type.NONE: + return None + case Type.ELLIPSIS: + return Ellipsis + case Type.FALSE: + return False + case Type.TRUE: + return True + case Type.INT: + return R_REF(self.r_long()) + case Type.INT64: + return R_REF(self.r_long64()) + case Type.LONG: + return R_REF(self.r_PyLong()) + case Type.FLOAT: + return R_REF(self.r_float_str()) + case Type.BINARY_FLOAT: + return R_REF(self.r_float_bin()) + case Type.COMPLEX: + return R_REF(complex(self.r_float_str(), + self.r_float_str())) + case Type.BINARY_COMPLEX: + return R_REF(complex(self.r_float_bin(), + self.r_float_bin())) + case Type.STRING: + n = self.r_long() + return R_REF(self.r_string(n)) + case Type.ASCII_INTERNED | Type.ASCII: + n = self.r_long() + return R_REF(self.r_string(n).decode("ascii")) + case Type.SHORT_ASCII_INTERNED | Type.SHORT_ASCII: + n = self.r_byte() + return R_REF(self.r_string(n).decode("ascii")) + case Type.INTERNED | Type.UNICODE: + n = self.r_long() + return R_REF(self.r_string(n).decode("utf8", "surrogatepass")) + case Type.SMALL_TUPLE: + n = self.r_byte() + idx = self.r_ref_reserve(flag) + retval: Any = tuple(self.r_object() for _ in range(n)) + self.r_ref_insert(retval, idx, flag) + return retval + case Type.TUPLE: + n = self.r_long() + idx = self.r_ref_reserve(flag) + retval = tuple(self.r_object() for _ in range(n)) + self.r_ref_insert(retval, idx, flag) + return retval + case Type.LIST: + n = self.r_long() + retval = R_REF([]) + for _ in range(n): + retval.append(self.r_object()) + return retval + case Type.DICT: + retval = R_REF({}) + while True: + key = self.r_object() + if key == NULL: + break + val = self.r_object() + retval[key] = val + return retval + case Type.SET: + n = self.r_long() + retval = R_REF(set()) + for _ in range(n): + v = self.r_object() + retval.add(v) + return retval + case Type.FROZENSET: + n = self.r_long() + s: set[Any] = set() + idx = self.r_ref_reserve(flag) + for _ in range(n): + v = self.r_object() + s.add(v) + retval = frozenset(s) + self.r_ref_insert(retval, idx, flag) + return retval + case Type.CODE: + retval = R_REF(Code()) + retval.co_argcount = self.r_long() + retval.co_posonlyargcount = self.r_long() + retval.co_kwonlyargcount = self.r_long() + retval.co_stacksize = self.r_long() + retval.co_flags = self.r_long() + retval.co_code = self.r_object() + retval.co_consts = self.r_object() + retval.co_names = self.r_object() + retval.co_localsplusnames = self.r_object() + retval.co_localspluskinds = self.r_object() + retval.co_filename = self.r_object() + retval.co_name = self.r_object() + retval.co_qualname = self.r_object() + retval.co_firstlineno = self.r_long() + retval.co_linetable = self.r_object() + retval.co_endlinetable = self.r_object() + retval.co_columntable = self.r_object() + retval.co_exceptiontable = self.r_object() + return retval + case Type.REF: + n = self.r_long() + retval = self.refs[n] + assert retval is not None + return retval + case _: + breakpoint() + raise AssertionError(f"Unknown type {type} {chr(type)!r}") + + +def loads(data: bytes) -> Any: + assert isinstance(data, bytes) + r = Reader(data) + return r.r_object() + + +def main(): + # Test + import marshal, pprint + sample = {'foo': {(42, "bar", 3.14)}} + data = marshal.dumps(sample) + retval = loads(data) + assert retval == sample, retval + sample = main.__code__ + data = marshal.dumps(sample) + retval = loads(data) + assert isinstance(retval, Code), retval + pprint.pprint(retval.__dict__) + + +if __name__ == "__main__": + main() From webhook-mailer at python.org Mon Nov 22 15:27:33 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 22 Nov 2021 20:27:33 -0000 Subject: [Python-checkins] bpo-45847: Port xxlimited and xxlimited_35 to PY_STDLIB_MOD (GH-29707) Message-ID: https://github.com/python/cpython/commit/2dc7d3dda61e7ce07721f46b14c706fbc879dfd6 commit: 2dc7d3dda61e7ce07721f46b14c706fbc879dfd6 branch: main author: Erlend Egeberg Aasland committer: tiran date: 2021-11-22T21:27:05+01:00 summary: bpo-45847: Port xxlimited and xxlimited_35 to PY_STDLIB_MOD (GH-29707) files: M Modules/Setup.stdlib.in M configure M configure.ac M setup.py diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index b12ae9db5e9b2..0c88eed3b5e65 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -135,9 +135,14 @@ @MODULE__TESTBUFFER_TRUE at _testbuffer _testbuffer.c @MODULE__TESTINTERNALCAPI_TRUE at _testinternalcapi _testinternalcapi.c + # Some testing modules MUST be built as shared libraries. *shared* @MODULE__TESTCAPI_TRUE at _testcapi _testcapimodule.c @MODULE__TESTIMPORTMULTIPLE_TRUE at _testimportmultiple _testimportmultiple.c @MODULE__TESTMULTIPHASE_TRUE at _testmultiphase _testmultiphase.c @MODULE__CTYPES_TEST_TRUE at _ctypes_test _ctypes/_ctypes_test.c + +# Limited API template modules; must be built as shared modules. + at MODULE_XXLIMITED_TRUE@xxlimited xxlimited.c + at MODULE_XXLIMITED_35_TRUE@xxlimited_35 xxlimited_35.c diff --git a/configure b/configure index a1fc09fc04854..dafcce61d132d 100755 --- a/configure +++ b/configure @@ -624,6 +624,10 @@ ac_includes_default="\ ac_subst_vars='LTLIBOBJS MODULE_BLOCK +MODULE_XXLIMITED_35_FALSE +MODULE_XXLIMITED_35_TRUE +MODULE_XXLIMITED_FALSE +MODULE_XXLIMITED_TRUE MODULE__CTYPES_TEST_FALSE MODULE__CTYPES_TEST_TRUE MODULE__XXTESTFUZZ_FALSE @@ -21838,6 +21842,79 @@ fi $as_echo "$py_cv_module__ctypes_test" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module xxlimited" >&5 +$as_echo_n "checking for stdlib extension module xxlimited... " >&6; } + case $py_stdlib_not_available in #( + *xxlimited*) : + py_cv_module_xxlimited=n/a ;; #( + *) : + if test "$Py_TRACE_REFS" = no; then : + if true; then : + py_cv_module_xxlimited=yes +else + py_cv_module_xxlimited=missing +fi +else + py_cv_module_xxlimited=disabled +fi + ;; +esac + as_fn_append MODULE_BLOCK "MODULE_XXLIMITED=$py_cv_module_xxlimited$as_nl" + if test "x$py_cv_module_xxlimited" = xyes; then : + + + + +fi + if test "$py_cv_module_xxlimited" = yes; then + MODULE_XXLIMITED_TRUE= + MODULE_XXLIMITED_FALSE='#' +else + MODULE_XXLIMITED_TRUE='#' + MODULE_XXLIMITED_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module_xxlimited" >&5 +$as_echo "$py_cv_module_xxlimited" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module xxlimited_35" >&5 +$as_echo_n "checking for stdlib extension module xxlimited_35... " >&6; } + case $py_stdlib_not_available in #( + *xxlimited_35*) : + py_cv_module_xxlimited_35=n/a ;; #( + *) : + if test "$Py_TRACE_REFS" = no; then : + if true; then : + py_cv_module_xxlimited_35=yes +else + py_cv_module_xxlimited_35=missing +fi +else + py_cv_module_xxlimited_35=disabled +fi + ;; +esac + as_fn_append MODULE_BLOCK "MODULE_XXLIMITED_35=$py_cv_module_xxlimited_35$as_nl" + if test "x$py_cv_module_xxlimited_35" = xyes; then : + + + + +fi + if test "$py_cv_module_xxlimited_35" = yes; then + MODULE_XXLIMITED_35_TRUE= + MODULE_XXLIMITED_35_FALSE='#' +else + MODULE_XXLIMITED_35_TRUE='#' + MODULE_XXLIMITED_35_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module_xxlimited_35" >&5 +$as_echo "$py_cv_module_xxlimited_35" >&6; } + + # substitute multiline block, must come after last PY_STDLIB_MOD() @@ -22214,6 +22291,14 @@ if test -z "${MODULE__CTYPES_TEST_TRUE}" && test -z "${MODULE__CTYPES_TEST_FALSE as_fn_error $? "conditional \"MODULE__CTYPES_TEST\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE_XXLIMITED_TRUE}" && test -z "${MODULE_XXLIMITED_FALSE}"; then + as_fn_error $? "conditional \"MODULE_XXLIMITED\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE_XXLIMITED_35_TRUE}" && test -z "${MODULE_XXLIMITED_35_FALSE}"; then + as_fn_error $? "conditional \"MODULE_XXLIMITED_35\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 diff --git a/configure.ac b/configure.ac index 5757c3b2586bc..ec7d1a48a0bee 100644 --- a/configure.ac +++ b/configure.ac @@ -6219,6 +6219,11 @@ PY_STDLIB_MOD([_testmultiphase], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_xxtestfuzz], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_ctypes_test], [test "$TEST_MODULES" = yes], [], [], [-lm]) +dnl Limited API template modules. +dnl The limited C API is not compatible with the Py_TRACE_REFS macro. +PY_STDLIB_MOD([xxlimited], [test "$Py_TRACE_REFS" = no]) +PY_STDLIB_MOD([xxlimited_35], [test "$Py_TRACE_REFS" = no]) + # substitute multiline block, must come after last PY_STDLIB_MOD() AC_SUBST([MODULE_BLOCK]) diff --git a/setup.py b/setup.py index a3aa787a1b708..a3d377a696abb 100644 --- a/setup.py +++ b/setup.py @@ -1477,13 +1477,11 @@ def detect_modules(self): self.missing.append('_tkinter') self.detect_uuid() -## # Uncomment these lines if you want to play with xxmodule.c -## self.add(Extension('xx', ['xxmodule.c'])) + # Uncomment the next line if you want to play with xxmodule.c +# self.add(Extension('xx', ['xxmodule.c'])) - # The limited C API is not compatible with the Py_TRACE_REFS macro. - if not sysconfig.get_config_var('Py_TRACE_REFS'): - self.add(Extension('xxlimited', ['xxlimited.c'])) - self.add(Extension('xxlimited_35', ['xxlimited_35.c'])) + self.addext(Extension('xxlimited', ['xxlimited.c'])) + self.addext(Extension('xxlimited_35', ['xxlimited_35.c'])) def detect_tkinter_fromenv(self): # Build _tkinter using the Tcl/Tk locations specified by From webhook-mailer at python.org Mon Nov 22 18:09:24 2021 From: webhook-mailer at python.org (brettcannon) Date: Mon, 22 Nov 2021 23:09:24 -0000 Subject: [Python-checkins] [3.10] bpo-45250: fix docs regarding `__iter__` and iterators being inconsistently required by CPython (GH-29170) (GH-29650) Message-ID: https://github.com/python/cpython/commit/99aad31b7ad493d4feea04064bcd6b04061477f9 commit: 99aad31b7ad493d4feea04064bcd6b04061477f9 branch: 3.10 author: Brett Cannon committer: brettcannon date: 2021-11-22T15:09:15-08:00 summary: [3.10] bpo-45250: fix docs regarding `__iter__` and iterators being inconsistently required by CPython (GH-29170) (GH-29650) It is now considered a historical accident that e.g. `for` loops and the `iter()` built-in function do not require the iterators they work with to define `__iter__`, only `__next__`. (cherry picked from commit be36e0634060c7d5dee8e8876fb888bbb53d992a) Co-authored-by: Brett Cannon files: A Misc/NEWS.d/next/Documentation/2021-10-22-12-09-18.bpo-45250.Iit5-Y.rst M Doc/c-api/iter.rst M Doc/c-api/typeobj.rst M Doc/glossary.rst M Doc/library/functions.rst M Doc/library/stdtypes.rst M Doc/reference/datamodel.rst diff --git a/Doc/c-api/iter.rst b/Doc/c-api/iter.rst index f7106f4ef0990..3e388bb917a02 100644 --- a/Doc/c-api/iter.rst +++ b/Doc/c-api/iter.rst @@ -9,8 +9,8 @@ There are two functions specifically for working with iterators. .. c:function:: int PyIter_Check(PyObject *o) - Return non-zero if the object *o* supports the iterator protocol, and ``0`` - otherwise. This function always succeeds. + Return non-zero if the object *o* can be safely passed to + :c:func:`PyIter_Next`, and ``0`` otherwise. This function always succeeds. .. c:function:: int PyAIter_Check(PyObject *o) @@ -21,10 +21,11 @@ There are two functions specifically for working with iterators. .. c:function:: PyObject* PyIter_Next(PyObject *o) - Return the next value from the iteration *o*. The object must be an iterator - (it is up to the caller to check this). If there are no remaining values, - returns ``NULL`` with no exception set. If an error occurs while retrieving - the item, returns ``NULL`` and passes along the exception. + Return the next value from the iterator *o*. The object must be an iterator + according to :c:func:`PyIter_Check` (it is up to the caller to check this). + If there are no remaining values, returns ``NULL`` with no exception set. + If an error occurs while retrieving the item, returns ``NULL`` and passes + along the exception. To write a loop which iterates over an iterator, the C code should look something like this:: diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index faef6ab5fed50..e491c26f981b5 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -1520,9 +1520,9 @@ and :c:type:`PyType_Type` effectively act as defaults.) .. c:member:: getiterfunc PyTypeObject.tp_iter - An optional pointer to a function that returns an iterator for the object. Its - presence normally signals that the instances of this type are iterable (although - sequences may be iterable without this function). + An optional pointer to a function that returns an :term:`iterator` for the + object. Its presence normally signals that the instances of this type are + :term:`iterable` (although sequences may be iterable without this function). This function has the same signature as :c:func:`PyObject_GetIter`:: @@ -1535,8 +1535,8 @@ and :c:type:`PyType_Type` effectively act as defaults.) .. c:member:: iternextfunc PyTypeObject.tp_iternext - An optional pointer to a function that returns the next item in an iterator. - The signature is:: + An optional pointer to a function that returns the next item in an + :term:`iterator`. The signature is:: PyObject *tp_iternext(PyObject *self); @@ -2428,8 +2428,8 @@ Async Object Structures PyObject *am_await(PyObject *self); - The returned object must be an iterator, i.e. :c:func:`PyIter_Check` must - return ``1`` for it. + The returned object must be an :term:`iterator`, i.e. :c:func:`PyIter_Check` + must return ``1`` for it. This slot may be set to ``NULL`` if an object is not an :term:`awaitable`. diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 40b57bd41e8c6..1bbd05a5bcecd 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -669,6 +669,11 @@ Glossary More information can be found in :ref:`typeiter`. + .. impl-detail:: + + CPython does not consistently apply the requirement that an iterator + define :meth:`__iter__`. + key function A key function or collation function is a callable that returns a value used for sorting or ordering. For example, :func:`locale.strxfrm` is diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 47ebbd0b509a5..307d67978559c 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -66,9 +66,6 @@ are always available. They are listed here in alphabetical order. Return an :term:`asynchronous iterator` for an :term:`asynchronous iterable`. Equivalent to calling ``x.__aiter__()``. - ``aiter(x)`` itself has an ``__aiter__()`` method that returns ``x``, - so ``aiter(aiter(x))`` is the same as ``aiter(x)``. - Note: Unlike :func:`iter`, :func:`aiter` has no 2-argument variant. .. versionadded:: 3.10 @@ -929,8 +926,8 @@ are always available. They are listed here in alphabetical order. Return an :term:`iterator` object. The first argument is interpreted very differently depending on the presence of the second argument. Without a second argument, *object* must be a collection object which supports the - iteration protocol (the :meth:`__iter__` method), or it must support the - sequence protocol (the :meth:`__getitem__` method with integer arguments + :term:`iterable` protocol (the :meth:`__iter__` method), or it must support + the sequence protocol (the :meth:`__getitem__` method with integer arguments starting at ``0``). If it does not support either of those protocols, :exc:`TypeError` is raised. If the second argument, *sentinel*, is given, then *object* must be a callable object. The iterator created in this case @@ -1060,7 +1057,7 @@ are always available. They are listed here in alphabetical order. .. function:: next(iterator[, default]) - Retrieve the next item from the *iterator* by calling its + Retrieve the next item from the :term:`iterator` by calling its :meth:`~iterator.__next__` method. If *default* is given, it is returned if the iterator is exhausted, otherwise :exc:`StopIteration` is raised. diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index d6eff144cce54..1b18abcd6c95c 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -772,21 +772,21 @@ using two distinct methods; these are used to allow user-defined classes to support iteration. Sequences, described below in more detail, always support the iteration methods. -One method needs to be defined for container objects to provide iteration +One method needs to be defined for container objects to provide :term:`iterable` support: .. XXX duplicated in reference/datamodel! .. method:: container.__iter__() - Return an iterator object. The object is required to support the iterator - protocol described below. If a container supports different types of - iteration, additional methods can be provided to specifically request + Return an :term:`iterator` object. The object is required to support the + iterator protocol described below. If a container supports different types + of iteration, additional methods can be provided to specifically request iterators for those iteration types. (An example of an object supporting multiple forms of iteration would be a tree structure which supports both breadth-first and depth-first traversal.) This method corresponds to the - :c:member:`~PyTypeObject.tp_iter` slot of the type structure for Python objects in the Python/C - API. + :c:member:`~PyTypeObject.tp_iter` slot of the type structure for Python + objects in the Python/C API. The iterator objects themselves are required to support the following two methods, which together form the :dfn:`iterator protocol`: @@ -794,18 +794,19 @@ methods, which together form the :dfn:`iterator protocol`: .. method:: iterator.__iter__() - Return the iterator object itself. This is required to allow both containers - and iterators to be used with the :keyword:`for` and :keyword:`in` statements. - This method corresponds to the :c:member:`~PyTypeObject.tp_iter` slot of the type structure for - Python objects in the Python/C API. + Return the :term:`iterator` object itself. This is required to allow both + containers and iterators to be used with the :keyword:`for` and + :keyword:`in` statements. This method corresponds to the + :c:member:`~PyTypeObject.tp_iter` slot of the type structure for Python + objects in the Python/C API. .. method:: iterator.__next__() - Return the next item from the container. If there are no further items, raise - the :exc:`StopIteration` exception. This method corresponds to the - :c:member:`~PyTypeObject.tp_iternext` slot of the type structure for Python objects in the - Python/C API. + Return the next item from the :term:`iterator`. If there are no further + items, raise the :exc:`StopIteration` exception. This method corresponds to + the :c:member:`~PyTypeObject.tp_iternext` slot of the type structure for + Python objects in the Python/C API. Python defines several iterator objects to support iteration over general and specific sequence types, dictionaries, and other more specialized forms. The diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index f480915eeb50b..111417d937fbb 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -648,13 +648,13 @@ Callable types A function or method which uses the :keyword:`yield` statement (see section :ref:`yield`) is called a :dfn:`generator function`. Such a function, when - called, always returns an iterator object which can be used to execute the - body of the function: calling the iterator's :meth:`iterator.__next__` - method will cause the function to execute until it provides a value - using the :keyword:`!yield` statement. When the function executes a - :keyword:`return` statement or falls off the end, a :exc:`StopIteration` - exception is raised and the iterator will have reached the end of the set of - values to be returned. + called, always returns an :term:`iterator` object which can be used to + execute the body of the function: calling the iterator's + :meth:`iterator.__next__` method will cause the function to execute until + it provides a value using the :keyword:`!yield` statement. When the + function executes a :keyword:`return` statement or falls off the end, a + :exc:`StopIteration` exception is raised and the iterator will have + reached the end of the set of values to be returned. Coroutine functions .. index:: @@ -674,7 +674,7 @@ Callable types A function or method which is defined using :keyword:`async def` and which uses the :keyword:`yield` statement is called a :dfn:`asynchronous generator function`. Such a function, when called, - returns an asynchronous iterator object which can be used in an + returns an :term:`asynchronous iterator` object which can be used in an :keyword:`async for` statement to execute the body of the function. Calling the asynchronous iterator's :meth:`aiterator.__anext__` method @@ -2464,12 +2464,10 @@ through the object's keys; for sequences, it should iterate through the values. .. method:: object.__iter__(self) - This method is called when an iterator is required for a container. This method - should return a new iterator object that can iterate over all the objects in the - container. For mappings, it should iterate over the keys of the container. - - Iterator objects also need to implement this method; they are required to return - themselves. For more information on iterator objects, see :ref:`typeiter`. + This method is called when an :term:`iterator` is required for a container. + This method should return a new iterator object that can iterate over all the + objects in the container. For mappings, it should iterate over the keys of + the container. .. method:: object.__reversed__(self) diff --git a/Misc/NEWS.d/next/Documentation/2021-10-22-12-09-18.bpo-45250.Iit5-Y.rst b/Misc/NEWS.d/next/Documentation/2021-10-22-12-09-18.bpo-45250.Iit5-Y.rst new file mode 100644 index 0000000000000..0c2bf18b20010 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-10-22-12-09-18.bpo-45250.Iit5-Y.rst @@ -0,0 +1,2 @@ +Update the documentation to note that CPython does not consistently +require iterators to define ``__iter__``. From webhook-mailer at python.org Mon Nov 22 18:18:02 2021 From: webhook-mailer at python.org (willingc) Date: Mon, 22 Nov 2021 23:18:02 -0000 Subject: [Python-checkins] bpo-42238: [doc] Announce the future removal of make suspicous. (GH-29652) Message-ID: https://github.com/python/cpython/commit/024209401ebc8a011f242af00efdd8ecece6953d commit: 024209401ebc8a011f242af00efdd8ecece6953d branch: main author: Julien Palard committer: willingc date: 2021-11-22T15:17:54-08:00 summary: bpo-42238: [doc] Announce the future removal of make suspicous. (GH-29652) * bpo-42238: [doc] Announce the future removal of make suspicous. * Add a news entry. files: A Misc/NEWS.d/next/Documentation/2021-11-20-02-46-39.bpo-42238.hlfMIc.rst M Doc/Makefile diff --git a/Doc/Makefile b/Doc/Makefile index 24528a1c4f326..19ddafc5f2f9f 100644 --- a/Doc/Makefile +++ b/Doc/Makefile @@ -117,6 +117,10 @@ suspicious: "or in build/$(BUILDER)/suspicious.csv. If all issues are false" \ "positives, append that file to tools/susp-ignored.csv."; \ false; } + @echo "? make suspicious is deprecated and will be removed soon." + @echo "? Use:" + @echo "? make check" + @echo "? instead." coverage: BUILDER = coverage coverage: build diff --git a/Misc/NEWS.d/next/Documentation/2021-11-20-02-46-39.bpo-42238.hlfMIc.rst b/Misc/NEWS.d/next/Documentation/2021-11-20-02-46-39.bpo-42238.hlfMIc.rst new file mode 100644 index 0000000000000..dac8b17d15d40 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-20-02-46-39.bpo-42238.hlfMIc.rst @@ -0,0 +1,2 @@ +``make -C Doc suspicious`` will be removed soon in favor of ``make -C Doc +check``, mark it as deprecated. From webhook-mailer at python.org Tue Nov 23 02:51:10 2021 From: webhook-mailer at python.org (tiran) Date: Tue, 23 Nov 2021 07:51:10 -0000 Subject: [Python-checkins] bpo-45561: Run smelly.py tool from $(srcdir) (GH-29138) Message-ID: https://github.com/python/cpython/commit/457e6a6e96b5afad403a0bc892508a77beef4d33 commit: 457e6a6e96b5afad403a0bc892508a77beef4d33 branch: main author: Neil Schemenauer committer: tiran date: 2021-11-23T08:51:02+01:00 summary: bpo-45561: Run smelly.py tool from $(srcdir) (GH-29138) files: A Misc/NEWS.d/next/Build/2021-10-21-14-38-30.bpo-45561.PVqhZE.rst M Makefile.pre.in M Tools/scripts/smelly.py diff --git a/Makefile.pre.in b/Makefile.pre.in index d52f73620795c..afa0414ce04cb 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -2420,7 +2420,7 @@ distclean: clobber # Check that all symbols exported by libpython start with "Py" or "_Py" smelly: @DEF_MAKE_RULE@ - $(RUNSHARED) ./$(BUILDPYTHON) Tools/scripts/smelly.py + $(RUNSHARED) ./$(BUILDPYTHON) $(srcdir)/Tools/scripts/smelly.py # Find files with funny names funny: diff --git a/Misc/NEWS.d/next/Build/2021-10-21-14-38-30.bpo-45561.PVqhZE.rst b/Misc/NEWS.d/next/Build/2021-10-21-14-38-30.bpo-45561.PVqhZE.rst new file mode 100644 index 0000000000000..cf5d8686b9840 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-10-21-14-38-30.bpo-45561.PVqhZE.rst @@ -0,0 +1 @@ +Run smelly.py tool from $(srcdir). diff --git a/Tools/scripts/smelly.py b/Tools/scripts/smelly.py index fb01660dea33a..276a5ab2cc84c 100755 --- a/Tools/scripts/smelly.py +++ b/Tools/scripts/smelly.py @@ -108,8 +108,11 @@ def check_library(library, dynamic=False): def check_extensions(): print(__file__) - srcdir = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) - filename = os.path.join(srcdir, "pybuilddir.txt") + # This assumes pybuilddir.txt is in same directory as pyconfig.h. + # In the case of out-of-tree builds, we can't assume pybuilddir.txt is + # in the source folder. + config_dir = os.path.dirname(sysconfig.get_config_h_filename()) + filename = os.path.join(config_dir, "pybuilddir.txt") try: with open(filename, encoding="utf-8") as fp: pybuilddir = fp.readline() @@ -118,7 +121,7 @@ def check_extensions(): return True print(f"Check extension modules from {pybuilddir} directory") - builddir = os.path.join(srcdir, pybuilddir) + builddir = os.path.join(config_dir, pybuilddir) nsymbol = 0 for name in os.listdir(builddir): if not name.endswith(".so"): From webhook-mailer at python.org Tue Nov 23 02:51:36 2021 From: webhook-mailer at python.org (tiran) Date: Tue, 23 Nov 2021 07:51:36 -0000 Subject: [Python-checkins] bpo-45847: Fix xxlimited and xxlimited_35 build conditions (GH-29715) Message-ID: https://github.com/python/cpython/commit/758a23d1c4db97b578bc16e0ea110074d65c4c52 commit: 758a23d1c4db97b578bc16e0ea110074d65c4c52 branch: main author: Erlend Egeberg Aasland committer: tiran date: 2021-11-23T08:51:30+01:00 summary: bpo-45847: Fix xxlimited and xxlimited_35 build conditions (GH-29715) files: M configure M configure.ac diff --git a/configure b/configure index dafcce61d132d..7c0d866cb92a2 100755 --- a/configure +++ b/configure @@ -21849,7 +21849,7 @@ $as_echo_n "checking for stdlib extension module xxlimited... " >&6; } *xxlimited*) : py_cv_module_xxlimited=n/a ;; #( *) : - if test "$Py_TRACE_REFS" = no; then : + if test "$with_trace_refs" = "no"; then : if true; then : py_cv_module_xxlimited=yes else @@ -21885,7 +21885,7 @@ $as_echo_n "checking for stdlib extension module xxlimited_35... " >&6; } *xxlimited_35*) : py_cv_module_xxlimited_35=n/a ;; #( *) : - if test "$Py_TRACE_REFS" = no; then : + if test "$with_trace_refs" = "no"; then : if true; then : py_cv_module_xxlimited_35=yes else diff --git a/configure.ac b/configure.ac index ec7d1a48a0bee..e63d8af807b78 100644 --- a/configure.ac +++ b/configure.ac @@ -6221,8 +6221,8 @@ PY_STDLIB_MOD([_ctypes_test], [test "$TEST_MODULES" = yes], [], [], [-lm]) dnl Limited API template modules. dnl The limited C API is not compatible with the Py_TRACE_REFS macro. -PY_STDLIB_MOD([xxlimited], [test "$Py_TRACE_REFS" = no]) -PY_STDLIB_MOD([xxlimited_35], [test "$Py_TRACE_REFS" = no]) +PY_STDLIB_MOD([xxlimited], [test "$with_trace_refs" = "no"]) +PY_STDLIB_MOD([xxlimited_35], [test "$with_trace_refs" = "no"]) # substitute multiline block, must come after last PY_STDLIB_MOD() AC_SUBST([MODULE_BLOCK]) From webhook-mailer at python.org Tue Nov 23 02:52:10 2021 From: webhook-mailer at python.org (tiran) Date: Tue, 23 Nov 2021 07:52:10 -0000 Subject: [Python-checkins] bpo-45847: Port _socket to PY_STDLIB_MOD (GH-29713) Message-ID: https://github.com/python/cpython/commit/d82f2caf942fa8b94e797a2f116ee54ec303c2df commit: d82f2caf942fa8b94e797a2f116ee54ec303c2df branch: main author: Erlend Egeberg Aasland committer: tiran date: 2021-11-23T08:52:05+01:00 summary: bpo-45847: Port _socket to PY_STDLIB_MOD (GH-29713) files: M Modules/Setup.stdlib.in M configure M configure.ac M setup.py diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 0c88eed3b5e65..338de84f09ebc 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -109,6 +109,7 @@ @MODULE__POSIXSUBPROCESS_TRUE at _posixsubprocess _posixsubprocess.c @MODULE_RESOURCE_TRUE at resource resource.c @MODULE_SELECT_TRUE at select selectmodule.c + at MODULE__SOCKET_TRUE@_socket socketmodule.c # AIX has shadow passwords, but does not provide getspent API @MODULE_SPWD_TRUE at spwd spwdmodule.c @MODULE_SYSLOG_TRUE at syslog syslogmodule.c diff --git a/configure b/configure index 7c0d866cb92a2..148ef58b6a5b8 100755 --- a/configure +++ b/configure @@ -724,6 +724,8 @@ MODULE__TYPING_FALSE MODULE__TYPING_TRUE MODULE__STRUCT_FALSE MODULE__STRUCT_TRUE +MODULE__SOCKET_FALSE +MODULE__SOCKET_TRUE MODULE_SELECT_FALSE MODULE_SELECT_TRUE MODULE__RANDOM_FALSE @@ -20577,6 +20579,15 @@ else fi as_fn_append MODULE_BLOCK "MODULE_SELECT=yes$as_nl" + if true; then + MODULE__SOCKET_TRUE= + MODULE__SOCKET_FALSE='#' +else + MODULE__SOCKET_TRUE='#' + MODULE__SOCKET_FALSE= +fi + as_fn_append MODULE_BLOCK "MODULE__SOCKET=yes$as_nl" + if true; then MODULE__STRUCT_TRUE= MODULE__STRUCT_FALSE='#' @@ -22099,6 +22110,10 @@ if test -z "${MODULE_SELECT_TRUE}" && test -z "${MODULE_SELECT_FALSE}"; then as_fn_error $? "conditional \"MODULE_SELECT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__SOCKET_TRUE}" && test -z "${MODULE__SOCKET_FALSE}"; then + as_fn_error $? "conditional \"MODULE__SOCKET\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__STRUCT_TRUE}" && test -z "${MODULE__STRUCT_FALSE}"; then as_fn_error $? "conditional \"MODULE__STRUCT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index e63d8af807b78..a950cc91d657b 100644 --- a/configure.ac +++ b/configure.ac @@ -6137,6 +6137,7 @@ PY_STDLIB_MOD_SIMPLE([_posixsubprocess]) PY_STDLIB_MOD_SIMPLE([_queue]) PY_STDLIB_MOD_SIMPLE([_random]) PY_STDLIB_MOD_SIMPLE([select]) +PY_STDLIB_MOD_SIMPLE([_socket]) PY_STDLIB_MOD_SIMPLE([_struct]) PY_STDLIB_MOD_SIMPLE([_typing]) PY_STDLIB_MOD_SIMPLE([_xxsubinterpreters]) diff --git a/setup.py b/setup.py index a3d377a696abb..304168a657c85 100644 --- a/setup.py +++ b/setup.py @@ -1034,6 +1034,8 @@ def detect_simple_extensions(self): self.addext(Extension('fcntl', ['fcntlmodule.c'])) # grp(3) self.addext(Extension('grp', ['grpmodule.c'])) + + self.addext(Extension('_socket', ['socketmodule.c'])) self.addext(Extension('spwd', ['spwdmodule.c'])) # select(2); not on ancient System V @@ -1254,9 +1256,6 @@ def detect_crypt(self): self.add(Extension('_crypt', ['_cryptmodule.c'], libraries=libs)) - def detect_socket(self): - self.add(Extension('_socket', ['socketmodule.c'])) - def detect_dbm_gdbm(self): # Modules that provide persistent dictionary-like semantics. You will # probably want to arrange for at least one of them to be available on @@ -1460,7 +1459,6 @@ def detect_modules(self): self.detect_test_extensions() self.detect_readline_curses() self.detect_crypt() - self.detect_socket() self.detect_openssl_hashlib() self.detect_hash_builtins() self.detect_dbm_gdbm() From webhook-mailer at python.org Tue Nov 23 04:53:41 2021 From: webhook-mailer at python.org (markshannon) Date: Tue, 23 Nov 2021 09:53:41 -0000 Subject: [Python-checkins] bpo-44525: Copy free variables in bytecode to allow calls to inner functions to be specialized (GH-29595) Message-ID: https://github.com/python/cpython/commit/135cabd328504e1648d17242b42b675cdbd0193b commit: 135cabd328504e1648d17242b42b675cdbd0193b branch: main author: Mark Shannon committer: markshannon date: 2021-11-23T09:53:24Z summary: bpo-44525: Copy free variables in bytecode to allow calls to inner functions to be specialized (GH-29595) * Make internal APIs that take PyFrameConstructor take a PyFunctionObject instead. * Add reference to function to frame, borrow references to builtins and globals. * Add COPY_FREE_VARS instruction to allow specialization of calls to inner functions. files: A Include/internal/pycore_function.h A Misc/NEWS.d/next/Core and Builtins/2021-11-18-10-02-02.bpo-44525.M4xwn_.rst M Doc/library/dis.rst M Include/cpython/funcobject.h M Include/internal/pycore_ceval.h M Include/internal/pycore_frame.h M Include/opcode.h M Lib/importlib/_bootstrap_external.py M Lib/opcode.py M Lib/test/test_code.py M Lib/test/test_dis.py M Makefile.pre.in M Objects/call.c M Objects/frameobject.c M Objects/funcobject.c M Objects/genobject.c M Objects/typeobject.c M PCbuild/pythoncore.vcxproj M Python/bltinmodule.c M Python/ceval.c M Python/compile.c M Python/frame.c M Python/opcode_targets.h M Python/pystate.c M Python/specialize.c diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 5fe9f65f46a71..6fe64be9f0fb3 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -991,6 +991,15 @@ All of the following opcodes use their arguments. ``i`` is no longer offset by the length of ``co_varnames``. +.. opcode:: COPY_FREE_VARS (n) + + Copies the ``n`` free variables from the closure into the frame. + Removes the need for special code on the caller's side when calling + closures. + + .. versionadded:: 3.11 + + .. opcode:: RAISE_VARARGS (argc) Raises an exception using one of the 3 forms of the ``raise`` statement, diff --git a/Include/cpython/funcobject.h b/Include/cpython/funcobject.h index 60b702218a1f4..9f0560fb72503 100644 --- a/Include/cpython/funcobject.h +++ b/Include/cpython/funcobject.h @@ -101,9 +101,6 @@ uint32_t _PyFunction_GetVersionForCurrentState(PyFunctionObject *func); #define PyFunction_GET_ANNOTATIONS(func) \ (((PyFunctionObject *)func) -> func_annotations) -#define PyFunction_AS_FRAME_CONSTRUCTOR(func) \ - ((PyFrameConstructor *)&((PyFunctionObject *)(func))->func_globals) - /* The classmethod and staticmethod types lives here, too */ PyAPI_DATA(PyTypeObject) PyClassMethod_Type; PyAPI_DATA(PyTypeObject) PyStaticMethod_Type; diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index c2251b04be65d..9987f2076cd59 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -52,7 +52,7 @@ _PyEval_EvalFrame(PyThreadState *tstate, struct _interpreter_frame *frame, int t extern PyObject * _PyEval_Vector(PyThreadState *tstate, - PyFrameConstructor *desc, PyObject *locals, + PyFunctionObject *func, PyObject *locals, PyObject* const* args, size_t argcount, PyObject *kwnames); @@ -113,7 +113,7 @@ static inline void _Py_LeaveRecursiveCall_inline(void) { struct _interpreter_frame *_PyEval_GetFrame(void); -PyObject *_Py_MakeCoro(PyFrameConstructor *, struct _interpreter_frame *); +PyObject *_Py_MakeCoro(PyFunctionObject *func, struct _interpreter_frame *); #ifdef __cplusplus } diff --git a/Include/internal/pycore_frame.h b/Include/internal/pycore_frame.h index b025ca0b8d766..e36241f4a6a65 100644 --- a/Include/internal/pycore_frame.h +++ b/Include/internal/pycore_frame.h @@ -20,13 +20,13 @@ enum _framestate { typedef signed char PyFrameState; typedef struct _interpreter_frame { - PyObject *f_globals; - PyObject *f_builtins; - PyObject *f_locals; - PyCodeObject *f_code; - PyFrameObject *frame_obj; - /* Borrowed reference to a generator, or NULL */ - PyObject *generator; + PyFunctionObject *f_func; /* Strong reference */ + PyObject *f_globals; /* Borrowed reference */ + PyObject *f_builtins; /* Borrowed reference */ + PyObject *f_locals; /* Strong reference, may be NULL */ + PyCodeObject *f_code; /* Strong reference */ + PyFrameObject *frame_obj; /* Strong reference, may be NULL */ + PyObject *generator; /* Borrowed reference, may be NULL */ struct _interpreter_frame *previous; int f_lasti; /* Last instruction if called */ int stacktop; /* Offset of TOS from localsplus */ @@ -70,16 +70,18 @@ static inline void _PyFrame_StackPush(InterpreterFrame *f, PyObject *value) { #define FRAME_SPECIALS_SIZE ((sizeof(InterpreterFrame)-1)/sizeof(PyObject *)) InterpreterFrame * -_PyInterpreterFrame_HeapAlloc(PyFrameConstructor *con, PyObject *locals); +_PyInterpreterFrame_HeapAlloc(PyFunctionObject *func, PyObject *locals); static inline void _PyFrame_InitializeSpecials( - InterpreterFrame *frame, PyFrameConstructor *con, + InterpreterFrame *frame, PyFunctionObject *func, PyObject *locals, int nlocalsplus) { - frame->f_code = (PyCodeObject *)Py_NewRef(con->fc_code); - frame->f_builtins = Py_NewRef(con->fc_builtins); - frame->f_globals = Py_NewRef(con->fc_globals); + Py_INCREF(func); + frame->f_func = func; + frame->f_code = (PyCodeObject *)Py_NewRef(func->func_code); + frame->f_builtins = func->func_builtins; + frame->f_globals = func->func_globals; frame->f_locals = Py_XNewRef(locals); frame->stacktop = nlocalsplus; frame->frame_obj = NULL; @@ -150,7 +152,7 @@ void _PyFrame_LocalsToFast(InterpreterFrame *frame, int clear); InterpreterFrame *_PyThreadState_PushFrame( - PyThreadState *tstate, PyFrameConstructor *con, PyObject *locals); + PyThreadState *tstate, PyFunctionObject *func, PyObject *locals); extern InterpreterFrame * _PyThreadState_BumpFramePointerSlow(PyThreadState *tstate, size_t size); diff --git a/Include/internal/pycore_function.h b/Include/internal/pycore_function.h new file mode 100644 index 0000000000000..dc4422df3eb53 --- /dev/null +++ b/Include/internal/pycore_function.h @@ -0,0 +1,11 @@ +#ifndef Py_INTERNAL_FUNCTION_H +#define Py_INTERNAL_FUNCTION_H + + +#include "Python.h" + +PyFunctionObject * +_PyFunction_FromConstructor(PyFrameConstructor *constr); + + +#endif /* !Py_INTERNAL_FUNCTION_H */ diff --git a/Include/opcode.h b/Include/opcode.h index 3ec89bd4c0be6..2c1a212cbd634 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -100,6 +100,7 @@ extern "C" { #define SET_ADD 146 #define MAP_ADD 147 #define LOAD_CLASSDEREF 148 +#define COPY_FREE_VARS 149 #define MATCH_CLASS 152 #define FORMAT_VALUE 155 #define BUILD_CONST_KEY_MAP 156 diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 303ca728ec892..85c5193407d80 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -370,6 +370,7 @@ def _write_atomic(path, data, mode=0o666): # active exception) # Python 3.11a3 3464 (bpo-45636: Merge numeric BINARY_*/INPLACE_* into # BINARY_OP) +# Python 3.11a3 3465 (Add COPY_FREE_VARS opcode) # # MAGIC must change whenever the bytecode emitted by the compiler may no @@ -379,7 +380,7 @@ def _write_atomic(path, data, mode=0o666): # Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array # in PC/launcher.c must also be updated. -MAGIC_NUMBER = (3464).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3465).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c _PYCACHE = '__pycache__' diff --git a/Lib/opcode.py b/Lib/opcode.py index 3603bb422b150..60805e92ff3c4 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -177,6 +177,7 @@ def jabs_op(name, op): def_op('MAP_ADD', 147) def_op('LOAD_CLASSDEREF', 148) hasfree.append(148) +def_op('COPY_FREE_VARS', 149) def_op('MATCH_CLASS', 152) diff --git a/Lib/test/test_code.py b/Lib/test/test_code.py index 0d46258d0c371..b42213bde0744 100644 --- a/Lib/test/test_code.py +++ b/Lib/test/test_code.py @@ -141,6 +141,8 @@ check_impl_detail, requires_debug_ranges, gc_collect) from test.support.script_helper import assert_python_ok +from opcode import opmap +COPY_FREE_VARS = opmap['COPY_FREE_VARS'] def consts(t): @@ -185,7 +187,7 @@ def create_closure(__class__): def new_code(c): '''A new code object with a __class__ cell added to freevars''' - return c.replace(co_freevars=c.co_freevars + ('__class__',)) + return c.replace(co_freevars=c.co_freevars + ('__class__',), co_code=bytes([COPY_FREE_VARS, 1])+c.co_code) def add_foreign_method(cls, name, f): code = new_code(f.__code__) diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index 3b8ebb5dba95b..dd328f072e45d 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -459,16 +459,17 @@ def foo(x): dis_nested_1 = """%s Disassembly of : - 0 MAKE_CELL 0 (x) - -%3d 2 LOAD_CLOSURE 0 (x) - 4 BUILD_TUPLE 1 - 6 LOAD_CONST 1 ( at 0x..., file "%s", line %d>) - 8 MAKE_FUNCTION 8 (closure) - 10 LOAD_DEREF 1 (y) - 12 GET_ITER - 14 CALL_FUNCTION 1 - 16 RETURN_VALUE + 0 COPY_FREE_VARS 1 + 2 MAKE_CELL 0 (x) + +%3d 4 LOAD_CLOSURE 0 (x) + 6 BUILD_TUPLE 1 + 8 LOAD_CONST 1 ( at 0x..., file "%s", line %d>) + 10 MAKE_FUNCTION 8 (closure) + 12 LOAD_DEREF 1 (y) + 14 GET_ITER + 16 CALL_FUNCTION 1 + 18 RETURN_VALUE """ % (dis_nested_0, __file__, _h.__code__.co_firstlineno + 1, @@ -479,16 +480,18 @@ def foo(x): dis_nested_2 = """%s Disassembly of at 0x..., file "%s", line %d>: -%3d 0 BUILD_LIST 0 - 2 LOAD_FAST 0 (.0) - >> 4 FOR_ITER 6 (to 18) - 6 STORE_FAST 1 (z) - 8 LOAD_DEREF 2 (x) - 10 LOAD_FAST 1 (z) - 12 BINARY_OP 0 (+) - 14 LIST_APPEND 2 - 16 JUMP_ABSOLUTE 2 (to 4) - >> 18 RETURN_VALUE + 0 COPY_FREE_VARS 1 + +%3d 2 BUILD_LIST 0 + 4 LOAD_FAST 0 (.0) + >> 6 FOR_ITER 6 (to 20) + 8 STORE_FAST 1 (z) + 10 LOAD_DEREF 2 (x) + 12 LOAD_FAST 1 (z) + 14 BINARY_OP 0 (+) + 16 LIST_APPEND 2 + 18 JUMP_ABSOLUTE 3 (to 6) + >> 20 RETURN_VALUE """ % (dis_nested_1, __file__, _h.__code__.co_firstlineno + 3, @@ -1007,42 +1010,43 @@ def _prepare_test_cases(): Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=40, starts_line=None, is_jump_target=False, positions=None), ] - expected_opinfo_f = [ - Instruction(opname='MAKE_CELL', opcode=135, arg=0, argval='c', argrepr='c', offset=0, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='MAKE_CELL', opcode=135, arg=1, argval='d', argrepr='d', offset=2, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval=(5, 6), argrepr='(5, 6)', offset=4, starts_line=3, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CLOSURE', opcode=136, arg=3, argval='a', argrepr='a', offset=6, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CLOSURE', opcode=136, arg=4, argval='b', argrepr='b', offset=8, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CLOSURE', opcode=136, arg=0, argval='c', argrepr='c', offset=10, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CLOSURE', opcode=136, arg=1, argval='d', argrepr='d', offset=12, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='BUILD_TUPLE', opcode=102, arg=4, argval=4, argrepr='', offset=14, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=code_object_inner, argrepr=repr(code_object_inner), offset=16, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='MAKE_FUNCTION', opcode=132, arg=9, argval=9, argrepr='defaults, closure', offset=18, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='STORE_FAST', opcode=125, arg=2, argval='inner', argrepr='inner', offset=20, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='print', argrepr='print', offset=22, starts_line=5, is_jump_target=False, positions=None), - Instruction(opname='LOAD_DEREF', opcode=137, arg=3, argval='a', argrepr='a', offset=24, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_DEREF', opcode=137, arg=4, argval='b', argrepr='b', offset=26, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_DEREF', opcode=137, arg=0, argval='c', argrepr='c', offset=28, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_DEREF', opcode=137, arg=1, argval='d', argrepr='d', offset=30, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=4, argval=4, argrepr='', offset=32, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=34, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='inner', argrepr='inner', offset=36, starts_line=6, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=38, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COPY_FREE_VARS', opcode=149, arg=2, argval=2, argrepr='', offset=0, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='MAKE_CELL', opcode=135, arg=0, argval='c', argrepr='c', offset=2, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='MAKE_CELL', opcode=135, arg=1, argval='d', argrepr='d', offset=4, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval=(5, 6), argrepr='(5, 6)', offset=6, starts_line=3, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CLOSURE', opcode=136, arg=3, argval='a', argrepr='a', offset=8, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CLOSURE', opcode=136, arg=4, argval='b', argrepr='b', offset=10, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CLOSURE', opcode=136, arg=0, argval='c', argrepr='c', offset=12, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CLOSURE', opcode=136, arg=1, argval='d', argrepr='d', offset=14, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='BUILD_TUPLE', opcode=102, arg=4, argval=4, argrepr='', offset=16, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=code_object_inner, argrepr=repr(code_object_inner), offset=18, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='MAKE_FUNCTION', opcode=132, arg=9, argval=9, argrepr='defaults, closure', offset=20, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='STORE_FAST', opcode=125, arg=2, argval='inner', argrepr='inner', offset=22, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='print', argrepr='print', offset=24, starts_line=5, is_jump_target=False, positions=None), + Instruction(opname='LOAD_DEREF', opcode=137, arg=3, argval='a', argrepr='a', offset=26, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_DEREF', opcode=137, arg=4, argval='b', argrepr='b', offset=28, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_DEREF', opcode=137, arg=0, argval='c', argrepr='c', offset=30, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_DEREF', opcode=137, arg=1, argval='d', argrepr='d', offset=32, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=4, argval=4, argrepr='', offset=34, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=36, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='inner', argrepr='inner', offset=38, starts_line=6, is_jump_target=False, positions=None), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=40, starts_line=None, is_jump_target=False, positions=None), ] expected_opinfo_inner = [ - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='print', argrepr='print', offset=0, starts_line=4, is_jump_target=False, positions=None), - Instruction(opname='LOAD_DEREF', opcode=137, arg=2, argval='a', argrepr='a', offset=2, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_DEREF', opcode=137, arg=3, argval='b', argrepr='b', offset=4, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_DEREF', opcode=137, arg=4, argval='c', argrepr='c', offset=6, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_DEREF', opcode=137, arg=5, argval='d', argrepr='d', offset=8, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='e', argrepr='e', offset=10, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=1, argval='f', argrepr='f', offset=12, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=6, argval=6, argrepr='', offset=14, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=16, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=18, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=20, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COPY_FREE_VARS', opcode=149, arg=4, argval=4, argrepr='', offset=0, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='print', argrepr='print', offset=2, starts_line=4, is_jump_target=False, positions=None), + Instruction(opname='LOAD_DEREF', opcode=137, arg=2, argval='a', argrepr='a', offset=4, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_DEREF', opcode=137, arg=3, argval='b', argrepr='b', offset=6, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_DEREF', opcode=137, arg=4, argval='c', argrepr='c', offset=8, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_DEREF', opcode=137, arg=5, argval='d', argrepr='d', offset=10, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='e', argrepr='e', offset=12, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=1, argval='f', argrepr='f', offset=14, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=6, argval=6, argrepr='', offset=16, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=18, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=20, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=22, starts_line=None, is_jump_target=False, positions=None), ] expected_opinfo_jumpy = [ diff --git a/Makefile.pre.in b/Makefile.pre.in index afa0414ce04cb..046b0e86e6758 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1605,6 +1605,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/internal/pycore_fileutils.h \ $(srcdir)/Include/internal/pycore_floatobject.h \ $(srcdir)/Include/internal/pycore_format.h \ + $(srcdir)/Include/internal/pycore_function.h \ $(srcdir)/Include/internal/pycore_getopt.h \ $(srcdir)/Include/internal/pycore_gil.h \ $(srcdir)/Include/internal/pycore_hamt.h \ diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-18-10-02-02.bpo-44525.M4xwn_.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-18-10-02-02.bpo-44525.M4xwn_.rst new file mode 100644 index 0000000000000..f1c806d4858fd --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-18-10-02-02.bpo-44525.M4xwn_.rst @@ -0,0 +1,3 @@ +Adds new :opcode:`COPY_FREE_VARS` opcode, to make copying of free variables +from function to frame explicit. Helps optimization of calls to Python +function. diff --git a/Objects/call.c b/Objects/call.c index 5e55518b04cbf..310a2d732d170 100644 --- a/Objects/call.c +++ b/Objects/call.c @@ -383,16 +383,16 @@ _PyFunction_Vectorcall(PyObject *func, PyObject* const* stack, size_t nargsf, PyObject *kwnames) { assert(PyFunction_Check(func)); - PyFrameConstructor *f = PyFunction_AS_FRAME_CONSTRUCTOR(func); + PyFunctionObject *f = (PyFunctionObject *)func; Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); assert(nargs >= 0); PyThreadState *tstate = _PyThreadState_GET(); assert(nargs == 0 || stack != NULL); - if (((PyCodeObject *)f->fc_code)->co_flags & CO_OPTIMIZED) { + if (((PyCodeObject *)f->func_code)->co_flags & CO_OPTIMIZED) { return _PyEval_Vector(tstate, f, NULL, stack, nargs, kwnames); } else { - return _PyEval_Vector(tstate, f, f->fc_globals, stack, nargs, kwnames); + return _PyEval_Vector(tstate, f, f->func_globals, stack, nargs, kwnames); } } diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 09857c7fa007d..2a283b3113cb5 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -5,6 +5,7 @@ #include "pycore_moduleobject.h" // _PyModule_GetDict() #include "pycore_object.h" // _PyObject_GC_UNTRACK() #include "pycore_code.h" // CO_FAST_LOCAL, etc. +#include "pycore_function.h" // _PyFunction_FromConstructor() #include "frameobject.h" // PyFrameObject #include "pycore_frame.h" @@ -626,8 +627,7 @@ frame_dealloc(PyFrameObject *f) /* Don't clear code object until the end */ co = frame->f_code; frame->f_code = NULL; - Py_CLEAR(frame->f_globals); - Py_CLEAR(frame->f_builtins); + Py_CLEAR(frame->f_func); Py_CLEAR(frame->f_locals); PyObject **locals = _PyFrame_GetLocalsArray(frame); for (int i = 0; i < frame->stacktop; i++) { @@ -782,16 +782,16 @@ PyTypeObject PyFrame_Type = { _Py_IDENTIFIER(__builtins__); static InterpreterFrame * -allocate_heap_frame(PyFrameConstructor *con, PyObject *locals) +allocate_heap_frame(PyFunctionObject *func, PyObject *locals) { - PyCodeObject *code = (PyCodeObject *)con->fc_code; + PyCodeObject *code = (PyCodeObject *)func->func_code; int size = code->co_nlocalsplus+code->co_stacksize + FRAME_SPECIALS_SIZE; InterpreterFrame *frame = (InterpreterFrame *)PyMem_Malloc(sizeof(PyObject *)*size); if (frame == NULL) { PyErr_NoMemory(); return NULL; } - _PyFrame_InitializeSpecials(frame, con, locals, code->co_nlocalsplus); + _PyFrame_InitializeSpecials(frame, func, locals, code->co_nlocalsplus); for (Py_ssize_t i = 0; i < code->co_nlocalsplus; i++) { frame->localsplus[i] = NULL; } @@ -872,7 +872,12 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, .fc_kwdefaults = NULL, .fc_closure = NULL }; - InterpreterFrame *frame = allocate_heap_frame(&desc, locals); + PyFunctionObject *func = _PyFunction_FromConstructor(&desc); + if (func == NULL) { + return NULL; + } + InterpreterFrame *frame = allocate_heap_frame(func, locals); + Py_DECREF(func); if (frame == NULL) { return NULL; } @@ -910,6 +915,18 @@ _PyFrame_FastToLocalsWithError(InterpreterFrame *frame) { } co = frame->f_code; fast = _PyFrame_GetLocalsArray(frame); + if (frame->f_lasti < 0 && _Py_OPCODE(co->co_firstinstr[0]) == COPY_FREE_VARS) { + /* Free vars have not been initialized -- Do that */ + PyCodeObject *co = frame->f_code; + PyObject *closure = frame->f_func->func_closure; + int offset = co->co_nlocals + co->co_nplaincellvars; + for (int i = 0; i < co->co_nfreevars; ++i) { + PyObject *o = PyTuple_GET_ITEM(closure, i); + Py_INCREF(o); + frame->localsplus[offset + i] = o; + } + frame->f_lasti = 0; + } for (int i = 0; i < co->co_nlocalsplus; i++) { _PyLocals_Kind kind = _PyLocals_GetKind(co->co_localspluskinds, i); @@ -929,8 +946,7 @@ _PyFrame_FastToLocalsWithError(InterpreterFrame *frame) { PyObject *value = fast[i]; if (frame->f_state != FRAME_CLEARED) { if (kind & CO_FAST_FREE) { - // The cell was set when the frame was created from - // the function's closure. + // The cell was set by COPY_FREE_VARS. assert(value != NULL && PyCell_Check(value)); value = PyCell_GET(value); } diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 5a170380cb3e9..7891e4f3122b1 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -9,6 +9,39 @@ static uint32_t next_func_version = 1; +PyFunctionObject * +_PyFunction_FromConstructor(PyFrameConstructor *constr) +{ + + PyFunctionObject *op = PyObject_GC_New(PyFunctionObject, &PyFunction_Type); + if (op == NULL) { + return NULL; + } + Py_INCREF(constr->fc_globals); + op->func_globals = constr->fc_globals; + Py_INCREF(constr->fc_builtins); + op->func_builtins = constr->fc_builtins; + Py_INCREF(constr->fc_name); + op->func_name = constr->fc_name; + Py_INCREF(constr->fc_qualname); + op->func_qualname = constr->fc_qualname; + Py_INCREF(constr->fc_code); + op->func_code = constr->fc_code; + op->func_defaults = NULL; + op->func_kwdefaults = NULL; + op->func_closure = NULL; + Py_INCREF(Py_None); + op->func_doc = Py_None; + op->func_dict = NULL; + op->func_weakreflist = NULL; + op->func_module = NULL; + op->func_annotations = NULL; + op->vectorcall = _PyFunction_Vectorcall; + op->func_version = 0; + _PyObject_GC_TRACK(op); + return op; +} + PyObject * PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname) { diff --git a/Objects/genobject.c b/Objects/genobject.c index c899ed6a82e30..24d5f3579cbf2 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -188,7 +188,6 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, } assert(_PyFrame_IsRunnable(frame)); - assert(frame->f_lasti >= 0 || ((unsigned char *)PyBytes_AS_STRING(gen->gi_code->co_code))[0] == GEN_START); /* Push arg onto the frame's value stack */ result = arg ? arg : Py_None; Py_INCREF(result); @@ -841,7 +840,7 @@ PyTypeObject PyGen_Type = { }; static PyObject * -make_gen(PyTypeObject *type, PyFrameConstructor *con, InterpreterFrame *frame) +make_gen(PyTypeObject *type, PyFunctionObject *func, InterpreterFrame *frame) { PyGenObject *gen = PyObject_GC_New(PyGenObject, type); if (gen == NULL) { @@ -858,13 +857,13 @@ make_gen(PyTypeObject *type, PyFrameConstructor *con, InterpreterFrame *frame) gen->gi_exc_state.exc_value = NULL; gen->gi_exc_state.exc_traceback = NULL; gen->gi_exc_state.previous_item = NULL; - if (con->fc_name != NULL) - gen->gi_name = con->fc_name; + if (func->func_name != NULL) + gen->gi_name = func->func_name; else gen->gi_name = gen->gi_code->co_name; Py_INCREF(gen->gi_name); - if (con->fc_qualname != NULL) - gen->gi_qualname = con->fc_qualname; + if (func->func_qualname != NULL) + gen->gi_qualname = func->func_qualname; else gen->gi_qualname = gen->gi_name; Py_INCREF(gen->gi_qualname); @@ -876,17 +875,17 @@ static PyObject * compute_cr_origin(int origin_depth); PyObject * -_Py_MakeCoro(PyFrameConstructor *con, InterpreterFrame *frame) +_Py_MakeCoro(PyFunctionObject *func, InterpreterFrame *frame) { - int coro_flags = ((PyCodeObject *)con->fc_code)->co_flags & + int coro_flags = ((PyCodeObject *)func->func_code)->co_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR); assert(coro_flags); if (coro_flags == CO_GENERATOR) { - return make_gen(&PyGen_Type, con, frame); + return make_gen(&PyGen_Type, func, frame); } if (coro_flags == CO_ASYNC_GENERATOR) { PyAsyncGenObject *o; - o = (PyAsyncGenObject *)make_gen(&PyAsyncGen_Type, con, frame); + o = (PyAsyncGenObject *)make_gen(&PyAsyncGen_Type, func, frame); if (o == NULL) { return NULL; } @@ -897,7 +896,7 @@ _Py_MakeCoro(PyFrameConstructor *con, InterpreterFrame *frame) return (PyObject*)o; } assert (coro_flags == CO_COROUTINE); - PyObject *coro = make_gen(&PyCoro_Type, con, frame); + PyObject *coro = make_gen(&PyCoro_Type, func, frame); if (!coro) { return NULL; } diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 4180a9d13c45f..22e509be26fff 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -8936,7 +8936,7 @@ super_init_without_args(PyFrameObject *f, PyCodeObject *co, // "firstarg" is a cell here unless (very unlikely) super() // was called from the C-API before the first MAKE_CELL op. if (f->f_frame->f_lasti >= 0) { - assert(_Py_OPCODE(*co->co_firstinstr) == MAKE_CELL); + assert(_Py_OPCODE(*co->co_firstinstr) == MAKE_CELL || _Py_OPCODE(*co->co_firstinstr) == COPY_FREE_VARS); assert(PyCell_Check(firstarg)); firstarg = PyCell_GET(firstarg); } diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index e1d59de7bc8f2..9d96f4bd5361b 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -193,6 +193,7 @@ + diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 9e3b25c59a550..6763f9969707d 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -212,9 +212,8 @@ builtin___build_class__(PyObject *self, PyObject *const *args, Py_ssize_t nargs, Py_TYPE(ns)->tp_name); goto error; } - PyFrameConstructor *f = PyFunction_AS_FRAME_CONSTRUCTOR(func); PyThreadState *tstate = _PyThreadState_GET(); - cell = _PyEval_Vector(tstate, f, ns, NULL, 0, NULL); + cell = _PyEval_Vector(tstate, (PyFunctionObject *)func, ns, NULL, 0, NULL); if (cell != NULL) { if (bases != orig_bases) { if (PyMapping_SetItemString(ns, "__orig_bases__", orig_bases) < 0) { diff --git a/Python/ceval.c b/Python/ceval.c index 1d69708576fa4..0aec5aa7fb9b0 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -14,6 +14,7 @@ #include "pycore_call.h" // _PyObject_FastCallDictTstate() #include "pycore_ceval.h" // _PyEval_SignalAsyncExc() #include "pycore_code.h" +#include "pycore_function.h" #include "pycore_initconfig.h" // _PyStatus_OK() #include "pycore_long.h" // _PyLong_GetZero() #include "pycore_object.h" // _PyObject_GC_TRACK() @@ -98,7 +99,7 @@ static void format_kwargs_error(PyThreadState *, PyObject *func, PyObject *kwarg static void format_awaitable_error(PyThreadState *, PyTypeObject *, int, int); static int get_exception_handler(PyCodeObject *, int, int*, int*, int*); static InterpreterFrame * -_PyEvalFramePushAndInit(PyThreadState *tstate, PyFrameConstructor *con, +_PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func, PyObject *locals, PyObject* const* args, size_t argcount, PyObject *kwnames); static int @@ -1135,7 +1136,13 @@ PyEval_EvalCode(PyObject *co, PyObject *globals, PyObject *locals) .fc_kwdefaults = NULL, .fc_closure = NULL }; - return _PyEval_Vector(tstate, &desc, locals, NULL, 0, NULL); + PyFunctionObject *func = _PyFunction_FromConstructor(&desc); + if (func == NULL) { + return NULL; + } + PyObject *res = _PyEval_Vector(tstate, func, locals, NULL, 0, NULL); + Py_DECREF(func); + return res; } @@ -1570,7 +1577,7 @@ trace_function_entry(PyThreadState *tstate, InterpreterFrame *frame) } static PyObject * -make_coro(PyThreadState *tstate, PyFrameConstructor *con, +make_coro(PyThreadState *tstate, PyFunctionObject *func, PyObject *locals, PyObject* const* args, size_t argcount, PyObject *kwnames); @@ -2240,7 +2247,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr if (new_frame == NULL) { goto error; } - _PyFrame_InitializeSpecials(new_frame, PyFunction_AS_FRAME_CONSTRUCTOR(getitem), + _PyFrame_InitializeSpecials(new_frame, getitem, NULL, code->co_nlocalsplus); STACK_SHRINK(2); new_frame->localsplus[0] = container; @@ -3179,6 +3186,20 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr DISPATCH(); } + TARGET(COPY_FREE_VARS) { + /* Copy closure variables to free variables */ + PyCodeObject *co = frame->f_code; + PyObject *closure = frame->f_func->func_closure; + int offset = co->co_nlocals + co->co_nplaincellvars; + assert(oparg == co->co_nfreevars); + for (int i = 0; i < oparg; ++i) { + PyObject *o = PyTuple_GET_ITEM(closure, i); + Py_INCREF(o); + frame->localsplus[offset + i] = o; + } + DISPATCH(); + } + TARGET(BUILD_STRING) { PyObject *str; PyObject *empty = PyUnicode_New(0, 0); @@ -4423,9 +4444,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : PyFunction_GET_GLOBALS(function); STACK_SHRINK(oparg); InterpreterFrame *new_frame = _PyEvalFramePushAndInit( - tstate, PyFunction_AS_FRAME_CONSTRUCTOR(function), locals, - stack_pointer, - nargs, kwnames); + tstate, (PyFunctionObject *)function, locals, + stack_pointer, nargs, kwnames + ); STACK_SHRINK(postcall_shrink); // The frame has stolen all the arguments from the stack, // so there is no need to clean them up. @@ -4506,7 +4527,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr if (new_frame == NULL) { goto error; } - _PyFrame_InitializeSpecials(new_frame, PyFunction_AS_FRAME_CONSTRUCTOR(func), + _PyFrame_InitializeSpecials(new_frame, func, NULL, code->co_nlocalsplus); STACK_SHRINK(argcount); for (int i = 0; i < argcount; i++) { @@ -5426,11 +5447,11 @@ get_exception_handler(PyCodeObject *code, int index, int *level, int *handler, i } static int -initialize_locals(PyThreadState *tstate, PyFrameConstructor *con, +initialize_locals(PyThreadState *tstate, PyFunctionObject *func, PyObject **localsplus, PyObject *const *args, Py_ssize_t argcount, PyObject *kwnames) { - PyCodeObject *co = (PyCodeObject*)con->fc_code; + PyCodeObject *co = (PyCodeObject*)func->func_code; const Py_ssize_t total_args = co->co_argcount + co->co_kwonlyargcount; /* Create a dictionary for keyword parameters (**kwags) */ @@ -5495,7 +5516,7 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con, if (keyword == NULL || !PyUnicode_Check(keyword)) { _PyErr_Format(tstate, PyExc_TypeError, "%U() keywords must be strings", - con->fc_qualname); + func->func_qualname); goto kw_fail; } @@ -5527,14 +5548,14 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con, if (co->co_posonlyargcount && positional_only_passed_as_keyword(tstate, co, kwcount, kwnames, - con->fc_qualname)) + func->func_qualname)) { goto kw_fail; } _PyErr_Format(tstate, PyExc_TypeError, "%U() got an unexpected keyword argument '%S'", - con->fc_qualname, keyword); + func->func_qualname, keyword); goto kw_fail; } @@ -5555,7 +5576,7 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con, if (localsplus[j] != NULL) { _PyErr_Format(tstate, PyExc_TypeError, "%U() got multiple values for argument '%S'", - con->fc_qualname, keyword); + func->func_qualname, keyword); goto kw_fail; } localsplus[j] = value; @@ -5564,14 +5585,14 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con, /* Check the number of positional arguments */ if ((argcount > co->co_argcount) && !(co->co_flags & CO_VARARGS)) { - too_many_positional(tstate, co, argcount, con->fc_defaults, localsplus, - con->fc_qualname); + too_many_positional(tstate, co, argcount, func->func_defaults, localsplus, + func->func_qualname); goto fail_post_args; } /* Add missing positional arguments (copy default values from defs) */ if (argcount < co->co_argcount) { - Py_ssize_t defcount = con->fc_defaults == NULL ? 0 : PyTuple_GET_SIZE(con->fc_defaults); + Py_ssize_t defcount = func->func_defaults == NULL ? 0 : PyTuple_GET_SIZE(func->func_defaults); Py_ssize_t m = co->co_argcount - defcount; Py_ssize_t missing = 0; for (i = argcount; i < m; i++) { @@ -5581,7 +5602,7 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con, } if (missing) { missing_arguments(tstate, co, missing, defcount, localsplus, - con->fc_qualname); + func->func_qualname); goto fail_post_args; } if (n > m) @@ -5589,7 +5610,7 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con, else i = 0; if (defcount) { - PyObject **defs = &PyTuple_GET_ITEM(con->fc_defaults, 0); + PyObject **defs = &PyTuple_GET_ITEM(func->func_defaults, 0); for (; i < defcount; i++) { if (localsplus[m+i] == NULL) { PyObject *def = defs[i]; @@ -5607,8 +5628,8 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con, if (localsplus[i] != NULL) continue; PyObject *varname = PyTuple_GET_ITEM(co->co_localsplusnames, i); - if (con->fc_kwdefaults != NULL) { - PyObject *def = PyDict_GetItemWithError(con->fc_kwdefaults, varname); + if (func->func_kwdefaults != NULL) { + PyObject *def = PyDict_GetItemWithError(func->func_kwdefaults, varname); if (def) { Py_INCREF(def); localsplus[i] = def; @@ -5622,16 +5643,10 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con, } if (missing) { missing_arguments(tstate, co, missing, -1, localsplus, - con->fc_qualname); + func->func_qualname); goto fail_post_args; } } - /* Copy closure variables to free variables */ - for (i = 0; i < co->co_nfreevars; ++i) { - PyObject *o = PyTuple_GET_ITEM(con->fc_closure, i); - Py_INCREF(o); - localsplus[co->co_nlocals + co->co_nplaincellvars + i] = o; - } return 0; fail_pre_positional: @@ -5653,24 +5668,24 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con, static InterpreterFrame * make_coro_frame(PyThreadState *tstate, - PyFrameConstructor *con, PyObject *locals, + PyFunctionObject *func, PyObject *locals, PyObject *const *args, Py_ssize_t argcount, PyObject *kwnames) { assert(is_tstate_valid(tstate)); - assert(con->fc_defaults == NULL || PyTuple_CheckExact(con->fc_defaults)); - PyCodeObject *code = (PyCodeObject *)con->fc_code; + assert(func->func_defaults == NULL || PyTuple_CheckExact(func->func_defaults)); + PyCodeObject *code = (PyCodeObject *)func->func_code; int size = code->co_nlocalsplus+code->co_stacksize + FRAME_SPECIALS_SIZE; InterpreterFrame *frame = (InterpreterFrame *)PyMem_Malloc(sizeof(PyObject *)*size); if (frame == NULL) { goto fail_no_memory; } - _PyFrame_InitializeSpecials(frame, con, locals, code->co_nlocalsplus); + _PyFrame_InitializeSpecials(frame, func, locals, code->co_nlocalsplus); for (int i = 0; i < code->co_nlocalsplus; i++) { frame->localsplus[i] = NULL; } assert(frame->frame_obj == NULL); - if (initialize_locals(tstate, con, frame->localsplus, args, argcount, kwnames)) { + if (initialize_locals(tstate, func, frame->localsplus, args, argcount, kwnames)) { _PyFrame_Clear(frame, 1); return NULL; } @@ -5692,17 +5707,17 @@ make_coro_frame(PyThreadState *tstate, /* Consumes all the references to the args */ static PyObject * -make_coro(PyThreadState *tstate, PyFrameConstructor *con, +make_coro(PyThreadState *tstate, PyFunctionObject *func, PyObject *locals, PyObject* const* args, size_t argcount, PyObject *kwnames) { - assert (((PyCodeObject *)con->fc_code)->co_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR)); - InterpreterFrame *frame = make_coro_frame(tstate, con, locals, args, argcount, kwnames); + assert (((PyCodeObject *)func->func_code)->co_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR)); + InterpreterFrame *frame = make_coro_frame(tstate, func, locals, args, argcount, kwnames); if (frame == NULL) { return NULL; } - PyObject *gen = _Py_MakeCoro(con, frame); + PyObject *gen = _Py_MakeCoro(func, frame); if (gen == NULL) { return NULL; } @@ -5711,22 +5726,22 @@ make_coro(PyThreadState *tstate, PyFrameConstructor *con, /* Consumes all the references to the args */ static InterpreterFrame * -_PyEvalFramePushAndInit(PyThreadState *tstate, PyFrameConstructor *con, +_PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func, PyObject *locals, PyObject* const* args, size_t argcount, PyObject *kwnames) { - PyCodeObject * code = (PyCodeObject *)con->fc_code; + PyCodeObject * code = (PyCodeObject *)func->func_code; size_t size = code->co_nlocalsplus + code->co_stacksize + FRAME_SPECIALS_SIZE; InterpreterFrame *frame = _PyThreadState_BumpFramePointer(tstate, size); if (frame == NULL) { goto fail; } - _PyFrame_InitializeSpecials(frame, con, locals, code->co_nlocalsplus); + _PyFrame_InitializeSpecials(frame, func, locals, code->co_nlocalsplus); PyObject **localsarray = &frame->localsplus[0]; for (int i = 0; i < code->co_nlocalsplus; i++) { localsarray[i] = NULL; } - if (initialize_locals(tstate, con, localsarray, args, argcount, kwnames)) { + if (initialize_locals(tstate, func, localsarray, args, argcount, kwnames)) { _PyFrame_Clear(frame, 0); return NULL; } @@ -5761,12 +5776,12 @@ _PyEvalFrameClearAndPop(PyThreadState *tstate, InterpreterFrame * frame) } PyObject * -_PyEval_Vector(PyThreadState *tstate, PyFrameConstructor *con, +_PyEval_Vector(PyThreadState *tstate, PyFunctionObject *func, PyObject *locals, PyObject* const* args, size_t argcount, PyObject *kwnames) { - PyCodeObject *code = (PyCodeObject *)con->fc_code; + PyCodeObject *code = (PyCodeObject *)func->func_code; /* _PyEvalFramePushAndInit and make_coro consume * all the references to their arguments */ @@ -5782,10 +5797,10 @@ _PyEval_Vector(PyThreadState *tstate, PyFrameConstructor *con, int is_coro = code->co_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR); if (is_coro) { - return make_coro(tstate, con, locals, args, argcount, kwnames); + return make_coro(tstate, func, locals, args, argcount, kwnames); } InterpreterFrame *frame = _PyEvalFramePushAndInit( - tstate, con, locals, args, argcount, kwnames); + tstate, func, locals, args, argcount, kwnames); if (frame == NULL) { return NULL; } @@ -5869,9 +5884,14 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals, .fc_kwdefaults = kwdefs, .fc_closure = closure }; - res = _PyEval_Vector(tstate, &constr, locals, + PyFunctionObject *func = _PyFunction_FromConstructor(&constr); + if (func == NULL) { + return NULL; + } + res = _PyEval_Vector(tstate, func, locals, allargs, argcount, kwnames); + Py_DECREF(func); if (kwcount) { Py_DECREF(kwnames); PyMem_Free(newargs); diff --git a/Python/compile.c b/Python/compile.c index 40bd1fde0a9fd..87de7baab4819 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1171,6 +1171,7 @@ stack_effect(int opcode, int oparg, int jump) /* Closures */ case MAKE_CELL: + case COPY_FREE_VARS: return 0; case LOAD_CLOSURE: return 1; @@ -7611,7 +7612,7 @@ insert_instruction(basicblock *block, int pos, struct instr *instr) { static int insert_prefix_instructions(struct compiler *c, basicblock *entryblock, - int *fixed) + int *fixed, int nfreevars) { int flags = compute_code_flags(c); @@ -7684,6 +7685,22 @@ insert_prefix_instructions(struct compiler *c, basicblock *entryblock, } } + if (nfreevars) { + struct instr copy_frees = { + .i_opcode = COPY_FREE_VARS, + .i_oparg = nfreevars, + .i_lineno = -1, + .i_col_offset = -1, + .i_end_lineno = -1, + .i_end_col_offset = -1, + .i_target = NULL, + }; + if (insert_instruction(entryblock, 0, ©_frees) < 0) { + return -1; + } + + } + return 0; } @@ -7818,7 +7835,7 @@ assemble(struct compiler *c, int addNone) } // This must be called before fix_cell_offsets(). - if (insert_prefix_instructions(c, entryblock, cellfixedoffsets)) { + if (insert_prefix_instructions(c, entryblock, cellfixedoffsets, nfreevars)) { goto error; } diff --git a/Python/frame.c b/Python/frame.c index a5c93eaaa5f37..79b0f77a0657e 100644 --- a/Python/frame.c +++ b/Python/frame.c @@ -8,9 +8,8 @@ int _PyFrame_Traverse(InterpreterFrame *frame, visitproc visit, void *arg) { Py_VISIT(frame->frame_obj); - Py_VISIT(frame->f_globals); - Py_VISIT(frame->f_builtins); Py_VISIT(frame->f_locals); + Py_VISIT(frame->f_func); Py_VISIT(frame->f_code); /* locals */ PyObject **locals = _PyFrame_GetLocalsArray(frame); @@ -62,8 +61,7 @@ clear_specials(InterpreterFrame *frame) frame->generator = NULL; Py_XDECREF(frame->frame_obj); Py_XDECREF(frame->f_locals); - Py_DECREF(frame->f_globals); - Py_DECREF(frame->f_builtins); + Py_DECREF(frame->f_func); Py_DECREF(frame->f_code); } diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 903b967c3a52e..c9d430d26814c 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -148,7 +148,7 @@ static void *opcode_targets[256] = { &&TARGET_SET_ADD, &&TARGET_MAP_ADD, &&TARGET_LOAD_CLASSDEREF, - &&_unknown_opcode, + &&TARGET_COPY_FREE_VARS, &&_unknown_opcode, &&_unknown_opcode, &&TARGET_MATCH_CLASS, diff --git a/Python/pystate.c b/Python/pystate.c index 273982b4bd2f5..56db095d24b8a 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -2087,9 +2087,9 @@ _PyThreadState_BumpFramePointerSlow(PyThreadState *tstate, size_t size) InterpreterFrame * -_PyThreadState_PushFrame(PyThreadState *tstate, PyFrameConstructor *con, PyObject *locals) +_PyThreadState_PushFrame(PyThreadState *tstate, PyFunctionObject *func, PyObject *locals) { - PyCodeObject *code = (PyCodeObject *)con->fc_code; + PyCodeObject *code = (PyCodeObject *)func->func_code; int nlocalsplus = code->co_nlocalsplus; size_t size = nlocalsplus + code->co_stacksize + FRAME_SPECIALS_SIZE; @@ -2097,7 +2097,7 @@ _PyThreadState_PushFrame(PyThreadState *tstate, PyFrameConstructor *con, PyObjec if (frame == NULL) { return NULL; } - _PyFrame_InitializeSpecials(frame, con, locals, nlocalsplus); + _PyFrame_InitializeSpecials(frame, func, locals, nlocalsplus); for (int i=0; i < nlocalsplus; i++) { frame->localsplus[i] = NULL; } diff --git a/Python/specialize.c b/Python/specialize.c index 130da008ad8ce..f5f12139df79b 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -479,7 +479,7 @@ initial_counter_value(void) { #define SPEC_FAIL_WRONG_NUMBER_ARGUMENTS 9 #define SPEC_FAIL_CO_NOT_OPTIMIZED 10 /* SPEC_FAIL_METHOD defined as 11 above */ -#define SPEC_FAIL_FREE_VARS 12 + #define SPEC_FAIL_PYCFUNCTION 13 #define SPEC_FAIL_PYCFUNCTION_WITH_KEYWORDS 14 #define SPEC_FAIL_PYCFUNCTION_FAST_WITH_KEYWORDS 15 @@ -1158,9 +1158,6 @@ function_kind(PyCodeObject *code) { if ((flags & CO_OPTIMIZED) == 0) { return SPEC_FAIL_CO_NOT_OPTIMIZED; } - if (code->co_nfreevars) { - return SPEC_FAIL_FREE_VARS; - } return SIMPLE_FUNCTION; } From webhook-mailer at python.org Tue Nov 23 05:28:26 2021 From: webhook-mailer at python.org (encukou) Date: Tue, 23 Nov 2021 10:28:26 -0000 Subject: [Python-checkins] Clarify that discutils.(plat)include is for CPython's headers (GH-29578) Message-ID: https://github.com/python/cpython/commit/2c047f604e6a999390b5fa4ebfb6e8222c5cc096 commit: 2c047f604e6a999390b5fa4ebfb6e8222c5cc096 branch: main author: Petr Viktorin committer: encukou date: 2021-11-23T11:28:14+01:00 summary: Clarify that discutils.(plat)include is for CPython's headers (GH-29578) Change the docs to note that "include" and "platinclude" are for CPython's headers, and not necessarily for headers of third-party libraries. See discussion in: https://discuss.python.org/t/clarification-on-a-wheels-header-data/9305/19 files: M Doc/library/sysconfig.rst diff --git a/Doc/library/sysconfig.rst b/Doc/library/sysconfig.rst index 7ef3b2489673e..713be1e02cea6 100644 --- a/Doc/library/sysconfig.rst +++ b/Doc/library/sysconfig.rst @@ -96,8 +96,10 @@ identifier. Python currently uses eight paths: platform-specific. - *platlib*: directory for site-specific, platform-specific files. - *purelib*: directory for site-specific, non-platform-specific files. -- *include*: directory for non-platform-specific header files. -- *platinclude*: directory for platform-specific header files. +- *include*: directory for non-platform-specific header files for + the Python C-API. +- *platinclude*: directory for platform-specific header files for + the Python C-API. - *scripts*: directory for script files. - *data*: directory for data files. From webhook-mailer at python.org Tue Nov 23 05:32:44 2021 From: webhook-mailer at python.org (miss-islington) Date: Tue, 23 Nov 2021 10:32:44 -0000 Subject: [Python-checkins] bpo-45561: Run smelly.py tool from $(srcdir) (GH-29138) Message-ID: https://github.com/python/cpython/commit/327c764fa2a032e34dc268164c3c9c2f95b978c4 commit: 327c764fa2a032e34dc268164c3c9c2f95b978c4 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-23T02:32:31-08:00 summary: bpo-45561: Run smelly.py tool from $(srcdir) (GH-29138) (cherry picked from commit 457e6a6e96b5afad403a0bc892508a77beef4d33) Co-authored-by: Neil Schemenauer files: A Misc/NEWS.d/next/Build/2021-10-21-14-38-30.bpo-45561.PVqhZE.rst M Makefile.pre.in M Tools/scripts/smelly.py diff --git a/Makefile.pre.in b/Makefile.pre.in index ae6555c8e2fe1..86014227c3387 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1962,7 +1962,7 @@ distclean: clobber # Check that all symbols exported by libpython start with "Py" or "_Py" smelly: @DEF_MAKE_RULE@ - $(RUNSHARED) ./$(BUILDPYTHON) Tools/scripts/smelly.py + $(RUNSHARED) ./$(BUILDPYTHON) $(srcdir)/Tools/scripts/smelly.py # Find files with funny names funny: diff --git a/Misc/NEWS.d/next/Build/2021-10-21-14-38-30.bpo-45561.PVqhZE.rst b/Misc/NEWS.d/next/Build/2021-10-21-14-38-30.bpo-45561.PVqhZE.rst new file mode 100644 index 0000000000000..cf5d8686b9840 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-10-21-14-38-30.bpo-45561.PVqhZE.rst @@ -0,0 +1 @@ +Run smelly.py tool from $(srcdir). diff --git a/Tools/scripts/smelly.py b/Tools/scripts/smelly.py index fb01660dea33a..276a5ab2cc84c 100755 --- a/Tools/scripts/smelly.py +++ b/Tools/scripts/smelly.py @@ -108,8 +108,11 @@ def check_library(library, dynamic=False): def check_extensions(): print(__file__) - srcdir = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) - filename = os.path.join(srcdir, "pybuilddir.txt") + # This assumes pybuilddir.txt is in same directory as pyconfig.h. + # In the case of out-of-tree builds, we can't assume pybuilddir.txt is + # in the source folder. + config_dir = os.path.dirname(sysconfig.get_config_h_filename()) + filename = os.path.join(config_dir, "pybuilddir.txt") try: with open(filename, encoding="utf-8") as fp: pybuilddir = fp.readline() @@ -118,7 +121,7 @@ def check_extensions(): return True print(f"Check extension modules from {pybuilddir} directory") - builddir = os.path.join(srcdir, pybuilddir) + builddir = os.path.join(config_dir, pybuilddir) nsymbol = 0 for name in os.listdir(builddir): if not name.endswith(".so"): From webhook-mailer at python.org Tue Nov 23 06:12:27 2021 From: webhook-mailer at python.org (serhiy-storchaka) Date: Tue, 23 Nov 2021 11:12:27 -0000 Subject: [Python-checkins] bpo-45878: convert `try/except` to `self.assertRaises` in `Lib/ctypes/test/test_functions.py` (GH-29721) Message-ID: https://github.com/python/cpython/commit/b48ac6fe38b2fca9963b097c04cdecfc6083104e commit: b48ac6fe38b2fca9963b097c04cdecfc6083104e branch: main author: Nikita Sobolev committer: serhiy-storchaka date: 2021-11-23T13:12:13+02:00 summary: bpo-45878: convert `try/except` to `self.assertRaises` in `Lib/ctypes/test/test_functions.py` (GH-29721) files: A Misc/NEWS.d/next/Tests/2021-11-23-12-36-21.bpo-45878.eOs_Mp.rst M Lib/ctypes/test/test_functions.py diff --git a/Lib/ctypes/test/test_functions.py b/Lib/ctypes/test/test_functions.py index c5456ba107ae3..f9e92e1cc6b06 100644 --- a/Lib/ctypes/test/test_functions.py +++ b/Lib/ctypes/test/test_functions.py @@ -35,34 +35,24 @@ def test_mro(self): # wasn't checked, and it even crashed Python. # Found by Greg Chapman. - try: + with self.assertRaises(TypeError): class X(object, Array): _length_ = 5 _type_ = "i" - except TypeError: - pass - from _ctypes import _Pointer - try: + with self.assertRaises(TypeError): class X(object, _Pointer): pass - except TypeError: - pass from _ctypes import _SimpleCData - try: + with self.assertRaises(TypeError): class X(object, _SimpleCData): _type_ = "i" - except TypeError: - pass - try: + with self.assertRaises(TypeError): class X(object, Structure): _fields_ = [] - except TypeError: - pass - @need_symbol('c_wchar') def test_wchar_parm(self): diff --git a/Misc/NEWS.d/next/Tests/2021-11-23-12-36-21.bpo-45878.eOs_Mp.rst b/Misc/NEWS.d/next/Tests/2021-11-23-12-36-21.bpo-45878.eOs_Mp.rst new file mode 100644 index 0000000000000..fca90ef46981b --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-11-23-12-36-21.bpo-45878.eOs_Mp.rst @@ -0,0 +1,2 @@ +Test ``Lib/ctypes/test/test_functions.py::test_mro`` now uses +``self.assertRaises`` instead of ``try/except``. From webhook-mailer at python.org Tue Nov 23 08:43:51 2021 From: webhook-mailer at python.org (encukou) Date: Tue, 23 Nov 2021 13:43:51 -0000 Subject: [Python-checkins] bpo-45783: Preserve file moves and deletions in the tests for the freeze tool. (GH-29527) Message-ID: https://github.com/python/cpython/commit/8ed1495ad900dd815ff8fb97926da5312aaa23f9 commit: 8ed1495ad900dd815ff8fb97926da5312aaa23f9 branch: main author: Eric Snow committer: encukou date: 2021-11-23T14:43:40+01:00 summary: bpo-45783: Preserve file moves and deletions in the tests for the freeze tool. (GH-29527) Use shutil.copytree rather than Git, which might be missing (or configured differently) when testing Python built from a source release. files: A Misc/NEWS.d/next/Tests/2021-11-11-13-56-00.bpo-45783.8k1Rng.rst M Lib/test/test_tools/test_freeze.py M Tools/freeze/test/freeze.py diff --git a/Lib/test/test_tools/test_freeze.py b/Lib/test/test_tools/test_freeze.py index 392a776f042e4..386c35a973bc2 100644 --- a/Lib/test/test_tools/test_freeze.py +++ b/Lib/test/test_tools/test_freeze.py @@ -5,6 +5,7 @@ import unittest from test import support +from test.support import os_helper from . import imports_under_tool, skip_if_missing skip_if_missing('freeze') @@ -22,8 +23,8 @@ def test_freeze_simple_script(self): print('running...') sys.exit(0) """) - outdir, scriptfile, python = helper.prepare(script) - - executable = helper.freeze(python, scriptfile, outdir) - text = helper.run(executable) + with os_helper.temp_dir() as outdir: + outdir, scriptfile, python = helper.prepare(script, outdir) + executable = helper.freeze(python, scriptfile, outdir) + text = helper.run(executable) self.assertEqual(text, 'running...') diff --git a/Misc/NEWS.d/next/Tests/2021-11-11-13-56-00.bpo-45783.8k1Rng.rst b/Misc/NEWS.d/next/Tests/2021-11-11-13-56-00.bpo-45783.8k1Rng.rst new file mode 100644 index 0000000000000..cb0e07f27fb55 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-11-11-13-56-00.bpo-45783.8k1Rng.rst @@ -0,0 +1 @@ +The test for the freeze tool now handles file moves and deletions. diff --git a/Tools/freeze/test/freeze.py b/Tools/freeze/test/freeze.py index 387f1ff70b234..db2aa3101d879 100644 --- a/Tools/freeze/test/freeze.py +++ b/Tools/freeze/test/freeze.py @@ -11,7 +11,6 @@ SRCDIR = os.path.dirname(os.path.dirname(TOOL_ROOT)) MAKE = shutil.which('make') -GIT = shutil.which('git') FREEZE = os.path.join(TOOL_ROOT, 'freeze.py') OUTDIR = os.path.join(TESTS_DIR, 'outdir') @@ -75,36 +74,15 @@ def ensure_opt(args, name, value): args[pos] = f'{opt}={value}' -def git_copy_repo(newroot, oldroot): - if not GIT: - raise UnsupportedError('git') - +def copy_source_tree(newroot, oldroot): + print(f'copying the source tree into {newroot}...') if os.path.exists(newroot): - print(f'updating copied repo {newroot}...') if newroot == SRCDIR: raise Exception('this probably isn\'t what you wanted') - _run_quiet([GIT, 'clean', '-d', '-f'], newroot) - _run_quiet([GIT, 'reset'], newroot) - _run_quiet([GIT, 'checkout', '.'], newroot) - _run_quiet([GIT, 'pull', '-f', oldroot], newroot) - else: - print(f'copying repo into {newroot}...') - _run_quiet([GIT, 'clone', oldroot, newroot]) - - # Copy over any uncommited files. - text = _run_stdout([GIT, 'status', '-s'], oldroot) - for line in text.splitlines(): - _, _, relfile = line.strip().partition(' ') - relfile = relfile.strip() - isdir = relfile.endswith(os.path.sep) - relfile = relfile.rstrip(os.path.sep) - srcfile = os.path.join(oldroot, relfile) - dstfile = os.path.join(newroot, relfile) - os.makedirs(os.path.dirname(dstfile), exist_ok=True) - if isdir: - shutil.copytree(srcfile, dstfile, dirs_exist_ok=True) - else: - shutil.copy2(srcfile, dstfile) + shutil.rmtree(newroot) + shutil.copytree(oldroot, newroot) + if os.path.exists(os.path.join(newroot, 'Makefile')): + _run_quiet([MAKE, 'clean'], newroot) def get_makefile_var(builddir, name): @@ -146,12 +124,14 @@ def prepare(script=None, outdir=None): # Write the script to disk. if script: scriptfile = os.path.join(outdir, 'app.py') + print(f'creating the script to be frozen at {scriptfile}') with open(scriptfile, 'w') as outfile: outfile.write(script) - # Make a copy of the repo to avoid affecting the current build. + # Make a copy of the repo to avoid affecting the current build + # (e.g. changing PREFIX). srcdir = os.path.join(outdir, 'cpython') - git_copy_repo(srcdir, SRCDIR) + copy_source_tree(srcdir, SRCDIR) # We use an out-of-tree build (instead of srcdir). builddir = os.path.join(outdir, 'python-build') @@ -172,7 +152,7 @@ def prepare(script=None, outdir=None): raise UnsupportedError('make') # Build python. - print('building python...') + print(f'building python in {builddir}...') if os.path.exists(os.path.join(srcdir, 'Makefile')): # Out-of-tree builds require a clean srcdir. _run_quiet([MAKE, '-C', srcdir, 'clean']) From webhook-mailer at python.org Tue Nov 23 10:38:11 2021 From: webhook-mailer at python.org (miss-islington) Date: Tue, 23 Nov 2021 15:38:11 -0000 Subject: [Python-checkins] =?utf-8?q?bpo-45703=3A_Invalidate_=5FNamespace?= =?utf-8?q?Path_cache_on_importlib=2Einvalidate=5Fca=E2=80=A6_=28GH-29384?= =?utf-8?q?=29?= Message-ID: https://github.com/python/cpython/commit/ae1965ccb4b1fad63fab40fe8805d1b8247668d3 commit: ae1965ccb4b1fad63fab40fe8805d1b8247668d3 branch: main author: Miro Hron?ok committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-23T07:38:02-08:00 summary: bpo-45703: Invalidate _NamespacePath cache on importlib.invalidate_ca? (GH-29384) Consider the following directory structure: . ??? PATH1 ??? namespace ??? sub1 ??? __init__.py And both PATH1 and PATH2 in sys path: $ PYTHONPATH=PATH1:PATH2 python3.11 >>> import namespace >>> import namespace.sub1 >>> namespace.__path__ _NamespacePath(['.../PATH1/namespace']) >>> ... While this interpreter still runs, PATH2/namespace/sub2 is created: . ??? PATH1 ? ??? namespace ? ??? sub1 ? ??? __init__.py ??? PATH2 ??? namespace ??? sub2 ??? __init__.py The newly created module cannot be imported: >>> ... >>> namespace.__path__ _NamespacePath(['.../PATH1/namespace']) >>> import namespace.sub2 Traceback (most recent call last): File "", line 1, in ModuleNotFoundError: No module named 'namespace.sub2' Calling importlib.invalidate_caches() now newly allows to import it: >>> import importlib >>> importlib.invalidate_caches() >>> namespace.__path__ _NamespacePath(['.../PATH1/namespace']) >>> import namespace.sub2 >>> namespace.__path__ _NamespacePath(['.../PATH1/namespace', '.../PATH2/namespace']) This was not previously possible. files: A Misc/NEWS.d/next/Library/2021-11-03-13-41-49.bpo-45703.35AagL.rst M Doc/library/importlib.rst M Lib/importlib/_bootstrap_external.py M Lib/test/test_importlib/test_namespace_pkgs.py diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index 6b71e64bcbfa7..59c8c64acdc3b 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -145,6 +145,10 @@ Functions .. versionadded:: 3.3 + .. versionchanged:: 3.10 + Namespace packages created/installed in a different :data:`sys.path` + location after the same namespace was already imported are noticed. + .. function:: reload(module) Reload a previously imported *module*. The argument must be a module object, diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 85c5193407d80..6970e9f0a94d4 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -1231,10 +1231,15 @@ class _NamespacePath: using path_finder. For top-level modules, the parent module's path is sys.path.""" + # When invalidate_caches() is called, this epoch is incremented + # https://bugs.python.org/issue45703 + _epoch = 0 + def __init__(self, name, path, path_finder): self._name = name self._path = path self._last_parent_path = tuple(self._get_parent_path()) + self._last_epoch = self._epoch self._path_finder = path_finder def _find_parent_path_names(self): @@ -1254,7 +1259,7 @@ def _get_parent_path(self): def _recalculate(self): # If the parent's path has changed, recalculate _path parent_path = tuple(self._get_parent_path()) # Make a copy - if parent_path != self._last_parent_path: + if parent_path != self._last_parent_path or self._epoch != self._last_epoch: spec = self._path_finder(self._name, parent_path) # Note that no changes are made if a loader is returned, but we # do remember the new parent path @@ -1262,6 +1267,7 @@ def _recalculate(self): if spec.submodule_search_locations: self._path = spec.submodule_search_locations self._last_parent_path = parent_path # Save the copy + self._last_epoch = self._epoch return self._path def __iter__(self): @@ -1355,6 +1361,9 @@ def invalidate_caches(): del sys.path_importer_cache[name] elif hasattr(finder, 'invalidate_caches'): finder.invalidate_caches() + # Also invalidate the caches of _NamespacePaths + # https://bugs.python.org/issue45703 + _NamespacePath._epoch += 1 @staticmethod def _path_hooks(path): diff --git a/Lib/test/test_importlib/test_namespace_pkgs.py b/Lib/test/test_importlib/test_namespace_pkgs.py index f80283233f977..2ea41b7a4c5c3 100644 --- a/Lib/test/test_importlib/test_namespace_pkgs.py +++ b/Lib/test/test_importlib/test_namespace_pkgs.py @@ -4,6 +4,7 @@ import importlib.machinery import os import sys +import tempfile import unittest import warnings @@ -130,6 +131,40 @@ def test_imports(self): self.assertEqual(foo.two.attr, 'portion2 foo two') +class SeparatedNamespacePackagesCreatedWhileRunning(NamespacePackageTest): + paths = ['portion1'] + + def test_invalidate_caches(self): + with tempfile.TemporaryDirectory() as temp_dir: + # we manipulate sys.path before anything is imported to avoid + # accidental cache invalidation when changing it + sys.path.append(temp_dir) + + import foo.one + self.assertEqual(foo.one.attr, 'portion1 foo one') + + # the module does not exist, so it cannot be imported + with self.assertRaises(ImportError): + import foo.just_created + + # util.create_modules() manipulates sys.path + # so we must create the modules manually instead + namespace_path = os.path.join(temp_dir, 'foo') + os.mkdir(namespace_path) + module_path = os.path.join(namespace_path, 'just_created.py') + with open(module_path, 'w', encoding='utf-8') as file: + file.write('attr = "just_created foo"') + + # the module is not known, so it cannot be imported yet + with self.assertRaises(ImportError): + import foo.just_created + + # but after explicit cache invalidation, it is importable + importlib.invalidate_caches() + import foo.just_created + self.assertEqual(foo.just_created.attr, 'just_created foo') + + class SeparatedOverlappingNamespacePackages(NamespacePackageTest): paths = ['portion1', 'both_portions'] diff --git a/Misc/NEWS.d/next/Library/2021-11-03-13-41-49.bpo-45703.35AagL.rst b/Misc/NEWS.d/next/Library/2021-11-03-13-41-49.bpo-45703.35AagL.rst new file mode 100644 index 0000000000000..9fa9be56b8327 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-03-13-41-49.bpo-45703.35AagL.rst @@ -0,0 +1,5 @@ +When a namespace package is imported before another module from the same +namespace is created/installed in a different :data:`sys.path` location +while the program is running, calling the +:func:`importlib.invalidate_caches` function will now also guarantee the new +module is noticed. From webhook-mailer at python.org Tue Nov 23 11:56:30 2021 From: webhook-mailer at python.org (gvanrossum) Date: Tue, 23 Nov 2021 16:56:30 -0000 Subject: [Python-checkins] bpo-45873: Get rid of bootstrap_python (#29717) Message-ID: https://github.com/python/cpython/commit/5be98e57b3c3b36d1a1176b49c73b8822c6380e7 commit: 5be98e57b3c3b36d1a1176b49c73b8822c6380e7 branch: main author: Guido van Rossum committer: gvanrossum date: 2021-11-23T08:56:06-08:00 summary: bpo-45873: Get rid of bootstrap_python (#29717) Instead we use $(PYTHON_FOR_REGEN) .../deepfreeze.py with the frozen .h file as input, as we did for Windows in bpo-45850. We also get rid of the code that generates the .h files when make regen-frozen is run (i.e., .../make_frozen.py), and the MANIFEST file. Restore Python 3.8 and 3.9 as Windows host Python again Co-authored-by: Kumar Aditya <59607654+kumaraditya303 at users.noreply.github.com> files: A Misc/NEWS.d/next/Build/2021-11-23-04-28-40.bpo-45873.9dldZ4.rst M Makefile.pre.in M PCbuild/find_python.bat M Tools/scripts/deepfreeze.py M Tools/scripts/freeze_modules.py M Tools/scripts/umarshal.py M configure M configure.ac diff --git a/Makefile.pre.in b/Makefile.pre.in index 046b0e86e6758..476a64cb7a500 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -275,7 +275,6 @@ LIBOBJS= @LIBOBJS@ PYTHON= python$(EXE) BUILDPYTHON= python$(BUILDEXE) -BOOTSTRAP= _bootstrap_python PYTHON_FOR_REGEN?=@PYTHON_FOR_REGEN@ UPDATE_FILE=$(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/update_file.py @@ -710,9 +709,9 @@ platform: $(BUILDPYTHON) pybuilddir.txt # problems by creating a dummy pybuilddir.txt just to allow interpreter # initialization to succeed. It will be overwritten by generate-posix-vars # or removed in case of failure. -pybuilddir.txt: $(BOOTSTRAP) +pybuilddir.txt: $(BUILDPYTHON) @echo "none" > ./pybuilddir.txt - ./$(BOOTSTRAP) -S -m sysconfig --generate-posix-vars ;\ + $(RUNSHARED) $(PYTHON_FOR_BUILD) -S -m sysconfig --generate-posix-vars ;\ if test $$? -ne 0 ; then \ echo "generate-posix-vars failed" ; \ rm -f ./pybuilddir.txt ; \ @@ -934,155 +933,75 @@ regen-test-frozenmain: $(BUILDPYTHON) Programs/_testembed: Programs/_testembed.o $(LIBRARY_DEPS) $(LINKCC) $(PY_CORE_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/_testembed.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) -############################################################################ -# "Bootstrap Python" used to run deepfreeze.py - -BOOTSTRAP_HEADERS = \ - Python/frozen_modules/importlib._bootstrap.h \ - Python/frozen_modules/importlib._bootstrap_external.h \ - Python/frozen_modules/zipimport.h - -Python/bootstrap_frozen.o: Python/bootstrap_frozen.c Include/cpython/import.h $(BOOTSTRAP_HEADERS) - -$(BOOTSTRAP): $(LIBRARY_OBJS_OMIT_FROZEN) \ - Python/bootstrap_frozen.o Programs/python.o - $(LINKCC) $(PY_CORE_LDFLAGS) -o $@ $(LIBRARY_OBJS_OMIT_FROZEN) \ - Python/bootstrap_frozen.o \ - Programs/python.o \ - $(LIBS) $(MODLIBS) $(SYSLIBS) - ############################################################################ # Deepfreeze targets .PHONY: regen-deepfreeze regen-deepfreeze: $(DEEPFREEZE_OBJS) -DEEPFREEZE_DEPS = \ - $(BOOTSTRAP) \ - pybuilddir.txt \ - $(srcdir)/Tools/scripts/deepfreeze.py +DEEPFREEZE_DEPS=$(srcdir)/Tools/scripts/deepfreeze.py # BEGIN: deepfreeze modules -Python/deepfreeze/importlib._bootstrap.c: $(srcdir)/Lib/importlib/_bootstrap.py $(DEEPFREEZE_DEPS) - @echo "Deepfreezing Python/deepfreeze/importlib._bootstrap.c from Lib/importlib/_bootstrap.py" - @./$(BOOTSTRAP) \ - $(srcdir)/Tools/scripts/deepfreeze.py \ - $(srcdir)/Lib/importlib/_bootstrap.py -m importlib._bootstrap -o Python/deepfreeze/importlib._bootstrap.c - -Python/deepfreeze/importlib._bootstrap_external.c: $(srcdir)/Lib/importlib/_bootstrap_external.py $(DEEPFREEZE_DEPS) - @echo "Deepfreezing Python/deepfreeze/importlib._bootstrap_external.c from Lib/importlib/_bootstrap_external.py" - @./$(BOOTSTRAP) \ - $(srcdir)/Tools/scripts/deepfreeze.py \ - $(srcdir)/Lib/importlib/_bootstrap_external.py -m importlib._bootstrap_external -o Python/deepfreeze/importlib._bootstrap_external.c - -Python/deepfreeze/zipimport.c: $(srcdir)/Lib/zipimport.py $(DEEPFREEZE_DEPS) - @echo "Deepfreezing Python/deepfreeze/zipimport.c from Lib/zipimport.py" - @./$(BOOTSTRAP) \ - $(srcdir)/Tools/scripts/deepfreeze.py \ - $(srcdir)/Lib/zipimport.py -m zipimport -o Python/deepfreeze/zipimport.c - -Python/deepfreeze/abc.c: $(srcdir)/Lib/abc.py $(DEEPFREEZE_DEPS) - @echo "Deepfreezing Python/deepfreeze/abc.c from Lib/abc.py" - @./$(BOOTSTRAP) \ - $(srcdir)/Tools/scripts/deepfreeze.py \ - $(srcdir)/Lib/abc.py -m abc -o Python/deepfreeze/abc.c - -Python/deepfreeze/codecs.c: $(srcdir)/Lib/codecs.py $(DEEPFREEZE_DEPS) - @echo "Deepfreezing Python/deepfreeze/codecs.c from Lib/codecs.py" - @./$(BOOTSTRAP) \ - $(srcdir)/Tools/scripts/deepfreeze.py \ - $(srcdir)/Lib/codecs.py -m codecs -o Python/deepfreeze/codecs.c - -Python/deepfreeze/io.c: $(srcdir)/Lib/io.py $(DEEPFREEZE_DEPS) - @echo "Deepfreezing Python/deepfreeze/io.c from Lib/io.py" - @./$(BOOTSTRAP) \ - $(srcdir)/Tools/scripts/deepfreeze.py \ - $(srcdir)/Lib/io.py -m io -o Python/deepfreeze/io.c - -Python/deepfreeze/_collections_abc.c: $(srcdir)/Lib/_collections_abc.py $(DEEPFREEZE_DEPS) - @echo "Deepfreezing Python/deepfreeze/_collections_abc.c from Lib/_collections_abc.py" - @./$(BOOTSTRAP) \ - $(srcdir)/Tools/scripts/deepfreeze.py \ - $(srcdir)/Lib/_collections_abc.py -m _collections_abc -o Python/deepfreeze/_collections_abc.c - -Python/deepfreeze/_sitebuiltins.c: $(srcdir)/Lib/_sitebuiltins.py $(DEEPFREEZE_DEPS) - @echo "Deepfreezing Python/deepfreeze/_sitebuiltins.c from Lib/_sitebuiltins.py" - @./$(BOOTSTRAP) \ - $(srcdir)/Tools/scripts/deepfreeze.py \ - $(srcdir)/Lib/_sitebuiltins.py -m _sitebuiltins -o Python/deepfreeze/_sitebuiltins.c - -Python/deepfreeze/genericpath.c: $(srcdir)/Lib/genericpath.py $(DEEPFREEZE_DEPS) - @echo "Deepfreezing Python/deepfreeze/genericpath.c from Lib/genericpath.py" - @./$(BOOTSTRAP) \ - $(srcdir)/Tools/scripts/deepfreeze.py \ - $(srcdir)/Lib/genericpath.py -m genericpath -o Python/deepfreeze/genericpath.c - -Python/deepfreeze/ntpath.c: $(srcdir)/Lib/ntpath.py $(DEEPFREEZE_DEPS) - @echo "Deepfreezing Python/deepfreeze/ntpath.c from Lib/ntpath.py" - @./$(BOOTSTRAP) \ - $(srcdir)/Tools/scripts/deepfreeze.py \ - $(srcdir)/Lib/ntpath.py -m ntpath -o Python/deepfreeze/ntpath.c - -Python/deepfreeze/posixpath.c: $(srcdir)/Lib/posixpath.py $(DEEPFREEZE_DEPS) - @echo "Deepfreezing Python/deepfreeze/posixpath.c from Lib/posixpath.py" - @./$(BOOTSTRAP) \ - $(srcdir)/Tools/scripts/deepfreeze.py \ - $(srcdir)/Lib/posixpath.py -m posixpath -o Python/deepfreeze/posixpath.c - -Python/deepfreeze/os.c: $(srcdir)/Lib/os.py $(DEEPFREEZE_DEPS) - @echo "Deepfreezing Python/deepfreeze/os.c from Lib/os.py" - @./$(BOOTSTRAP) \ - $(srcdir)/Tools/scripts/deepfreeze.py \ - $(srcdir)/Lib/os.py -m os -o Python/deepfreeze/os.c - -Python/deepfreeze/site.c: $(srcdir)/Lib/site.py $(DEEPFREEZE_DEPS) - @echo "Deepfreezing Python/deepfreeze/site.c from Lib/site.py" - @./$(BOOTSTRAP) \ - $(srcdir)/Tools/scripts/deepfreeze.py \ - $(srcdir)/Lib/site.py -m site -o Python/deepfreeze/site.c - -Python/deepfreeze/stat.c: $(srcdir)/Lib/stat.py $(DEEPFREEZE_DEPS) - @echo "Deepfreezing Python/deepfreeze/stat.c from Lib/stat.py" - @./$(BOOTSTRAP) \ - $(srcdir)/Tools/scripts/deepfreeze.py \ - $(srcdir)/Lib/stat.py -m stat -o Python/deepfreeze/stat.c - -Python/deepfreeze/__hello__.c: $(srcdir)/Lib/__hello__.py $(DEEPFREEZE_DEPS) - @echo "Deepfreezing Python/deepfreeze/__hello__.c from Lib/__hello__.py" - @./$(BOOTSTRAP) \ - $(srcdir)/Tools/scripts/deepfreeze.py \ - $(srcdir)/Lib/__hello__.py -m __hello__ -o Python/deepfreeze/__hello__.c - -Python/deepfreeze/__phello__.c: $(srcdir)/Lib/__phello__/__init__.py $(DEEPFREEZE_DEPS) - @echo "Deepfreezing Python/deepfreeze/__phello__.c from Lib/__phello__/__init__.py" - @./$(BOOTSTRAP) \ - $(srcdir)/Tools/scripts/deepfreeze.py \ - $(srcdir)/Lib/__phello__/__init__.py -m __phello__ -o Python/deepfreeze/__phello__.c - -Python/deepfreeze/__phello__.ham.c: $(srcdir)/Lib/__phello__/ham/__init__.py $(DEEPFREEZE_DEPS) - @echo "Deepfreezing Python/deepfreeze/__phello__.ham.c from Lib/__phello__/ham/__init__.py" - @./$(BOOTSTRAP) \ - $(srcdir)/Tools/scripts/deepfreeze.py \ - $(srcdir)/Lib/__phello__/ham/__init__.py -m __phello__.ham -o Python/deepfreeze/__phello__.ham.c - -Python/deepfreeze/__phello__.ham.eggs.c: $(srcdir)/Lib/__phello__/ham/eggs.py $(DEEPFREEZE_DEPS) - @echo "Deepfreezing Python/deepfreeze/__phello__.ham.eggs.c from Lib/__phello__/ham/eggs.py" - @./$(BOOTSTRAP) \ - $(srcdir)/Tools/scripts/deepfreeze.py \ - $(srcdir)/Lib/__phello__/ham/eggs.py -m __phello__.ham.eggs -o Python/deepfreeze/__phello__.ham.eggs.c - -Python/deepfreeze/__phello__.spam.c: $(srcdir)/Lib/__phello__/spam.py $(DEEPFREEZE_DEPS) - @echo "Deepfreezing Python/deepfreeze/__phello__.spam.c from Lib/__phello__/spam.py" - @./$(BOOTSTRAP) \ - $(srcdir)/Tools/scripts/deepfreeze.py \ - $(srcdir)/Lib/__phello__/spam.py -m __phello__.spam -o Python/deepfreeze/__phello__.spam.c - -Python/deepfreeze/frozen_only.c: $(srcdir)/Tools/freeze/flag.py $(DEEPFREEZE_DEPS) - @echo "Deepfreezing Python/deepfreeze/frozen_only.c from Tools/freeze/flag.py" - @./$(BOOTSTRAP) \ - $(srcdir)/Tools/scripts/deepfreeze.py \ - $(srcdir)/Tools/freeze/flag.py -m frozen_only -o Python/deepfreeze/frozen_only.c +Python/deepfreeze/importlib._bootstrap.c: Python/frozen_modules/importlib._bootstrap.h $(DEEPFREEZE_DEPS) + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/importlib._bootstrap.h -m importlib._bootstrap -o Python/deepfreeze/importlib._bootstrap.c + +Python/deepfreeze/importlib._bootstrap_external.c: Python/frozen_modules/importlib._bootstrap_external.h $(DEEPFREEZE_DEPS) + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/importlib._bootstrap_external.h -m importlib._bootstrap_external -o Python/deepfreeze/importlib._bootstrap_external.c + +Python/deepfreeze/zipimport.c: Python/frozen_modules/zipimport.h $(DEEPFREEZE_DEPS) + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/zipimport.h -m zipimport -o Python/deepfreeze/zipimport.c + +Python/deepfreeze/abc.c: Python/frozen_modules/abc.h $(DEEPFREEZE_DEPS) + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/abc.h -m abc -o Python/deepfreeze/abc.c + +Python/deepfreeze/codecs.c: Python/frozen_modules/codecs.h $(DEEPFREEZE_DEPS) + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/codecs.h -m codecs -o Python/deepfreeze/codecs.c + +Python/deepfreeze/io.c: Python/frozen_modules/io.h $(DEEPFREEZE_DEPS) + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/io.h -m io -o Python/deepfreeze/io.c + +Python/deepfreeze/_collections_abc.c: Python/frozen_modules/_collections_abc.h $(DEEPFREEZE_DEPS) + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/_collections_abc.h -m _collections_abc -o Python/deepfreeze/_collections_abc.c + +Python/deepfreeze/_sitebuiltins.c: Python/frozen_modules/_sitebuiltins.h $(DEEPFREEZE_DEPS) + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/_sitebuiltins.h -m _sitebuiltins -o Python/deepfreeze/_sitebuiltins.c + +Python/deepfreeze/genericpath.c: Python/frozen_modules/genericpath.h $(DEEPFREEZE_DEPS) + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/genericpath.h -m genericpath -o Python/deepfreeze/genericpath.c + +Python/deepfreeze/ntpath.c: Python/frozen_modules/ntpath.h $(DEEPFREEZE_DEPS) + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/ntpath.h -m ntpath -o Python/deepfreeze/ntpath.c + +Python/deepfreeze/posixpath.c: Python/frozen_modules/posixpath.h $(DEEPFREEZE_DEPS) + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/posixpath.h -m posixpath -o Python/deepfreeze/posixpath.c + +Python/deepfreeze/os.c: Python/frozen_modules/os.h $(DEEPFREEZE_DEPS) + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/os.h -m os -o Python/deepfreeze/os.c + +Python/deepfreeze/site.c: Python/frozen_modules/site.h $(DEEPFREEZE_DEPS) + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/site.h -m site -o Python/deepfreeze/site.c + +Python/deepfreeze/stat.c: Python/frozen_modules/stat.h $(DEEPFREEZE_DEPS) + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/stat.h -m stat -o Python/deepfreeze/stat.c + +Python/deepfreeze/__hello__.c: Python/frozen_modules/__hello__.h $(DEEPFREEZE_DEPS) + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/__hello__.h -m __hello__ -o Python/deepfreeze/__hello__.c + +Python/deepfreeze/__phello__.c: Python/frozen_modules/__phello__.h $(DEEPFREEZE_DEPS) + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/__phello__.h -m __phello__ -o Python/deepfreeze/__phello__.c + +Python/deepfreeze/__phello__.ham.c: Python/frozen_modules/__phello__.ham.h $(DEEPFREEZE_DEPS) + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/__phello__.ham.h -m __phello__.ham -o Python/deepfreeze/__phello__.ham.c + +Python/deepfreeze/__phello__.ham.eggs.c: Python/frozen_modules/__phello__.ham.eggs.h $(DEEPFREEZE_DEPS) + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/__phello__.ham.eggs.h -m __phello__.ham.eggs -o Python/deepfreeze/__phello__.ham.eggs.c + +Python/deepfreeze/__phello__.spam.c: Python/frozen_modules/__phello__.spam.h $(DEEPFREEZE_DEPS) + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/__phello__.spam.h -m __phello__.spam -o Python/deepfreeze/__phello__.spam.c + +Python/deepfreeze/frozen_only.c: Python/frozen_modules/frozen_only.h $(DEEPFREEZE_DEPS) + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/scripts/deepfreeze.py Python/frozen_modules/frozen_only.h -m frozen_only -o Python/deepfreeze/frozen_only.c # END: deepfreeze modules @@ -1143,64 +1062,64 @@ Programs/_freeze_module: Programs/_freeze_module.o $(LIBRARY_OBJS_OMIT_FROZEN) # BEGIN: freezing modules Python/frozen_modules/importlib._bootstrap.h: Programs/_freeze_module Lib/importlib/_bootstrap.py - Programs/_freeze_module importlib._bootstrap $(srcdir)/Lib/importlib/_bootstrap.py $(srcdir)/Python/frozen_modules/importlib._bootstrap.h + Programs/_freeze_module importlib._bootstrap $(srcdir)/Lib/importlib/_bootstrap.py Python/frozen_modules/importlib._bootstrap.h Python/frozen_modules/importlib._bootstrap_external.h: Programs/_freeze_module Lib/importlib/_bootstrap_external.py - Programs/_freeze_module importlib._bootstrap_external $(srcdir)/Lib/importlib/_bootstrap_external.py $(srcdir)/Python/frozen_modules/importlib._bootstrap_external.h + Programs/_freeze_module importlib._bootstrap_external $(srcdir)/Lib/importlib/_bootstrap_external.py Python/frozen_modules/importlib._bootstrap_external.h Python/frozen_modules/zipimport.h: Programs/_freeze_module Lib/zipimport.py - Programs/_freeze_module zipimport $(srcdir)/Lib/zipimport.py $(srcdir)/Python/frozen_modules/zipimport.h + Programs/_freeze_module zipimport $(srcdir)/Lib/zipimport.py Python/frozen_modules/zipimport.h Python/frozen_modules/abc.h: Programs/_freeze_module Lib/abc.py - Programs/_freeze_module abc $(srcdir)/Lib/abc.py $(srcdir)/Python/frozen_modules/abc.h + Programs/_freeze_module abc $(srcdir)/Lib/abc.py Python/frozen_modules/abc.h Python/frozen_modules/codecs.h: Programs/_freeze_module Lib/codecs.py - Programs/_freeze_module codecs $(srcdir)/Lib/codecs.py $(srcdir)/Python/frozen_modules/codecs.h + Programs/_freeze_module codecs $(srcdir)/Lib/codecs.py Python/frozen_modules/codecs.h Python/frozen_modules/io.h: Programs/_freeze_module Lib/io.py - Programs/_freeze_module io $(srcdir)/Lib/io.py $(srcdir)/Python/frozen_modules/io.h + Programs/_freeze_module io $(srcdir)/Lib/io.py Python/frozen_modules/io.h Python/frozen_modules/_collections_abc.h: Programs/_freeze_module Lib/_collections_abc.py - Programs/_freeze_module _collections_abc $(srcdir)/Lib/_collections_abc.py $(srcdir)/Python/frozen_modules/_collections_abc.h + Programs/_freeze_module _collections_abc $(srcdir)/Lib/_collections_abc.py Python/frozen_modules/_collections_abc.h Python/frozen_modules/_sitebuiltins.h: Programs/_freeze_module Lib/_sitebuiltins.py - Programs/_freeze_module _sitebuiltins $(srcdir)/Lib/_sitebuiltins.py $(srcdir)/Python/frozen_modules/_sitebuiltins.h + Programs/_freeze_module _sitebuiltins $(srcdir)/Lib/_sitebuiltins.py Python/frozen_modules/_sitebuiltins.h Python/frozen_modules/genericpath.h: Programs/_freeze_module Lib/genericpath.py - Programs/_freeze_module genericpath $(srcdir)/Lib/genericpath.py $(srcdir)/Python/frozen_modules/genericpath.h + Programs/_freeze_module genericpath $(srcdir)/Lib/genericpath.py Python/frozen_modules/genericpath.h Python/frozen_modules/ntpath.h: Programs/_freeze_module Lib/ntpath.py - Programs/_freeze_module ntpath $(srcdir)/Lib/ntpath.py $(srcdir)/Python/frozen_modules/ntpath.h + Programs/_freeze_module ntpath $(srcdir)/Lib/ntpath.py Python/frozen_modules/ntpath.h Python/frozen_modules/posixpath.h: Programs/_freeze_module Lib/posixpath.py - Programs/_freeze_module posixpath $(srcdir)/Lib/posixpath.py $(srcdir)/Python/frozen_modules/posixpath.h + Programs/_freeze_module posixpath $(srcdir)/Lib/posixpath.py Python/frozen_modules/posixpath.h Python/frozen_modules/os.h: Programs/_freeze_module Lib/os.py - Programs/_freeze_module os $(srcdir)/Lib/os.py $(srcdir)/Python/frozen_modules/os.h + Programs/_freeze_module os $(srcdir)/Lib/os.py Python/frozen_modules/os.h Python/frozen_modules/site.h: Programs/_freeze_module Lib/site.py - Programs/_freeze_module site $(srcdir)/Lib/site.py $(srcdir)/Python/frozen_modules/site.h + Programs/_freeze_module site $(srcdir)/Lib/site.py Python/frozen_modules/site.h Python/frozen_modules/stat.h: Programs/_freeze_module Lib/stat.py - Programs/_freeze_module stat $(srcdir)/Lib/stat.py $(srcdir)/Python/frozen_modules/stat.h + Programs/_freeze_module stat $(srcdir)/Lib/stat.py Python/frozen_modules/stat.h Python/frozen_modules/__hello__.h: Programs/_freeze_module Lib/__hello__.py - Programs/_freeze_module __hello__ $(srcdir)/Lib/__hello__.py $(srcdir)/Python/frozen_modules/__hello__.h + Programs/_freeze_module __hello__ $(srcdir)/Lib/__hello__.py Python/frozen_modules/__hello__.h Python/frozen_modules/__phello__.h: Programs/_freeze_module Lib/__phello__/__init__.py - Programs/_freeze_module __phello__ $(srcdir)/Lib/__phello__/__init__.py $(srcdir)/Python/frozen_modules/__phello__.h + Programs/_freeze_module __phello__ $(srcdir)/Lib/__phello__/__init__.py Python/frozen_modules/__phello__.h Python/frozen_modules/__phello__.ham.h: Programs/_freeze_module Lib/__phello__/ham/__init__.py - Programs/_freeze_module __phello__.ham $(srcdir)/Lib/__phello__/ham/__init__.py $(srcdir)/Python/frozen_modules/__phello__.ham.h + Programs/_freeze_module __phello__.ham $(srcdir)/Lib/__phello__/ham/__init__.py Python/frozen_modules/__phello__.ham.h Python/frozen_modules/__phello__.ham.eggs.h: Programs/_freeze_module Lib/__phello__/ham/eggs.py - Programs/_freeze_module __phello__.ham.eggs $(srcdir)/Lib/__phello__/ham/eggs.py $(srcdir)/Python/frozen_modules/__phello__.ham.eggs.h + Programs/_freeze_module __phello__.ham.eggs $(srcdir)/Lib/__phello__/ham/eggs.py Python/frozen_modules/__phello__.ham.eggs.h Python/frozen_modules/__phello__.spam.h: Programs/_freeze_module Lib/__phello__/spam.py - Programs/_freeze_module __phello__.spam $(srcdir)/Lib/__phello__/spam.py $(srcdir)/Python/frozen_modules/__phello__.spam.h + Programs/_freeze_module __phello__.spam $(srcdir)/Lib/__phello__/spam.py Python/frozen_modules/__phello__.spam.h Python/frozen_modules/frozen_only.h: Programs/_freeze_module Tools/freeze/flag.py - Programs/_freeze_module frozen_only $(srcdir)/Tools/freeze/flag.py $(srcdir)/Python/frozen_modules/frozen_only.h + Programs/_freeze_module frozen_only $(srcdir)/Tools/freeze/flag.py Python/frozen_modules/frozen_only.h # END: freezing modules @@ -2368,7 +2287,7 @@ clean-retain-profile: pycremoval find build -name '*.py[co]' -exec rm -f {} ';' || true -rm -f pybuilddir.txt -rm -f Lib/lib2to3/*Grammar*.pickle - -rm -f Programs/_testembed Programs/_freeze_module $(BOOTSTRAP) + -rm -f Programs/_testembed Programs/_freeze_module -rm -f Python/deepfreeze/*.[co] -find build -type f -a ! -name '*.gc??' -exec rm -f {} ';' -rm -f Include/pydtrace_probes.h diff --git a/Misc/NEWS.d/next/Build/2021-11-23-04-28-40.bpo-45873.9dldZ4.rst b/Misc/NEWS.d/next/Build/2021-11-23-04-28-40.bpo-45873.9dldZ4.rst new file mode 100644 index 0000000000000..901a3d6650b61 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-23-04-28-40.bpo-45873.9dldZ4.rst @@ -0,0 +1 @@ +Get rid of the ``_bootstrap_python`` build step. The deepfreeze.py script is now run using ``$(PYTHON_FOR_REGEN)`` which can be Python 3.7 or newer (on Windows, 3.8 or newer). \ No newline at end of file diff --git a/PCbuild/find_python.bat b/PCbuild/find_python.bat index a9f14c5277ffa..a9bbe5a6279a6 100644 --- a/PCbuild/find_python.bat +++ b/PCbuild/find_python.bat @@ -31,13 +31,13 @@ @if "%_Py_EXTERNALS_DIR%"=="" (set _Py_EXTERNALS_DIR=%~dp0\..\externals) @rem If we have Python in externals, use that one - at if exist "%_Py_EXTERNALS_DIR%\pythonx86\tools\python.exe" ("%_Py_EXTERNALS_DIR%\pythonx86\tools\python.exe" -Ec "import sys; assert sys.version_info[:2] >= (3, 10)" >nul 2>nul) && (set PYTHON="%_Py_EXTERNALS_DIR%\pythonx86\tools\python.exe") && (set _Py_Python_Source=found in externals directory) && goto :found || rmdir /Q /S "%_Py_EXTERNALS_DIR%\pythonx86" + at if exist "%_Py_EXTERNALS_DIR%\pythonx86\tools\python.exe" ("%_Py_EXTERNALS_DIR%\pythonx86\tools\python.exe" -Ec "import sys; assert sys.version_info[:2] >= (3, 8)" >nul 2>nul) && (set PYTHON="%_Py_EXTERNALS_DIR%\pythonx86\tools\python.exe") && (set _Py_Python_Source=found in externals directory) && goto :found || rmdir /Q /S "%_Py_EXTERNALS_DIR%\pythonx86" @rem If HOST_PYTHON is recent enough, use that - at if NOT "%HOST_PYTHON%"=="" @%HOST_PYTHON% -Ec "import sys; assert sys.version_info[:2] >= (3, 10)" >nul 2>nul && (set PYTHON="%HOST_PYTHON%") && (set _Py_Python_Source=found as HOST_PYTHON) && goto :found + at if NOT "%HOST_PYTHON%"=="" @%HOST_PYTHON% -Ec "import sys; assert sys.version_info[:2] >= (3, 8)" >nul 2>nul && (set PYTHON="%HOST_PYTHON%") && (set _Py_Python_Source=found as HOST_PYTHON) && goto :found @rem If py.exe finds a recent enough version, use that one - at for %%p in (3.10) do @py -%%p -EV >nul 2>&1 && (set PYTHON=py -%%p) && (set _Py_Python_Source=found %%p with py.exe) && goto :found + at for %%p in (3.10 3.9 3.8) do @py -%%p -EV >nul 2>&1 && (set PYTHON=py -%%p) && (set _Py_Python_Source=found %%p with py.exe) && goto :found @if NOT exist "%_Py_EXTERNALS_DIR%" mkdir "%_Py_EXTERNALS_DIR%" @set _Py_NUGET=%NUGET% diff --git a/Tools/scripts/deepfreeze.py b/Tools/scripts/deepfreeze.py index b6d52b7454965..b840c4b51d73a 100644 --- a/Tools/scripts/deepfreeze.py +++ b/Tools/scripts/deepfreeze.py @@ -7,7 +7,7 @@ import re import time import types -import typing +from typing import Dict, FrozenSet, Tuple, TextIO import umarshal @@ -42,13 +42,14 @@ def get_localsplus(code: types.CodeType): def get_localsplus_counts(code: types.CodeType, - names: tuple[str, ...], - kinds: bytes) -> tuple[int, int, int, int]: + names: Tuple[str, ...], + kinds: bytes) -> Tuple[int, int, int, int]: nlocals = 0 nplaincellvars = 0 ncellvars = 0 nfreevars = 0 - for name, kind in zip(names, kinds, strict=True): + assert len(names) == len(kinds) + for name, kind in zip(names, kinds): if kind & CO_FAST_LOCAL: nlocals += 1 if kind & CO_FAST_CELL: @@ -71,7 +72,7 @@ def get_localsplus_counts(code: types.CodeType, PyUnicode_4BYTE_KIND = 4 -def analyze_character_width(s: str) -> tuple[int, bool]: +def analyze_character_width(s: str) -> Tuple[int, bool]: maxchar = ' ' for c in s: maxchar = max(maxchar, c) @@ -86,12 +87,17 @@ def analyze_character_width(s: str) -> tuple[int, bool]: return kind, ascii +def removesuffix(base: str, suffix: str) -> str: + if base.endswith(suffix): + return base[:len(base) - len(suffix)] + return base + class Printer: - def __init__(self, file: typing.TextIO): + def __init__(self, file: TextIO): self.level = 0 self.file = file - self.cache: dict[tuple[type, object], str] = {} + self.cache: Dict[Tuple[type, object], str] = {} self.hits, self.misses = 0, 0 self.patchups: list[str] = [] self.write('#include "Python.h"') @@ -231,7 +237,7 @@ def generate_code(self, name: str, code: types.CodeType) -> str: # otherwise MSVC doesn't like it. self.write(f".co_consts = {co_consts},") self.write(f".co_names = {co_names},") - self.write(f".co_firstinstr = (_Py_CODEUNIT *) {co_code.removesuffix('.ob_base.ob_base')}.ob_sval,") + self.write(f".co_firstinstr = (_Py_CODEUNIT *) {removesuffix(co_code, '.ob_base.ob_base')}.ob_sval,") self.write(f".co_exceptiontable = {co_exceptiontable},") self.field(code, "co_flags") self.write(".co_warmup = QUICKENING_INITIAL_WARMUP_VALUE,") @@ -259,7 +265,7 @@ def generate_code(self, name: str, code: types.CodeType) -> str: self.write(f".co_freevars = {co_freevars},") return f"& {name}.ob_base" - def generate_tuple(self, name: str, t: tuple[object, ...]) -> str: + def generate_tuple(self, name: str, t: Tuple[object, ...]) -> str: items = [self.generate(f"{name}_{i}", it) for i, it in enumerate(t)] self.write("static") with self.indent(): @@ -323,7 +329,7 @@ def generate_complex(self, name: str, z: complex) -> str: self.write(f".cval = {{ {z.real}, {z.imag} }},") return f"&{name}.ob_base" - def generate_frozenset(self, name: str, fs: frozenset[object]) -> str: + def generate_frozenset(self, name: str, fs: FrozenSet[object]) -> str: ret = self.generate_tuple(name, tuple(sorted(fs))) self.write("// TODO: The above tuple should be a frozenset") return ret @@ -336,34 +342,33 @@ def generate(self, name: str, obj: object) -> str: # print(f"Cache hit {key!r:.40}: {self.cache[key]!r:.40}") return self.cache[key] self.misses += 1 - match obj: - case types.CodeType() | umarshal.Code() as code: - val = self.generate_code(name, code) - case tuple(t): - val = self.generate_tuple(name, t) - case str(s): - val = self.generate_unicode(name, s) - case bytes(b): - val = self.generate_bytes(name, b) - case True: - return "Py_True" - case False: - return "Py_False" - case int(i): - val = self.generate_int(name, i) - case float(x): - val = self.generate_float(name, x) - case complex() as z: - val = self.generate_complex(name, z) - case frozenset(fs): - val = self.generate_frozenset(name, fs) - case builtins.Ellipsis: - return "Py_Ellipsis" - case None: - return "Py_None" - case _: - raise TypeError( - f"Cannot generate code for {type(obj).__name__} object") + if isinstance(obj, types.CodeType) or isinstance(obj, umarshal.Code): + val = self.generate_code(name, obj) + elif isinstance(obj, tuple): + val = self.generate_tuple(name, obj) + elif isinstance(obj, str): + val = self.generate_unicode(name, obj) + elif isinstance(obj, bytes): + val = self.generate_bytes(name, obj) + elif obj is True: + return "Py_True" + elif obj is False: + return "Py_False" + elif isinstance(obj, int): + val = self.generate_int(name, obj) + elif isinstance(obj, float): + val = self.generate_float(name, obj) + elif isinstance(obj, complex): + val = self.generate_complex(name, obj) + elif isinstance(obj, frozenset): + val = self.generate_frozenset(name, obj) + elif obj is builtins.Ellipsis: + return "Py_Ellipsis" + elif obj is None: + return "Py_None" + else: + raise TypeError( + f"Cannot generate code for {type(obj).__name__} object") # print(f"Cache store {key!r:.40}: {val!r:.40}") self.cache[key] = val return val @@ -393,12 +398,12 @@ def decode_frozen_data(source: str) -> types.CodeType: del lines[0] while lines and re.match(FROZEN_DATA_LINE, lines[-1]) is None: del lines[-1] - values: tuple[int, ...] = ast.literal_eval("".join(lines)) + values: Tuple[int, ...] = ast.literal_eval("".join(lines).strip()) data = bytes(values) return umarshal.loads(data) -def generate(source: str, filename: str, modname: str, file: typing.TextIO) -> None: +def generate(source: str, filename: str, modname: str, file: TextIO) -> None: if is_frozen_header(source): code = decode_frozen_data(source) else: @@ -439,7 +444,7 @@ def main() -> None: verbose = args.verbose with open(args.file, encoding="utf-8") as f: source = f.read() - modname = args.module or os.path.basename(args.file).removesuffix(".py") + modname = args.module or removesuffix(os.path.basename(args.file), ".py") output = args.output or modname + ".c" with open(output, "w", encoding="utf-8") as file: with report_time("generate"): diff --git a/Tools/scripts/freeze_modules.py b/Tools/scripts/freeze_modules.py index 61ccae61e4f96..4281b67e27cb3 100644 --- a/Tools/scripts/freeze_modules.py +++ b/Tools/scripts/freeze_modules.py @@ -25,31 +25,6 @@ # need to be updated. MODULES_DIR = os.path.join(ROOT_DIR, 'Python', 'frozen_modules') -if sys.platform != "win32": - TOOL = os.path.join(ROOT_DIR, 'Programs', '_freeze_module') - if not os.path.isfile(TOOL): - # When building out of the source tree, get the tool from directory - # of the Python executable - TOOL = os.path.dirname(sys.executable) - TOOL = os.path.join(TOOL, 'Programs', '_freeze_module') - TOOL = os.path.abspath(TOOL) - if not os.path.isfile(TOOL): - sys.exit("ERROR: missing _freeze_module") -else: - def find_tool(): - archs = ['amd64', 'win32'] - if platform.machine() == "ARM64": - archs.append('arm64') - for arch in archs: - for exe in ['_freeze_module.exe', '_freeze_module_d.exe']: - tool = os.path.join(ROOT_DIR, 'PCbuild', arch, exe) - if os.path.isfile(tool): - return tool - sys.exit("ERROR: missing _freeze_module.exe; you need to run PCbuild/build.bat") - TOOL = find_tool() - del find_tool - -MANIFEST = os.path.join(MODULES_DIR, 'MANIFEST') FROZEN_FILE = os.path.join(ROOT_DIR, 'Python', 'frozen.c') MAKEFILE = os.path.join(ROOT_DIR, 'Makefile.pre.in') PCBUILD_PROJECT = os.path.join(ROOT_DIR, 'PCbuild', '_freeze_module.vcxproj') @@ -480,45 +455,6 @@ def replace_block(lines, start_marker, end_marker, replacements, file): return lines[:start_pos + 1] + replacements + lines[end_pos:] -def regen_manifest(modules): - header = 'module ispkg source frozen checksum'.split() - widths = [5] * len(header) - rows = [] - for mod in modules: - info = mod.summarize() - row = [] - for i, col in enumerate(header): - value = info[col] - if col == 'checksum': - value = value[:12] - elif col == 'ispkg': - value = 'YES' if value else 'no' - widths[i] = max(widths[i], len(value)) - row.append(value or '-') - rows.append(row) - - modlines = [ - '# The list of frozen modules with key information.', - '# Note that the "check_generated_files" CI job will identify', - '# when source files were changed but regen-frozen wasn\'t run.', - '# This file is auto-generated by Tools/scripts/freeze_modules.py.', - ' '.join(c.center(w) for c, w in zip(header, widths)).rstrip(), - ' '.join('-' * w for w in widths), - ] - for row in rows: - for i, w in enumerate(widths): - if header[i] == 'ispkg': - row[i] = row[i].center(w) - else: - row[i] = row[i].ljust(w) - modlines.append(' '.join(row).rstrip()) - - print(f'# Updating {os.path.relpath(MANIFEST)}') - with open(MANIFEST, 'w', encoding="utf-8") as outfile: - lines = (l + '\n' for l in modlines) - outfile.writelines(lines) - - def regen_frozen(modules): headerlines = [] parentdir = os.path.dirname(FROZEN_FILE) @@ -648,11 +584,11 @@ def regen_makefile(modules): deepfreezefiles.append(f"\t\t{ofile} \\") # Also add a deepfreeze rule. - deepfreezerules.append(f'{cfile}: $(srcdir)/{_pyfile} $(DEEPFREEZE_DEPS)') - deepfreezerules.append(f'\t at echo "Deepfreezing {cfile} from {_pyfile}"') - deepfreezerules.append(f"\t at ./$(BOOTSTRAP) \\") - deepfreezerules.append(f"\t\t$(srcdir)/Tools/scripts/deepfreeze.py \\") - deepfreezerules.append(f"\t\t$(srcdir)/{_pyfile} -m {src.frozenid} -o {cfile}") + deepfreezerules.append(f'{cfile}: {header} $(DEEPFREEZE_DEPS)') + deepfreezerules.append( + f"\t$(PYTHON_FOR_REGEN) " + f"$(srcdir)/Tools/scripts/deepfreeze.py " + f"{header} -m {src.frozenid} -o {cfile}") deepfreezerules.append('') for src in _iter_sources(modules): @@ -663,7 +599,7 @@ def regen_makefile(modules): pyfiles.append(f'\t\t{pyfile} \\') freeze = (f'Programs/_freeze_module {src.frozenid} ' - f'$(srcdir)/{pyfile} $(srcdir)/{header}') + f'$(srcdir)/{pyfile} {header}') rules.extend([ f'{header}: Programs/_freeze_module {pyfile}', f'\t{freeze}', @@ -774,32 +710,6 @@ def regen_pcbuild(modules): outfile.writelines(lines) -####################################### -# freezing modules - -def freeze_module(modname, pyfile=None, destdir=MODULES_DIR): - """Generate the frozen module .h file for the given module.""" - tmpsuffix = f'.{int(time.time())}' - for modname, pyfile, ispkg in resolve_modules(modname, pyfile): - frozenfile = resolve_frozen_file(modname, destdir) - _freeze_module(modname, pyfile, frozenfile, tmpsuffix) - - -def _freeze_module(frozenid, pyfile, frozenfile, tmpsuffix): - tmpfile = f'{frozenfile}.{int(time.time())}' - - argv = [TOOL, frozenid, pyfile, tmpfile] - print('#', ' '.join(os.path.relpath(a) for a in argv), flush=True) - try: - subprocess.run(argv, check=True) - except (FileNotFoundError, subprocess.CalledProcessError): - if not os.path.exists(TOOL): - sys.exit(f'ERROR: missing {TOOL}; you need to run "make regen-frozen"') - raise # re-raise - - update_file_with_tmpfile(frozenfile, tmpfile, create=True) - - ####################################### # the script @@ -810,15 +720,7 @@ def main(): # Regen build-related files. regen_makefile(modules) regen_pcbuild(modules) - - # Freeze the target modules. - tmpsuffix = f'.{int(time.time())}' - for src in _iter_sources(modules): - _freeze_module(src.frozenid, src.pyfile, src.frozenfile, tmpsuffix) - - # Regen files dependent of frozen file details. regen_frozen(modules) - regen_manifest(modules) if __name__ == '__main__': diff --git a/Tools/scripts/umarshal.py b/Tools/scripts/umarshal.py index e0d18c89e7531..2eaaa7ce2d95b 100644 --- a/Tools/scripts/umarshal.py +++ b/Tools/scripts/umarshal.py @@ -2,7 +2,7 @@ import ast -from typing import Any +from typing import Any, Tuple class Type: @@ -55,10 +55,10 @@ def __init__(self, **kwds: Any): def __repr__(self) -> str: return f"Code(**{self.__dict__})" - co_localsplusnames: tuple[str] - co_localspluskinds: tuple[int] + co_localsplusnames: Tuple[str] + co_localspluskinds: Tuple[int] - def get_localsplus_names(self, select_kind: int) -> tuple[str, ...]: + def get_localsplus_names(self, select_kind: int) -> Tuple[str, ...]: varnames: list[str] = [] for name, kind in zip(self.co_localsplusnames, self.co_localspluskinds): @@ -67,15 +67,15 @@ def get_localsplus_names(self, select_kind: int) -> tuple[str, ...]: return tuple(varnames) @property - def co_varnames(self) -> tuple[str, ...]: + def co_varnames(self) -> Tuple[str, ...]: return self.get_localsplus_names(CO_FAST_LOCAL) @property - def co_cellvars(self) -> tuple[str, ...]: + def co_cellvars(self) -> Tuple[str, ...]: return self.get_localsplus_names(CO_FAST_CELL) @property - def co_freevars(self) -> tuple[str, ...]: + def co_freevars(self) -> Tuple[str, ...]: return self.get_localsplus_names(CO_FAST_FREE) @property @@ -190,118 +190,117 @@ def R_REF(obj: Any) -> Any: obj = self.r_ref(obj, flag) return obj - match type: - case Type.NULL: - return NULL - case Type.NONE: - return None - case Type.ELLIPSIS: - return Ellipsis - case Type.FALSE: - return False - case Type.TRUE: - return True - case Type.INT: - return R_REF(self.r_long()) - case Type.INT64: - return R_REF(self.r_long64()) - case Type.LONG: - return R_REF(self.r_PyLong()) - case Type.FLOAT: - return R_REF(self.r_float_str()) - case Type.BINARY_FLOAT: - return R_REF(self.r_float_bin()) - case Type.COMPLEX: - return R_REF(complex(self.r_float_str(), - self.r_float_str())) - case Type.BINARY_COMPLEX: - return R_REF(complex(self.r_float_bin(), - self.r_float_bin())) - case Type.STRING: - n = self.r_long() - return R_REF(self.r_string(n)) - case Type.ASCII_INTERNED | Type.ASCII: - n = self.r_long() - return R_REF(self.r_string(n).decode("ascii")) - case Type.SHORT_ASCII_INTERNED | Type.SHORT_ASCII: - n = self.r_byte() - return R_REF(self.r_string(n).decode("ascii")) - case Type.INTERNED | Type.UNICODE: - n = self.r_long() - return R_REF(self.r_string(n).decode("utf8", "surrogatepass")) - case Type.SMALL_TUPLE: - n = self.r_byte() - idx = self.r_ref_reserve(flag) - retval: Any = tuple(self.r_object() for _ in range(n)) - self.r_ref_insert(retval, idx, flag) - return retval - case Type.TUPLE: - n = self.r_long() - idx = self.r_ref_reserve(flag) - retval = tuple(self.r_object() for _ in range(n)) - self.r_ref_insert(retval, idx, flag) - return retval - case Type.LIST: - n = self.r_long() - retval = R_REF([]) - for _ in range(n): - retval.append(self.r_object()) - return retval - case Type.DICT: - retval = R_REF({}) - while True: - key = self.r_object() - if key == NULL: - break - val = self.r_object() - retval[key] = val - return retval - case Type.SET: - n = self.r_long() - retval = R_REF(set()) - for _ in range(n): - v = self.r_object() - retval.add(v) - return retval - case Type.FROZENSET: - n = self.r_long() - s: set[Any] = set() - idx = self.r_ref_reserve(flag) - for _ in range(n): - v = self.r_object() - s.add(v) - retval = frozenset(s) - self.r_ref_insert(retval, idx, flag) - return retval - case Type.CODE: - retval = R_REF(Code()) - retval.co_argcount = self.r_long() - retval.co_posonlyargcount = self.r_long() - retval.co_kwonlyargcount = self.r_long() - retval.co_stacksize = self.r_long() - retval.co_flags = self.r_long() - retval.co_code = self.r_object() - retval.co_consts = self.r_object() - retval.co_names = self.r_object() - retval.co_localsplusnames = self.r_object() - retval.co_localspluskinds = self.r_object() - retval.co_filename = self.r_object() - retval.co_name = self.r_object() - retval.co_qualname = self.r_object() - retval.co_firstlineno = self.r_long() - retval.co_linetable = self.r_object() - retval.co_endlinetable = self.r_object() - retval.co_columntable = self.r_object() - retval.co_exceptiontable = self.r_object() - return retval - case Type.REF: - n = self.r_long() - retval = self.refs[n] - assert retval is not None - return retval - case _: - breakpoint() - raise AssertionError(f"Unknown type {type} {chr(type)!r}") + if type == Type.NULL: + return NULL + elif type == Type.NONE: + return None + elif type == Type.ELLIPSIS: + return Ellipsis + elif type == Type.FALSE: + return False + elif type == Type.TRUE: + return True + elif type == Type.INT: + return R_REF(self.r_long()) + elif type == Type.INT64: + return R_REF(self.r_long64()) + elif type == Type.LONG: + return R_REF(self.r_PyLong()) + elif type == Type.FLOAT: + return R_REF(self.r_float_str()) + elif type == Type.BINARY_FLOAT: + return R_REF(self.r_float_bin()) + elif type == Type.COMPLEX: + return R_REF(complex(self.r_float_str(), + self.r_float_str())) + elif type == Type.BINARY_COMPLEX: + return R_REF(complex(self.r_float_bin(), + self.r_float_bin())) + elif type == Type.STRING: + n = self.r_long() + return R_REF(self.r_string(n)) + elif type == Type.ASCII_INTERNED or type == Type.ASCII: + n = self.r_long() + return R_REF(self.r_string(n).decode("ascii")) + elif type == Type.SHORT_ASCII_INTERNED or type == Type.SHORT_ASCII: + n = self.r_byte() + return R_REF(self.r_string(n).decode("ascii")) + elif type == Type.INTERNED or type == Type.UNICODE: + n = self.r_long() + return R_REF(self.r_string(n).decode("utf8", "surrogatepass")) + elif type == Type.SMALL_TUPLE: + n = self.r_byte() + idx = self.r_ref_reserve(flag) + retval: Any = tuple(self.r_object() for _ in range(n)) + self.r_ref_insert(retval, idx, flag) + return retval + elif type == Type.TUPLE: + n = self.r_long() + idx = self.r_ref_reserve(flag) + retval = tuple(self.r_object() for _ in range(n)) + self.r_ref_insert(retval, idx, flag) + return retval + elif type == Type.LIST: + n = self.r_long() + retval = R_REF([]) + for _ in range(n): + retval.append(self.r_object()) + return retval + elif type == Type.DICT: + retval = R_REF({}) + while True: + key = self.r_object() + if key == NULL: + break + val = self.r_object() + retval[key] = val + return retval + elif type == Type.SET: + n = self.r_long() + retval = R_REF(set()) + for _ in range(n): + v = self.r_object() + retval.add(v) + return retval + elif type == Type.FROZENSET: + n = self.r_long() + s: set[Any] = set() + idx = self.r_ref_reserve(flag) + for _ in range(n): + v = self.r_object() + s.add(v) + retval = frozenset(s) + self.r_ref_insert(retval, idx, flag) + return retval + elif type == Type.CODE: + retval = R_REF(Code()) + retval.co_argcount = self.r_long() + retval.co_posonlyargcount = self.r_long() + retval.co_kwonlyargcount = self.r_long() + retval.co_stacksize = self.r_long() + retval.co_flags = self.r_long() + retval.co_code = self.r_object() + retval.co_consts = self.r_object() + retval.co_names = self.r_object() + retval.co_localsplusnames = self.r_object() + retval.co_localspluskinds = self.r_object() + retval.co_filename = self.r_object() + retval.co_name = self.r_object() + retval.co_qualname = self.r_object() + retval.co_firstlineno = self.r_long() + retval.co_linetable = self.r_object() + retval.co_endlinetable = self.r_object() + retval.co_columntable = self.r_object() + retval.co_exceptiontable = self.r_object() + return retval + elif type == Type.REF: + n = self.r_long() + retval = self.refs[n] + assert retval is not None + return retval + else: + breakpoint() + raise AssertionError(f"Unknown type {type} {chr(type)!r}") def loads(data: bytes) -> Any: diff --git a/configure b/configure index 148ef58b6a5b8..0684921f41a42 100755 --- a/configure +++ b/configure @@ -19441,6 +19441,7 @@ SRCDIRS="\ Parser \ Programs \ Python \ + Python/frozen_modules \ Python/deepfreeze" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for build directories" >&5 $as_echo_n "checking for build directories... " >&6; } diff --git a/configure.ac b/configure.ac index a950cc91d657b..ba22418b40694 100644 --- a/configure.ac +++ b/configure.ac @@ -5613,6 +5613,7 @@ SRCDIRS="\ Parser \ Programs \ Python \ + Python/frozen_modules \ Python/deepfreeze" AC_MSG_CHECKING(for build directories) for dir in $SRCDIRS; do From webhook-mailer at python.org Tue Nov 23 12:59:09 2021 From: webhook-mailer at python.org (vstinner) Date: Tue, 23 Nov 2021 17:59:09 -0000 Subject: [Python-checkins] bpo-39026: Fix Python.h when building with Xcode (GH-29488) Message-ID: https://github.com/python/cpython/commit/4ae26b9c1d0c33e3db92c6f305293f9240dea358 commit: 4ae26b9c1d0c33e3db92c6f305293f9240dea358 branch: main author: Victor Stinner committer: vstinner date: 2021-11-23T18:58:57+01:00 summary: bpo-39026: Fix Python.h when building with Xcode (GH-29488) Fix Python.h to build C extensions with Xcode: remove a relative include from Include/cpython/pystate.h. files: A Misc/NEWS.d/next/C API/2021-11-09-15-42-11.bpo-39026.sUnYWn.rst M Include/Python.h M Include/cpython/pystate.h diff --git a/Include/Python.h b/Include/Python.h index 6e3303ac9a3b0..7260ae5cd0b4f 100644 --- a/Include/Python.h +++ b/Include/Python.h @@ -72,6 +72,7 @@ #include "sliceobject.h" #include "cpython/cellobject.h" #include "iterobject.h" +#include "cpython/initconfig.h" #include "pystate.h" #include "cpython/genobject.h" #include "descrobject.h" @@ -83,7 +84,6 @@ #include "cpython/pytime.h" #include "codecs.h" #include "pyerrors.h" -#include "cpython/initconfig.h" #include "pythread.h" #include "cpython/context.h" #include "modsupport.h" diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index 9ac0a298baab4..5adbf3b495316 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -2,8 +2,6 @@ # error "this header file must not be included directly" #endif -#include "cpython/initconfig.h" - PyAPI_FUNC(int) _PyInterpreterState_RequiresIDRef(PyInterpreterState *); PyAPI_FUNC(void) _PyInterpreterState_RequireIDRef(PyInterpreterState *, int); diff --git a/Misc/NEWS.d/next/C API/2021-11-09-15-42-11.bpo-39026.sUnYWn.rst b/Misc/NEWS.d/next/C API/2021-11-09-15-42-11.bpo-39026.sUnYWn.rst new file mode 100644 index 0000000000000..77a0119792152 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2021-11-09-15-42-11.bpo-39026.sUnYWn.rst @@ -0,0 +1,2 @@ +Fix Python.h to build C extensions with Xcode: remove a relative include +from ``Include/cpython/pystate.h``. From webhook-mailer at python.org Tue Nov 23 15:36:52 2021 From: webhook-mailer at python.org (tiran) Date: Tue, 23 Nov 2021 20:36:52 -0000 Subject: [Python-checkins] bpo-45873: Restore Python 3.6 compatibility (GH-29730) Message-ID: https://github.com/python/cpython/commit/f840398a5fd8741653c26eb8641c48656c9800d4 commit: f840398a5fd8741653c26eb8641c48656c9800d4 branch: main author: Christian Heimes committer: tiran date: 2021-11-23T21:36:40+01:00 summary: bpo-45873: Restore Python 3.6 compatibility (GH-29730) Co-authored-by: Guido van Rossum files: M Tools/scripts/deepfreeze.py M configure M configure.ac diff --git a/Tools/scripts/deepfreeze.py b/Tools/scripts/deepfreeze.py index b840c4b51d73a..e51a408ae7f6a 100644 --- a/Tools/scripts/deepfreeze.py +++ b/Tools/scripts/deepfreeze.py @@ -5,8 +5,10 @@ import contextlib import os import re +import sys import time import types +import unicodedata from typing import Dict, FrozenSet, Tuple, TextIO import umarshal @@ -14,9 +16,13 @@ verbose = False +def isprintable(b: bytes) -> bool: + return all(0x20 <= c < 0x7f for c in b) + + def make_string_literal(b: bytes) -> str: res = ['"'] - if b.isascii() and b.decode("ascii").isprintable(): + if isprintable(b): res.append(b.decode("ascii").replace("\\", "\\\\").replace("\"", "\\\"")) else: for i in b: diff --git a/configure b/configure index 0684921f41a42..711b6d2805f16 100755 --- a/configure +++ b/configure @@ -3142,7 +3142,7 @@ case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac # pybuilddir.txt will be created by --generate-posix-vars in the Makefile rm -f pybuilddir.txt -for ac_prog in python$PACKAGE_VERSION python3 python +for ac_prog in python$PACKAGE_VERSION python3.10 python3.9 python3.8 python3.7 python3.6 python3 python do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 @@ -3187,6 +3187,16 @@ test -n "$PYTHON_FOR_REGEN" || PYTHON_FOR_REGEN="python3" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking Python for regen version" >&5 +$as_echo_n "checking Python for regen version... " >&6; } +if command -v $PYTHON_FOR_REGEN >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $($PYTHON_FOR_REGEN -V 2>/dev/null)" >&5 +$as_echo "$($PYTHON_FOR_REGEN -V 2>/dev/null)" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: missing" >&5 +$as_echo "missing" >&6; } +fi + if test "$cross_compiling" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for python interpreter for cross build" >&5 $as_echo_n "checking for python interpreter for cross build... " >&6; } diff --git a/configure.ac b/configure.ac index ba22418b40694..e539d3bb87d66 100644 --- a/configure.ac +++ b/configure.ac @@ -96,9 +96,18 @@ AC_SUBST(host) # pybuilddir.txt will be created by --generate-posix-vars in the Makefile rm -f pybuilddir.txt -AC_CHECK_PROGS(PYTHON_FOR_REGEN, python$PACKAGE_VERSION python3 python, python3) +AC_CHECK_PROGS([PYTHON_FOR_REGEN], + [python$PACKAGE_VERSION python3.10 python3.9 python3.8 python3.7 python3.6 python3 python], + [python3]) AC_SUBST(PYTHON_FOR_REGEN) +AC_MSG_CHECKING([Python for regen version]) +if command -v $PYTHON_FOR_REGEN >/dev/null 2>&1; then + AC_MSG_RESULT([$($PYTHON_FOR_REGEN -V 2>/dev/null)]) +else + AC_MSG_RESULT([missing]) +fi + if test "$cross_compiling" = yes; then AC_MSG_CHECKING([for python interpreter for cross build]) if test -z "$PYTHON_FOR_BUILD"; then From webhook-mailer at python.org Tue Nov 23 16:27:00 2021 From: webhook-mailer at python.org (tiran) Date: Tue, 23 Nov 2021 21:27:00 -0000 Subject: [Python-checkins] bpo-45847: Port _crypt to PY_STDLIB_MOD (GH-29725) Message-ID: https://github.com/python/cpython/commit/095bc8f0d6845dded8f67fbc6eca20dfac8b3929 commit: 095bc8f0d6845dded8f67fbc6eca20dfac8b3929 branch: main author: Christian Heimes committer: tiran date: 2021-11-23T22:26:50+01:00 summary: bpo-45847: Port _crypt to PY_STDLIB_MOD (GH-29725) files: M Modules/Setup.stdlib.in M configure M configure.ac M setup.py diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 338de84f09ebc..7422ddb59e309 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -98,6 +98,8 @@ # Modules with some UNIX dependencies # +# needs -lcrypt on some systems + at MODULE__CRYPT_TRUE@_crypt _cryptmodule.c @MODULE_FCNTL_TRUE at fcntl fcntlmodule.c @MODULE_GRP_TRUE at grp grpmodule.c @MODULE_MMAP_TRUE at mmap mmapmodule.c diff --git a/configure b/configure index 711b6d2805f16..01aa80091cd49 100755 --- a/configure +++ b/configure @@ -656,6 +656,8 @@ MODULE_NIS_FALSE MODULE_NIS_TRUE MODULE__DECIMAL_FALSE MODULE__DECIMAL_TRUE +MODULE__CRYPT_FALSE +MODULE__CRYPT_TRUE MODULE__BLAKE2_FALSE MODULE__BLAKE2_TRUE MODULE__SHA3_FALSE @@ -784,6 +786,8 @@ HAVE_GETHOSTBYNAME_R HAVE_GETHOSTBYNAME_R_3_ARG HAVE_GETHOSTBYNAME_R_5_ARG HAVE_GETHOSTBYNAME_R_6_ARG +LIBCRYPT_LIBS +LIBCRYPT_CFLAGS LIBOBJS LIBLZMA_LIBS LIBLZMA_CFLAGS @@ -1041,7 +1045,9 @@ ZLIB_LIBS BZIP2_CFLAGS BZIP2_LIBS LIBLZMA_CFLAGS -LIBLZMA_LIBS' +LIBLZMA_LIBS +LIBCRYPT_CFLAGS +LIBCRYPT_LIBS' # Initialize some variables set by options. @@ -1831,6 +1837,10 @@ Some influential environment variables: C compiler flags for LIBLZMA, overriding pkg-config LIBLZMA_LIBS linker flags for LIBLZMA, overriding pkg-config + LIBCRYPT_CFLAGS + C compiler flags for LIBCRYPT, overriding pkg-config + LIBCRYPT_LIBS + linker flags for LIBCRYPT, overriding pkg-config Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. @@ -15251,11 +15261,75 @@ fi done -# We search for both crypt and crypt_r as one or the other may be defined -# This gets us our -lcrypt in LIBS when required on the target platform. -# Save/restore LIBS to avoid linking libpython with libcrypt. -LIBS_SAVE=$LIBS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing crypt_r" >&5 + + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBCRYPT" >&5 +$as_echo_n "checking for LIBCRYPT... " >&6; } + +if test -n "$LIBCRYPT_CFLAGS"; then + pkg_cv_LIBCRYPT_CFLAGS="$LIBCRYPT_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libxcrypt >= 3.1.1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libxcrypt >= 3.1.1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBCRYPT_CFLAGS=`$PKG_CONFIG --cflags "libxcrypt >= 3.1.1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LIBCRYPT_LIBS"; then + pkg_cv_LIBCRYPT_LIBS="$LIBCRYPT_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libxcrypt >= 3.1.1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libxcrypt >= 3.1.1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBCRYPT_LIBS=`$PKG_CONFIG --libs "libxcrypt >= 3.1.1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LIBCRYPT_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libxcrypt >= 3.1.1" 2>&1` + else + LIBCRYPT_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libxcrypt >= 3.1.1" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LIBCRYPT_PKG_ERRORS" >&5 + + + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing crypt_r" >&5 $as_echo_n "checking for library containing crypt_r... " >&6; } if ${ac_cv_search_crypt_r+:} false; then : $as_echo_n "(cached) " >&6 @@ -15309,12 +15383,37 @@ ac_res=$ac_cv_search_crypt_r if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + $as_echo "#define HAVE_CRYPT_R 1" >>confdefs.h + + if test "$ac_cv_search_crypt_r" = "none required"; then + LIBCRYPT_LIBS= + else + LIBCRYPT_LIBS="$ac_cv_search_crypt_r" + fi + fi -LIBS="$LIBS_SAVE" -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing crypt" >&5 -$as_echo_n "checking for library containing crypt... " >&6; } -if ${ac_cv_search_crypt+:} false; then : + +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS + + + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing crypt_r" >&5 +$as_echo_n "checking for library containing crypt_r... " >&6; } +if ${ac_cv_search_crypt_r+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS @@ -15327,11 +15426,11 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext #ifdef __cplusplus extern "C" #endif -char crypt (); +char crypt_r (); int main () { -return crypt (); +return crypt_r (); ; return 0; } @@ -15344,59 +15443,112 @@ for ac_lib in '' crypt; do LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_crypt=$ac_res + ac_cv_search_crypt_r=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext - if ${ac_cv_search_crypt+:} false; then : + if ${ac_cv_search_crypt_r+:} false; then : break fi done -if ${ac_cv_search_crypt+:} false; then : +if ${ac_cv_search_crypt_r+:} false; then : else - ac_cv_search_crypt=no + ac_cv_search_crypt_r=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_crypt" >&5 -$as_echo "$ac_cv_search_crypt" >&6; } -ac_res=$ac_cv_search_crypt +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_crypt_r" >&5 +$as_echo "$ac_cv_search_crypt_r" >&6; } +ac_res=$ac_cv_search_crypt_r if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + $as_echo "#define HAVE_CRYPT_R 1" >>confdefs.h + + if test "$ac_cv_search_crypt_r" = "none required"; then + LIBCRYPT_LIBS= + else + LIBCRYPT_LIBS="$ac_cv_search_crypt_r" + fi + fi -ac_fn_c_check_func "$LINENO" "crypt_r" "ac_cv_func_crypt_r" -if test "x$ac_cv_func_crypt_r" = xyes; then : - cat confdefs.h - <<_ACEOF >conftest.$ac_ext +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS + + + +else + LIBCRYPT_CFLAGS=$pkg_cv_LIBCRYPT_CFLAGS + LIBCRYPT_LIBS=$pkg_cv_LIBCRYPT_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + $as_echo "#define HAVE_CRYPT_R 1" >>confdefs.h + + +fi + +save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + CPPFLAGS="$LIBCRYPT_CFLAGS $CFLAGS" + LDFLAGS="$LIBCRYPT_LIBS $LDFLAGS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for crypt or crypt_r" >&5 +$as_echo_n "checking for crypt or crypt_r... " >&6; } +if ${ac_cv_crypt_crypt+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include + #ifdef HAVE_CRYPT_H + #include + #endif + #include int main () { -struct crypt_data d; -char *r = crypt_r("", "", &d); + #ifdef HAVE_CRYPT_R + void *x = crypt_r; + #else + void *x = crypt; + #endif ; return 0; } -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - -$as_echo "#define HAVE_CRYPT_R 1" >>confdefs.h +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_crypt_crypt=yes +else + ac_cv_crypt_crypt=no fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_crypt_crypt" >&5 +$as_echo "$ac_cv_crypt_crypt" >&6; } + +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS + -LIBS=$LIBS_SAVE for ac_func in clock_gettime do : @@ -21381,6 +21533,42 @@ $as_echo "$py_cv_module__blake2" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _crypt" >&5 +$as_echo_n "checking for stdlib extension module _crypt... " >&6; } + case $py_stdlib_not_available in #( + *_crypt*) : + py_cv_module__crypt=n/a ;; #( + *) : + if true; then : + if test "$ac_cv_crypt_crypt" = yes; then : + py_cv_module__crypt=yes +else + py_cv_module__crypt=missing +fi +else + py_cv_module__crypt=disabled +fi + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__CRYPT=$py_cv_module__crypt$as_nl" + if test "x$py_cv_module__crypt" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE__CRYPT_CFLAGS=$LIBCRYPT_CFLAGS$as_nl" + as_fn_append MODULE_BLOCK "MODULE__CRYPT_LDFLAGS=$LIBCRYPT_LIBS$as_nl" + +fi + if test "$py_cv_module__crypt" = yes; then + MODULE__CRYPT_TRUE= + MODULE__CRYPT_FALSE='#' +else + MODULE__CRYPT_TRUE='#' + MODULE__CRYPT_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__crypt" >&5 +$as_echo "$py_cv_module__crypt" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _decimal" >&5 $as_echo_n "checking for stdlib extension module _decimal... " >&6; } case $py_stdlib_not_available in #( @@ -22261,6 +22449,10 @@ if test -z "${MODULE__BLAKE2_TRUE}" && test -z "${MODULE__BLAKE2_FALSE}"; then as_fn_error $? "conditional \"MODULE__BLAKE2\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__CRYPT_TRUE}" && test -z "${MODULE__CRYPT_FALSE}"; then + as_fn_error $? "conditional \"MODULE__CRYPT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__DECIMAL_TRUE}" && test -z "${MODULE__DECIMAL_FALSE}"; then as_fn_error $? "conditional \"MODULE__DECIMAL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index e539d3bb87d66..0008e8a746c7b 100644 --- a/configure.ac +++ b/configure.ac @@ -4190,25 +4190,46 @@ AC_CHECK_FUNCS(setpgrp, []) ) -# We search for both crypt and crypt_r as one or the other may be defined -# This gets us our -lcrypt in LIBS when required on the target platform. -# Save/restore LIBS to avoid linking libpython with libcrypt. -LIBS_SAVE=$LIBS -AC_SEARCH_LIBS(crypt_r, crypt) -LIBS="$LIBS_SAVE" -AC_SEARCH_LIBS(crypt, crypt) +dnl We search for both crypt and crypt_r as one or the other may be defined +dnl libxcrypt provides and libcrypt with crypt_r() since +dnl at least 3.1.1 from 2015. +dnl FreeBSD defines crypt_r() in +AH_TEMPLATE([HAVE_CRYPT_R], [Define if you have the crypt_r() function.]) + +PKG_CHECK_MODULES([LIBCRYPT], [libxcrypt >= 3.1.1], [ + AC_DEFINE([HAVE_CRYPT_R], [1]) +], [ + WITH_SAVE_ENV([ + AC_SEARCH_LIBS([crypt_r], [crypt], [ + AC_DEFINE([HAVE_CRYPT_R], [1]) + if test "$ac_cv_search_crypt_r" = "none required"; then + LIBCRYPT_LIBS= + else + LIBCRYPT_LIBS="$ac_cv_search_crypt_r" + fi + ]) + ]) +]) -AC_CHECK_FUNC(crypt_r, - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#include -]], [[ -struct crypt_data d; -char *r = crypt_r("", "", &d); -]])], - [AC_DEFINE(HAVE_CRYPT_R, 1, [Define if you have the crypt_r() function.])], - []) -) -LIBS=$LIBS_SAVE +WITH_SAVE_ENV([ + CPPFLAGS="$LIBCRYPT_CFLAGS $CFLAGS" + LDFLAGS="$LIBCRYPT_LIBS $LDFLAGS" + AC_CACHE_CHECK([for crypt or crypt_r], [ac_cv_crypt_crypt], [ + AC_LINK_IFELSE([AC_LANG_PROGRAM([ + #ifdef HAVE_CRYPT_H + #include + #endif + #include + ], [ + #ifdef HAVE_CRYPT_R + void *x = crypt_r; + #else + void *x = crypt; + #endif + ]) + ], [ac_cv_crypt_crypt=yes], [ac_cv_crypt_crypt=no]) + ]) +]) AC_CHECK_FUNCS(clock_gettime, [], [ AC_CHECK_LIB(rt, clock_gettime, [ @@ -6202,6 +6223,9 @@ PY_STDLIB_MOD([_sha512], [test "$with_builtin_sha512" = yes]) PY_STDLIB_MOD([_sha3], [test "$with_builtin_sha3" = yes]) PY_STDLIB_MOD([_blake2], [test "$with_builtin_blake2" = yes]) +PY_STDLIB_MOD([_crypt], + [], [test "$ac_cv_crypt_crypt" = yes], + [$LIBCRYPT_CFLAGS], [$LIBCRYPT_LIBS]) PY_STDLIB_MOD([_decimal], [], [], [$LIBMPDEC_CFLAGS], [$LIBMPDEC_LDFLAGS]) PY_STDLIB_MOD([nis], [], [test "$have_nis" = yes -a "$ac_cv_header_rpc_rpc_h" = yes], diff --git a/setup.py b/setup.py index 304168a657c85..721103e7fceb7 100644 --- a/setup.py +++ b/setup.py @@ -1241,20 +1241,7 @@ def detect_readline_curses(self): self.missing.append('_curses_panel') def detect_crypt(self): - # crypt module. - if VXWORKS: - # bpo-31904: crypt() function is not provided by VxWorks. - # DES_crypt() OpenSSL provides is too weak to implement - # the encryption. - self.missing.append('_crypt') - return - - if self.compiler.find_library_file(self.lib_dirs, 'crypt'): - libs = ['crypt'] - else: - libs = [] - - self.add(Extension('_crypt', ['_cryptmodule.c'], libraries=libs)) + self.addext(Extension('_crypt', ['_cryptmodule.c'])) def detect_dbm_gdbm(self): # Modules that provide persistent dictionary-like semantics. You will From webhook-mailer at python.org Tue Nov 23 16:58:23 2021 From: webhook-mailer at python.org (tiran) Date: Tue, 23 Nov 2021 21:58:23 -0000 Subject: [Python-checkins] bpo-45847: Port _ssl and _hashlib to PY_STDLIB_MOD (GH-29727) Message-ID: https://github.com/python/cpython/commit/b9e9292d75fdea621e05e39b8629e6935d282d0d commit: b9e9292d75fdea621e05e39b8629e6935d282d0d branch: main author: Christian Heimes committer: tiran date: 2021-11-23T22:58:13+01:00 summary: bpo-45847: Port _ssl and _hashlib to PY_STDLIB_MOD (GH-29727) files: M Modules/Setup.stdlib.in M configure M configure.ac M setup.py diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 7422ddb59e309..9f66d531fef0f 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -123,6 +123,11 @@ # @MODULE__SQLITE3_TRUE at _sqlite3 _sqlite/connection.c _sqlite/cursor.c _sqlite/microprotocols.c _sqlite/module.c _sqlite/prepare_protocol.c _sqlite/row.c _sqlite/statement.c _sqlite/util.c +# needs -lssl and -lcrypt + at MODULE__SSL_TRUE@_ssl _ssl.c +# needs -lcrypt + at MODULE__HASHLIB_TRUE@_hashlib _hashopenssl.c + ############################################################################ # macOS specific modules diff --git a/configure b/configure index 01aa80091cd49..ac0a1f320b2a7 100755 --- a/configure +++ b/configure @@ -642,6 +642,10 @@ MODULE__TESTINTERNALCAPI_FALSE MODULE__TESTINTERNALCAPI_TRUE MODULE__TESTCAPI_FALSE MODULE__TESTCAPI_TRUE +MODULE__HASHLIB_FALSE +MODULE__HASHLIB_TRUE +MODULE__SSL_FALSE +MODULE__SSL_TRUE MODULE__LZMA_FALSE MODULE__LZMA_TRUE MODULE__BZ2_FALSE @@ -20297,6 +20301,16 @@ rm -f core conftest.err conftest.$ac_objext \ # rpath to libssl and libcrypto +if test "x$GNULD" = xyes; then : + + rpath_arg="-Wl,--enable-new-dtags,-rpath=" + +else + + rpath_arg="-Wl,-rpath=" + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-openssl-rpath" >&5 $as_echo_n "checking for --with-openssl-rpath... " >&6; } @@ -20310,12 +20324,26 @@ fi case $with_openssl_rpath in #( auto|yes) : - OPENSSL_RPATH=auto ;; #( + + OPENSSL_RPATH=auto + for arg in "$OPENSSL_LDFLAGS"; do + case $arg in #( + -L*) : + OPENSSL_LDFLAGS_RPATH="$OPENSSL_LDFLAGS_RPATH ${rpath_arg}$(echo $arg | cut -c3-)" + ;; #( + *) : + ;; +esac + done + ;; #( no) : OPENSSL_RPATH= ;; #( *) : if test -d "$with_openssl_rpath"; then : - OPENSSL_RPATH="$with_openssl_rpath" + + OPENSSL_RPATH="$with_openssl_rpath" + OPENSSL_LDFLAGS_RPATH="${rpath_arg}$with_openssl_rpath" + else as_fn_error $? "--with-openssl-rpath \"$with_openssl_rpath\" is not a directory" "$LINENO" 5 fi @@ -20326,71 +20354,163 @@ esac $as_echo "$OPENSSL_RPATH" >&6; } +# This static linking is NOT OFFICIALLY SUPPORTED and not advertised. +# Requires static OpenSSL build with position-independent code. Some features +# like DSO engines or external OSSL providers don't work. Only tested with GCC +# and clang on X86_64. +if test "x$PY_UNSUPPORTED_OPENSSL_BUILD" = xstatic; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for unsupported static openssl build" >&5 +$as_echo_n "checking for unsupported static openssl build... " >&6; } + new_OPENSSL_LIBS= + for arg in $OPENSSL_LIBS; do + case $arg in #( + -l*) : + + libname=$(echo $arg | cut -c3-) + new_OPENSSL_LIBS="$new_OPENSSL_LIBS -l:lib${libname}.a -Wl,--exclude-libs,lib${libname}.a" + ;; #( + *) : + new_OPENSSL_LIBS="$new_OPENSSL_LIBS $arg" + ;; +esac + done + OPENSSL_LIBS="$new_OPENSSL_LIBS $ZLIB_LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OPENSSL_LIBS" >&5 +$as_echo "$OPENSSL_LIBS" >&6; } + +fi + +LIBCRYPTO_LIBS= +for arg in $OPENSSL_LIBS; do + case $arg in #( + -l*ssl*|-Wl*ssl*) : + ;; #( + *) : + LIBCRYPTO_LIBS="$LIBCRYPTO_LIBS $arg" + ;; +esac +done + # check if OpenSSL libraries work as expected -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL provides required APIs" >&5 -$as_echo_n "checking whether OpenSSL provides required APIs... " >&6; } -if ${ac_cv_working_openssl+:} false; then : +save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + LIBS="$LIBS $OPENSSL_LIBS" + CFLAGS="$CFLAGS $OPENSSL_INCLUDES" + LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL provides required ssl module APIs" >&5 +$as_echo_n "checking whether OpenSSL provides required ssl module APIs... " >&6; } +if ${ac_cv_working_openssl_ssl+:} false; then : $as_echo_n "(cached) " >&6 else -save_LIBS="$LIBS" -save_CFLAGS="$CFLAGS" -save_LDFLAGS="$LDFLAGS" -LIBS="$LIBS $OPENSSL_LIBS" -CFLAGS="$CFLAGS_NODIST $OPENSSL_INCLUDES" -LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS" - -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include -#include -#include + #include + #include + #if OPENSSL_VERSION_NUMBER < 0x10101000L + #error "OpenSSL >= 1.1.1 is required" + #endif + static void keylog_cb(const SSL *ssl, const char *line) {} -#if OPENSSL_VERSION_NUMBER < 0x10101000L -#error "OpenSSL >= 1.1.1 is required" -#endif +int +main () +{ + + SSL_CTX *ctx = SSL_CTX_new(TLS_client_method()); + SSL_CTX_set_keylog_callback(ctx, keylog_cb); + SSL *ssl = SSL_new(ctx); + X509_VERIFY_PARAM *param = SSL_get0_param(ssl); + X509_VERIFY_PARAM_set1_host(param, "python.org", 0); + SSL_free(ssl); + SSL_CTX_free(ctx); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_working_openssl_ssl=yes +else + ac_cv_working_openssl_ssl=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_openssl_ssl" >&5 +$as_echo "$ac_cv_working_openssl_ssl" >&6; } + +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS + + + +save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + LIBS="$LIBS $LIBCRYPTO_LIBS" + CFLAGS="$CFLAGS $OPENSSL_INCLUDES" + LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL provides required hashlib module APIs" >&5 +$as_echo_n "checking whether OpenSSL provides required hashlib module APIs... " >&6; } +if ${ac_cv_working_openssl_hashlib+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ -static void keylog_cb(const SSL *ssl, const char *line) {} + #include + #include + #if OPENSSL_VERSION_NUMBER < 0x10101000L + #error "OpenSSL >= 1.1.1 is required" + #endif int main () { -/* SSL APIs */ -SSL_CTX *ctx = SSL_CTX_new(TLS_client_method()); -SSL_CTX_set_keylog_callback(ctx, keylog_cb); -SSL *ssl = SSL_new(ctx); -X509_VERIFY_PARAM *param = SSL_get0_param(ssl); -X509_VERIFY_PARAM_set1_host(param, "python.org", 0); -SSL_free(ssl); -SSL_CTX_free(ctx); - -/* hashlib APIs */ -OBJ_nid2sn(NID_md5); -OBJ_nid2sn(NID_sha1); -OBJ_nid2sn(NID_sha3_512); -OBJ_nid2sn(NID_blake2b512); -EVP_PBE_scrypt(NULL, 0, NULL, 0, 2, 8, 1, 0, NULL, 0); + OBJ_nid2sn(NID_md5); + OBJ_nid2sn(NID_sha1); + OBJ_nid2sn(NID_sha3_512); + OBJ_nid2sn(NID_blake2b512); + EVP_PBE_scrypt(NULL, 0, NULL, 0, 2, 8, 1, 0, NULL, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ac_cv_working_openssl=yes + ac_cv_working_openssl_hashlib=yes else - ac_cv_working_openssl=no + ac_cv_working_openssl_hashlib=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -LIBS="$save_LIBS" -CFLAGS="$save_CFLAGS" -LDFLAGS="$save_LDFLAGS" fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_openssl" >&5 -$as_echo "$ac_cv_working_openssl" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_openssl_hashlib" >&5 +$as_echo "$ac_cv_working_openssl_hashlib" >&6; } + +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS + + # ssl module default cipher suite string @@ -21800,6 +21920,79 @@ $as_echo "$py_cv_module__lzma" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _ssl" >&5 +$as_echo_n "checking for stdlib extension module _ssl... " >&6; } + case $py_stdlib_not_available in #( + *_ssl*) : + py_cv_module__ssl=n/a ;; #( + *) : + if true; then : + if test "$ac_cv_working_openssl_ssl" = yes; then : + py_cv_module__ssl=yes +else + py_cv_module__ssl=missing +fi +else + py_cv_module__ssl=disabled +fi + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__SSL=$py_cv_module__ssl$as_nl" + if test "x$py_cv_module__ssl" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE__SSL_CFLAGS=$OPENSSL_INCLUDES$as_nl" + as_fn_append MODULE_BLOCK "MODULE__SSL_LDFLAGS=$OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH $OPENSSL_LIBS$as_nl" + +fi + if test "$py_cv_module__ssl" = yes; then + MODULE__SSL_TRUE= + MODULE__SSL_FALSE='#' +else + MODULE__SSL_TRUE='#' + MODULE__SSL_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__ssl" >&5 +$as_echo "$py_cv_module__ssl" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _hashlib" >&5 +$as_echo_n "checking for stdlib extension module _hashlib... " >&6; } + case $py_stdlib_not_available in #( + *_hashlib*) : + py_cv_module__hashlib=n/a ;; #( + *) : + if true; then : + if test "$ac_cv_working_openssl_hashlib" = yes; then : + py_cv_module__hashlib=yes +else + py_cv_module__hashlib=missing +fi +else + py_cv_module__hashlib=disabled +fi + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__HASHLIB=$py_cv_module__hashlib$as_nl" + if test "x$py_cv_module__hashlib" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE__HASHLIB_CFLAGS=$OPENSSL_INCLUDES$as_nl" + as_fn_append MODULE_BLOCK "MODULE__HASHLIB_LDFLAGS=$OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH $LIBCRYPTO_LIBS$as_nl" + +fi + if test "$py_cv_module__hashlib" = yes; then + MODULE__HASHLIB_TRUE= + MODULE__HASHLIB_FALSE='#' +else + MODULE__HASHLIB_TRUE='#' + MODULE__HASHLIB_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__hashlib" >&5 +$as_echo "$py_cv_module__hashlib" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _testcapi" >&5 $as_echo_n "checking for stdlib extension module _testcapi... " >&6; } case $py_stdlib_not_available in #( @@ -22481,6 +22674,14 @@ if test -z "${MODULE__LZMA_TRUE}" && test -z "${MODULE__LZMA_FALSE}"; then as_fn_error $? "conditional \"MODULE__LZMA\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__SSL_TRUE}" && test -z "${MODULE__SSL_FALSE}"; then + as_fn_error $? "conditional \"MODULE__SSL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__HASHLIB_TRUE}" && test -z "${MODULE__HASHLIB_FALSE}"; then + as_fn_error $? "conditional \"MODULE__HASHLIB\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE__TESTCAPI_TRUE}" && test -z "${MODULE__TESTCAPI_FALSE}"; then as_fn_error $? "conditional \"MODULE__TESTCAPI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index 0008e8a746c7b..92afdf39fefc0 100644 --- a/configure.ac +++ b/configure.ac @@ -5891,6 +5891,12 @@ ac_includes_default="$save_includes_default" AX_CHECK_OPENSSL([have_openssl=yes],[have_openssl=no]) # rpath to libssl and libcrypto +AS_VAR_IF([GNULD], [yes], [ + rpath_arg="-Wl,--enable-new-dtags,-rpath=" +], [ + rpath_arg="-Wl,-rpath=" +]) + AC_MSG_CHECKING(for --with-openssl-rpath) AC_ARG_WITH(openssl-rpath, AS_HELP_STRING([--with-openssl-rpath=@<:@DIR|auto|no@:>@], @@ -5903,58 +5909,104 @@ AC_ARG_WITH(openssl-rpath, [with_openssl_rpath=no] ) AS_CASE($with_openssl_rpath, - [auto|yes],[OPENSSL_RPATH=auto], - [no],[OPENSSL_RPATH=], + [auto|yes], [ + OPENSSL_RPATH=auto + dnl look for linker directories + for arg in "$OPENSSL_LDFLAGS"; do + AS_CASE([$arg], + [-L*], [OPENSSL_LDFLAGS_RPATH="$OPENSSL_LDFLAGS_RPATH ${rpath_arg}$(echo $arg | cut -c3-)"] + ) + done + ], + [no], [OPENSSL_RPATH=], [AS_IF( [test -d "$with_openssl_rpath"], - [OPENSSL_RPATH="$with_openssl_rpath"], + [ + OPENSSL_RPATH="$with_openssl_rpath" + OPENSSL_LDFLAGS_RPATH="${rpath_arg}$with_openssl_rpath" + ], AC_MSG_ERROR([--with-openssl-rpath "$with_openssl_rpath" is not a directory])) ] ) AC_MSG_RESULT($OPENSSL_RPATH) AC_SUBST([OPENSSL_RPATH]) +# This static linking is NOT OFFICIALLY SUPPORTED and not advertised. +# Requires static OpenSSL build with position-independent code. Some features +# like DSO engines or external OSSL providers don't work. Only tested with GCC +# and clang on X86_64. +AS_VAR_IF([PY_UNSUPPORTED_OPENSSL_BUILD], [static], [ + AC_MSG_CHECKING([for unsupported static openssl build]) + new_OPENSSL_LIBS= + for arg in $OPENSSL_LIBS; do + AS_CASE([$arg], + [-l*], [ + libname=$(echo $arg | cut -c3-) + new_OPENSSL_LIBS="$new_OPENSSL_LIBS -l:lib${libname}.a -Wl,--exclude-libs,lib${libname}.a" + ], + [new_OPENSSL_LIBS="$new_OPENSSL_LIBS $arg"] + ) + done + dnl include libz for OpenSSL build flavors with compression support + OPENSSL_LIBS="$new_OPENSSL_LIBS $ZLIB_LIBS" + AC_MSG_RESULT([$OPENSSL_LIBS]) +]) + +dnl AX_CHECK_OPENSSL does not export libcrypto-only libs +LIBCRYPTO_LIBS= +for arg in $OPENSSL_LIBS; do + AS_CASE([$arg], + [-l*ssl*|-Wl*ssl*], [], + [LIBCRYPTO_LIBS="$LIBCRYPTO_LIBS $arg"] + ) +done + # check if OpenSSL libraries work as expected -AC_CACHE_CHECK([whether OpenSSL provides required APIs], [ac_cv_working_openssl], [ -save_LIBS="$LIBS" -save_CFLAGS="$CFLAGS" -save_LDFLAGS="$LDFLAGS" -LIBS="$LIBS $OPENSSL_LIBS" -CFLAGS="$CFLAGS_NODIST $OPENSSL_INCLUDES" -LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS" +WITH_SAVE_ENV([ + LIBS="$LIBS $OPENSSL_LIBS" + CFLAGS="$CFLAGS $OPENSSL_INCLUDES" + LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH" -AC_LINK_IFELSE([AC_LANG_PROGRAM([[ -#include -#include -#include + AC_CACHE_CHECK([whether OpenSSL provides required ssl module APIs], [ac_cv_working_openssl_ssl], [ + AC_LINK_IFELSE([AC_LANG_PROGRAM([ + #include + #include + #if OPENSSL_VERSION_NUMBER < 0x10101000L + #error "OpenSSL >= 1.1.1 is required" + #endif + static void keylog_cb(const SSL *ssl, const char *line) {} + ], [ + SSL_CTX *ctx = SSL_CTX_new(TLS_client_method()); + SSL_CTX_set_keylog_callback(ctx, keylog_cb); + SSL *ssl = SSL_new(ctx); + X509_VERIFY_PARAM *param = SSL_get0_param(ssl); + X509_VERIFY_PARAM_set1_host(param, "python.org", 0); + SSL_free(ssl); + SSL_CTX_free(ctx); + ])], [ac_cv_working_openssl_ssl=yes], [ac_cv_working_openssl_ssl=no]) + ]) +]) -#if OPENSSL_VERSION_NUMBER < 0x10101000L -#error "OpenSSL >= 1.1.1 is required" -#endif +WITH_SAVE_ENV([ + LIBS="$LIBS $LIBCRYPTO_LIBS" + CFLAGS="$CFLAGS $OPENSSL_INCLUDES" + LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH" -static void keylog_cb(const SSL *ssl, const char *line) {} -]], [[ -/* SSL APIs */ -SSL_CTX *ctx = SSL_CTX_new(TLS_client_method()); -SSL_CTX_set_keylog_callback(ctx, keylog_cb); -SSL *ssl = SSL_new(ctx); -X509_VERIFY_PARAM *param = SSL_get0_param(ssl); -X509_VERIFY_PARAM_set1_host(param, "python.org", 0); -SSL_free(ssl); -SSL_CTX_free(ctx); - -/* hashlib APIs */ -OBJ_nid2sn(NID_md5); -OBJ_nid2sn(NID_sha1); -OBJ_nid2sn(NID_sha3_512); -OBJ_nid2sn(NID_blake2b512); -EVP_PBE_scrypt(NULL, 0, NULL, 0, 2, 8, 1, 0, NULL, 0); -]])], - [ac_cv_working_openssl=yes], - [ac_cv_working_openssl=no]) -LIBS="$save_LIBS" -CFLAGS="$save_CFLAGS" -LDFLAGS="$save_LDFLAGS" + AC_CACHE_CHECK([whether OpenSSL provides required hashlib module APIs], [ac_cv_working_openssl_hashlib], [ + AC_LINK_IFELSE([AC_LANG_PROGRAM([ + #include + #include + #if OPENSSL_VERSION_NUMBER < 0x10101000L + #error "OpenSSL >= 1.1.1 is required" + #endif + ], [ + OBJ_nid2sn(NID_md5); + OBJ_nid2sn(NID_sha1); + OBJ_nid2sn(NID_sha3_512); + OBJ_nid2sn(NID_blake2b512); + EVP_PBE_scrypt(NULL, 0, NULL, 0, 2, 8, 1, 0, NULL, 0); + ])], [ac_cv_working_openssl_hashlib=yes], [ac_cv_working_openssl_hashlib=no]) + ]) ]) # ssl module default cipher suite string @@ -6245,6 +6297,12 @@ PY_STDLIB_MOD([_bz2], [], [test "$have_bzip2" = yes], PY_STDLIB_MOD([_lzma], [], [test "$have_liblzma" = yes], [$LIBLZMA_CFLAGS], [$LIBLZMA_LIBS]) +dnl OpenSSL bindings +PY_STDLIB_MOD([_ssl], [], [test "$ac_cv_working_openssl_ssl" = yes], + [$OPENSSL_INCLUDES], [$OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH $OPENSSL_LIBS]) +PY_STDLIB_MOD([_hashlib], [], [test "$ac_cv_working_openssl_hashlib" = yes], + [$OPENSSL_INCLUDES], [$OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH $LIBCRYPTO_LIBS]) + dnl test modules PY_STDLIB_MOD([_testcapi], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_testinternalcapi], [test "$TEST_MODULES" = yes]) diff --git a/setup.py b/setup.py index 721103e7fceb7..7972bac46c106 100644 --- a/setup.py +++ b/setup.py @@ -1883,81 +1883,8 @@ def detect_decimal(self): ) def detect_openssl_hashlib(self): - # Detect SSL support for the socket module (via _ssl) - config_vars = sysconfig.get_config_vars() - - def split_var(name, sep): - # poor man's shlex, the re module is not available yet. - value = config_vars.get(name) - if not value: - return () - # This trick works because ax_check_openssl uses --libs-only-L, - # --libs-only-l, and --cflags-only-I. - value = ' ' + value - sep = ' ' + sep - return [v.strip() for v in value.split(sep) if v.strip()] - - openssl_includes = split_var('OPENSSL_INCLUDES', '-I') - openssl_libdirs = split_var('OPENSSL_LDFLAGS', '-L') - openssl_libs = split_var('OPENSSL_LIBS', '-l') - openssl_rpath = config_vars.get('OPENSSL_RPATH') - if not openssl_libs: - # libssl and libcrypto not found - self.missing.extend(['_ssl', '_hashlib']) - return None, None - - # Find OpenSSL includes - ssl_incs = find_file( - 'openssl/ssl.h', self.inc_dirs, openssl_includes - ) - if ssl_incs is None: - self.missing.extend(['_ssl', '_hashlib']) - return None, None - - if openssl_rpath == 'auto': - runtime_library_dirs = openssl_libdirs[:] - elif not openssl_rpath: - runtime_library_dirs = [] - else: - runtime_library_dirs = [openssl_rpath] - - openssl_extension_kwargs = dict( - include_dirs=openssl_includes, - library_dirs=openssl_libdirs, - libraries=openssl_libs, - runtime_library_dirs=runtime_library_dirs, - ) - - # This static linking is NOT OFFICIALLY SUPPORTED. - # Requires static OpenSSL build with position-independent code. Some - # features like DSO engines or external OSSL providers don't work. - # Only tested on GCC and clang on X86_64. - if os.environ.get("PY_UNSUPPORTED_OPENSSL_BUILD") == "static": - extra_linker_args = [] - for lib in openssl_extension_kwargs["libraries"]: - # link statically - extra_linker_args.append(f"-l:lib{lib}.a") - # don't export symbols - extra_linker_args.append(f"-Wl,--exclude-libs,lib{lib}.a") - openssl_extension_kwargs["extra_link_args"] = extra_linker_args - # don't link OpenSSL shared libraries. - # include libz for OpenSSL build flavors with compression support - openssl_extension_kwargs["libraries"] = ["z"] - - self.add( - Extension( - '_ssl', - ['_ssl.c'], - **openssl_extension_kwargs - ) - ) - self.add( - Extension( - '_hashlib', - ['_hashopenssl.c'], - **openssl_extension_kwargs, - ) - ) + self.addext(Extension('_ssl', ['_ssl.c'])) + self.addext(Extension('_hashlib', ['_hashopenssl.c'])) def detect_hash_builtins(self): # By default we always compile these even when OpenSSL is available From webhook-mailer at python.org Tue Nov 23 16:58:49 2021 From: webhook-mailer at python.org (tiran) Date: Tue, 23 Nov 2021 21:58:49 -0000 Subject: [Python-checkins] bpo-45847: Port _gdbm to PY_STDLIB_MOD (GH-29720) Message-ID: https://github.com/python/cpython/commit/9cf5646bb465b7d3d68bfe6d4711feb43d565051 commit: 9cf5646bb465b7d3d68bfe6d4711feb43d565051 branch: main author: Christian Heimes committer: tiran date: 2021-11-23T22:58:38+01:00 summary: bpo-45847: Port _gdbm to PY_STDLIB_MOD (GH-29720) files: M Modules/Setup.stdlib.in M configure M configure.ac M pyconfig.h.in M setup.py diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 9f66d531fef0f..9de0096c06783 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -66,6 +66,11 @@ @MODULE__LZMA_TRUE at _lzma _lzmamodule.c @MODULE_ZLIB_TRUE at zlib zlibmodule.c +# dbm/gdbm +# dbm needs either libndbm, libgdbm_compat, or libdb 5.x +# gdbm module needs -lgdbm + at MODULE__GDBM_TRUE@_gdbm _gdbmmodule.c + # hashing builtins, can be disabled with --without-builtin-hashlib-hashes @MODULE__MD5_TRUE at _md5 md5module.c @MODULE__SHA1_TRUE at _sha1 sha1module.c diff --git a/configure b/configure index ac0a1f320b2a7..630102585e87e 100755 --- a/configure +++ b/configure @@ -658,6 +658,8 @@ MODULE__SQLITE3_FALSE MODULE__SQLITE3_TRUE MODULE_NIS_FALSE MODULE_NIS_TRUE +MODULE__GDBM_FALSE +MODULE__GDBM_TRUE MODULE__DECIMAL_FALSE MODULE__DECIMAL_TRUE MODULE__CRYPT_FALSE @@ -807,6 +809,8 @@ DTRACE_OBJS DTRACE_HEADERS DFLAGS DTRACE +GDBM_LIBS +GDBM_CFLAGS TCLTK_LIBS TCLTK_INCLUDES LIBSQLITE3_LIBS @@ -1044,6 +1048,8 @@ LIBNSL_CFLAGS LIBNSL_LIBS LIBSQLITE3_CFLAGS LIBSQLITE3_LIBS +GDBM_CFLAGS +GDBM_LIBS ZLIB_CFLAGS ZLIB_LIBS BZIP2_CFLAGS @@ -1832,6 +1838,8 @@ Some influential environment variables: C compiler flags for LIBSQLITE3, overriding pkg-config LIBSQLITE3_LIBS linker flags for LIBSQLITE3, overriding pkg-config + GDBM_CFLAGS C compiler flags for gdbm + GDBM_LIBS additional linker flags for gdbm ZLIB_CFLAGS C compiler flags for ZLIB, overriding pkg-config ZLIB_LIBS linker flags for ZLIB, overriding pkg-config BZIP2_CFLAGS @@ -11668,8 +11676,17 @@ else TCLTK_LIBS="$with_tcltk_libs" fi -# check for _gdbmmodulec dependencies -for ac_header in gdbm.h + + +save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + CPPFLAGS="$GDBM_CFLAGS $CFLAGS" + LDFLAGS="$GDBM_LIBS $LDFLAGS" + for ac_header in gdbm.h do : ac_fn_c_check_header_mongrel "$LINENO" "gdbm.h" "ac_cv_header_gdbm_h" "$ac_includes_default" if test "x$ac_cv_header_gdbm_h" = xyes; then : @@ -11677,8 +11694,7 @@ if test "x$ac_cv_header_gdbm_h" = xyes; then : #define HAVE_GDBM_H 1 _ACEOF - LIBS_SAVE=$LIBS - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gdbm_open in -lgdbm" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gdbm_open in -lgdbm" >&5 $as_echo_n "checking for gdbm_open in -lgdbm... " >&6; } if ${ac_cv_lib_gdbm_gdbm_open+:} false; then : $as_echo_n "(cached) " >&6 @@ -11715,21 +11731,29 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gdbm_gdbm_open" >&5 $as_echo "$ac_cv_lib_gdbm_gdbm_open" >&6; } if test "x$ac_cv_lib_gdbm_gdbm_open" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBGDBM 1 -_ACEOF - LIBS="-lgdbm $LIBS" + have_gdbm=yes + GDBM_LIBS="$GDBM_LIBS -lgdbm" +else + have_gdbm=no fi - LIBS=$LIBS_SAVE +else + have_gdbm=no fi done +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS + + + # check for _dbmmodule.c dependencies for ac_header in ndbm.h do : @@ -12009,22 +12033,33 @@ $as_echo_n "checking for --with-dbmliborder... " >&6; } # Check whether --with-dbmliborder was given. if test "${with_dbmliborder+set}" = set; then : withval=$with_dbmliborder; -if test x$with_dbmliborder = xyes -then -as_fn_error $? "proper usage is --with-dbmliborder=db1:db2:..." "$LINENO" 5 else - as_save_IFS=$IFS - IFS=: - for db in $with_dbmliborder; do - if test x$db != xndbm && test x$db != xgdbm && test x$db != xbdb - then - as_fn_error $? "proper usage is --with-dbmliborder=db1:db2:..." "$LINENO" 5 - fi - done - IFS=$as_save_IFS -fi + with_dbmliborder=ndbm:gdbm:bdb fi + +have_gdbm_dbmliborder=no +as_save_IFS=$IFS +IFS=: +for db in $with_dbmliborder; do + case $db in #( + ndbm) : + ;; #( + gdbm) : + have_gdbm_dbmliborder=yes ;; #( + bdb) : + ;; #( + *) : + with_dbmliborder=error + ;; +esac +done +IFS=$as_save_IFS +if test "x$with_dbmliborder" = xerror; then : + + as_fn_error $? "proper usage is --with-dbmliborder=db1:db2:... (ndbm:gdbm:bdb)" "$LINENO" 5 + +fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_dbmliborder" >&5 $as_echo "$with_dbmliborder" >&6; } @@ -21725,6 +21760,42 @@ fi $as_echo "$py_cv_module__decimal" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _gdbm" >&5 +$as_echo_n "checking for stdlib extension module _gdbm... " >&6; } + case $py_stdlib_not_available in #( + *_gdbm*) : + py_cv_module__gdbm=n/a ;; #( + *) : + if test "$have_gdbm_dbmliborder" = yes; then : + if test "$have_gdbm" = yes; then : + py_cv_module__gdbm=yes +else + py_cv_module__gdbm=missing +fi +else + py_cv_module__gdbm=disabled +fi + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__GDBM=$py_cv_module__gdbm$as_nl" + if test "x$py_cv_module__gdbm" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE__GDBM_CFLAGS=$GDBM_CFLAGS$as_nl" + as_fn_append MODULE_BLOCK "MODULE__GDBM_LDFLAGS=$GDBM_LIBS$as_nl" + +fi + if test "$py_cv_module__gdbm" = yes; then + MODULE__GDBM_TRUE= + MODULE__GDBM_FALSE='#' +else + MODULE__GDBM_TRUE='#' + MODULE__GDBM_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__gdbm" >&5 +$as_echo "$py_cv_module__gdbm" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module nis" >&5 $as_echo_n "checking for stdlib extension module nis... " >&6; } case $py_stdlib_not_available in #( @@ -22650,6 +22721,10 @@ if test -z "${MODULE__DECIMAL_TRUE}" && test -z "${MODULE__DECIMAL_FALSE}"; then as_fn_error $? "conditional \"MODULE__DECIMAL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__GDBM_TRUE}" && test -z "${MODULE__GDBM_FALSE}"; then + as_fn_error $? "conditional \"MODULE__GDBM\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE_NIS_TRUE}" && test -z "${MODULE_NIS_FALSE}"; then as_fn_error $? "conditional \"MODULE_NIS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index 92afdf39fefc0..34a2c694ddfc2 100644 --- a/configure.ac +++ b/configure.ac @@ -3303,11 +3303,19 @@ else TCLTK_LIBS="$with_tcltk_libs" fi -# check for _gdbmmodulec dependencies -AC_CHECK_HEADERS([gdbm.h], [ - LIBS_SAVE=$LIBS - AC_CHECK_LIB([gdbm], [gdbm_open]) - LIBS=$LIBS_SAVE +dnl check for _gdbmmodule dependencies +dnl NOTE: gdbm does not provide a pkgconf file. +AC_ARG_VAR([GDBM_CFLAGS], [C compiler flags for gdbm]) +AC_ARG_VAR([GDBM_LIBS], [additional linker flags for gdbm]) +WITH_SAVE_ENV([ + CPPFLAGS="$GDBM_CFLAGS $CFLAGS" + LDFLAGS="$GDBM_LIBS $LDFLAGS" + AC_CHECK_HEADERS([gdbm.h], [ + AC_CHECK_LIB([gdbm], [gdbm_open], [ + have_gdbm=yes + GDBM_LIBS="$GDBM_LIBS -lgdbm" + ], [have_gdbm=no]) + ], [have_gdbm=no]) ]) # check for _dbmmodule.c dependencies @@ -3375,21 +3383,23 @@ AC_CHECK_HEADERS([db.h], [ AC_MSG_CHECKING(for --with-dbmliborder) AC_ARG_WITH(dbmliborder, AS_HELP_STRING([--with-dbmliborder=db1:db2:...], [override order to check db backends for dbm; a valid value is a colon separated string with the backend names `ndbm', `gdbm' and `bdb'.]), -[ -if test x$with_dbmliborder = xyes -then -AC_MSG_ERROR([proper usage is --with-dbmliborder=db1:db2:...]) -else - as_save_IFS=$IFS - IFS=: - for db in $with_dbmliborder; do - if test x$db != xndbm && test x$db != xgdbm && test x$db != xbdb - then - AC_MSG_ERROR([proper usage is --with-dbmliborder=db1:db2:...]) - fi - done - IFS=$as_save_IFS -fi]) +[], [with_dbmliborder=ndbm:gdbm:bdb]) + +have_gdbm_dbmliborder=no +as_save_IFS=$IFS +IFS=: +for db in $with_dbmliborder; do + AS_CASE([$db], + [ndbm], [], + [gdbm], [have_gdbm_dbmliborder=yes], + [bdb], [], + [with_dbmliborder=error] + ) +done +IFS=$as_save_IFS +AS_VAR_IF([with_dbmliborder], [error], [ + AC_MSG_ERROR([proper usage is --with-dbmliborder=db1:db2:... (ndbm:gdbm:bdb)]) +]) AC_MSG_RESULT($with_dbmliborder) # Templates for things AC_DEFINEd more than once. @@ -6279,6 +6289,9 @@ PY_STDLIB_MOD([_crypt], [], [test "$ac_cv_crypt_crypt" = yes], [$LIBCRYPT_CFLAGS], [$LIBCRYPT_LIBS]) PY_STDLIB_MOD([_decimal], [], [], [$LIBMPDEC_CFLAGS], [$LIBMPDEC_LDFLAGS]) +PY_STDLIB_MOD([_gdbm], + [test "$have_gdbm_dbmliborder" = yes], [test "$have_gdbm" = yes], + [$GDBM_CFLAGS], [$GDBM_LIBS]) PY_STDLIB_MOD([nis], [], [test "$have_nis" = yes -a "$ac_cv_header_rpc_rpc_h" = yes], [$LIBNSL_CFLAGS], [$LIBNSL_LIBS]) diff --git a/pyconfig.h.in b/pyconfig.h.in index c9c58656f58ac..bb9ae4c3dbc82 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -604,9 +604,6 @@ /* Define to 1 if you have the `dld' library (-ldld). */ #undef HAVE_LIBDLD -/* Define to 1 if you have the `gdbm' library (-lgdbm). */ -#undef HAVE_LIBGDBM - /* Define to 1 if you have the `gdbm_compat' library (-lgdbm_compat). */ #undef HAVE_LIBGDBM_COMPAT diff --git a/setup.py b/setup.py index 7972bac46c106..98a20150c1e0b 100644 --- a/setup.py +++ b/setup.py @@ -1256,11 +1256,9 @@ def detect_dbm_gdbm(self): # libdb, gdbm and ndbm headers and libraries have_ndbm_h = sysconfig.get_config_var("HAVE_NDBM_H") - have_gdbm_h = sysconfig.get_config_var("HAVE_GDBM_H") have_gdbm_ndbm_h = sysconfig.get_config_var("HAVE_GDBM_NDBM_H") have_gdbm_dash_ndbm_h = sysconfig.get_config_var("HAVE_GDBM_DASH_NDBM_H") have_libndbm = sysconfig.get_config_var("HAVE_LIBNDBM") - have_libgdbm = sysconfig.get_config_var("HAVE_LIBGDBM") have_libgdbm_compat = sysconfig.get_config_var("HAVE_LIBGDBM_COMPAT") have_libdb = sysconfig.get_config_var("HAVE_LIBDB") @@ -1318,11 +1316,7 @@ def detect_dbm_gdbm(self): self.missing.append('_dbm') # Anthony Baxter's gdbm module. GNU dbm(3) will require -lgdbm: - if 'gdbm' in dbm_order and have_libgdbm: - self.add(Extension('_gdbm', ['_gdbmmodule.c'], - libraries=['gdbm'])) - else: - self.missing.append('_gdbm') + self.addext(Extension('_gdbm', ['_gdbmmodule.c'])) def detect_sqlite(self): sources = [ From webhook-mailer at python.org Tue Nov 23 23:41:12 2021 From: webhook-mailer at python.org (zware) Date: Wed, 24 Nov 2021 04:41:12 -0000 Subject: [Python-checkins] bpo-45616: Let py.exe distinguish between v3.1 and v3.10 (GH-29731) Message-ID: https://github.com/python/cpython/commit/f9de97aae5fe9dafb58a8099171f4a09c449f4e8 commit: f9de97aae5fe9dafb58a8099171f4a09c449f4e8 branch: main author: Zachary Ware committer: zware date: 2021-11-23T22:41:04-06:00 summary: bpo-45616: Let py.exe distinguish between v3.1 and v3.10 (GH-29731) files: A Misc/NEWS.d/next/Windows/2021-11-23-11-44-42.bpo-45616.K52PLZ.rst M PC/launcher.c diff --git a/Misc/NEWS.d/next/Windows/2021-11-23-11-44-42.bpo-45616.K52PLZ.rst b/Misc/NEWS.d/next/Windows/2021-11-23-11-44-42.bpo-45616.K52PLZ.rst new file mode 100644 index 0000000000000..000f2fd3cc989 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2021-11-23-11-44-42.bpo-45616.K52PLZ.rst @@ -0,0 +1,4 @@ +Fix Python Launcher's ability to distinguish between versions 3.1 and 3.10 +when either one is explicitly requested. Previously, 3.1 would be used if +3.10 was requested but not installed, and 3.10 would be used if 3.1 was +requested but 3.10 was installed. diff --git a/PC/launcher.c b/PC/launcher.c index fbfb49ae857ac..f8b8a3db39775 100644 --- a/PC/launcher.c +++ b/PC/launcher.c @@ -542,8 +542,17 @@ find_python_by_version(wchar_t const * wanted_ver) } for (i = 0; i < num_installed_pythons; i++, ip++) { n = wcslen(ip->version); - if (n > wlen) + /* + * If wlen is greater than 1, we're probably trying to find a specific + * version and thus want an exact match: 3.1 != 3.10. Otherwise, we + * just want a prefix match. + */ + if ((wlen > 1) && (n != wlen)) { + continue; + } + if (n > wlen) { n = wlen; + } if ((wcsncmp(ip->version, wanted_ver, n) == 0) && /* bits == 0 => don't care */ ((bits == 0) || (ip->bits == bits))) { From webhook-mailer at python.org Wed Nov 24 00:02:42 2021 From: webhook-mailer at python.org (miss-islington) Date: Wed, 24 Nov 2021 05:02:42 -0000 Subject: [Python-checkins] bpo-45616: Let py.exe distinguish between v3.1 and v3.10 (GH-29731) Message-ID: https://github.com/python/cpython/commit/ae065f83625f3abcf75d928f405e05582fc035b4 commit: ae065f83625f3abcf75d928f405e05582fc035b4 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-23T21:02:32-08:00 summary: bpo-45616: Let py.exe distinguish between v3.1 and v3.10 (GH-29731) (cherry picked from commit f9de97aae5fe9dafb58a8099171f4a09c449f4e8) Co-authored-by: Zachary Ware files: A Misc/NEWS.d/next/Windows/2021-11-23-11-44-42.bpo-45616.K52PLZ.rst M PC/launcher.c diff --git a/Misc/NEWS.d/next/Windows/2021-11-23-11-44-42.bpo-45616.K52PLZ.rst b/Misc/NEWS.d/next/Windows/2021-11-23-11-44-42.bpo-45616.K52PLZ.rst new file mode 100644 index 0000000000000..000f2fd3cc989 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2021-11-23-11-44-42.bpo-45616.K52PLZ.rst @@ -0,0 +1,4 @@ +Fix Python Launcher's ability to distinguish between versions 3.1 and 3.10 +when either one is explicitly requested. Previously, 3.1 would be used if +3.10 was requested but not installed, and 3.10 would be used if 3.1 was +requested but 3.10 was installed. diff --git a/PC/launcher.c b/PC/launcher.c index f5b225ac08cfe..84c8a1d14ea41 100644 --- a/PC/launcher.c +++ b/PC/launcher.c @@ -542,8 +542,17 @@ find_python_by_version(wchar_t const * wanted_ver) } for (i = 0; i < num_installed_pythons; i++, ip++) { n = wcslen(ip->version); - if (n > wlen) + /* + * If wlen is greater than 1, we're probably trying to find a specific + * version and thus want an exact match: 3.1 != 3.10. Otherwise, we + * just want a prefix match. + */ + if ((wlen > 1) && (n != wlen)) { + continue; + } + if (n > wlen) { n = wlen; + } if ((wcsncmp(ip->version, wanted_ver, n) == 0) && /* bits == 0 => don't care */ ((bits == 0) || (ip->bits == bits))) { From webhook-mailer at python.org Wed Nov 24 02:07:24 2021 From: webhook-mailer at python.org (tiran) Date: Wed, 24 Nov 2021 07:07:24 -0000 Subject: [Python-checkins] bpo-45886: Allow overriding freeze command for cross compiling (GH-29735) Message-ID: https://github.com/python/cpython/commit/dd8ce9ea8d7e45224a348ea7962b5f50cbf86dc5 commit: dd8ce9ea8d7e45224a348ea7962b5f50cbf86dc5 branch: main author: Christian Heimes committer: tiran date: 2021-11-24T08:07:15+01:00 summary: bpo-45886: Allow overriding freeze command for cross compiling (GH-29735) files: A Misc/NEWS.d/next/Build/2021-11-23-23-37-49.bpo-45886._Ulnh-.rst M Makefile.pre.in M Tools/scripts/freeze_modules.py diff --git a/Makefile.pre.in b/Makefile.pre.in index 476a64cb7a500..bb624755dd3ee 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1008,6 +1008,9 @@ Python/deepfreeze/frozen_only.c: Python/frozen_modules/frozen_only.h $(DEEPFREEZ ############################################################################ # frozen modules (including importlib) +# Allow developers to override freeze_module command for cross building (bpo-45886) +FREEZE_MODULE?=Programs/_freeze_module + # FROZEN_FILES_* are auto-generated by Tools/scripts/freeze_modules.py. FROZEN_FILES_IN = \ Lib/importlib/_bootstrap.py \ @@ -1061,69 +1064,69 @@ Programs/_freeze_module: Programs/_freeze_module.o $(LIBRARY_OBJS_OMIT_FROZEN) # BEGIN: freezing modules -Python/frozen_modules/importlib._bootstrap.h: Programs/_freeze_module Lib/importlib/_bootstrap.py - Programs/_freeze_module importlib._bootstrap $(srcdir)/Lib/importlib/_bootstrap.py Python/frozen_modules/importlib._bootstrap.h +Python/frozen_modules/importlib._bootstrap.h: $(FREEZE_MODULE) Lib/importlib/_bootstrap.py + $(FREEZE_MODULE) importlib._bootstrap $(srcdir)/Lib/importlib/_bootstrap.py Python/frozen_modules/importlib._bootstrap.h -Python/frozen_modules/importlib._bootstrap_external.h: Programs/_freeze_module Lib/importlib/_bootstrap_external.py - Programs/_freeze_module importlib._bootstrap_external $(srcdir)/Lib/importlib/_bootstrap_external.py Python/frozen_modules/importlib._bootstrap_external.h +Python/frozen_modules/importlib._bootstrap_external.h: $(FREEZE_MODULE) Lib/importlib/_bootstrap_external.py + $(FREEZE_MODULE) importlib._bootstrap_external $(srcdir)/Lib/importlib/_bootstrap_external.py Python/frozen_modules/importlib._bootstrap_external.h -Python/frozen_modules/zipimport.h: Programs/_freeze_module Lib/zipimport.py - Programs/_freeze_module zipimport $(srcdir)/Lib/zipimport.py Python/frozen_modules/zipimport.h +Python/frozen_modules/zipimport.h: $(FREEZE_MODULE) Lib/zipimport.py + $(FREEZE_MODULE) zipimport $(srcdir)/Lib/zipimport.py Python/frozen_modules/zipimport.h -Python/frozen_modules/abc.h: Programs/_freeze_module Lib/abc.py - Programs/_freeze_module abc $(srcdir)/Lib/abc.py Python/frozen_modules/abc.h +Python/frozen_modules/abc.h: $(FREEZE_MODULE) Lib/abc.py + $(FREEZE_MODULE) abc $(srcdir)/Lib/abc.py Python/frozen_modules/abc.h -Python/frozen_modules/codecs.h: Programs/_freeze_module Lib/codecs.py - Programs/_freeze_module codecs $(srcdir)/Lib/codecs.py Python/frozen_modules/codecs.h +Python/frozen_modules/codecs.h: $(FREEZE_MODULE) Lib/codecs.py + $(FREEZE_MODULE) codecs $(srcdir)/Lib/codecs.py Python/frozen_modules/codecs.h -Python/frozen_modules/io.h: Programs/_freeze_module Lib/io.py - Programs/_freeze_module io $(srcdir)/Lib/io.py Python/frozen_modules/io.h +Python/frozen_modules/io.h: $(FREEZE_MODULE) Lib/io.py + $(FREEZE_MODULE) io $(srcdir)/Lib/io.py Python/frozen_modules/io.h -Python/frozen_modules/_collections_abc.h: Programs/_freeze_module Lib/_collections_abc.py - Programs/_freeze_module _collections_abc $(srcdir)/Lib/_collections_abc.py Python/frozen_modules/_collections_abc.h +Python/frozen_modules/_collections_abc.h: $(FREEZE_MODULE) Lib/_collections_abc.py + $(FREEZE_MODULE) _collections_abc $(srcdir)/Lib/_collections_abc.py Python/frozen_modules/_collections_abc.h -Python/frozen_modules/_sitebuiltins.h: Programs/_freeze_module Lib/_sitebuiltins.py - Programs/_freeze_module _sitebuiltins $(srcdir)/Lib/_sitebuiltins.py Python/frozen_modules/_sitebuiltins.h +Python/frozen_modules/_sitebuiltins.h: $(FREEZE_MODULE) Lib/_sitebuiltins.py + $(FREEZE_MODULE) _sitebuiltins $(srcdir)/Lib/_sitebuiltins.py Python/frozen_modules/_sitebuiltins.h -Python/frozen_modules/genericpath.h: Programs/_freeze_module Lib/genericpath.py - Programs/_freeze_module genericpath $(srcdir)/Lib/genericpath.py Python/frozen_modules/genericpath.h +Python/frozen_modules/genericpath.h: $(FREEZE_MODULE) Lib/genericpath.py + $(FREEZE_MODULE) genericpath $(srcdir)/Lib/genericpath.py Python/frozen_modules/genericpath.h -Python/frozen_modules/ntpath.h: Programs/_freeze_module Lib/ntpath.py - Programs/_freeze_module ntpath $(srcdir)/Lib/ntpath.py Python/frozen_modules/ntpath.h +Python/frozen_modules/ntpath.h: $(FREEZE_MODULE) Lib/ntpath.py + $(FREEZE_MODULE) ntpath $(srcdir)/Lib/ntpath.py Python/frozen_modules/ntpath.h -Python/frozen_modules/posixpath.h: Programs/_freeze_module Lib/posixpath.py - Programs/_freeze_module posixpath $(srcdir)/Lib/posixpath.py Python/frozen_modules/posixpath.h +Python/frozen_modules/posixpath.h: $(FREEZE_MODULE) Lib/posixpath.py + $(FREEZE_MODULE) posixpath $(srcdir)/Lib/posixpath.py Python/frozen_modules/posixpath.h -Python/frozen_modules/os.h: Programs/_freeze_module Lib/os.py - Programs/_freeze_module os $(srcdir)/Lib/os.py Python/frozen_modules/os.h +Python/frozen_modules/os.h: $(FREEZE_MODULE) Lib/os.py + $(FREEZE_MODULE) os $(srcdir)/Lib/os.py Python/frozen_modules/os.h -Python/frozen_modules/site.h: Programs/_freeze_module Lib/site.py - Programs/_freeze_module site $(srcdir)/Lib/site.py Python/frozen_modules/site.h +Python/frozen_modules/site.h: $(FREEZE_MODULE) Lib/site.py + $(FREEZE_MODULE) site $(srcdir)/Lib/site.py Python/frozen_modules/site.h -Python/frozen_modules/stat.h: Programs/_freeze_module Lib/stat.py - Programs/_freeze_module stat $(srcdir)/Lib/stat.py Python/frozen_modules/stat.h +Python/frozen_modules/stat.h: $(FREEZE_MODULE) Lib/stat.py + $(FREEZE_MODULE) stat $(srcdir)/Lib/stat.py Python/frozen_modules/stat.h -Python/frozen_modules/__hello__.h: Programs/_freeze_module Lib/__hello__.py - Programs/_freeze_module __hello__ $(srcdir)/Lib/__hello__.py Python/frozen_modules/__hello__.h +Python/frozen_modules/__hello__.h: $(FREEZE_MODULE) Lib/__hello__.py + $(FREEZE_MODULE) __hello__ $(srcdir)/Lib/__hello__.py Python/frozen_modules/__hello__.h -Python/frozen_modules/__phello__.h: Programs/_freeze_module Lib/__phello__/__init__.py - Programs/_freeze_module __phello__ $(srcdir)/Lib/__phello__/__init__.py Python/frozen_modules/__phello__.h +Python/frozen_modules/__phello__.h: $(FREEZE_MODULE) Lib/__phello__/__init__.py + $(FREEZE_MODULE) __phello__ $(srcdir)/Lib/__phello__/__init__.py Python/frozen_modules/__phello__.h -Python/frozen_modules/__phello__.ham.h: Programs/_freeze_module Lib/__phello__/ham/__init__.py - Programs/_freeze_module __phello__.ham $(srcdir)/Lib/__phello__/ham/__init__.py Python/frozen_modules/__phello__.ham.h +Python/frozen_modules/__phello__.ham.h: $(FREEZE_MODULE) Lib/__phello__/ham/__init__.py + $(FREEZE_MODULE) __phello__.ham $(srcdir)/Lib/__phello__/ham/__init__.py Python/frozen_modules/__phello__.ham.h -Python/frozen_modules/__phello__.ham.eggs.h: Programs/_freeze_module Lib/__phello__/ham/eggs.py - Programs/_freeze_module __phello__.ham.eggs $(srcdir)/Lib/__phello__/ham/eggs.py Python/frozen_modules/__phello__.ham.eggs.h +Python/frozen_modules/__phello__.ham.eggs.h: $(FREEZE_MODULE) Lib/__phello__/ham/eggs.py + $(FREEZE_MODULE) __phello__.ham.eggs $(srcdir)/Lib/__phello__/ham/eggs.py Python/frozen_modules/__phello__.ham.eggs.h -Python/frozen_modules/__phello__.spam.h: Programs/_freeze_module Lib/__phello__/spam.py - Programs/_freeze_module __phello__.spam $(srcdir)/Lib/__phello__/spam.py Python/frozen_modules/__phello__.spam.h +Python/frozen_modules/__phello__.spam.h: $(FREEZE_MODULE) Lib/__phello__/spam.py + $(FREEZE_MODULE) __phello__.spam $(srcdir)/Lib/__phello__/spam.py Python/frozen_modules/__phello__.spam.h -Python/frozen_modules/frozen_only.h: Programs/_freeze_module Tools/freeze/flag.py - Programs/_freeze_module frozen_only $(srcdir)/Tools/freeze/flag.py Python/frozen_modules/frozen_only.h +Python/frozen_modules/frozen_only.h: $(FREEZE_MODULE) Tools/freeze/flag.py + $(FREEZE_MODULE) frozen_only $(srcdir)/Tools/freeze/flag.py Python/frozen_modules/frozen_only.h # END: freezing modules -Tools/scripts/freeze_modules.py: Programs/_freeze_module +Tools/scripts/freeze_modules.py: $(FREEZE_MODULE) .PHONY: regen-frozen regen-frozen: Tools/scripts/freeze_modules.py $(FROZEN_FILES_IN) diff --git a/Misc/NEWS.d/next/Build/2021-11-23-23-37-49.bpo-45886._Ulnh-.rst b/Misc/NEWS.d/next/Build/2021-11-23-23-37-49.bpo-45886._Ulnh-.rst new file mode 100644 index 0000000000000..b08b9c8a5441e --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-23-23-37-49.bpo-45886._Ulnh-.rst @@ -0,0 +1,2 @@ +The ``_freeze_module`` program path can now be overridden on the command +line, e.g. ``make FREEZE_MODULE=../x86_64/Program/_freeze_module``. diff --git a/Tools/scripts/freeze_modules.py b/Tools/scripts/freeze_modules.py index 4281b67e27cb3..a36f74ced4187 100644 --- a/Tools/scripts/freeze_modules.py +++ b/Tools/scripts/freeze_modules.py @@ -598,10 +598,10 @@ def regen_makefile(modules): pyfile = relpath_for_posix_display(src.pyfile, ROOT_DIR) pyfiles.append(f'\t\t{pyfile} \\') - freeze = (f'Programs/_freeze_module {src.frozenid} ' + freeze = (f'$(FREEZE_MODULE) {src.frozenid} ' f'$(srcdir)/{pyfile} {header}') rules.extend([ - f'{header}: Programs/_freeze_module {pyfile}', + f'{header}: $(FREEZE_MODULE) {pyfile}', f'\t{freeze}', '', ]) From webhook-mailer at python.org Wed Nov 24 02:19:33 2021 From: webhook-mailer at python.org (tiran) Date: Wed, 24 Nov 2021 07:19:33 -0000 Subject: [Python-checkins] bpo-45847: Port _posixshmem to PY_STDLIB_MOD (GH-29738) Message-ID: https://github.com/python/cpython/commit/324527012fa1078428a6207918640cf860e28c81 commit: 324527012fa1078428a6207918640cf860e28c81 branch: main author: Erlend Egeberg Aasland committer: tiran date: 2021-11-24T08:19:17+01:00 summary: bpo-45847: Port _posixshmem to PY_STDLIB_MOD (GH-29738) files: M Modules/Setup.stdlib.in M configure M configure.ac M pyconfig.h.in M setup.py diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 9de0096c06783..e999775caf3f7 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -122,6 +122,9 @@ @MODULE_SYSLOG_TRUE at syslog syslogmodule.c @MODULE_TERMIOS_TRUE at termios termios.c +# multiprocessing + at MODULE__POSIXSHMEM_TRUE@_posixshmem _multiprocessing/posixshmem.c + ############################################################################ # Modules with third party dependencies diff --git a/configure b/configure index 630102585e87e..70c94a4e24d60 100755 --- a/configure +++ b/configure @@ -710,6 +710,8 @@ MODULE_OSSAUDIODEV_FALSE MODULE_OSSAUDIODEV_TRUE MODULE_GRP_FALSE MODULE_GRP_TRUE +MODULE__POSIXSHMEM_FALSE +MODULE__POSIXSHMEM_TRUE MODULE_MMAP_FALSE MODULE_MMAP_TRUE MODULE_FCNTL_FALSE @@ -20030,9 +20032,14 @@ fi # checks for POSIX shared memory, used by Modules/_multiprocessing/posixshmem.c # shm_* may only be available if linking against librt -save_LIBS="$LIBS" -save_includes_default="$ac_includes_default" -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing shm_open" >&5 +POSIXSHMEM_CFLAGS='-I$(srcdir)/Modules/_multiprocessing' +save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing shm_open" >&5 $as_echo_n "checking for library containing shm_open... " >&6; } if ${ac_cv_search_shm_open+:} false; then : $as_echo_n "(cached) " >&6 @@ -20088,33 +20095,20 @@ if test "$ac_res" != no; then : fi -if test "$ac_cv_search_shm_open" = "-lrt"; then - -$as_echo "#define SHM_NEEDS_LIBRT 1" >>confdefs.h - -fi -for ac_header in sys/mman.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_mman_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_SYS_MMAN_H 1 -_ACEOF - + if test "x$ac_cv_search_shm_open" = x-lrt; then : + POSIXSHMEM_LIBS="-lrt" fi -done - -# temporarily override ac_includes_default for AC_CHECK_FUNCS below -ac_includes_default="\ -${ac_includes_default} -#ifndef __cplusplus -# ifdef HAVE_SYS_MMAN_H -# include -# endif -#endif -" -for ac_func in shm_open shm_unlink + save_ac_includes_default=$ac_includes_default + ac_includes_default="\ + ${ac_includes_default} + #ifndef __cplusplus + # ifdef HAVE_SYS_MMAN_H + # include + # endif + #endif + " + for ac_func in shm_open shm_unlink do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" @@ -20122,13 +20116,20 @@ if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF - + have_posix_shmem=yes +else + have_posix_shmem=no fi done -# we don't want to link with librt always, restore LIBS -LIBS="$save_LIBS" -ac_includes_default="$save_includes_default" + ac_includes_default=$save_ac_includes_default + +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS + + # Check for usable OpenSSL @@ -21072,6 +21073,42 @@ fi $as_echo "$py_cv_module_mmap" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _posixshmem" >&5 +$as_echo_n "checking for stdlib extension module _posixshmem... " >&6; } + case $py_stdlib_not_available in #( + *_posixshmem*) : + py_cv_module__posixshmem=n/a ;; #( + *) : + if true; then : + if test "$have_posix_shmem" = "yes"; then : + py_cv_module__posixshmem=yes +else + py_cv_module__posixshmem=missing +fi +else + py_cv_module__posixshmem=disabled +fi + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__POSIXSHMEM=$py_cv_module__posixshmem$as_nl" + if test "x$py_cv_module__posixshmem" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE__POSIXSHMEM_CFLAGS=$POSIXSHMEM_CFLAGS$as_nl" + as_fn_append MODULE_BLOCK "MODULE__POSIXSHMEM_LDFLAGS=$POSIXSHMEM_LIBS$as_nl" + +fi + if test "$py_cv_module__posixshmem" = yes; then + MODULE__POSIXSHMEM_TRUE= + MODULE__POSIXSHMEM_FALSE='#' +else + MODULE__POSIXSHMEM_TRUE='#' + MODULE__POSIXSHMEM_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__posixshmem" >&5 +$as_echo "$py_cv_module__posixshmem" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module grp" >&5 $as_echo_n "checking for stdlib extension module grp... " >&6; } @@ -22621,6 +22658,10 @@ if test -z "${MODULE_MMAP_TRUE}" && test -z "${MODULE_MMAP_FALSE}"; then as_fn_error $? "conditional \"MODULE_MMAP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__POSIXSHMEM_TRUE}" && test -z "${MODULE__POSIXSHMEM_FALSE}"; then + as_fn_error $? "conditional \"MODULE__POSIXSHMEM\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE_GRP_TRUE}" && test -z "${MODULE_GRP_FALSE}"; then as_fn_error $? "conditional \"MODULE_GRP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index 34a2c694ddfc2..a161a8cf88545 100644 --- a/configure.ac +++ b/configure.ac @@ -5875,27 +5875,24 @@ AS_VAR_IF([ac_cv_func_getrandom], [yes], [ # checks for POSIX shared memory, used by Modules/_multiprocessing/posixshmem.c # shm_* may only be available if linking against librt -save_LIBS="$LIBS" -save_includes_default="$ac_includes_default" -AC_SEARCH_LIBS(shm_open, rt) -if test "$ac_cv_search_shm_open" = "-lrt"; then - AC_DEFINE(SHM_NEEDS_LIBRT, 1, - [Define to 1 if you must link with -lrt for shm_open().]) -fi -AC_CHECK_HEADERS(sys/mman.h) -# temporarily override ac_includes_default for AC_CHECK_FUNCS below -ac_includes_default="\ -${ac_includes_default} -#ifndef __cplusplus -# ifdef HAVE_SYS_MMAN_H -# include -# endif -#endif -" -AC_CHECK_FUNCS([shm_open shm_unlink]) -# we don't want to link with librt always, restore LIBS -LIBS="$save_LIBS" -ac_includes_default="$save_includes_default" +POSIXSHMEM_CFLAGS='-I$(srcdir)/Modules/_multiprocessing' +WITH_SAVE_ENV([ + AC_SEARCH_LIBS([shm_open], [rt]) + AS_VAR_IF([ac_cv_search_shm_open], [-lrt], [POSIXSHMEM_LIBS="-lrt"]) + + dnl Temporarily override ac_includes_default for AC_CHECK_FUNCS below. + _SAVE_VAR([ac_includes_default]) + ac_includes_default="\ + ${ac_includes_default} + #ifndef __cplusplus + # ifdef HAVE_SYS_MMAN_H + # include + # endif + #endif + " + AC_CHECK_FUNCS([shm_open shm_unlink], [have_posix_shmem=yes], [have_posix_shmem=no]) + _RESTORE_VAR([ac_includes_default]) +]) # Check for usable OpenSSL AX_CHECK_OPENSSL([have_openssl=yes],[have_openssl=no]) @@ -6251,6 +6248,9 @@ PY_STDLIB_MOD([fcntl], [], [$FCNTL_LIBS]) PY_STDLIB_MOD([mmap], [], [test "$ac_cv_header_sys_mman_h" = "yes" -a "$ac_cv_header_sys_stat_h" = "yes"]) +PY_STDLIB_MOD([_posixshmem], + [], [test "$have_posix_shmem" = "yes"], + [$POSIXSHMEM_CFLAGS], [$POSIXSHMEM_LIBS]) dnl platform specific extensions PY_STDLIB_MOD([grp], [], [test "$ac_cv_func_getgrgid" = yes -o "$ac_cv_func_getgrgid_r" = yes]) diff --git a/pyconfig.h.in b/pyconfig.h.in index bb9ae4c3dbc82..67f27c2b17e3b 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -1469,9 +1469,6 @@ /* Define if setpgrp() must be called as setpgrp(0, 0). */ #undef SETPGRP_HAVE_ARG -/* Define to 1 if you must link with -lrt for shm_open(). */ -#undef SHM_NEEDS_LIBRT - /* Define if i>>j for signed int i does not extend the sign bit when i < 0 */ #undef SIGNED_RIGHT_SHIFT_ZERO_FILLS diff --git a/setup.py b/setup.py index 98a20150c1e0b..72497de5c0d3a 100644 --- a/setup.py +++ b/setup.py @@ -1397,20 +1397,7 @@ def detect_multiprocessing(self): self.add(Extension('_multiprocessing', multiprocessing_srcs, include_dirs=["Modules/_multiprocessing"])) - if (not MS_WINDOWS and - sysconfig.get_config_var('HAVE_SHM_OPEN') and - sysconfig.get_config_var('HAVE_SHM_UNLINK')): - posixshmem_srcs = ['_multiprocessing/posixshmem.c'] - libs = [] - if sysconfig.get_config_var('SHM_NEEDS_LIBRT'): - # need to link with librt to get shm_open() - libs.append('rt') - self.add(Extension('_posixshmem', posixshmem_srcs, - define_macros={}, - libraries=libs, - include_dirs=["Modules/_multiprocessing"])) - else: - self.missing.append('_posixshmem') + self.addext(Extension('_posixshmem', ['_multiprocessing/posixshmem.c'])) def detect_uuid(self): # Build the _uuid module if possible From webhook-mailer at python.org Wed Nov 24 02:51:48 2021 From: webhook-mailer at python.org (jaraco) Date: Wed, 24 Nov 2021 07:51:48 -0000 Subject: [Python-checkins] bpo-45514: Deprecate importlib resources legacy functions. (GH-29036) Message-ID: https://github.com/python/cpython/commit/d5cd2effa69551c6bc7edfef8a414d545dea9117 commit: d5cd2effa69551c6bc7edfef8a414d545dea9117 branch: main author: Jason R. Coombs committer: jaraco date: 2021-11-24T02:51:37-05:00 summary: bpo-45514: Deprecate importlib resources legacy functions. (GH-29036) * bpo-45514: Apply changes from importlib_resources at a3ef4128c6 * Mark legacy functions as deprecated in the docs and link to the migration docs in importlib_resources docs. * Apply changes from importlib_resources at 329ae9d5f2c. * Indicate importlib.resources as a module. Co-authored-by: Filipe La?ns files: A Misc/NEWS.d/next/Library/2021-10-18-14-25-35.bpo-45514.YmlzIl.rst M Doc/library/importlib.rst M Lib/importlib/_itertools.py M Lib/importlib/_legacy.py M Lib/test/test_importlib/resources/util.py M Lib/test/test_importlib/test_contents.py M Lib/test/test_importlib/test_open.py M Lib/test/test_importlib/test_path.py M Lib/test/test_importlib/test_read.py M Lib/test/test_importlib/test_resource.py diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index 59c8c64acdc3b..347e08e4a2846 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -917,7 +917,9 @@ not** have to exist as physical files and directories on the file system. on `using importlib.resources `_ and `migrating from pkg_resources to importlib.resources - `_. + `_ + and + `migrating legacy usage `_. Loaders that wish to support resource reading should implement a ``get_resource_reader(fullname)`` method as specified by @@ -979,6 +981,8 @@ The following functions are available. sub-resources (i.e. it cannot be a directory). This function returns a ``typing.BinaryIO`` instance, a binary I/O stream open for reading. + .. deprecated:: 3.11 + .. function:: open_text(package, resource, encoding='utf-8', errors='strict') @@ -994,6 +998,8 @@ The following functions are available. This function returns a ``typing.TextIO`` instance, a text I/O stream open for reading. + .. deprecated:: 3.11 + .. function:: read_binary(package, resource) @@ -1006,6 +1012,8 @@ The following functions are available. sub-resources (i.e. it cannot be a directory). This function returns the contents of the resource as :class:`bytes`. + .. deprecated:: 3.11 + .. function:: read_text(package, resource, encoding='utf-8', errors='strict') @@ -1019,6 +1027,8 @@ The following functions are available. have the same meaning as with built-in :func:`open`. This function returns the contents of the resource as :class:`str`. + .. deprecated:: 3.11 + .. function:: path(package, resource) @@ -1034,6 +1044,8 @@ The following functions are available. within *package*; it may not contain path separators and it may not have sub-resources (i.e. it cannot be a directory). + .. deprecated:: 3.11 + .. function:: is_resource(package, name) @@ -1042,6 +1054,8 @@ The following functions are available. *package* is either a name or a module object which conforms to the ``Package`` requirements. + .. deprecated:: 3.11 + .. function:: contents(package) @@ -1052,6 +1066,8 @@ The following functions are available. *package* is either a name or a module object which conforms to the ``Package`` requirements. + .. deprecated:: 3.11 + :mod:`importlib.machinery` -- Importers and path hooks ------------------------------------------------------ diff --git a/Lib/importlib/_itertools.py b/Lib/importlib/_itertools.py index dd45f2f096630..cce05582ffc6f 100644 --- a/Lib/importlib/_itertools.py +++ b/Lib/importlib/_itertools.py @@ -1,11 +1,27 @@ from itertools import filterfalse +from typing import ( + Callable, + Iterable, + Iterator, + Optional, + Set, + TypeVar, + Union, +) -def unique_everseen(iterable, key=None): +# Type and type variable definitions +_T = TypeVar('_T') +_U = TypeVar('_U') + + +def unique_everseen( + iterable: Iterable[_T], key: Optional[Callable[[_T], _U]] = None +) -> Iterator[_T]: "List unique elements, preserving order. Remember all elements ever seen." # unique_everseen('AAAABBBCCDAABBB') --> A B C D # unique_everseen('ABBCcAD', str.lower) --> A B C D - seen = set() + seen: Set[Union[_T, _U]] = set() seen_add = seen.add if key is None: for element in filterfalse(seen.__contains__, iterable): diff --git a/Lib/importlib/_legacy.py b/Lib/importlib/_legacy.py index 2ddec5f90a323..477f89e4c3abd 100644 --- a/Lib/importlib/_legacy.py +++ b/Lib/importlib/_legacy.py @@ -1,6 +1,8 @@ +import functools import os import pathlib import types +import warnings from typing import Union, Iterable, ContextManager, BinaryIO, TextIO @@ -10,16 +12,34 @@ Resource = Union[str, os.PathLike] +def deprecated(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + warnings.warn( + f"{func.__name__} is deprecated. Use files() instead. " + "Refer to https://importlib-resources.readthedocs.io" + "/en/latest/using.html#migrating-from-legacy for migration advice.", + DeprecationWarning, + stacklevel=2, + ) + return func(*args, **kwargs) + + return wrapper + + + at deprecated def open_binary(package: Package, resource: Resource) -> BinaryIO: """Return a file-like object opened for binary reading of the resource.""" return (_common.files(package) / _common.normalize_path(resource)).open('rb') + at deprecated def read_binary(package: Package, resource: Resource) -> bytes: """Return the binary contents of the resource.""" return (_common.files(package) / _common.normalize_path(resource)).read_bytes() + at deprecated def open_text( package: Package, resource: Resource, @@ -32,6 +52,7 @@ def open_text( ) + at deprecated def read_text( package: Package, resource: Resource, @@ -47,6 +68,7 @@ def read_text( return fp.read() + at deprecated def contents(package: Package) -> Iterable[str]: """Return an iterable of entries in `package`. @@ -57,6 +79,7 @@ def contents(package: Package) -> Iterable[str]: return [path.name for path in _common.files(package).iterdir()] + at deprecated def is_resource(package: Package, name: str) -> bool: """True if `name` is a resource inside `package`. @@ -69,6 +92,7 @@ def is_resource(package: Package, name: str) -> bool: ) + at deprecated def path( package: Package, resource: Resource, diff --git a/Lib/test/test_importlib/resources/util.py b/Lib/test/test_importlib/resources/util.py index d7a049bf8044c..719263223032a 100644 --- a/Lib/test/test_importlib/resources/util.py +++ b/Lib/test/test_importlib/resources/util.py @@ -1,8 +1,10 @@ import abc +import contextlib import importlib import io import sys import types +import warnings from pathlib import Path, PurePath from .. import data01 @@ -67,6 +69,13 @@ def create_package(file=None, path=None, is_package=True, contents=()): ) + at contextlib.contextmanager +def suppress_known_deprecation(): + with warnings.catch_warnings(record=True) as ctx: + warnings.simplefilter('default', category=DeprecationWarning) + yield ctx + + class CommonTests(metaclass=abc.ABCMeta): """ Tests shared by test_open, test_path, and test_read. diff --git a/Lib/test/test_importlib/test_contents.py b/Lib/test/test_importlib/test_contents.py index 0f3aa84f5b512..575dcd2f30473 100644 --- a/Lib/test/test_importlib/test_contents.py +++ b/Lib/test/test_importlib/test_contents.py @@ -15,7 +15,8 @@ class ContentsTests: } def test_contents(self): - assert self.expected <= set(resources.contents(self.data)) + with util.suppress_known_deprecation(): + assert self.expected <= set(resources.contents(self.data)) class ContentsDiskTests(ContentsTests, unittest.TestCase): diff --git a/Lib/test/test_importlib/test_open.py b/Lib/test/test_importlib/test_open.py index 6f88ff78b73a0..a9c4a7085c197 100644 --- a/Lib/test/test_importlib/test_open.py +++ b/Lib/test/test_importlib/test_open.py @@ -7,38 +7,47 @@ class CommonBinaryTests(util.CommonTests, unittest.TestCase): def execute(self, package, path): - with resources.open_binary(package, path): - pass + with util.suppress_known_deprecation(): + with resources.open_binary(package, path): + pass class CommonTextTests(util.CommonTests, unittest.TestCase): def execute(self, package, path): - with resources.open_text(package, path): - pass + with util.suppress_known_deprecation(): + with resources.open_text(package, path): + pass class OpenTests: def test_open_binary(self): - with resources.open_binary(self.data, 'binary.file') as fp: - result = fp.read() - self.assertEqual(result, b'\x00\x01\x02\x03') + with util.suppress_known_deprecation(): + with resources.open_binary(self.data, 'binary.file') as fp: + result = fp.read() + self.assertEqual(result, b'\x00\x01\x02\x03') def test_open_text_default_encoding(self): - with resources.open_text(self.data, 'utf-8.file') as fp: - result = fp.read() + with util.suppress_known_deprecation(): + with resources.open_text(self.data, 'utf-8.file') as fp: + result = fp.read() self.assertEqual(result, 'Hello, UTF-8 world!\n') def test_open_text_given_encoding(self): - with resources.open_text(self.data, 'utf-16.file', 'utf-16', 'strict') as fp: - result = fp.read() + with util.suppress_known_deprecation(): + with resources.open_text( + self.data, 'utf-16.file', 'utf-16', 'strict' + ) as fp: + result = fp.read() self.assertEqual(result, 'Hello, UTF-16 world!\n') def test_open_text_with_errors(self): # Raises UnicodeError without the 'errors' argument. - with resources.open_text(self.data, 'utf-16.file', 'utf-8', 'strict') as fp: - self.assertRaises(UnicodeError, fp.read) - with resources.open_text(self.data, 'utf-16.file', 'utf-8', 'ignore') as fp: - result = fp.read() + with util.suppress_known_deprecation(): + with resources.open_text(self.data, 'utf-16.file', 'utf-8', 'strict') as fp: + self.assertRaises(UnicodeError, fp.read) + with util.suppress_known_deprecation(): + with resources.open_text(self.data, 'utf-16.file', 'utf-8', 'ignore') as fp: + result = fp.read() self.assertEqual( result, 'H\x00e\x00l\x00l\x00o\x00,\x00 ' @@ -47,14 +56,16 @@ def test_open_text_with_errors(self): ) def test_open_binary_FileNotFoundError(self): - self.assertRaises( - FileNotFoundError, resources.open_binary, self.data, 'does-not-exist' - ) + with util.suppress_known_deprecation(): + self.assertRaises( + FileNotFoundError, resources.open_binary, self.data, 'does-not-exist' + ) def test_open_text_FileNotFoundError(self): - self.assertRaises( - FileNotFoundError, resources.open_text, self.data, 'does-not-exist' - ) + with util.suppress_known_deprecation(): + self.assertRaises( + FileNotFoundError, resources.open_text, self.data, 'does-not-exist' + ) class OpenDiskTests(OpenTests, unittest.TestCase): diff --git a/Lib/test/test_importlib/test_path.py b/Lib/test/test_importlib/test_path.py index 4436d7f34ef41..3ccbc6fbd2af3 100644 --- a/Lib/test/test_importlib/test_path.py +++ b/Lib/test/test_importlib/test_path.py @@ -8,8 +8,9 @@ class CommonTests(util.CommonTests, unittest.TestCase): def execute(self, package, path): - with resources.path(package, path): - pass + with util.suppress_known_deprecation(): + with resources.path(package, path): + pass class PathTests: @@ -17,12 +18,13 @@ def test_reading(self): # Path should be readable. # Test also implicitly verifies the returned object is a pathlib.Path # instance. - with resources.path(self.data, 'utf-8.file') as path: - self.assertTrue(path.name.endswith("utf-8.file"), repr(path)) - # pathlib.Path.read_text() was introduced in Python 3.5. - with path.open('r', encoding='utf-8') as file: - text = file.read() - self.assertEqual('Hello, UTF-8 world!\n', text) + with util.suppress_known_deprecation(): + with resources.path(self.data, 'utf-8.file') as path: + self.assertTrue(path.name.endswith("utf-8.file"), repr(path)) + # pathlib.Path.read_text() was introduced in Python 3.5. + with path.open('r', encoding='utf-8') as file: + text = file.read() + self.assertEqual('Hello, UTF-8 world!\n', text) class PathDiskTests(PathTests, unittest.TestCase): @@ -32,8 +34,9 @@ def test_natural_path(self): # Guarantee the internal implementation detail that # file-system-backed resources do not get the tempdir # treatment. - with resources.path(self.data, 'utf-8.file') as path: - assert 'data' in str(path) + with util.suppress_known_deprecation(): + with resources.path(self.data, 'utf-8.file') as path: + assert 'data' in str(path) class PathMemoryTests(PathTests, unittest.TestCase): @@ -51,8 +54,9 @@ class PathZipTests(PathTests, util.ZipSetup, unittest.TestCase): def test_remove_in_context_manager(self): # It is not an error if the file that was temporarily stashed on the # file system is removed inside the `with` stanza. - with resources.path(self.data, 'utf-8.file') as path: - path.unlink() + with util.suppress_known_deprecation(): + with resources.path(self.data, 'utf-8.file') as path: + path.unlink() if __name__ == '__main__': diff --git a/Lib/test/test_importlib/test_read.py b/Lib/test/test_importlib/test_read.py index 357980132b6ec..1bab5c97f41bf 100644 --- a/Lib/test/test_importlib/test_read.py +++ b/Lib/test/test_importlib/test_read.py @@ -7,31 +7,40 @@ class CommonBinaryTests(util.CommonTests, unittest.TestCase): def execute(self, package, path): - resources.read_binary(package, path) + with util.suppress_known_deprecation(): + resources.read_binary(package, path) class CommonTextTests(util.CommonTests, unittest.TestCase): def execute(self, package, path): - resources.read_text(package, path) + with util.suppress_known_deprecation(): + resources.read_text(package, path) class ReadTests: def test_read_binary(self): - result = resources.read_binary(self.data, 'binary.file') + with util.suppress_known_deprecation(): + result = resources.read_binary(self.data, 'binary.file') self.assertEqual(result, b'\0\1\2\3') def test_read_text_default_encoding(self): - result = resources.read_text(self.data, 'utf-8.file') + with util.suppress_known_deprecation(): + result = resources.read_text(self.data, 'utf-8.file') self.assertEqual(result, 'Hello, UTF-8 world!\n') def test_read_text_given_encoding(self): - result = resources.read_text(self.data, 'utf-16.file', encoding='utf-16') + with util.suppress_known_deprecation(): + result = resources.read_text(self.data, 'utf-16.file', encoding='utf-16') self.assertEqual(result, 'Hello, UTF-16 world!\n') def test_read_text_with_errors(self): # Raises UnicodeError without the 'errors' argument. - self.assertRaises(UnicodeError, resources.read_text, self.data, 'utf-16.file') - result = resources.read_text(self.data, 'utf-16.file', errors='ignore') + with util.suppress_known_deprecation(): + self.assertRaises( + UnicodeError, resources.read_text, self.data, 'utf-16.file' + ) + with util.suppress_known_deprecation(): + result = resources.read_text(self.data, 'utf-16.file', errors='ignore') self.assertEqual( result, 'H\x00e\x00l\x00l\x00o\x00,\x00 ' @@ -47,11 +56,13 @@ class ReadDiskTests(ReadTests, unittest.TestCase): class ReadZipTests(ReadTests, util.ZipSetup, unittest.TestCase): def test_read_submodule_resource(self): submodule = import_module('ziptestdata.subdirectory') - result = resources.read_binary(submodule, 'binary.file') + with util.suppress_known_deprecation(): + result = resources.read_binary(submodule, 'binary.file') self.assertEqual(result, b'\0\1\2\3') def test_read_submodule_resource_by_name(self): - result = resources.read_binary('ziptestdata.subdirectory', 'binary.file') + with util.suppress_known_deprecation(): + result = resources.read_binary('ziptestdata.subdirectory', 'binary.file') self.assertEqual(result, b'\0\1\2\3') diff --git a/Lib/test/test_importlib/test_resource.py b/Lib/test/test_importlib/test_resource.py index 612bada5e0316..39904591a5248 100644 --- a/Lib/test/test_importlib/test_resource.py +++ b/Lib/test/test_importlib/test_resource.py @@ -15,17 +15,21 @@ class ResourceTests: # Subclasses are expected to set the `data` attribute. def test_is_resource_good_path(self): - self.assertTrue(resources.is_resource(self.data, 'binary.file')) + with util.suppress_known_deprecation(): + self.assertTrue(resources.is_resource(self.data, 'binary.file')) def test_is_resource_missing(self): - self.assertFalse(resources.is_resource(self.data, 'not-a-file')) + with util.suppress_known_deprecation(): + self.assertFalse(resources.is_resource(self.data, 'not-a-file')) def test_is_resource_subresource_directory(self): # Directories are not resources. - self.assertFalse(resources.is_resource(self.data, 'subdirectory')) + with util.suppress_known_deprecation(): + self.assertFalse(resources.is_resource(self.data, 'subdirectory')) def test_contents(self): - contents = set(resources.contents(self.data)) + with util.suppress_known_deprecation(): + contents = set(resources.contents(self.data)) # There may be cruft in the directory listing of the data directory. # It could have a __pycache__ directory, # an artifact of the @@ -58,25 +62,29 @@ def test_resource_contents(self): package = util.create_package( file=data01, path=data01.__file__, contents=['A', 'B', 'C'] ) - self.assertEqual(set(resources.contents(package)), {'A', 'B', 'C'}) + with util.suppress_known_deprecation(): + self.assertEqual(set(resources.contents(package)), {'A', 'B', 'C'}) def test_resource_is_resource(self): package = util.create_package( file=data01, path=data01.__file__, contents=['A', 'B', 'C', 'D/E', 'D/F'] ) - self.assertTrue(resources.is_resource(package, 'B')) + with util.suppress_known_deprecation(): + self.assertTrue(resources.is_resource(package, 'B')) def test_resource_directory_is_not_resource(self): package = util.create_package( file=data01, path=data01.__file__, contents=['A', 'B', 'C', 'D/E', 'D/F'] ) - self.assertFalse(resources.is_resource(package, 'D')) + with util.suppress_known_deprecation(): + self.assertFalse(resources.is_resource(package, 'D')) def test_resource_missing_is_not_resource(self): package = util.create_package( file=data01, path=data01.__file__, contents=['A', 'B', 'C', 'D/E', 'D/F'] ) - self.assertFalse(resources.is_resource(package, 'Z')) + with util.suppress_known_deprecation(): + self.assertFalse(resources.is_resource(package, 'Z')) class ResourceCornerCaseTests(unittest.TestCase): @@ -94,7 +102,8 @@ def test_package_has_no_reader_fallback(self): module.__file__ = '/path/which/shall/not/be/named' module.__spec__.loader = module.__loader__ module.__spec__.origin = module.__file__ - self.assertFalse(resources.is_resource(module, 'A')) + with util.suppress_known_deprecation(): + self.assertFalse(resources.is_resource(module, 'A')) class ResourceFromZipsTest01(util.ZipSetupBase, unittest.TestCase): @@ -102,24 +111,28 @@ class ResourceFromZipsTest01(util.ZipSetupBase, unittest.TestCase): def test_is_submodule_resource(self): submodule = import_module('ziptestdata.subdirectory') - self.assertTrue(resources.is_resource(submodule, 'binary.file')) + with util.suppress_known_deprecation(): + self.assertTrue(resources.is_resource(submodule, 'binary.file')) def test_read_submodule_resource_by_name(self): - self.assertTrue( - resources.is_resource('ziptestdata.subdirectory', 'binary.file') - ) + with util.suppress_known_deprecation(): + self.assertTrue( + resources.is_resource('ziptestdata.subdirectory', 'binary.file') + ) def test_submodule_contents(self): submodule = import_module('ziptestdata.subdirectory') - self.assertEqual( - set(resources.contents(submodule)), {'__init__.py', 'binary.file'} - ) + with util.suppress_known_deprecation(): + self.assertEqual( + set(resources.contents(submodule)), {'__init__.py', 'binary.file'} + ) def test_submodule_contents_by_name(self): - self.assertEqual( - set(resources.contents('ziptestdata.subdirectory')), - {'__init__.py', 'binary.file'}, - ) + with util.suppress_known_deprecation(): + self.assertEqual( + set(resources.contents('ziptestdata.subdirectory')), + {'__init__.py', 'binary.file'}, + ) class ResourceFromZipsTest02(util.ZipSetupBase, unittest.TestCase): @@ -130,12 +143,16 @@ def test_unrelated_contents(self): Test thata zip with two unrelated subpackages return distinct resources. Ref python/importlib_resources#44. """ - self.assertEqual( - set(resources.contents('ziptestdata.one')), {'__init__.py', 'resource1.txt'} - ) - self.assertEqual( - set(resources.contents('ziptestdata.two')), {'__init__.py', 'resource2.txt'} - ) + with util.suppress_known_deprecation(): + self.assertEqual( + set(resources.contents('ziptestdata.one')), + {'__init__.py', 'resource1.txt'}, + ) + with util.suppress_known_deprecation(): + self.assertEqual( + set(resources.contents('ziptestdata.two')), + {'__init__.py', 'resource2.txt'}, + ) class DeletingZipsTest(unittest.TestCase): @@ -176,17 +193,20 @@ def tearDown(self): pass def test_contents_does_not_keep_open(self): - c = resources.contents('ziptestdata') + with util.suppress_known_deprecation(): + c = resources.contents('ziptestdata') self.zip_path.unlink() del c def test_is_resource_does_not_keep_open(self): - c = resources.is_resource('ziptestdata', 'binary.file') + with util.suppress_known_deprecation(): + c = resources.is_resource('ziptestdata', 'binary.file') self.zip_path.unlink() del c def test_is_resource_failure_does_not_keep_open(self): - c = resources.is_resource('ziptestdata', 'not-present') + with util.suppress_known_deprecation(): + c = resources.is_resource('ziptestdata', 'not-present') self.zip_path.unlink() del c @@ -199,17 +219,20 @@ def test_path_does_not_keep_open(self): def test_entered_path_does_not_keep_open(self): # This is what certifi does on import to make its bundle # available for the process duration. - c = resources.path('ziptestdata', 'binary.file').__enter__() + with util.suppress_known_deprecation(): + c = resources.path('ziptestdata', 'binary.file').__enter__() self.zip_path.unlink() del c def test_read_binary_does_not_keep_open(self): - c = resources.read_binary('ziptestdata', 'binary.file') + with util.suppress_known_deprecation(): + c = resources.read_binary('ziptestdata', 'binary.file') self.zip_path.unlink() del c def test_read_text_does_not_keep_open(self): - c = resources.read_text('ziptestdata', 'utf-8.file', encoding='utf-8') + with util.suppress_known_deprecation(): + c = resources.read_text('ziptestdata', 'utf-8.file', encoding='utf-8') self.zip_path.unlink() del c @@ -226,15 +249,18 @@ def tearDownClass(cls): sys.path.remove(cls.site_dir) def test_is_submodule_resource(self): - self.assertTrue( - resources.is_resource(import_module('namespacedata01'), 'binary.file') - ) + with util.suppress_known_deprecation(): + self.assertTrue( + resources.is_resource(import_module('namespacedata01'), 'binary.file') + ) def test_read_submodule_resource_by_name(self): - self.assertTrue(resources.is_resource('namespacedata01', 'binary.file')) + with util.suppress_known_deprecation(): + self.assertTrue(resources.is_resource('namespacedata01', 'binary.file')) def test_submodule_contents(self): - contents = set(resources.contents(import_module('namespacedata01'))) + with util.suppress_known_deprecation(): + contents = set(resources.contents(import_module('namespacedata01'))) try: contents.remove('__pycache__') except KeyError: @@ -242,7 +268,8 @@ def test_submodule_contents(self): self.assertEqual(contents, {'binary.file', 'utf-8.file', 'utf-16.file'}) def test_submodule_contents_by_name(self): - contents = set(resources.contents('namespacedata01')) + with util.suppress_known_deprecation(): + contents = set(resources.contents('namespacedata01')) try: contents.remove('__pycache__') except KeyError: diff --git a/Misc/NEWS.d/next/Library/2021-10-18-14-25-35.bpo-45514.YmlzIl.rst b/Misc/NEWS.d/next/Library/2021-10-18-14-25-35.bpo-45514.YmlzIl.rst new file mode 100644 index 0000000000000..03f944faa8fd7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-10-18-14-25-35.bpo-45514.YmlzIl.rst @@ -0,0 +1 @@ +Deprecated legacy functions in :mod:`importlib.resources`. From webhook-mailer at python.org Wed Nov 24 04:20:49 2021 From: webhook-mailer at python.org (tiran) Date: Wed, 24 Nov 2021 09:20:49 -0000 Subject: [Python-checkins] bpo-45847: Port _uuid to PY_STDLIB_MOD (GH-29741) Message-ID: https://github.com/python/cpython/commit/8af6481f6b7d43646c47d8fa6cc6d5eb465e2b0f commit: 8af6481f6b7d43646c47d8fa6cc6d5eb465e2b0f branch: main author: Christian Heimes committer: tiran date: 2021-11-24T10:20:37+01:00 summary: bpo-45847: Port _uuid to PY_STDLIB_MOD (GH-29741) files: M Modules/Setup.stdlib.in M Modules/_uuidmodule.c M configure M configure.ac M pyconfig.h.in M setup.py diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index e999775caf3f7..eadd1619a3b38 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -136,6 +136,8 @@ # needs -lcrypt @MODULE__HASHLIB_TRUE at _hashlib _hashopenssl.c +# Linux: -luuid, BSD/AIX: libc's uuid_create() + at MODULE__UUID_TRUE@_uuid _uuidmodule.c ############################################################################ # macOS specific modules diff --git a/Modules/_uuidmodule.c b/Modules/_uuidmodule.c index 3f33e22a055c6..eae38f5c98cc7 100644 --- a/Modules/_uuidmodule.c +++ b/Modules/_uuidmodule.c @@ -6,10 +6,12 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" -#ifdef HAVE_UUID_UUID_H -#include -#elif defined(HAVE_UUID_H) -#include +#if defined(HAVE_UUID_H) + // AIX, FreeBSD, libuuid with pkgconf + #include +#elif defined(HAVE_UUID_UUID_H) + // libuuid without pkgconf + #include #endif #ifdef MS_WINDOWS diff --git a/configure b/configure index 70c94a4e24d60..d2d79920d08ff 100755 --- a/configure +++ b/configure @@ -654,6 +654,8 @@ MODULE_BINASCII_FALSE MODULE_BINASCII_TRUE MODULE_ZLIB_FALSE MODULE_ZLIB_TRUE +MODULE__UUID_FALSE +MODULE__UUID_TRUE MODULE__SQLITE3_FALSE MODULE__SQLITE3_TRUE MODULE_NIS_FALSE @@ -827,6 +829,8 @@ LIBEXPAT_INTERNAL LIBEXPAT_LDFLAGS LIBEXPAT_CFLAGS TZPATH +LIBUUID_LIBS +LIBUUID_CFLAGS SHLIBS CFLAGSFORSHARED LINKFORSHARED @@ -1046,6 +1050,8 @@ LIBS CPPFLAGS CPP PROFILE_TASK +LIBUUID_CFLAGS +LIBUUID_LIBS LIBNSL_CFLAGS LIBNSL_LIBS LIBSQLITE3_CFLAGS @@ -1833,6 +1839,10 @@ Some influential environment variables: CPP C preprocessor PROFILE_TASK Python args for PGO generation task + LIBUUID_CFLAGS + C compiler flags for LIBUUID, overriding pkg-config + LIBUUID_LIBS + linker flags for LIBUUID, overriding pkg-config LIBNSL_CFLAGS C compiler flags for LIBNSL, overriding pkg-config LIBNSL_LIBS linker flags for LIBNSL, overriding pkg-config @@ -10371,62 +10381,252 @@ _ACEOF fi # Dynamic linking for HP-UX -# checks for uuid.h location -for ac_header in uuid/uuid.h uuid.h + +have_uuid=missing + +for ac_header in uuid.h do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + ac_fn_c_check_header_mongrel "$LINENO" "uuid.h" "ac_cv_header_uuid_h" "$ac_includes_default" +if test "x$ac_cv_header_uuid_h" = xyes; then : cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +#define HAVE_UUID_H 1 _ACEOF + for ac_func in uuid_create uuid_enc_be +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + + have_uuid=yes + LIBUUID_CFLAGS= + LIBUUID_LIBS= + +fi +done + + fi done -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time_safe" >&5 -$as_echo_n "checking for uuid_generate_time_safe... " >&6; } -if ${ac_cv_lib_uuid_uuid_generate_time_safe+:} false; then : - $as_echo_n "(cached) " >&6 + + + + +if test "x$have_uuid" = xmissing; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBUUID" >&5 +$as_echo_n "checking for LIBUUID... " >&6; } + +if test -n "$LIBUUID_CFLAGS"; then + pkg_cv_LIBUUID_CFLAGS="$LIBUUID_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"uuid >= 2.20\""; } >&5 + ($PKG_CONFIG --exists --print-errors "uuid >= 2.20") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBUUID_CFLAGS=`$PKG_CONFIG --cflags "uuid >= 2.20" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LIBUUID_LIBS"; then + pkg_cv_LIBUUID_LIBS="$LIBUUID_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"uuid >= 2.20\""; } >&5 + ($PKG_CONFIG --exists --print-errors "uuid >= 2.20") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBUUID_LIBS=`$PKG_CONFIG --libs "uuid >= 2.20" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LIBUUID_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "uuid >= 2.20" 2>&1` + else + LIBUUID_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "uuid >= 2.20" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LIBUUID_PKG_ERRORS" >&5 + + + LIBUUID_LIBS="-luuid" + LIBUUID_CFLAGS= + have_uuid=no + for ac_header in uuid/uuid.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "uuid/uuid.h" "ac_cv_header_uuid_uuid_h" "$ac_includes_default" +if test "x$ac_cv_header_uuid_uuid_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_UUID_UUID_H 1 +_ACEOF + + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time in -luuid" >&5 +$as_echo_n "checking for uuid_generate_time in -luuid... " >&6; } +if ${ac_cv_lib_uuid_uuid_generate_time+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-luuid $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char uuid_generate_time (); int main () { +return uuid_generate_time (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_uuid_uuid_generate_time=yes +else + ac_cv_lib_uuid_uuid_generate_time=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_uuid_uuid_generate_time" >&5 +$as_echo "$ac_cv_lib_uuid_uuid_generate_time" >&6; } +if test "x$ac_cv_lib_uuid_uuid_generate_time" = xyes; then : + have_uuid=yes +fi -#ifndef uuid_generate_time_safe -void *x = uuid_generate_time_safe -#endif +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS + + + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time_safe in -luuid" >&5 +$as_echo_n "checking for uuid_generate_time_safe in -luuid... " >&6; } +if ${ac_cv_lib_uuid_uuid_generate_time_safe+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-luuid $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char uuid_generate_time_safe (); +int +main () +{ +return uuid_generate_time_safe (); ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_uuid_uuid_generate_time_safe=yes else ac_cv_lib_uuid_uuid_generate_time_safe=no fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_uuid_uuid_generate_time_safe" >&5 $as_echo "$ac_cv_lib_uuid_uuid_generate_time_safe" >&6; } if test "x$ac_cv_lib_uuid_uuid_generate_time_safe" = xyes; then : + have_uuid=yes + $as_echo "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h + + +fi + + +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS -$as_echo "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h fi -# check for libuuid from util-linux +done + + + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + LIBUUID_LIBS="-luuid" + LIBUUID_CFLAGS= + have_uuid=no + for ac_header in uuid/uuid.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "uuid/uuid.h" "ac_cv_header_uuid_uuid_h" "$ac_includes_default" +if test "x$ac_cv_header_uuid_uuid_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_UUID_UUID_H 1 +_ACEOF + + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS save_LIBS=$LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time in -luuid" >&5 $as_echo_n "checking for uuid_generate_time in -luuid... " >&6; } if ${ac_cv_lib_uuid_uuid_generate_time+:} false; then : @@ -10464,33 +10664,96 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_uuid_uuid_generate_time" >&5 $as_echo "$ac_cv_lib_uuid_uuid_generate_time" >&6; } if test "x$ac_cv_lib_uuid_uuid_generate_time" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBUUID 1 + have_uuid=yes +fi + + +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS + + + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time_safe in -luuid" >&5 +$as_echo_n "checking for uuid_generate_time_safe in -luuid... " >&6; } +if ${ac_cv_lib_uuid_uuid_generate_time_safe+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-luuid $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char uuid_generate_time_safe (); +int +main () +{ +return uuid_generate_time_safe (); + ; + return 0; +} _ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_uuid_uuid_generate_time_safe=yes +else + ac_cv_lib_uuid_uuid_generate_time_safe=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_uuid_uuid_generate_time_safe" >&5 +$as_echo "$ac_cv_lib_uuid_uuid_generate_time_safe" >&6; } +if test "x$ac_cv_lib_uuid_uuid_generate_time_safe" = xyes; then : + + have_uuid=yes + $as_echo "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h - LIBS="-luuid $LIBS" fi + +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS -# AIX provides support for RFC4122 (uuid) in libc.a starting with AIX 6.1 (anno 2007) -# FreeBSD and OpenBSD provides support in libc as well. -# Little-endian FreeBSD, OpenBSD and NetBSD needs encoding into an octet -# stream in big-endian byte-order -for ac_func in uuid_create uuid_enc_be -do : - as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` -ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -if eval test \"x\$"$as_ac_var"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF + fi + done + +else + LIBUUID_CFLAGS=$pkg_cv_LIBUUID_CFLAGS + LIBUUID_LIBS=$pkg_cv_LIBUUID_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + have_uuid=yes + $as_echo "#define HAVE_UUID_H 1" >>confdefs.h + + $as_echo "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h + + +fi + +fi + # 'Real Time' functions on Solaris # posix4 on Solaris 2.6 # pthread (first!) on Linux @@ -21905,6 +22168,42 @@ fi $as_echo "$py_cv_module__sqlite3" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _uuid" >&5 +$as_echo_n "checking for stdlib extension module _uuid... " >&6; } + case $py_stdlib_not_available in #( + *_uuid*) : + py_cv_module__uuid=n/a ;; #( + *) : + if true; then : + if test "$have_uuid" = "yes"; then : + py_cv_module__uuid=yes +else + py_cv_module__uuid=missing +fi +else + py_cv_module__uuid=disabled +fi + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__UUID=$py_cv_module__uuid$as_nl" + if test "x$py_cv_module__uuid" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE__UUID_CFLAGS=$LIBUUID_CFLAGS$as_nl" + as_fn_append MODULE_BLOCK "MODULE__UUID_LDFLAGS=$LIBUUID_LIBS$as_nl" + +fi + if test "$py_cv_module__uuid" = yes; then + MODULE__UUID_TRUE= + MODULE__UUID_FALSE='#' +else + MODULE__UUID_TRUE='#' + MODULE__UUID_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__uuid" >&5 +$as_echo "$py_cv_module__uuid" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module zlib" >&5 $as_echo_n "checking for stdlib extension module zlib... " >&6; } @@ -22774,6 +23073,10 @@ if test -z "${MODULE__SQLITE3_TRUE}" && test -z "${MODULE__SQLITE3_FALSE}"; then as_fn_error $? "conditional \"MODULE__SQLITE3\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__UUID_TRUE}" && test -z "${MODULE__UUID_FALSE}"; then + as_fn_error $? "conditional \"MODULE__UUID\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE_ZLIB_TRUE}" && test -z "${MODULE_ZLIB_FALSE}"; then as_fn_error $? "conditional \"MODULE_ZLIB\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index a161a8cf88545..4961e5a2553c3 100644 --- a/configure.ac +++ b/configure.ac @@ -2871,31 +2871,51 @@ AC_CHECK_LIB(sendfile, sendfile) AC_CHECK_LIB(dl, dlopen) # Dynamic linking for SunOS/Solaris and SYSV AC_CHECK_LIB(dld, shl_load) # Dynamic linking for HP-UX -# checks for uuid.h location -AC_CHECK_HEADERS([uuid/uuid.h uuid.h]) -AC_CACHE_CHECK([for uuid_generate_time_safe], [ac_cv_lib_uuid_uuid_generate_time_safe], [ -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ -#ifndef uuid_generate_time_safe -void *x = uuid_generate_time_safe -#endif -]])], -[ac_cv_lib_uuid_uuid_generate_time_safe=yes], [ac_cv_lib_uuid_uuid_generate_time_safe=no]) -]) -AS_VAR_IF([ac_cv_lib_uuid_uuid_generate_time_safe], [yes], [ - AC_DEFINE(HAVE_UUID_GENERATE_TIME_SAFE, 1, [Define if uuid_generate_time_safe() exists.]) +dnl check for uuid dependencies +AH_TEMPLATE([HAVE_UUID_H], [Define to 1 if you have the header file.]) +AH_TEMPLATE([HAVE_UUID_UUID_H], [Define to 1 if you have the header file.]) +AH_TEMPLATE([HAVE_UUID_GENERATE_TIME_SAFE], [Define if uuid_generate_time_safe() exists.]) +have_uuid=missing + +dnl AIX provides support for RFC4122 (uuid) in libc.a starting with AIX 6.1 +dnl (anno 2007). FreeBSD and OpenBSD provides support in libc as well. +dnl Little-endian FreeBSD, OpenBSD and NetBSD needs encoding into an octet +dnl stream in big-endian byte-order +AC_CHECK_HEADERS([uuid.h], [ + AC_CHECK_FUNCS([uuid_create uuid_enc_be], [ + have_uuid=yes + LIBUUID_CFLAGS= + LIBUUID_LIBS= + ]) ]) -# check for libuuid from util-linux -save_LIBS=$LIBS -AC_CHECK_LIB([uuid], [uuid_generate_time]) -LIBS=$save_LIBS - -# AIX provides support for RFC4122 (uuid) in libc.a starting with AIX 6.1 (anno 2007) -# FreeBSD and OpenBSD provides support in libc as well. -# Little-endian FreeBSD, OpenBSD and NetBSD needs encoding into an octet -# stream in big-endian byte-order -AC_CHECK_FUNCS([uuid_create uuid_enc_be]) +AS_VAR_IF([have_uuid], [missing], [ + PKG_CHECK_MODULES( + [LIBUUID], [uuid >= 2.20], [ + dnl linux-util's libuuid has uuid_generate_time_safe() since v2.20 (2011) + dnl and provides . + have_uuid=yes + AC_DEFINE([HAVE_UUID_H], [1]) + AC_DEFINE([HAVE_UUID_GENERATE_TIME_SAFE], [1]) + ], [ + LIBUUID_LIBS="-luuid" + LIBUUID_CFLAGS= + have_uuid=no + AC_CHECK_HEADERS([uuid/uuid.h], [ + WITH_SAVE_ENV( + [AC_CHECK_LIB([uuid], [uuid_generate_time], [have_uuid=yes]) + ]) + WITH_SAVE_ENV([ + AC_CHECK_LIB([uuid], [uuid_generate_time_safe], [ + have_uuid=yes + AC_DEFINE([HAVE_UUID_GENERATE_TIME_SAFE], [1]) + ]) + ]) + ]) + ] + ) +]) # 'Real Time' functions on Solaris # posix4 on Solaris 2.6 @@ -6299,6 +6319,9 @@ PY_STDLIB_MOD([_sqlite3], [test "$have_sqlite3" = "yes"], [test "$have_supported_sqlite3" = "yes"], [$LIBSQLITE3_CFLAGS], [$LIBSQLITE3_LIBS]) +PY_STDLIB_MOD([_uuid], + [], [test "$have_uuid" = "yes"], + [$LIBUUID_CFLAGS], [$LIBUUID_LIBS]) dnl compression libs PY_STDLIB_MOD([zlib], [], [test "$have_zlib" = yes], diff --git a/pyconfig.h.in b/pyconfig.h.in index 67f27c2b17e3b..842759fb213ae 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -628,9 +628,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LIBUTIL_H -/* Define to 1 if you have the `uuid' library (-luuid). */ -#undef HAVE_LIBUUID - /* Define if you have the 'link' function. */ #undef HAVE_LINK diff --git a/setup.py b/setup.py index 72497de5c0d3a..932667ad0c2ff 100644 --- a/setup.py +++ b/setup.py @@ -1401,17 +1401,7 @@ def detect_multiprocessing(self): def detect_uuid(self): # Build the _uuid module if possible - uuid_h = sysconfig.get_config_var("HAVE_UUID_H") - uuid_uuid_h = sysconfig.get_config_var("HAVE_UUID_UUID_H") - if uuid_h or uuid_uuid_h: - if sysconfig.get_config_var("HAVE_LIBUUID"): - uuid_libs = ["uuid"] - else: - uuid_libs = [] - self.add(Extension('_uuid', ['_uuidmodule.c'], - libraries=uuid_libs)) - else: - self.missing.append('_uuid') + self.addext(Extension('_uuid', ['_uuidmodule.c'])) def detect_modules(self): # remove dummy extension From webhook-mailer at python.org Wed Nov 24 04:47:31 2021 From: webhook-mailer at python.org (tiran) Date: Wed, 24 Nov 2021 09:47:31 -0000 Subject: [Python-checkins] bpo-45847: Fix _crypt detection on Ubuntu (GH-29743) Message-ID: https://github.com/python/cpython/commit/64c3807da93fc3e0c15bc376f220b2d24551023e commit: 64c3807da93fc3e0c15bc376f220b2d24551023e branch: main author: Christian Heimes committer: tiran date: 2021-11-24T10:47:22+01:00 summary: bpo-45847: Fix _crypt detection on Ubuntu (GH-29743) files: M configure M configure.ac diff --git a/configure b/configure index d2d79920d08ff..abfda2b00de74 100755 --- a/configure +++ b/configure @@ -15805,7 +15805,7 @@ save_LIBS=$LIBS CPPFLAGS="$LIBCRYPT_CFLAGS $CFLAGS" - LDFLAGS="$LIBCRYPT_LIBS $LDFLAGS" + LIBS="$LIBCRYPT_LIBS $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for crypt or crypt_r" >&5 $as_echo_n "checking for crypt or crypt_r... " >&6; } if ${ac_cv_crypt_crypt+:} false; then : diff --git a/configure.ac b/configure.ac index 4961e5a2553c3..1853baa5a8e8c 100644 --- a/configure.ac +++ b/configure.ac @@ -4243,7 +4243,7 @@ PKG_CHECK_MODULES([LIBCRYPT], [libxcrypt >= 3.1.1], [ WITH_SAVE_ENV([ CPPFLAGS="$LIBCRYPT_CFLAGS $CFLAGS" - LDFLAGS="$LIBCRYPT_LIBS $LDFLAGS" + LIBS="$LIBCRYPT_LIBS $LIBS" AC_CACHE_CHECK([for crypt or crypt_r], [ac_cv_crypt_crypt], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([ #ifdef HAVE_CRYPT_H From webhook-mailer at python.org Wed Nov 24 12:53:42 2021 From: webhook-mailer at python.org (tiran) Date: Wed, 24 Nov 2021 17:53:42 -0000 Subject: [Python-checkins] bpo-45881: Use CC from env first for cross building (GH-29752) Message-ID: https://github.com/python/cpython/commit/b30bf4520ae9d6e7eca09d812dd8a86c020b9202 commit: b30bf4520ae9d6e7eca09d812dd8a86c020b9202 branch: main author: Christian Heimes committer: tiran date: 2021-11-24T18:53:33+01:00 summary: bpo-45881: Use CC from env first for cross building (GH-29752) files: A Misc/NEWS.d/next/Build/2021-11-24-17-14-06.bpo-45881.GTXXLk.rst M setup.py diff --git a/Misc/NEWS.d/next/Build/2021-11-24-17-14-06.bpo-45881.GTXXLk.rst b/Misc/NEWS.d/next/Build/2021-11-24-17-14-06.bpo-45881.GTXXLk.rst new file mode 100644 index 0000000000000..b697658cf3aaa --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-24-17-14-06.bpo-45881.GTXXLk.rst @@ -0,0 +1,2 @@ +``setup.py`` now uses ``CC`` from environment first to discover multiarch +and cross compile paths. diff --git a/setup.py b/setup.py index 932667ad0c2ff..79f8f4ef50817 100644 --- a/setup.py +++ b/setup.py @@ -84,6 +84,9 @@ def get_platform(): MACOS = (HOST_PLATFORM == 'darwin') AIX = (HOST_PLATFORM.startswith('aix')) VXWORKS = ('vxworks' in HOST_PLATFORM) +CC = os.environ.get("CC") +if not CC: + CC = sysconfig.get_config_var("CC") SUMMARY = """ @@ -556,6 +559,9 @@ def set_compiler_executables(self): def build_extensions(self): self.set_srcdir() + self.set_compiler_executables() + self.configure_compiler() + self.init_inc_lib_dirs() # Detect which modules should be compiled self.detect_modules() @@ -565,7 +571,6 @@ def build_extensions(self): self.update_sources_depends() mods_built, mods_disabled = self.handle_configured_extensions() - self.set_compiler_executables() if LIST_MODULE_NAMES: for ext in self.extensions: @@ -751,12 +756,11 @@ def check_extension_import(self, ext): def add_multiarch_paths(self): # Debian/Ubuntu multiarch support. # https://wiki.ubuntu.com/MultiarchSpec - cc = sysconfig.get_config_var('CC') tmpfile = os.path.join(self.build_temp, 'multiarch') if not os.path.exists(self.build_temp): os.makedirs(self.build_temp) ret = run_command( - '%s -print-multiarch > %s 2> /dev/null' % (cc, tmpfile)) + '%s -print-multiarch > %s 2> /dev/null' % (CC, tmpfile)) multiarch_path_component = '' try: if ret == 0: @@ -818,11 +822,10 @@ def add_search_path(line): d = os.path.normpath(d) add_dir_to_list(self.compiler.library_dirs, d) - cc = sysconfig.get_config_var('CC') tmpfile = os.path.join(self.build_temp, 'wrccpaths') os.makedirs(self.build_temp, exist_ok=True) try: - ret = run_command('%s --print-search-dirs >%s' % (cc, tmpfile)) + ret = run_command('%s --print-search-dirs >%s' % (CC, tmpfile)) if ret: return with open(tmpfile) as fp: @@ -840,11 +843,10 @@ def add_search_path(line): pass def add_cross_compiling_paths(self): - cc = sysconfig.get_config_var('CC') tmpfile = os.path.join(self.build_temp, 'ccpaths') if not os.path.exists(self.build_temp): os.makedirs(self.build_temp) - ret = run_command('%s -E -v - %s 1>/dev/null' % (cc, tmpfile)) + ret = run_command('%s -E -v - %s 1>/dev/null' % (CC, tmpfile)) is_gcc = False is_clang = False in_incdirs = False @@ -1407,9 +1409,6 @@ def detect_modules(self): # remove dummy extension self.extensions = [] - self.configure_compiler() - self.init_inc_lib_dirs() - # Some C extensions are built by entries in Modules/Setup.bootstrap. # These are extensions are required to bootstrap the interpreter or # build process. From webhook-mailer at python.org Wed Nov 24 13:30:14 2021 From: webhook-mailer at python.org (pablogsal) Date: Wed, 24 Nov 2021 18:30:14 -0000 Subject: [Python-checkins] bpo-45822: Minor cleanups to the test_Py_CompileString test (GH-29750) Message-ID: https://github.com/python/cpython/commit/abfc794bbf2c6a0939ddd81b6e700c46944ba87a commit: abfc794bbf2c6a0939ddd81b6e700c46944ba87a branch: main author: Pablo Galindo Salgado committer: pablogsal date: 2021-11-24T18:30:03Z summary: bpo-45822: Minor cleanups to the test_Py_CompileString test (GH-29750) files: M Lib/test/test_capi.py M Modules/_testcapimodule.c diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index 5e1619bf7dc9d..d51247003ded1 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -635,6 +635,14 @@ 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): @@ -1017,14 +1025,6 @@ def test_state_access(self): with self.assertRaises(TypeError): increment_count(1, 2, 3) - 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) - if __name__ == "__main__": unittest.main() diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index c9ba148973162..0216c985415ce 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -391,7 +391,7 @@ pycompilestring(PyObject* self, PyObject *obj) { if (the_string == NULL) { return NULL; } - return Py_CompileString(the_string, "blech", Py_file_input); + return Py_CompileString(the_string, "", Py_file_input); } static PyObject* From webhook-mailer at python.org Wed Nov 24 14:01:48 2021 From: webhook-mailer at python.org (tiran) Date: Wed, 24 Nov 2021 19:01:48 -0000 Subject: [Python-checkins] bpo-45020: Fix strict-prototypes warning (GH-29755) Message-ID: https://github.com/python/cpython/commit/5c4b19ec49a5fbad65a682225f7cfed8b78f2a2f commit: 5c4b19ec49a5fbad65a682225f7cfed8b78f2a2f branch: main author: Christian Heimes committer: tiran date: 2021-11-24T20:01:39+01:00 summary: bpo-45020: Fix strict-prototypes warning (GH-29755) files: M Python/import.c M Tools/scripts/deepfreeze.py diff --git a/Python/import.c b/Python/import.c index 225fbf43a3054..51b779ca17c52 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1087,7 +1087,7 @@ use_frozen(void) } static PyObject * -list_frozen_module_names() +list_frozen_module_names(void) { PyObject *names = PyList_New(0); if (names == NULL) { diff --git a/Tools/scripts/deepfreeze.py b/Tools/scripts/deepfreeze.py index e51a408ae7f6a..46776c768e648 100644 --- a/Tools/scripts/deepfreeze.py +++ b/Tools/scripts/deepfreeze.py @@ -417,7 +417,7 @@ def generate(source: str, filename: str, modname: str, file: TextIO) -> None: printer = Printer(file) printer.generate("toplevel", code) printer.write("") - with printer.block("static void do_patchups()"): + with printer.block("static void do_patchups(void)"): for p in printer.patchups: printer.write(p) here = os.path.dirname(__file__) From webhook-mailer at python.org Wed Nov 24 14:12:11 2021 From: webhook-mailer at python.org (gvanrossum) Date: Wed, 24 Nov 2021 19:12:11 -0000 Subject: [Python-checkins] Fix typo in freeze_modules (#29744) Message-ID: https://github.com/python/cpython/commit/256f9c4588ac16b59e0fe690ccbdc4052aef1fee commit: 256f9c4588ac16b59e0fe690ccbdc4052aef1fee branch: main author: Kumar Aditya committer: gvanrossum date: 2021-11-24T11:12:03-08:00 summary: Fix typo in freeze_modules (#29744) files: M Tools/scripts/freeze_modules.py diff --git a/Tools/scripts/freeze_modules.py b/Tools/scripts/freeze_modules.py index a36f74ced4187..74b2c4857d088 100644 --- a/Tools/scripts/freeze_modules.py +++ b/Tools/scripts/freeze_modules.py @@ -726,5 +726,5 @@ def main(): if __name__ == '__main__': argv = sys.argv[1:] if argv: - sys.exit('ERROR: got unexpected args {argv}') + sys.exit(f'ERROR: got unexpected args {argv}') main() From webhook-mailer at python.org Wed Nov 24 14:44:09 2021 From: webhook-mailer at python.org (miss-islington) Date: Wed, 24 Nov 2021 19:44:09 -0000 Subject: [Python-checkins] bpo-45693: Document `port` parameter to `loop.create_server` (GH-29760) Message-ID: https://github.com/python/cpython/commit/d71c7bc7339eb82de493c66ebbbfa1cad250ac78 commit: d71c7bc7339eb82de493c66ebbbfa1cad250ac78 branch: main author: Jim Crist-Harif committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-24T11:43:57-08:00 summary: bpo-45693: Document `port` parameter to `loop.create_server` (GH-29760) Document the `port` parameter to `loop.create_server` in `asyncio`. In particular, note that if `host` resolves to multiple network interfaces, passing in `port=0` will result in a different random unused port being used for each interface. Automerge-Triggered-By: GH:ericvsmith files: M Doc/library/asyncio-eventloop.rst diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index c4408f122c378..5a3369415a745 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -631,6 +631,11 @@ Creating network servers assumed and a list of multiple sockets will be returned (most likely one for IPv4 and another one for IPv6). + * The *port* parameter can be set to specify which port the server should + listen on. If ``0`` or ``None`` (the default), a random unused port will + be selected (note that if *host* resolves to multiple network interfaces, + a different random port will be selected for each interface). + * *family* can be set to either :data:`socket.AF_INET` or :data:`~socket.AF_INET6` to force the socket to use IPv4 or IPv6. If not set, the *family* will be determined from host name From webhook-mailer at python.org Wed Nov 24 15:12:16 2021 From: webhook-mailer at python.org (tiran) Date: Wed, 24 Nov 2021 20:12:16 -0000 Subject: [Python-checkins] bpo-45893: Add missing extern C to initconfig.h (GH-29761) Message-ID: https://github.com/python/cpython/commit/f4afc53bf68c8ded20b281cd1baa88a679b4a3fd commit: f4afc53bf68c8ded20b281cd1baa88a679b4a3fd branch: main author: Christian Heimes committer: tiran date: 2021-11-24T21:12:12+01:00 summary: bpo-45893: Add missing extern C to initconfig.h (GH-29761) Co-authored-by: Steve Dower files: M .github/workflows/build.yml M Include/cpython/initconfig.h diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a11a368fd8311..fe4b14828699c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -95,6 +95,8 @@ jobs: runs-on: windows-latest needs: check_source if: needs.check_source.outputs.run_tests == 'true' + env: + IncludeUwp: 'true' steps: - uses: actions/checkout at v2 - name: Build CPython @@ -109,6 +111,8 @@ jobs: runs-on: windows-latest needs: check_source if: needs.check_source.outputs.run_tests == 'true' + env: + IncludeUwp: 'true' steps: - uses: actions/checkout at v2 - name: Register MSVC problem matcher diff --git a/Include/cpython/initconfig.h b/Include/cpython/initconfig.h index 05641001bcd74..76f3c5268ee5f 100644 --- a/Include/cpython/initconfig.h +++ b/Include/cpython/initconfig.h @@ -1,6 +1,9 @@ #ifndef Py_PYCORECONFIG_H #define Py_PYCORECONFIG_H #ifndef Py_LIMITED_API +#ifdef __cplusplus +extern "C" { +#endif /* --- PyStatus ----------------------------------------------- */ @@ -243,5 +246,8 @@ PyAPI_FUNC(PyStatus) PyConfig_SetWideStringList(PyConfig *config, See also PyConfig.orig_argv. */ PyAPI_FUNC(void) Py_GetArgcArgv(int *argc, wchar_t ***argv); +#ifdef __cplusplus +} +#endif #endif /* !Py_LIMITED_API */ #endif /* !Py_PYCORECONFIG_H */ From webhook-mailer at python.org Wed Nov 24 15:39:55 2021 From: webhook-mailer at python.org (ericvsmith) Date: Wed, 24 Nov 2021 20:39:55 -0000 Subject: [Python-checkins] bpo-45693: Document `port` parameter to `loop.create_server` (GH-29760) (GH-29762) Message-ID: https://github.com/python/cpython/commit/8cabcde8d66bfd8abc98b862c93c66946f8514a1 commit: 8cabcde8d66bfd8abc98b862c93c66946f8514a1 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ericvsmith date: 2021-11-24T15:39:51-05:00 summary: bpo-45693: Document `port` parameter to `loop.create_server` (GH-29760) (GH-29762) Document the `port` parameter to `loop.create_server` in `asyncio`. In particular, note that if `host` resolves to multiple network interfaces, passing in `port=0` will result in a different random unused port being used for each interface. Automerge-Triggered-By: GH:ericvsmith (cherry picked from commit d71c7bc7339eb82de493c66ebbbfa1cad250ac78) Co-authored-by: Jim Crist-Harif Co-authored-by: Jim Crist-Harif files: M Doc/library/asyncio-eventloop.rst diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index eee8095bd4c0f..44798dc3e23cb 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -631,6 +631,11 @@ Creating network servers assumed and a list of multiple sockets will be returned (most likely one for IPv4 and another one for IPv6). + * The *port* parameter can be set to specify which port the server should + listen on. If ``0`` or ``None`` (the default), a random unused port will + be selected (note that if *host* resolves to multiple network interfaces, + a different random port will be selected for each interface). + * *family* can be set to either :data:`socket.AF_INET` or :data:`~socket.AF_INET6` to force the socket to use IPv4 or IPv6. If not set, the *family* will be determined from host name From webhook-mailer at python.org Wed Nov 24 15:40:14 2021 From: webhook-mailer at python.org (ericvsmith) Date: Wed, 24 Nov 2021 20:40:14 -0000 Subject: [Python-checkins] bpo-45693: Document `port` parameter to `loop.create_server` (GH-29760) (GH-29763) Message-ID: https://github.com/python/cpython/commit/151c9bf649a049f52df388a8f2390988949abf59 commit: 151c9bf649a049f52df388a8f2390988949abf59 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ericvsmith date: 2021-11-24T15:40:09-05:00 summary: bpo-45693: Document `port` parameter to `loop.create_server` (GH-29760) (GH-29763) Document the `port` parameter to `loop.create_server` in `asyncio`. In particular, note that if `host` resolves to multiple network interfaces, passing in `port=0` will result in a different random unused port being used for each interface. Automerge-Triggered-By: GH:ericvsmith (cherry picked from commit d71c7bc7339eb82de493c66ebbbfa1cad250ac78) Co-authored-by: Jim Crist-Harif Co-authored-by: Jim Crist-Harif files: M Doc/library/asyncio-eventloop.rst diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index 4a64475f2a939..d70aeae766ae3 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -626,6 +626,11 @@ Creating network servers assumed and a list of multiple sockets will be returned (most likely one for IPv4 and another one for IPv6). + * The *port* parameter can be set to specify which port the server should + listen on. If ``0`` or ``None`` (the default), a random unused port will + be selected (note that if *host* resolves to multiple network interfaces, + a different random port will be selected for each interface). + * *family* can be set to either :data:`socket.AF_INET` or :data:`~socket.AF_INET6` to force the socket to use IPv4 or IPv6. If not set, the *family* will be determined from host name From webhook-mailer at python.org Wed Nov 24 16:57:52 2021 From: webhook-mailer at python.org (miss-islington) Date: Wed, 24 Nov 2021 21:57:52 -0000 Subject: [Python-checkins] bpo-45893: Add missing extern C to initconfig.h (GH-29761) Message-ID: https://github.com/python/cpython/commit/cd85d91bc66a587ce2ba668c897a5ecf118733cc commit: cd85d91bc66a587ce2ba668c897a5ecf118733cc branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-24T13:57:41-08:00 summary: bpo-45893: Add missing extern C to initconfig.h (GH-29761) Co-authored-by: Steve Dower (cherry picked from commit f4afc53bf68c8ded20b281cd1baa88a679b4a3fd) Co-authored-by: Christian Heimes files: M .github/workflows/build.yml M Include/cpython/initconfig.h diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 88f825e613bca..01b75aedafed5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -115,6 +115,8 @@ jobs: runs-on: windows-latest needs: check_source if: needs.check_source.outputs.run_tests == 'true' + env: + IncludeUwp: 'true' steps: - uses: actions/checkout at v2 - name: Build CPython @@ -129,6 +131,8 @@ jobs: runs-on: windows-latest needs: check_source if: needs.check_source.outputs.run_tests == 'true' + env: + IncludeUwp: 'true' steps: - uses: actions/checkout at v2 - name: Register MSVC problem matcher diff --git a/Include/cpython/initconfig.h b/Include/cpython/initconfig.h index 09f9a2947efef..583165bee48cc 100644 --- a/Include/cpython/initconfig.h +++ b/Include/cpython/initconfig.h @@ -1,6 +1,9 @@ #ifndef Py_PYCORECONFIG_H #define Py_PYCORECONFIG_H #ifndef Py_LIMITED_API +#ifdef __cplusplus +extern "C" { +#endif /* --- PyStatus ----------------------------------------------- */ @@ -239,5 +242,8 @@ PyAPI_FUNC(PyStatus) PyConfig_SetWideStringList(PyConfig *config, See also PyConfig.orig_argv. */ PyAPI_FUNC(void) Py_GetArgcArgv(int *argc, wchar_t ***argv); +#ifdef __cplusplus +} +#endif #endif /* !Py_LIMITED_API */ #endif /* !Py_PYCORECONFIG_H */ From webhook-mailer at python.org Wed Nov 24 17:21:34 2021 From: webhook-mailer at python.org (pablogsal) Date: Wed, 24 Nov 2021 22:21:34 -0000 Subject: [Python-checkins] bpo-45727: Only trigger the 'did you forgot a comma' error suggestion if inside parentheses (GH-29757) Message-ID: https://github.com/python/cpython/commit/24c10d2943c482c4d3ecc71d45df2d8c10fa5bb1 commit: 24c10d2943c482c4d3ecc71d45df2d8c10fa5bb1 branch: main author: Pablo Galindo Salgado committer: pablogsal date: 2021-11-24T22:21:23Z summary: bpo-45727: Only trigger the 'did you forgot a comma' error suggestion if inside parentheses (GH-29757) files: A Misc/NEWS.d/next/Core and Builtins/2021-11-24-18-24-49.bpo-45727._xVbbo.rst M Grammar/python.gram M Lib/test/test_exceptions.py M Lib/test/test_fstring.py M Parser/parser.c M Parser/pegen.c M Parser/pegen.h M Parser/pegen_errors.c diff --git a/Grammar/python.gram b/Grammar/python.gram index 60fbc400cf284..2c696a6a085ed 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -1084,7 +1084,8 @@ invalid_expression: # !(NAME STRING) is not matched so we don't show this error with some invalid string prefixes like: kf"dsfsdf" # Soft keywords need to also be ignored because they can be parsed as NAME NAME | !(NAME STRING | SOFT_KEYWORD) a=disjunction b=expression_without_invalid { - _PyPegen_check_legacy_stmt(p, a) ? NULL : RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "invalid syntax. Perhaps you forgot a comma?") } + _PyPegen_check_legacy_stmt(p, a) ? NULL : p->tokens[p->mark-1]->level == 0 ? NULL : + RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "invalid syntax. Perhaps you forgot a comma?") } | a=disjunction 'if' b=disjunction !('else'|':') { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "expected 'else' after 'if' expression") } invalid_named_expression: diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index eee178c8ca2af..7f087d085a810 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -226,14 +226,14 @@ def testSyntaxErrorOffset(self): check(b'Python = "\xcf\xb3\xf2\xee\xed" +', 1, 18) check('x = "a', 1, 5) check('lambda x: x = 2', 1, 1) - check('f{a + b + c}', 1, 1) + check('f{a + b + c}', 1, 2) check('[file for str(file) in []\n])', 1, 11) check('a = ? hello ? ? world ?', 1, 5) check('[\nfile\nfor str(file)\nin\n[]\n]', 3, 5) check('[file for\n str(file) in []]', 2, 2) check("ages = {'Alice'=22, 'Bob'=23}", 1, 16) check('match ...:\n case {**rest, "key": value}:\n ...', 2, 19) - check("a b c d e f", 1, 1) + check("[a b c d e f]", 1, 2) # Errors thrown by compile.c check('class foo:return 1', 1, 11) diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py index 14a4c678fc909..bd1ca943c7c09 100644 --- a/Lib/test/test_fstring.py +++ b/Lib/test/test_fstring.py @@ -944,7 +944,7 @@ def test_invalid_string_prefixes(self): "Bf''", "BF''",] double_quote_cases = [case.replace("'", '"') for case in single_quote_cases] - self.assertAllRaise(SyntaxError, 'unexpected EOF while parsing', + self.assertAllRaise(SyntaxError, 'invalid syntax', single_quote_cases + double_quote_cases) def test_leading_trailing_spaces(self): diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-24-18-24-49.bpo-45727._xVbbo.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-24-18-24-49.bpo-45727._xVbbo.rst new file mode 100644 index 0000000000000..d4b149ddccf5d --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-24-18-24-49.bpo-45727._xVbbo.rst @@ -0,0 +1,3 @@ +Refine the custom syntax error that suggests that a comma may be missing to +trigger only when the expressions are detected between parentheses or +brackets. Patch by Pablo Galindo diff --git a/Parser/parser.c b/Parser/parser.c index b3aa35989edcd..1cf6e356ad4bf 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -18298,7 +18298,7 @@ invalid_expression_rule(Parser *p) ) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid")); - _res = _PyPegen_check_legacy_stmt ( p , a ) ? NULL : RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Perhaps you forgot a comma?" ); + _res = _PyPegen_check_legacy_stmt ( p , a ) ? NULL : p -> tokens [p -> mark - 1] -> level == 0 ? NULL : RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Perhaps you forgot a comma?" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; D(p->level--); diff --git a/Parser/pegen.c b/Parser/pegen.c index 4f51c63c44353..ede281ac89cd9 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -170,6 +170,8 @@ initialize_token(Parser *p, Token *token, const char *start, const char *end, in return -1; } + token->level = p->tok->level; + const char *line_start = token_type == STRING ? p->tok->multi_line_start : p->tok->line_start; int lineno = token_type == STRING ? p->tok->first_lineno : p->tok->lineno; int end_lineno = p->tok->lineno; @@ -946,4 +948,4 @@ _PyPegen_run_parser_from_string(const char *str, int start_rule, PyObject *filen error: _PyTokenizer_Free(tok); return result; -} \ No newline at end of file +} diff --git a/Parser/pegen.h b/Parser/pegen.h index e5e712ab26b87..78e75d7060cf1 100644 --- a/Parser/pegen.h +++ b/Parser/pegen.h @@ -35,6 +35,7 @@ typedef struct _memo { typedef struct { int type; PyObject *bytes; + int level; int lineno, col_offset, end_lineno, end_col_offset; Memo *memo; } Token; diff --git a/Parser/pegen_errors.c b/Parser/pegen_errors.c index 694184a03b075..93057d151db38 100644 --- a/Parser/pegen_errors.c +++ b/Parser/pegen_errors.c @@ -399,7 +399,7 @@ _Pypegen_set_syntax_error(Parser* p, Token* last_token) { RAISE_SYNTAX_ERROR("error at start before reading any input"); } // Parser encountered EOF (End of File) unexpectedtly - if (p->tok->done == E_EOF) { + if (last_token->type == ERRORTOKEN && p->tok->done == E_EOF) { if (p->tok->level) { raise_unclosed_parentheses_error(p); } else { @@ -422,4 +422,4 @@ _Pypegen_set_syntax_error(Parser* p, Token* last_token) { // _PyPegen_tokenize_full_source_to_check_for_errors will override the existing // generic SyntaxError we just raised if errors are found. _PyPegen_tokenize_full_source_to_check_for_errors(p); -} \ No newline at end of file +} From webhook-mailer at python.org Wed Nov 24 20:01:50 2021 From: webhook-mailer at python.org (pablogsal) Date: Thu, 25 Nov 2021 01:01:50 -0000 Subject: [Python-checkins] [3.10] bpo-45727: Only trigger the 'did you forgot a comma' error suggestion if inside parentheses. (GH-29767) Message-ID: https://github.com/python/cpython/commit/c72311d91787005713bb5daf4532a86e06496afd commit: c72311d91787005713bb5daf4532a86e06496afd branch: 3.10 author: Pablo Galindo Salgado committer: pablogsal date: 2021-11-25T01:01:40Z summary: [3.10] bpo-45727: Only trigger the 'did you forgot a comma' error suggestion if inside parentheses. (GH-29767) Backport of GH-29757 Co-authored-by: Pablo Galindo files: A Misc/NEWS.d/next/Core and Builtins/2021-11-24-18-24-49.bpo-45727._xVbbo.rst M Grammar/python.gram M Lib/test/test_exceptions.py M Lib/test/test_fstring.py M Parser/parser.c M Parser/pegen.c M Parser/pegen.h M Parser/pegen_errors.c diff --git a/Grammar/python.gram b/Grammar/python.gram index 20cccfd8368af..f730658462147 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -859,8 +859,8 @@ invalid_expression: # !(NAME STRING) is not matched so we don't show this error with some invalid string prefixes like: kf"dsfsdf" # Soft keywords need to also be ignored because they can be parsed as NAME NAME | !(NAME STRING | SOFT_KEYWORD) a=disjunction b=expression_without_invalid { - _PyPegen_check_legacy_stmt(p, a) ? NULL : RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, - "invalid syntax. Perhaps you forgot a comma?") } + _PyPegen_check_legacy_stmt(p, a) ? NULL : p->tokens[p->mark-1]->level == 0 ? NULL : + RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "invalid syntax. Perhaps you forgot a comma?") } | a=disjunction 'if' b=disjunction !('else'|':') { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "expected 'else' after 'if' expression") } invalid_named_expression: diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 4c18a59f6e92c..ad2864bc41637 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -226,14 +226,14 @@ def testSyntaxErrorOffset(self): check(b'Python = "\xcf\xb3\xf2\xee\xed" +', 1, 18) check('x = "a', 1, 5) check('lambda x: x = 2', 1, 1) - check('f{a + b + c}', 1, 1) + check('f{a + b + c}', 1, 2) check('[file for str(file) in []\n])', 1, 11) check('a = ? hello ? ? world ?', 1, 5) check('[\nfile\nfor str(file)\nin\n[]\n]', 3, 5) check('[file for\n str(file) in []]', 2, 2) check("ages = {'Alice'=22, 'Bob'=23}", 1, 16) check('match ...:\n case {**rest, "key": value}:\n ...', 2, 19) - check("a b c d e f", 1, 1) + check("[a b c d e f]", 1, 2) # Errors thrown by compile.c check('class foo:return 1', 1, 11) diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py index 14a4c678fc909..bd1ca943c7c09 100644 --- a/Lib/test/test_fstring.py +++ b/Lib/test/test_fstring.py @@ -944,7 +944,7 @@ def test_invalid_string_prefixes(self): "Bf''", "BF''",] double_quote_cases = [case.replace("'", '"') for case in single_quote_cases] - self.assertAllRaise(SyntaxError, 'unexpected EOF while parsing', + self.assertAllRaise(SyntaxError, 'invalid syntax', single_quote_cases + double_quote_cases) def test_leading_trailing_spaces(self): diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-24-18-24-49.bpo-45727._xVbbo.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-24-18-24-49.bpo-45727._xVbbo.rst new file mode 100644 index 0000000000000..d4b149ddccf5d --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-24-18-24-49.bpo-45727._xVbbo.rst @@ -0,0 +1,3 @@ +Refine the custom syntax error that suggests that a comma may be missing to +trigger only when the expressions are detected between parentheses or +brackets. Patch by Pablo Galindo diff --git a/Parser/parser.c b/Parser/parser.c index b14092a483c32..0b6450c670bac 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -18288,7 +18288,7 @@ invalid_expression_rule(Parser *p) ) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid")); - _res = _PyPegen_check_legacy_stmt ( p , a ) ? NULL : RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Perhaps you forgot a comma?" ); + _res = _PyPegen_check_legacy_stmt ( p , a ) ? NULL : p -> tokens [ p -> mark - 1 ] -> level == 0 ? NULL : RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Perhaps you forgot a comma?" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; D(p->level--); diff --git a/Parser/pegen.c b/Parser/pegen.c index 8946aa33145b8..e37aaf7975bdd 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -692,6 +692,8 @@ initialize_token(Parser *p, Token *token, const char *start, const char *end, in return -1; } + token->level = p->tok->level; + const char *line_start = token_type == STRING ? p->tok->multi_line_start : p->tok->line_start; int lineno = token_type == STRING ? p->tok->first_lineno : p->tok->lineno; int end_lineno = p->tok->lineno; @@ -1357,7 +1359,7 @@ _PyPegen_run_parser(Parser *p) if (p->fill == 0) { RAISE_SYNTAX_ERROR("error at start before reading any input"); } - else if (p->tok->done == E_EOF) { + else if (last_token->type == ERRORTOKEN && p->tok->done == E_EOF) { if (p->tok->level) { raise_unclosed_parentheses_error(p); } else { diff --git a/Parser/pegen.h b/Parser/pegen.h index 40222d64499a9..04c7b9d19bb8a 100644 --- a/Parser/pegen.h +++ b/Parser/pegen.h @@ -33,6 +33,7 @@ typedef struct _memo { typedef struct { int type; PyObject *bytes; + int level; int lineno, col_offset, end_lineno, end_col_offset; Memo *memo; } Token; diff --git a/Parser/pegen_errors.c b/Parser/pegen_errors.c index 694184a03b075..93057d151db38 100644 --- a/Parser/pegen_errors.c +++ b/Parser/pegen_errors.c @@ -399,7 +399,7 @@ _Pypegen_set_syntax_error(Parser* p, Token* last_token) { RAISE_SYNTAX_ERROR("error at start before reading any input"); } // Parser encountered EOF (End of File) unexpectedtly - if (p->tok->done == E_EOF) { + if (last_token->type == ERRORTOKEN && p->tok->done == E_EOF) { if (p->tok->level) { raise_unclosed_parentheses_error(p); } else { @@ -422,4 +422,4 @@ _Pypegen_set_syntax_error(Parser* p, Token* last_token) { // _PyPegen_tokenize_full_source_to_check_for_errors will override the existing // generic SyntaxError we just raised if errors are found. _PyPegen_tokenize_full_source_to_check_for_errors(p); -} \ No newline at end of file +} From webhook-mailer at python.org Thu Nov 25 04:41:42 2021 From: webhook-mailer at python.org (iritkatriel) Date: Thu, 25 Nov 2021 09:41:42 -0000 Subject: [Python-checkins] bpo-45711: use exc_value instead of exc_type to determine if exc_info is valid. Add more assertions. (GH-29627) Message-ID: https://github.com/python/cpython/commit/c456dfafe9f9f6614fbcf2213a93707f0e101f4e commit: c456dfafe9f9f6614fbcf2213a93707f0e101f4e branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-11-25T09:41:28Z summary: bpo-45711: use exc_value instead of exc_type to determine if exc_info is valid. Add more assertions. (GH-29627) files: M Include/internal/pycore_pyerrors.h M Python/ceval.c M Python/errors.c M Python/pystate.c M Python/sysmodule.c diff --git a/Include/internal/pycore_pyerrors.h b/Include/internal/pycore_pyerrors.h index 0f4d41c7e0bab..14ea182f4f47a 100644 --- a/Include/internal/pycore_pyerrors.h +++ b/Include/internal/pycore_pyerrors.h @@ -28,6 +28,8 @@ static inline void _PyErr_ClearExcState(_PyErr_StackItem *exc_state) Py_XDECREF(tb); } +PyAPI_FUNC(PyObject*) _PyErr_StackItemToExcInfoTuple( + _PyErr_StackItem *err_info); PyAPI_FUNC(void) _PyErr_Fetch( PyThreadState *tstate, diff --git a/Python/ceval.c b/Python/ceval.c index 0aec5aa7fb9b0..9beb1a4368226 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1102,7 +1102,7 @@ static void _assert_exception_type_is_redundant(PyObject* type, PyObject* val) { if (type == NULL || type == Py_None) { - assert(val == NULL || val == Py_None); + assert(val == type); } else { assert(PyExceptionInstance_Check(val)); @@ -3738,7 +3738,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(JUMP_IF_NOT_EXC_MATCH) { PyObject *right = POP(); - PyObject *left = TOP(); + ASSERT_EXC_TYPE_IS_REDUNDANT(TOP(), SECOND()); + PyObject *left = SECOND(); + assert(PyExceptionInstance_Check(left)); if (check_except_type_valid(tstate, right) < 0) { Py_DECREF(right); goto error; @@ -4198,7 +4200,13 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr ASSERT_EXC_TYPE_IS_REDUNDANT(type, value); _PyErr_StackItem *exc_info = tstate->exc_info; SET_THIRD(exc_info->exc_traceback); - SET_SECOND(exc_info->exc_value); + if (exc_info->exc_value != NULL) { + SET_SECOND(exc_info->exc_value); + } + else { + Py_INCREF(Py_None); + SET_SECOND(Py_None); + } if (exc_info->exc_type != NULL) { SET_TOP(exc_info->exc_type); } @@ -5916,7 +5924,9 @@ do_raise(PyThreadState *tstate, PyObject *exc, PyObject *cause) type = exc_info->exc_type; value = exc_info->exc_value; tb = exc_info->exc_traceback; - if (Py_IsNone(type) || type == NULL) { + assert(((Py_IsNone(value) || value == NULL)) == + ((Py_IsNone(type) || type == NULL))); + if (Py_IsNone(value) || value == NULL) { _PyErr_SetString(tstate, PyExc_RuntimeError, "No active exception to reraise"); return 0; diff --git a/Python/errors.c b/Python/errors.c index cb3938d20856f..6e74d19b78ef3 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -79,11 +79,16 @@ _PyErr_StackItem * _PyErr_GetTopmostException(PyThreadState *tstate) { _PyErr_StackItem *exc_info = tstate->exc_info; - while ((exc_info->exc_type == NULL || exc_info->exc_type == Py_None) && + assert(exc_info); + + while ((exc_info->exc_value == NULL || exc_info->exc_value == Py_None) && exc_info->previous_item != NULL) { + assert(exc_info->exc_type == NULL || exc_info->exc_type == Py_None); exc_info = exc_info->previous_item; } + assert(exc_info->previous_item == NULL || + (exc_info->exc_type != NULL && exc_info->exc_type != Py_None)); return exc_info; } @@ -471,10 +476,20 @@ _PyErr_GetExcInfo(PyThreadState *tstate, PyObject **p_type, PyObject **p_value, PyObject **p_traceback) { _PyErr_StackItem *exc_info = _PyErr_GetTopmostException(tstate); - *p_type = exc_info->exc_type; + *p_value = exc_info->exc_value; *p_traceback = exc_info->exc_traceback; + if (*p_value == NULL || *p_value == Py_None) { + assert(exc_info->exc_type == NULL || exc_info->exc_type == Py_None); + *p_type = Py_None; + } + else { + assert(PyExceptionInstance_Check(*p_value)); + assert(exc_info->exc_type == PyExceptionInstance_Class(*p_value)); + *p_type = PyExceptionInstance_Class(*p_value); + } + Py_XINCREF(*p_type); Py_XINCREF(*p_value); Py_XINCREF(*p_traceback); @@ -507,42 +522,66 @@ PyErr_SetExcInfo(PyObject *p_type, PyObject *p_value, PyObject *p_traceback) Py_XDECREF(oldtraceback); } + +PyObject* +_PyErr_StackItemToExcInfoTuple(_PyErr_StackItem *err_info) +{ + PyObject *exc_value = err_info->exc_value; + if (exc_value == NULL) { + exc_value = Py_None; + } + + assert(exc_value == Py_None || PyExceptionInstance_Check(exc_value)); + + PyObject *exc_type = PyExceptionInstance_Check(exc_value) ? + PyExceptionInstance_Class(exc_value) : + Py_None; + + return Py_BuildValue( + "(OOO)", + exc_type, + exc_value, + err_info->exc_traceback != NULL ? + err_info->exc_traceback : Py_None); +} + + /* Like PyErr_Restore(), but if an exception is already set, set the context associated with it. The caller is responsible for ensuring that this call won't create any cycles in the exception context chain. */ void -_PyErr_ChainExceptions(PyObject *exc, PyObject *val, PyObject *tb) +_PyErr_ChainExceptions(PyObject *typ, PyObject *val, PyObject *tb) { - if (exc == NULL) + if (typ == NULL) return; PyThreadState *tstate = _PyThreadState_GET(); - if (!PyExceptionClass_Check(exc)) { + if (!PyExceptionClass_Check(typ)) { _PyErr_Format(tstate, PyExc_SystemError, "_PyErr_ChainExceptions: " "exception %R is not a BaseException subclass", - exc); + typ); return; } if (_PyErr_Occurred(tstate)) { - PyObject *exc2, *val2, *tb2; - _PyErr_Fetch(tstate, &exc2, &val2, &tb2); - _PyErr_NormalizeException(tstate, &exc, &val, &tb); + PyObject *typ2, *val2, *tb2; + _PyErr_Fetch(tstate, &typ2, &val2, &tb2); + _PyErr_NormalizeException(tstate, &typ, &val, &tb); if (tb != NULL) { PyException_SetTraceback(val, tb); Py_DECREF(tb); } - Py_DECREF(exc); - _PyErr_NormalizeException(tstate, &exc2, &val2, &tb2); + Py_DECREF(typ); + _PyErr_NormalizeException(tstate, &typ2, &val2, &tb2); PyException_SetContext(val2, val); - _PyErr_Restore(tstate, exc2, val2, tb2); + _PyErr_Restore(tstate, typ2, val2, tb2); } else { - _PyErr_Restore(tstate, exc, val, tb); + _PyErr_Restore(tstate, typ, val, tb); } } @@ -567,7 +606,11 @@ _PyErr_ChainStackItem(_PyErr_StackItem *exc_info) } else { exc_info_given = 1; } - if (exc_info->exc_type == NULL || exc_info->exc_type == Py_None) { + + assert( (exc_info->exc_type == NULL || exc_info->exc_type == Py_None) == + (exc_info->exc_value == NULL || exc_info->exc_value == Py_None) ); + + if (exc_info->exc_value == NULL || exc_info->exc_value == Py_None) { return; } @@ -579,21 +622,32 @@ _PyErr_ChainStackItem(_PyErr_StackItem *exc_info) tstate->exc_info = exc_info; } - PyObject *exc, *val, *tb; - _PyErr_Fetch(tstate, &exc, &val, &tb); + PyObject *typ, *val, *tb; + _PyErr_Fetch(tstate, &typ, &val, &tb); - PyObject *exc2, *val2, *tb2; - exc2 = exc_info->exc_type; + PyObject *typ2, *val2, *tb2; + typ2 = exc_info->exc_type; val2 = exc_info->exc_value; tb2 = exc_info->exc_traceback; - _PyErr_NormalizeException(tstate, &exc2, &val2, &tb2); +#ifdef Py_DEBUG + PyObject *typ2_before = typ2; + PyObject *val2_before = val2; + PyObject *tb2_before = tb2; +#endif + _PyErr_NormalizeException(tstate, &typ2, &val2, &tb2); +#ifdef Py_DEBUG + /* exc_info should already be normalized */ + assert(typ2 == typ2_before); + assert(val2 == val2_before); + assert(tb2 == tb2_before); +#endif if (tb2 != NULL) { PyException_SetTraceback(val2, tb2); } /* _PyErr_SetObject sets the context from PyThreadState. */ - _PyErr_SetObject(tstate, exc, val); - Py_DECREF(exc); // since _PyErr_Occurred was true + _PyErr_SetObject(tstate, typ, val); + Py_DECREF(typ); // since _PyErr_Occurred was true Py_XDECREF(val); Py_XDECREF(tb); diff --git a/Python/pystate.c b/Python/pystate.c index 56db095d24b8a..ba14c9d8af9fb 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1341,11 +1341,7 @@ _PyThread_CurrentExceptions(void) if (id == NULL) { goto fail; } - PyObject *exc_info = PyTuple_Pack( - 3, - err_info->exc_type != NULL ? err_info->exc_type : Py_None, - err_info->exc_value != NULL ? err_info->exc_value : Py_None, - err_info->exc_traceback != NULL ? err_info->exc_traceback : Py_None); + PyObject *exc_info = _PyErr_StackItemToExcInfoTuple(err_info); if (exc_info == NULL) { Py_DECREF(id); goto fail; diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 3e2091e70ab8a..13fae797b29c2 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -785,12 +785,7 @@ sys_exc_info_impl(PyObject *module) /*[clinic end generated code: output=3afd0940cf3a4d30 input=b5c5bf077788a3e5]*/ { _PyErr_StackItem *err_info = _PyErr_GetTopmostException(_PyThreadState_GET()); - return Py_BuildValue( - "(OOO)", - err_info->exc_type != NULL ? err_info->exc_type : Py_None, - err_info->exc_value != NULL ? err_info->exc_value : Py_None, - err_info->exc_traceback != NULL ? - err_info->exc_traceback : Py_None); + return _PyErr_StackItemToExcInfoTuple(err_info); } From webhook-mailer at python.org Thu Nov 25 06:29:12 2021 From: webhook-mailer at python.org (tiran) Date: Thu, 25 Nov 2021 11:29:12 -0000 Subject: [Python-checkins] bpo-41498: Fix build on platforms without sigset_t (GH-29770) Message-ID: https://github.com/python/cpython/commit/dc19e8698327cae3d6274b73c135375955f1d0d0 commit: dc19e8698327cae3d6274b73c135375955f1d0d0 branch: main author: Christian Heimes committer: tiran date: 2021-11-25T12:28:41+01:00 summary: bpo-41498: Fix build on platforms without sigset_t (GH-29770) files: A Misc/NEWS.d/next/Build/2021-11-25-09-15-04.bpo-41498.qAk5eo.rst M Modules/clinic/signalmodule.c.h M Modules/posixmodule.c M Modules/posixmodule.h M Modules/signalmodule.c diff --git a/Misc/NEWS.d/next/Build/2021-11-25-09-15-04.bpo-41498.qAk5eo.rst b/Misc/NEWS.d/next/Build/2021-11-25-09-15-04.bpo-41498.qAk5eo.rst new file mode 100644 index 0000000000000..18dc290dafd02 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-25-09-15-04.bpo-41498.qAk5eo.rst @@ -0,0 +1,4 @@ +Python now compiles on platforms without ``sigset_t``. Several functions +in :mod:`signal` are not available when ``sigset_t`` is missing. + +Based on patch by Roman Yurchak for pyodide. diff --git a/Modules/clinic/signalmodule.c.h b/Modules/clinic/signalmodule.c.h index 4713bab7486ac..4c27314a80c86 100644 --- a/Modules/clinic/signalmodule.c.h +++ b/Modules/clinic/signalmodule.c.h @@ -354,7 +354,7 @@ signal_getitimer(PyObject *module, PyObject *arg) #endif /* defined(HAVE_GETITIMER) */ -#if defined(PYPTHREAD_SIGMASK) +#if defined(HAVE_SIGSET_T) && defined(PYPTHREAD_SIGMASK) PyDoc_STRVAR(signal_pthread_sigmask__doc__, "pthread_sigmask($module, how, mask, /)\n" @@ -391,9 +391,9 @@ signal_pthread_sigmask(PyObject *module, PyObject *const *args, Py_ssize_t nargs return return_value; } -#endif /* defined(PYPTHREAD_SIGMASK) */ +#endif /* defined(HAVE_SIGSET_T) && defined(PYPTHREAD_SIGMASK) */ -#if defined(HAVE_SIGPENDING) +#if defined(HAVE_SIGSET_T) && defined(HAVE_SIGPENDING) PyDoc_STRVAR(signal_sigpending__doc__, "sigpending($module, /)\n" @@ -416,9 +416,9 @@ signal_sigpending(PyObject *module, PyObject *Py_UNUSED(ignored)) return signal_sigpending_impl(module); } -#endif /* defined(HAVE_SIGPENDING) */ +#endif /* defined(HAVE_SIGSET_T) && defined(HAVE_SIGPENDING) */ -#if defined(HAVE_SIGWAIT) +#if defined(HAVE_SIGSET_T) && defined(HAVE_SIGWAIT) PyDoc_STRVAR(signal_sigwait__doc__, "sigwait($module, sigset, /)\n" @@ -451,9 +451,9 @@ signal_sigwait(PyObject *module, PyObject *arg) return return_value; } -#endif /* defined(HAVE_SIGWAIT) */ +#endif /* defined(HAVE_SIGSET_T) && defined(HAVE_SIGWAIT) */ -#if (defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS)) +#if ((defined(HAVE_SIGFILLSET) && defined(HAVE_SIGSET_T)) || defined(MS_WINDOWS)) PyDoc_STRVAR(signal_valid_signals__doc__, "valid_signals($module, /)\n" @@ -476,9 +476,9 @@ signal_valid_signals(PyObject *module, PyObject *Py_UNUSED(ignored)) return signal_valid_signals_impl(module); } -#endif /* (defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS)) */ +#endif /* ((defined(HAVE_SIGFILLSET) && defined(HAVE_SIGSET_T)) || defined(MS_WINDOWS)) */ -#if defined(HAVE_SIGWAITINFO) +#if defined(HAVE_SIGSET_T) && defined(HAVE_SIGWAITINFO) PyDoc_STRVAR(signal_sigwaitinfo__doc__, "sigwaitinfo($module, sigset, /)\n" @@ -509,9 +509,9 @@ signal_sigwaitinfo(PyObject *module, PyObject *arg) return return_value; } -#endif /* defined(HAVE_SIGWAITINFO) */ +#endif /* defined(HAVE_SIGSET_T) && defined(HAVE_SIGWAITINFO) */ -#if defined(HAVE_SIGTIMEDWAIT) +#if defined(HAVE_SIGSET_T) && defined(HAVE_SIGTIMEDWAIT) PyDoc_STRVAR(signal_sigtimedwait__doc__, "sigtimedwait($module, sigset, timeout, /)\n" @@ -548,7 +548,7 @@ signal_sigtimedwait(PyObject *module, PyObject *const *args, Py_ssize_t nargs) return return_value; } -#endif /* defined(HAVE_SIGTIMEDWAIT) */ +#endif /* defined(HAVE_SIGSET_T) && defined(HAVE_SIGTIMEDWAIT) */ #if defined(HAVE_PTHREAD_KILL) @@ -698,4 +698,4 @@ signal_pidfd_send_signal(PyObject *module, PyObject *const *args, Py_ssize_t nar #ifndef SIGNAL_PIDFD_SEND_SIGNAL_METHODDEF #define SIGNAL_PIDFD_SEND_SIGNAL_METHODDEF #endif /* !defined(SIGNAL_PIDFD_SEND_SIGNAL_METHODDEF) */ -/*[clinic end generated code: output=59c33f0af42aebb5 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c353e686367bc384 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 667a3339f5ba8..c29d9fc2a7087 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -5934,6 +5934,7 @@ parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpg } +#ifdef HAVE_SIGSET_T if (setsigmask) { sigset_t set; if (!_Py_Sigset_Converter(setsigmask, &set)) { @@ -5959,6 +5960,13 @@ parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpg } all_flags |= POSIX_SPAWN_SETSIGDEF; } +#else + if (setsigmask || setsigdef) { + PyErr_SetString(PyExc_NotImplementedError, + "sigset is not supported on this platform"); + goto fail; + } +#endif if (scheduler) { #ifdef POSIX_SPAWN_SETSCHEDULER diff --git a/Modules/posixmodule.h b/Modules/posixmodule.h index 711ac686934b0..5452ffbf17acf 100644 --- a/Modules/posixmodule.h +++ b/Modules/posixmodule.h @@ -23,9 +23,7 @@ PyAPI_FUNC(int) _Py_Gid_Converter(PyObject *, gid_t *); # define HAVE_SIGSET_T #endif -#ifdef HAVE_SIGSET_T PyAPI_FUNC(int) _Py_Sigset_Converter(PyObject *, void *); -#endif /* HAVE_SIGSET_T */ #endif /* Py_LIMITED_API */ #ifdef __cplusplus diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index 927880376c323..bc891e8af3c0b 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -60,6 +60,8 @@ module signal [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=b0301a3bde5fe9d3]*/ +#ifdef HAVE_SETSIG_T + /*[python input] class sigset_t_converter(CConverter): @@ -68,6 +70,7 @@ class sigset_t_converter(CConverter): [python start generated code]*/ /*[python end generated code: output=da39a3ee5e6b4b0d input=b5689d14466b6823]*/ +#endif /* NOTES ON THE INTERACTION BETWEEN SIGNALS AND THREADS @@ -932,6 +935,7 @@ signal_getitimer_impl(PyObject *module, int which) #endif // HAVE_GETITIMER +#ifdef HAVE_SIGSET_T #if defined(PYPTHREAD_SIGMASK) || defined(HAVE_SIGPENDING) static PyObject* sigset_to_set(sigset_t mask) @@ -1063,9 +1067,9 @@ signal_sigwait_impl(PyObject *module, sigset_t sigset) } #endif /* #ifdef HAVE_SIGWAIT */ +#endif /* #ifdef HAVE_SIGSET_T */ - -#if defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS) +#if (defined(HAVE_SIGFILLSET) && defined(HAVE_SIGSET_T)) || defined(MS_WINDOWS) /*[clinic input] signal.valid_signals @@ -1103,7 +1107,8 @@ signal_valid_signals_impl(PyObject *module) #endif } -#endif /* #if defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS) */ +#endif /* #if (defined(HAVE_SIGFILLSET) && defined(HAVE_SIGSET_T)) || defined(MS_WINDOWS) */ + #if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT) @@ -1168,6 +1173,7 @@ fill_siginfo(siginfo_t *si) } #endif +#ifdef HAVE_SIGSET_T #ifdef HAVE_SIGWAITINFO /*[clinic input] @@ -1270,6 +1276,7 @@ signal_sigtimedwait_impl(PyObject *module, sigset_t sigset, } #endif /* #ifdef HAVE_SIGTIMEDWAIT */ +#endif /* #ifdef HAVE_SIGSET_T */ #if defined(HAVE_PTHREAD_KILL) From webhook-mailer at python.org Thu Nov 25 06:53:12 2021 From: webhook-mailer at python.org (miss-islington) Date: Thu, 25 Nov 2021 11:53:12 -0000 Subject: [Python-checkins] [3.10] bpo-41498: Fix build on platforms without sigset_t (GH-29770) (GH-29773) Message-ID: https://github.com/python/cpython/commit/632d589afcaac3b8441c8c042a98e1ae452533e0 commit: 632d589afcaac3b8441c8c042a98e1ae452533e0 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-25T03:53:07-08:00 summary: [3.10] bpo-41498: Fix build on platforms without sigset_t (GH-29770) (GH-29773) (cherry picked from commit dc19e8698327cae3d6274b73c135375955f1d0d0) Co-authored-by: Christian Heimes Automerge-Triggered-By: GH:tiran files: A Misc/NEWS.d/next/Build/2021-11-25-09-15-04.bpo-41498.qAk5eo.rst M Modules/clinic/signalmodule.c.h M Modules/posixmodule.c M Modules/posixmodule.h M Modules/signalmodule.c diff --git a/Misc/NEWS.d/next/Build/2021-11-25-09-15-04.bpo-41498.qAk5eo.rst b/Misc/NEWS.d/next/Build/2021-11-25-09-15-04.bpo-41498.qAk5eo.rst new file mode 100644 index 0000000000000..18dc290dafd02 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-25-09-15-04.bpo-41498.qAk5eo.rst @@ -0,0 +1,4 @@ +Python now compiles on platforms without ``sigset_t``. Several functions +in :mod:`signal` are not available when ``sigset_t`` is missing. + +Based on patch by Roman Yurchak for pyodide. diff --git a/Modules/clinic/signalmodule.c.h b/Modules/clinic/signalmodule.c.h index 4713bab7486ac..4c27314a80c86 100644 --- a/Modules/clinic/signalmodule.c.h +++ b/Modules/clinic/signalmodule.c.h @@ -354,7 +354,7 @@ signal_getitimer(PyObject *module, PyObject *arg) #endif /* defined(HAVE_GETITIMER) */ -#if defined(PYPTHREAD_SIGMASK) +#if defined(HAVE_SIGSET_T) && defined(PYPTHREAD_SIGMASK) PyDoc_STRVAR(signal_pthread_sigmask__doc__, "pthread_sigmask($module, how, mask, /)\n" @@ -391,9 +391,9 @@ signal_pthread_sigmask(PyObject *module, PyObject *const *args, Py_ssize_t nargs return return_value; } -#endif /* defined(PYPTHREAD_SIGMASK) */ +#endif /* defined(HAVE_SIGSET_T) && defined(PYPTHREAD_SIGMASK) */ -#if defined(HAVE_SIGPENDING) +#if defined(HAVE_SIGSET_T) && defined(HAVE_SIGPENDING) PyDoc_STRVAR(signal_sigpending__doc__, "sigpending($module, /)\n" @@ -416,9 +416,9 @@ signal_sigpending(PyObject *module, PyObject *Py_UNUSED(ignored)) return signal_sigpending_impl(module); } -#endif /* defined(HAVE_SIGPENDING) */ +#endif /* defined(HAVE_SIGSET_T) && defined(HAVE_SIGPENDING) */ -#if defined(HAVE_SIGWAIT) +#if defined(HAVE_SIGSET_T) && defined(HAVE_SIGWAIT) PyDoc_STRVAR(signal_sigwait__doc__, "sigwait($module, sigset, /)\n" @@ -451,9 +451,9 @@ signal_sigwait(PyObject *module, PyObject *arg) return return_value; } -#endif /* defined(HAVE_SIGWAIT) */ +#endif /* defined(HAVE_SIGSET_T) && defined(HAVE_SIGWAIT) */ -#if (defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS)) +#if ((defined(HAVE_SIGFILLSET) && defined(HAVE_SIGSET_T)) || defined(MS_WINDOWS)) PyDoc_STRVAR(signal_valid_signals__doc__, "valid_signals($module, /)\n" @@ -476,9 +476,9 @@ signal_valid_signals(PyObject *module, PyObject *Py_UNUSED(ignored)) return signal_valid_signals_impl(module); } -#endif /* (defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS)) */ +#endif /* ((defined(HAVE_SIGFILLSET) && defined(HAVE_SIGSET_T)) || defined(MS_WINDOWS)) */ -#if defined(HAVE_SIGWAITINFO) +#if defined(HAVE_SIGSET_T) && defined(HAVE_SIGWAITINFO) PyDoc_STRVAR(signal_sigwaitinfo__doc__, "sigwaitinfo($module, sigset, /)\n" @@ -509,9 +509,9 @@ signal_sigwaitinfo(PyObject *module, PyObject *arg) return return_value; } -#endif /* defined(HAVE_SIGWAITINFO) */ +#endif /* defined(HAVE_SIGSET_T) && defined(HAVE_SIGWAITINFO) */ -#if defined(HAVE_SIGTIMEDWAIT) +#if defined(HAVE_SIGSET_T) && defined(HAVE_SIGTIMEDWAIT) PyDoc_STRVAR(signal_sigtimedwait__doc__, "sigtimedwait($module, sigset, timeout, /)\n" @@ -548,7 +548,7 @@ signal_sigtimedwait(PyObject *module, PyObject *const *args, Py_ssize_t nargs) return return_value; } -#endif /* defined(HAVE_SIGTIMEDWAIT) */ +#endif /* defined(HAVE_SIGSET_T) && defined(HAVE_SIGTIMEDWAIT) */ #if defined(HAVE_PTHREAD_KILL) @@ -698,4 +698,4 @@ signal_pidfd_send_signal(PyObject *module, PyObject *const *args, Py_ssize_t nar #ifndef SIGNAL_PIDFD_SEND_SIGNAL_METHODDEF #define SIGNAL_PIDFD_SEND_SIGNAL_METHODDEF #endif /* !defined(SIGNAL_PIDFD_SEND_SIGNAL_METHODDEF) */ -/*[clinic end generated code: output=59c33f0af42aebb5 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c353e686367bc384 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 18761cc490448..03de4703239a7 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -5930,6 +5930,7 @@ parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpg } +#ifdef HAVE_SIGSET_T if (setsigmask) { sigset_t set; if (!_Py_Sigset_Converter(setsigmask, &set)) { @@ -5955,6 +5956,13 @@ parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpg } all_flags |= POSIX_SPAWN_SETSIGDEF; } +#else + if (setsigmask || setsigdef) { + PyErr_SetString(PyExc_NotImplementedError, + "sigset is not supported on this platform"); + goto fail; + } +#endif if (scheduler) { #ifdef POSIX_SPAWN_SETSCHEDULER diff --git a/Modules/posixmodule.h b/Modules/posixmodule.h index 711ac686934b0..5452ffbf17acf 100644 --- a/Modules/posixmodule.h +++ b/Modules/posixmodule.h @@ -23,9 +23,7 @@ PyAPI_FUNC(int) _Py_Gid_Converter(PyObject *, gid_t *); # define HAVE_SIGSET_T #endif -#ifdef HAVE_SIGSET_T PyAPI_FUNC(int) _Py_Sigset_Converter(PyObject *, void *); -#endif /* HAVE_SIGSET_T */ #endif /* Py_LIMITED_API */ #ifdef __cplusplus diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index 5c4ed183facae..96881d4a49f10 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -58,6 +58,8 @@ module signal [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=b0301a3bde5fe9d3]*/ +#ifdef HAVE_SETSIG_T + /*[python input] class sigset_t_converter(CConverter): @@ -66,6 +68,7 @@ class sigset_t_converter(CConverter): [python start generated code]*/ /*[python end generated code: output=da39a3ee5e6b4b0d input=b5689d14466b6823]*/ +#endif /* NOTES ON THE INTERACTION BETWEEN SIGNALS AND THREADS @@ -930,6 +933,7 @@ signal_getitimer_impl(PyObject *module, int which) #endif // HAVE_GETITIMER +#ifdef HAVE_SIGSET_T #if defined(PYPTHREAD_SIGMASK) || defined(HAVE_SIGPENDING) static PyObject* sigset_to_set(sigset_t mask) @@ -1061,9 +1065,9 @@ signal_sigwait_impl(PyObject *module, sigset_t sigset) } #endif /* #ifdef HAVE_SIGWAIT */ +#endif /* #ifdef HAVE_SIGSET_T */ - -#if defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS) +#if (defined(HAVE_SIGFILLSET) && defined(HAVE_SIGSET_T)) || defined(MS_WINDOWS) /*[clinic input] signal.valid_signals @@ -1101,7 +1105,8 @@ signal_valid_signals_impl(PyObject *module) #endif } -#endif /* #if defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS) */ +#endif /* #if (defined(HAVE_SIGFILLSET) && defined(HAVE_SIGSET_T)) || defined(MS_WINDOWS) */ + #if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT) @@ -1166,6 +1171,7 @@ fill_siginfo(siginfo_t *si) } #endif +#ifdef HAVE_SIGSET_T #ifdef HAVE_SIGWAITINFO /*[clinic input] @@ -1268,6 +1274,7 @@ signal_sigtimedwait_impl(PyObject *module, sigset_t sigset, } #endif /* #ifdef HAVE_SIGTIMEDWAIT */ +#endif /* #ifdef HAVE_SIGSET_T */ #if defined(HAVE_PTHREAD_KILL) From webhook-mailer at python.org Thu Nov 25 07:02:59 2021 From: webhook-mailer at python.org (tiran) Date: Thu, 25 Nov 2021 12:02:59 -0000 Subject: [Python-checkins] [3.9] bpo-41498: Fix build on platforms without sigset_t (GH-29770) (GH-29774) Message-ID: https://github.com/python/cpython/commit/71b414750eee7af98cc3cee3a64c59d48302a17a commit: 71b414750eee7af98cc3cee3a64c59d48302a17a branch: 3.9 author: Christian Heimes committer: tiran date: 2021-11-25T13:02:54+01:00 summary: [3.9] bpo-41498: Fix build on platforms without sigset_t (GH-29770) (GH-29774) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Build/2021-11-25-09-15-04.bpo-41498.qAk5eo.rst M Modules/clinic/signalmodule.c.h M Modules/posixmodule.c M Modules/posixmodule.h M Modules/signalmodule.c diff --git a/Misc/NEWS.d/next/Build/2021-11-25-09-15-04.bpo-41498.qAk5eo.rst b/Misc/NEWS.d/next/Build/2021-11-25-09-15-04.bpo-41498.qAk5eo.rst new file mode 100644 index 0000000000000..18dc290dafd02 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-25-09-15-04.bpo-41498.qAk5eo.rst @@ -0,0 +1,4 @@ +Python now compiles on platforms without ``sigset_t``. Several functions +in :mod:`signal` are not available when ``sigset_t`` is missing. + +Based on patch by Roman Yurchak for pyodide. diff --git a/Modules/clinic/signalmodule.c.h b/Modules/clinic/signalmodule.c.h index 7f60e28a3a28a..0fb25d5640bba 100644 --- a/Modules/clinic/signalmodule.c.h +++ b/Modules/clinic/signalmodule.c.h @@ -363,7 +363,7 @@ signal_getitimer(PyObject *module, PyObject *arg) #endif /* defined(HAVE_GETITIMER) */ -#if defined(PYPTHREAD_SIGMASK) +#if defined(HAVE_SIGSET_T) && defined(PYPTHREAD_SIGMASK) PyDoc_STRVAR(signal_pthread_sigmask__doc__, "pthread_sigmask($module, how, mask, /)\n" @@ -405,9 +405,9 @@ signal_pthread_sigmask(PyObject *module, PyObject *const *args, Py_ssize_t nargs return return_value; } -#endif /* defined(PYPTHREAD_SIGMASK) */ +#endif /* defined(HAVE_SIGSET_T) && defined(PYPTHREAD_SIGMASK) */ -#if defined(HAVE_SIGPENDING) +#if defined(HAVE_SIGSET_T) && defined(HAVE_SIGPENDING) PyDoc_STRVAR(signal_sigpending__doc__, "sigpending($module, /)\n" @@ -430,9 +430,9 @@ signal_sigpending(PyObject *module, PyObject *Py_UNUSED(ignored)) return signal_sigpending_impl(module); } -#endif /* defined(HAVE_SIGPENDING) */ +#endif /* defined(HAVE_SIGSET_T) && defined(HAVE_SIGPENDING) */ -#if defined(HAVE_SIGWAIT) +#if defined(HAVE_SIGSET_T) && defined(HAVE_SIGWAIT) PyDoc_STRVAR(signal_sigwait__doc__, "sigwait($module, sigset, /)\n" @@ -465,9 +465,9 @@ signal_sigwait(PyObject *module, PyObject *arg) return return_value; } -#endif /* defined(HAVE_SIGWAIT) */ +#endif /* defined(HAVE_SIGSET_T) && defined(HAVE_SIGWAIT) */ -#if (defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS)) +#if ((defined(HAVE_SIGFILLSET) && defined(HAVE_SIGSET_T)) || defined(MS_WINDOWS)) PyDoc_STRVAR(signal_valid_signals__doc__, "valid_signals($module, /)\n" @@ -490,9 +490,9 @@ signal_valid_signals(PyObject *module, PyObject *Py_UNUSED(ignored)) return signal_valid_signals_impl(module); } -#endif /* (defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS)) */ +#endif /* ((defined(HAVE_SIGFILLSET) && defined(HAVE_SIGSET_T)) || defined(MS_WINDOWS)) */ -#if defined(HAVE_SIGWAITINFO) +#if defined(HAVE_SIGSET_T) && defined(HAVE_SIGWAITINFO) PyDoc_STRVAR(signal_sigwaitinfo__doc__, "sigwaitinfo($module, sigset, /)\n" @@ -523,9 +523,9 @@ signal_sigwaitinfo(PyObject *module, PyObject *arg) return return_value; } -#endif /* defined(HAVE_SIGWAITINFO) */ +#endif /* defined(HAVE_SIGSET_T) && defined(HAVE_SIGWAITINFO) */ -#if defined(HAVE_SIGTIMEDWAIT) +#if defined(HAVE_SIGSET_T) && defined(HAVE_SIGTIMEDWAIT) PyDoc_STRVAR(signal_sigtimedwait__doc__, "sigtimedwait($module, sigset, timeout, /)\n" @@ -562,7 +562,7 @@ signal_sigtimedwait(PyObject *module, PyObject *const *args, Py_ssize_t nargs) return return_value; } -#endif /* defined(HAVE_SIGTIMEDWAIT) */ +#endif /* defined(HAVE_SIGSET_T) && defined(HAVE_SIGTIMEDWAIT) */ #if defined(HAVE_PTHREAD_KILL) @@ -732,4 +732,4 @@ signal_pidfd_send_signal(PyObject *module, PyObject *const *args, Py_ssize_t nar #ifndef SIGNAL_PIDFD_SEND_SIGNAL_METHODDEF #define SIGNAL_PIDFD_SEND_SIGNAL_METHODDEF #endif /* !defined(SIGNAL_PIDFD_SEND_SIGNAL_METHODDEF) */ -/*[clinic end generated code: output=b41b4b6bd9ad4da2 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3c8b80f14df17563 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index f2dcf965db760..29d61268e1b5d 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -5882,6 +5882,7 @@ parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpg } +#ifdef HAVE_SIGSET_T if (setsigmask) { sigset_t set; if (!_Py_Sigset_Converter(setsigmask, &set)) { @@ -5907,6 +5908,13 @@ parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpg } all_flags |= POSIX_SPAWN_SETSIGDEF; } +#else + if (setsigmask || setsigdef) { + PyErr_SetString(PyExc_NotImplementedError, + "sigset is not supported on this platform"); + goto fail; + } +#endif if (scheduler) { #ifdef POSIX_SPAWN_SETSCHEDULER diff --git a/Modules/posixmodule.h b/Modules/posixmodule.h index 711ac686934b0..5452ffbf17acf 100644 --- a/Modules/posixmodule.h +++ b/Modules/posixmodule.h @@ -23,9 +23,7 @@ PyAPI_FUNC(int) _Py_Gid_Converter(PyObject *, gid_t *); # define HAVE_SIGSET_T #endif -#ifdef HAVE_SIGSET_T PyAPI_FUNC(int) _Py_Sigset_Converter(PyObject *, void *); -#endif /* HAVE_SIGSET_T */ #endif /* Py_LIMITED_API */ #ifdef __cplusplus diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index de564c2db8353..e396a4ad8b44b 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -68,6 +68,8 @@ module signal [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=b0301a3bde5fe9d3]*/ +#ifdef HAVE_SETSIG_T + /*[python input] class sigset_t_converter(CConverter): @@ -76,6 +78,7 @@ class sigset_t_converter(CConverter): [python start generated code]*/ /*[python end generated code: output=da39a3ee5e6b4b0d input=b5689d14466b6823]*/ +#endif /* NOTES ON THE INTERACTION BETWEEN SIGNALS AND THREADS @@ -880,6 +883,7 @@ signal_getitimer_impl(PyObject *module, int which) #endif +#ifdef HAVE_SIGSET_T #if defined(PYPTHREAD_SIGMASK) || defined(HAVE_SIGPENDING) static PyObject* sigset_to_set(sigset_t mask) @@ -1011,9 +1015,9 @@ signal_sigwait_impl(PyObject *module, sigset_t sigset) } #endif /* #ifdef HAVE_SIGWAIT */ +#endif /* #ifdef HAVE_SIGSET_T */ - -#if defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS) +#if (defined(HAVE_SIGFILLSET) && defined(HAVE_SIGSET_T)) || defined(MS_WINDOWS) /*[clinic input] signal.valid_signals @@ -1051,7 +1055,8 @@ signal_valid_signals_impl(PyObject *module) #endif } -#endif /* #if defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS) */ +#endif /* #if (defined(HAVE_SIGFILLSET) && defined(HAVE_SIGSET_T)) || defined(MS_WINDOWS) */ + #if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT) @@ -1117,6 +1122,7 @@ fill_siginfo(siginfo_t *si) } #endif +#ifdef HAVE_SIGSET_T #ifdef HAVE_SIGWAITINFO /*[clinic input] @@ -1219,6 +1225,7 @@ signal_sigtimedwait_impl(PyObject *module, sigset_t sigset, } #endif /* #ifdef HAVE_SIGTIMEDWAIT */ +#endif /* #ifdef HAVE_SIGSET_T */ #if defined(HAVE_PTHREAD_KILL) From webhook-mailer at python.org Thu Nov 25 07:30:57 2021 From: webhook-mailer at python.org (miss-islington) Date: Thu, 25 Nov 2021 12:30:57 -0000 Subject: [Python-checkins] bpo-45568: Actually use @asynccontextmanager in usage example (GH-29151) Message-ID: https://github.com/python/cpython/commit/4dd82194f4a0e48a94191655e571b3aad1c4a22a commit: 4dd82194f4a0e48a94191655e571b3aad1c4a22a branch: main author: Zbigniew Siciarz committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-25T04:30:48-08:00 summary: bpo-45568: Actually use @asynccontextmanager in usage example (GH-29151) Automerge-Triggered-By: GH:asvetlov files: M Doc/library/contextlib.rst diff --git a/Doc/library/contextlib.rst b/Doc/library/contextlib.rst index a800a0b8dee4b..bb93088b3429e 100644 --- a/Doc/library/contextlib.rst +++ b/Doc/library/contextlib.rst @@ -130,7 +130,9 @@ Functions and classes provided: either as decorators or with :keyword:`async with` statements:: import time + from contextlib import asynccontextmanager + @asynccontextmanager async def timeit(): now = time.monotonic() try: From webhook-mailer at python.org Thu Nov 25 07:35:31 2021 From: webhook-mailer at python.org (vstinner) Date: Thu, 25 Nov 2021 12:35:31 -0000 Subject: [Python-checkins] bpo-39026: Fix Python.h when building with Xcode (GH-29488) (GH-29732) Message-ID: https://github.com/python/cpython/commit/ce5a6460aebdc51a810d2755782fe8f0d7918ec2 commit: ce5a6460aebdc51a810d2755782fe8f0d7918ec2 branch: 3.10 author: Victor Stinner committer: vstinner date: 2021-11-25T13:35:22+01:00 summary: bpo-39026: Fix Python.h when building with Xcode (GH-29488) (GH-29732) Fix Python.h to build C extensions with Xcode: remove a relative include from Include/cpython/pystate.h. (cherry picked from commit 4ae26b9c1d0c33e3db92c6f305293f9240dea358) files: A Misc/NEWS.d/next/C API/2021-11-09-15-42-11.bpo-39026.sUnYWn.rst M Include/Python.h M Include/cpython/pystate.h diff --git a/Include/Python.h b/Include/Python.h index a83befa311736..d3186c32e3550 100644 --- a/Include/Python.h +++ b/Include/Python.h @@ -106,6 +106,7 @@ #include "sliceobject.h" #include "cellobject.h" #include "iterobject.h" +#include "cpython/initconfig.h" #include "genobject.h" #include "descrobject.h" #include "genericaliasobject.h" @@ -118,8 +119,6 @@ #include "codecs.h" #include "pyerrors.h" - -#include "cpython/initconfig.h" #include "pythread.h" #include "pystate.h" #include "context.h" diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index b0d30bd079313..7c995b93074f6 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -2,8 +2,6 @@ # error "this header file must not be included directly" #endif -#include "cpython/initconfig.h" - PyAPI_FUNC(int) _PyInterpreterState_RequiresIDRef(PyInterpreterState *); PyAPI_FUNC(void) _PyInterpreterState_RequireIDRef(PyInterpreterState *, int); diff --git a/Misc/NEWS.d/next/C API/2021-11-09-15-42-11.bpo-39026.sUnYWn.rst b/Misc/NEWS.d/next/C API/2021-11-09-15-42-11.bpo-39026.sUnYWn.rst new file mode 100644 index 0000000000000..77a0119792152 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2021-11-09-15-42-11.bpo-39026.sUnYWn.rst @@ -0,0 +1,2 @@ +Fix Python.h to build C extensions with Xcode: remove a relative include +from ``Include/cpython/pystate.h``. From webhook-mailer at python.org Thu Nov 25 12:15:33 2021 From: webhook-mailer at python.org (miss-islington) Date: Thu, 25 Nov 2021 17:15:33 -0000 Subject: [Python-checkins] Add missing 'await writer.drain()' call to example (GH-29162) Message-ID: https://github.com/python/cpython/commit/e0f8a3e9b96bbc2597f61be96993ef0c768a19fe commit: e0f8a3e9b96bbc2597f61be96993ef0c768a19fe branch: main author: Sergey Kolesnikov committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-25T09:15:24-08:00 summary: Add missing 'await writer.drain()' call to example (GH-29162) Automerge-Triggered-By: GH:asvetlov files: M Doc/library/asyncio-stream.rst diff --git a/Doc/library/asyncio-stream.rst b/Doc/library/asyncio-stream.rst index 95a8e4649beed..ecf178adcd377 100644 --- a/Doc/library/asyncio-stream.rst +++ b/Doc/library/asyncio-stream.rst @@ -352,6 +352,7 @@ TCP echo client using the :func:`asyncio.open_connection` function:: print(f'Send: {message!r}') writer.write(message.encode()) + await writer.drain() data = await reader.read(100) print(f'Received: {data.decode()!r}') From webhook-mailer at python.org Thu Nov 25 12:20:27 2021 From: webhook-mailer at python.org (asvetlov) Date: Thu, 25 Nov 2021 17:20:27 -0000 Subject: [Python-checkins] [3.10] bpo-45568: Actually use @asynccontextmanager in usage example (GH-29151) (GH-29779) Message-ID: https://github.com/python/cpython/commit/52d10f6485a168141e7a50d68f9a9566fdd8379d commit: 52d10f6485a168141e7a50d68f9a9566fdd8379d branch: 3.10 author: Andrew Svetlov committer: asvetlov date: 2021-11-25T19:20:17+02:00 summary: [3.10] bpo-45568: Actually use @asynccontextmanager in usage example (GH-29151) (GH-29779) Automerge-Triggered-By: GH:asvetlov (cherry picked from commit 4dd82194f4a0e48a94191655e571b3aad1c4a22a) Co-authored-by: Zbigniew Siciarz Co-authored-by: Zbigniew Siciarz files: M Doc/library/contextlib.rst diff --git a/Doc/library/contextlib.rst b/Doc/library/contextlib.rst index 3dbf3a8f13da7..b6ec6b8c876be 100644 --- a/Doc/library/contextlib.rst +++ b/Doc/library/contextlib.rst @@ -130,7 +130,9 @@ Functions and classes provided: either as decorators or with :keyword:`async with` statements:: import time + from contextlib import asynccontextmanager + @asynccontextmanager async def timeit(): now = time.monotonic() try: From webhook-mailer at python.org Thu Nov 25 14:53:24 2021 From: webhook-mailer at python.org (tiran) Date: Thu, 25 Nov 2021 19:53:24 -0000 Subject: [Python-checkins] [3.9] bpo-45881: Use CC from env first for cross building (GH-29752) (GH-29754) Message-ID: https://github.com/python/cpython/commit/cd6d2577fadc4cc0275017f27f46b0a628216353 commit: cd6d2577fadc4cc0275017f27f46b0a628216353 branch: 3.9 author: Christian Heimes committer: tiran date: 2021-11-25T20:53:14+01:00 summary: [3.9] bpo-45881: Use CC from env first for cross building (GH-29752) (GH-29754) Co-authored-by: Christian Heimes . Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Build/2021-11-24-17-14-06.bpo-45881.GTXXLk.rst M setup.py diff --git a/Misc/NEWS.d/next/Build/2021-11-24-17-14-06.bpo-45881.GTXXLk.rst b/Misc/NEWS.d/next/Build/2021-11-24-17-14-06.bpo-45881.GTXXLk.rst new file mode 100644 index 0000000000000..b697658cf3aaa --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-24-17-14-06.bpo-45881.GTXXLk.rst @@ -0,0 +1,2 @@ +``setup.py`` now uses ``CC`` from environment first to discover multiarch +and cross compile paths. diff --git a/setup.py b/setup.py index 9a5887b59ffc4..c6023e1ab6353 100644 --- a/setup.py +++ b/setup.py @@ -65,6 +65,9 @@ def get_platform(): MACOS = (HOST_PLATFORM == 'darwin') AIX = (HOST_PLATFORM.startswith('aix')) VXWORKS = ('vxworks' in HOST_PLATFORM) +CC = os.environ.get("CC") +if not CC: + CC = sysconfig.get_config_var("CC") SUMMARY = """ @@ -443,6 +446,9 @@ def set_compiler_executables(self): def build_extensions(self): self.set_srcdir() + self.set_compiler_executables() + self.configure_compiler() + self.init_inc_lib_dirs() # Detect which modules should be compiled self.detect_modules() @@ -451,7 +457,6 @@ def build_extensions(self): self.update_sources_depends() mods_built, mods_disabled = self.remove_configured_extensions() - self.set_compiler_executables() build_ext.build_extensions(self) @@ -631,12 +636,11 @@ def check_extension_import(self, ext): def add_multiarch_paths(self): # Debian/Ubuntu multiarch support. # https://wiki.ubuntu.com/MultiarchSpec - cc = sysconfig.get_config_var('CC') tmpfile = os.path.join(self.build_temp, 'multiarch') if not os.path.exists(self.build_temp): os.makedirs(self.build_temp) ret = run_command( - '%s -print-multiarch > %s 2> /dev/null' % (cc, tmpfile)) + '%s -print-multiarch > %s 2> /dev/null' % (CC, tmpfile)) multiarch_path_component = '' try: if ret == 0: @@ -675,11 +679,10 @@ def add_multiarch_paths(self): os.unlink(tmpfile) def add_cross_compiling_paths(self): - cc = sysconfig.get_config_var('CC') tmpfile = os.path.join(self.build_temp, 'ccpaths') if not os.path.exists(self.build_temp): os.makedirs(self.build_temp) - ret = run_command('%s -E -v - %s 1>/dev/null' % (cc, tmpfile)) + ret = run_command('%s -E -v - %s 1>/dev/null' % (CC, tmpfile)) is_gcc = False is_clang = False in_incdirs = False @@ -1783,9 +1786,6 @@ def detect_uuid(self): self.missing.append('_uuid') def detect_modules(self): - self.configure_compiler() - self.init_inc_lib_dirs() - self.detect_simple_extensions() if TEST_EXTENSIONS: self.detect_test_extensions() From webhook-mailer at python.org Thu Nov 25 14:55:38 2021 From: webhook-mailer at python.org (tiran) Date: Thu, 25 Nov 2021 19:55:38 -0000 Subject: [Python-checkins] bpo-33393: Update config.guess and config.sub (GH-29781) Message-ID: https://github.com/python/cpython/commit/dfcc6ff36f8bedae420fe228312527ec3937c973 commit: dfcc6ff36f8bedae420fe228312527ec3937c973 branch: main author: Christian Heimes committer: tiran date: 2021-11-25T20:55:29+01:00 summary: bpo-33393: Update config.guess and config.sub (GH-29781) files: A Misc/NEWS.d/next/Build/2021-11-25-20-26-06.bpo-33393.24YNtM.rst M Makefile.pre.in M config.guess M config.sub diff --git a/Makefile.pre.in b/Makefile.pre.in index bb624755dd3ee..be9f68d4e0285 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -2383,6 +2383,12 @@ patchcheck: @DEF_MAKE_RULE@ check-limited-abi: all $(RUNSHARED) ./$(BUILDPYTHON) $(srcdir)/Tools/scripts/stable_abi.py --all $(srcdir)/Misc/stable_abi.txt +.PHONY: update-config +update-config: + curl -sL -o config.guess 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD' + curl -sL -o config.sub 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD' + chmod +x config.guess config.sub + # Dependencies Python/thread.o: @THREADHEADERS@ $(srcdir)/Python/condvar.h diff --git a/Misc/NEWS.d/next/Build/2021-11-25-20-26-06.bpo-33393.24YNtM.rst b/Misc/NEWS.d/next/Build/2021-11-25-20-26-06.bpo-33393.24YNtM.rst new file mode 100644 index 0000000000000..c27869c9b6ded --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-25-20-26-06.bpo-33393.24YNtM.rst @@ -0,0 +1,3 @@ +Update ``config.guess`` to 2021-06-03 and ``config.sub`` to 2021-08-14. +``Makefile`` now has an ``update-config`` target to make updating more +convenient. diff --git a/config.guess b/config.guess index 1972fda8eb05d..e81d3ae7c210b 100755 --- a/config.guess +++ b/config.guess @@ -2,7 +2,9 @@ # Attempt to guess a canonical system name. # Copyright 1992-2021 Free Software Foundation, Inc. -timestamp='2021-01-25' +# shellcheck disable=SC2006,SC2268 # see below for rationale + +timestamp='2021-06-03' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -32,7 +34,15 @@ timestamp='2021-01-25' # Please send patches to . -me=$(echo "$0" | sed -e 's,.*/,,') +# The "shellcheck disable" line above the timestamp inhibits complaints +# about features and limitations of the classic Bourne shell that were +# superseded or lifted in POSIX. However, this script identifies a wide +# variety of pre-POSIX systems that do not have POSIX shells at all, and +# even some reasonably current systems (Solaris 10 as case-in-point) still +# have a pre-POSIX /bin/sh. + + +me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] @@ -84,6 +94,9 @@ if test $# != 0; then exit 1 fi +# Just in case it came from the environment. +GUESS= + # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a @@ -102,8 +115,8 @@ set_cc_for_build() { # prevent multiple calls if $tmp is already set test "$tmp" && return 0 : "${TMPDIR=/tmp}" - # shellcheck disable=SC2039 - { tmp=$( (umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null) && test -n "$tmp" && test -d "$tmp" ; } || + # shellcheck disable=SC2039,SC3028 + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } @@ -112,7 +125,7 @@ set_cc_for_build() { ,,) echo "int x;" > "$dummy.c" for driver in cc gcc c89 c99 ; do if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then - CC_FOR_BUILD="$driver" + CC_FOR_BUILD=$driver break fi done @@ -131,12 +144,12 @@ if test -f /.attbin/uname ; then PATH=$PATH:/.attbin ; export PATH fi -UNAME_MACHINE=$( (uname -m) 2>/dev/null) || UNAME_MACHINE=unknown -UNAME_RELEASE=$( (uname -r) 2>/dev/null) || UNAME_RELEASE=unknown -UNAME_SYSTEM=$( (uname -s) 2>/dev/null) || UNAME_SYSTEM=unknown -UNAME_VERSION=$( (uname -v) 2>/dev/null) || UNAME_VERSION=unknown +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown -case "$UNAME_SYSTEM" in +case $UNAME_SYSTEM in Linux|GNU|GNU/*) LIBC=unknown @@ -157,7 +170,8 @@ Linux|GNU|GNU/*) #endif #endif EOF - eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g')" + cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + eval "$cc_set_libc" # Second heuristic to detect musl libc. if [ "$LIBC" = unknown ] && @@ -176,7 +190,7 @@ esac # Note: order is significant - the case branches are not exclusive. -case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in +case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, @@ -188,11 +202,11 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". - UNAME_MACHINE_ARCH=$( (uname -p 2>/dev/null || \ + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ /sbin/sysctl -n hw.machine_arch 2>/dev/null || \ /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \ - echo unknown)) - case "$UNAME_MACHINE_ARCH" in + echo unknown)` + case $UNAME_MACHINE_ARCH in aarch64eb) machine=aarch64_be-unknown ;; armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; @@ -200,15 +214,15 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; earmv*) - arch=$(echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,') - endian=$(echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p') - machine="${arch}${endian}"-unknown + arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` + machine=${arch}${endian}-unknown ;; - *) machine="$UNAME_MACHINE_ARCH"-unknown ;; + *) machine=$UNAME_MACHINE_ARCH-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently (or will in the future) and ABI. - case "$UNAME_MACHINE_ARCH" in + case $UNAME_MACHINE_ARCH in earm*) os=netbsdelf ;; @@ -229,10 +243,10 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in ;; esac # Determine ABI tags. - case "$UNAME_MACHINE_ARCH" in + case $UNAME_MACHINE_ARCH in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' - abi=$(echo "$UNAME_MACHINE_ARCH" | sed -e "$expr") + abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` ;; esac # The OS release @@ -240,76 +254,82 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. - case "$UNAME_VERSION" in + case $UNAME_VERSION in Debian*) release='-gnu' ;; *) - release=$(echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2) + release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "$machine-${os}${release}${abi-}" - exit ;; + GUESS=$machine-${os}${release}${abi-} + ;; *:Bitrig:*:*) - UNAME_MACHINE_ARCH=$(arch | sed 's/Bitrig.//') - echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" - exit ;; + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE + ;; *:OpenBSD:*:*) - UNAME_MACHINE_ARCH=$(arch | sed 's/OpenBSD.//') - echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" - exit ;; + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE + ;; + *:SecBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'` + GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE + ;; *:LibertyBSD:*:*) - UNAME_MACHINE_ARCH=$(arch | sed 's/^.*BSD\.//') - echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" - exit ;; + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE + ;; *:MidnightBSD:*:*) - echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE + ;; *:ekkoBSD:*:*) - echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE + ;; *:SolidBSD:*:*) - echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE + ;; *:OS108:*:*) - echo "$UNAME_MACHINE"-unknown-os108_"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE + ;; macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd"$UNAME_RELEASE" - exit ;; + GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE + ;; *:MirBSD:*:*) - echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE + ;; *:Sortix:*:*) - echo "$UNAME_MACHINE"-unknown-sortix - exit ;; + GUESS=$UNAME_MACHINE-unknown-sortix + ;; *:Twizzler:*:*) - echo "$UNAME_MACHINE"-unknown-twizzler - exit ;; + GUESS=$UNAME_MACHINE-unknown-twizzler + ;; *:Redox:*:*) - echo "$UNAME_MACHINE"-unknown-redox - exit ;; + GUESS=$UNAME_MACHINE-unknown-redox + ;; mips:OSF1:*.*) - echo mips-dec-osf1 - exit ;; + GUESS=mips-dec-osf1 + ;; alpha:OSF1:*:*) + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + trap '' 0 case $UNAME_RELEASE in *4.0) - UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $3}') + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) - UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $4}') + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. - ALPHA_CPU_TYPE=$(/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1) - case "$ALPHA_CPU_TYPE" in + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case $ALPHA_CPU_TYPE in "EV4 (21064)") UNAME_MACHINE=alpha ;; "EV4.5 (21064)") @@ -346,68 +366,69 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - echo "$UNAME_MACHINE"-dec-osf"$(echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz)" - # Reset EXIT trap before exiting to avoid spurious non-zero exit code. - exitcode=$? - trap '' 0 - exit $exitcode ;; + OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + GUESS=$UNAME_MACHINE-dec-osf$OSF_REL + ;; Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit ;; + GUESS=m68k-unknown-sysv4 + ;; *:[Aa]miga[Oo][Ss]:*:*) - echo "$UNAME_MACHINE"-unknown-amigaos - exit ;; + GUESS=$UNAME_MACHINE-unknown-amigaos + ;; *:[Mm]orph[Oo][Ss]:*:*) - echo "$UNAME_MACHINE"-unknown-morphos - exit ;; + GUESS=$UNAME_MACHINE-unknown-morphos + ;; *:OS/390:*:*) - echo i370-ibm-openedition - exit ;; + GUESS=i370-ibm-openedition + ;; *:z/VM:*:*) - echo s390-ibm-zvmoe - exit ;; + GUESS=s390-ibm-zvmoe + ;; *:OS400:*:*) - echo powerpc-ibm-os400 - exit ;; + GUESS=powerpc-ibm-os400 + ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix"$UNAME_RELEASE" - exit ;; + GUESS=arm-acorn-riscix$UNAME_RELEASE + ;; arm*:riscos:*:*|arm*:RISCOS:*:*) - echo arm-unknown-riscos - exit ;; + GUESS=arm-unknown-riscos + ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit ;; + GUESS=hppa1.1-hitachi-hiuxmpp + ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee at wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "$( (/bin/universe) 2>/dev/null)" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit ;; + case `(/bin/universe) 2>/dev/null` in + att) GUESS=pyramid-pyramid-sysv3 ;; + *) GUESS=pyramid-pyramid-bsd ;; + esac + ;; NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit ;; + GUESS=pyramid-pyramid-svr4 + ;; DRS?6000:unix:4.0:6*) - echo sparc-icl-nx6 - exit ;; + GUESS=sparc-icl-nx6 + ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) - case $(/usr/bin/uname -p) in - sparc) echo sparc-icl-nx7; exit ;; - esac ;; + case `/usr/bin/uname -p` in + sparc) GUESS=sparc-icl-nx7 ;; + esac + ;; s390x:SunOS:*:*) - echo "$UNAME_MACHINE"-ibm-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')" - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL + ;; sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')" - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=sparc-hal-solaris2$SUN_REL + ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')" - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=sparc-sun-solaris2$SUN_REL + ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux"$UNAME_RELEASE" - exit ;; + GUESS=i386-pc-auroraux$UNAME_RELEASE + ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) set_cc_for_build SUN_ARCH=i386 @@ -422,41 +443,44 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in SUN_ARCH=x86_64 fi fi - echo "$SUN_ARCH"-pc-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')" - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=$SUN_ARCH-pc-solaris2$SUN_REL + ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')" - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=sparc-sun-solaris3$SUN_REL + ;; sun4*:SunOS:*:*) - case "$(/usr/bin/arch -k)" in + case `/usr/bin/arch -k` in Series*|S4*) - UNAME_RELEASE=$(uname -v) + UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos"$(echo "$UNAME_RELEASE"|sed -e 's/-/_/')" - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'` + GUESS=sparc-sun-sunos$SUN_REL + ;; sun3*:SunOS:*:*) - echo m68k-sun-sunos"$UNAME_RELEASE" - exit ;; + GUESS=m68k-sun-sunos$UNAME_RELEASE + ;; sun*:*:4.2BSD:*) - UNAME_RELEASE=$( (sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 - case "$(/bin/arch)" in + case `/bin/arch` in sun3) - echo m68k-sun-sunos"$UNAME_RELEASE" + GUESS=m68k-sun-sunos$UNAME_RELEASE ;; sun4) - echo sparc-sun-sunos"$UNAME_RELEASE" + GUESS=sparc-sun-sunos$UNAME_RELEASE ;; esac - exit ;; + ;; aushp:SunOS:*:*) - echo sparc-auspex-sunos"$UNAME_RELEASE" - exit ;; + GUESS=sparc-auspex-sunos$UNAME_RELEASE + ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor @@ -466,41 +490,41 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint"$UNAME_RELEASE" - exit ;; + GUESS=m68k-atari-mint$UNAME_RELEASE + ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint"$UNAME_RELEASE" - exit ;; + GUESS=m68k-atari-mint$UNAME_RELEASE + ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint"$UNAME_RELEASE" - exit ;; + GUESS=m68k-atari-mint$UNAME_RELEASE + ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint"$UNAME_RELEASE" - exit ;; + GUESS=m68k-milan-mint$UNAME_RELEASE + ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint"$UNAME_RELEASE" - exit ;; + GUESS=m68k-hades-mint$UNAME_RELEASE + ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint"$UNAME_RELEASE" - exit ;; + GUESS=m68k-unknown-mint$UNAME_RELEASE + ;; m68k:machten:*:*) - echo m68k-apple-machten"$UNAME_RELEASE" - exit ;; + GUESS=m68k-apple-machten$UNAME_RELEASE + ;; powerpc:machten:*:*) - echo powerpc-apple-machten"$UNAME_RELEASE" - exit ;; + GUESS=powerpc-apple-machten$UNAME_RELEASE + ;; RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit ;; + GUESS=mips-dec-mach_bsd4.3 + ;; RISC*:ULTRIX:*:*) - echo mips-dec-ultrix"$UNAME_RELEASE" - exit ;; + GUESS=mips-dec-ultrix$UNAME_RELEASE + ;; VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix"$UNAME_RELEASE" - exit ;; + GUESS=vax-dec-ultrix$UNAME_RELEASE + ;; 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix"$UNAME_RELEASE" - exit ;; + GUESS=clipper-intergraph-clix$UNAME_RELEASE + ;; mips:*:*:UMIPS | mips:*:*:RISCos) set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" @@ -525,78 +549,79 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" && - dummyarg=$(echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p') && - SYSTEM_NAME=$("$dummy" "$dummyarg") && + dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`"$dummy" "$dummyarg"` && { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos"$UNAME_RELEASE" - exit ;; + GUESS=mips-mips-riscos$UNAME_RELEASE + ;; Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit ;; + GUESS=powerpc-motorola-powermax + ;; Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit ;; + GUESS=powerpc-harris-powermax + ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - echo powerpc-harris-powermax - exit ;; + GUESS=powerpc-harris-powermax + ;; Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit ;; + GUESS=powerpc-harris-powerunix + ;; m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit ;; + GUESS=m88k-harris-cxux7 + ;; m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit ;; + GUESS=m88k-motorola-sysv4 + ;; m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit ;; + GUESS=m88k-motorola-sysv3 + ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=$(/usr/bin/uname -p) + UNAME_PROCESSOR=`/usr/bin/uname -p` if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110 then if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \ test "$TARGET_BINARY_INTERFACE"x = x then - echo m88k-dg-dgux"$UNAME_RELEASE" + GUESS=m88k-dg-dgux$UNAME_RELEASE else - echo m88k-dg-dguxbcs"$UNAME_RELEASE" + GUESS=m88k-dg-dguxbcs$UNAME_RELEASE fi else - echo i586-dg-dgux"$UNAME_RELEASE" + GUESS=i586-dg-dgux$UNAME_RELEASE fi - exit ;; + ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit ;; + GUESS=m88k-dolphin-sysv3 + ;; M88*:*:R3*:*) # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit ;; + GUESS=m88k-motorola-sysv3 + ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit ;; + GUESS=m88k-tektronix-sysv3 + ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit ;; + GUESS=m68k-tektronix-bsd + ;; *:IRIX*:*:*) - echo mips-sgi-irix"$(echo "$UNAME_RELEASE"|sed -e 's/-/_/g')" - exit ;; + IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'` + GUESS=mips-sgi-irix$IRIX_REL + ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit ;; # Note that: echo "'$(uname -s)'" gives 'AIX ' + GUESS=romp-ibm-aix # uname -m gives an 8 hex-code CPU id + ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) - echo i386-ibm-aix - exit ;; + GUESS=i386-ibm-aix + ;; ia64:AIX:*:*) if test -x /usr/bin/oslevel ; then - IBM_REV=$(/usr/bin/oslevel) + IBM_REV=`/usr/bin/oslevel` else - IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" + IBM_REV=$UNAME_VERSION.$UNAME_RELEASE fi - echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" - exit ;; + GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV + ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then set_cc_for_build @@ -611,68 +636,68 @@ EOF exit(0); } EOF - if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=$("$dummy") + if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` then - echo "$SYSTEM_NAME" + GUESS=$SYSTEM_NAME else - echo rs6000-ibm-aix3.2.5 + GUESS=rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 + GUESS=rs6000-ibm-aix3.2.4 else - echo rs6000-ibm-aix3.2 + GUESS=rs6000-ibm-aix3.2 fi - exit ;; + ;; *:AIX:*:[4567]) - IBM_CPU_ID=$(/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }') + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if test -x /usr/bin/lslpp ; then - IBM_REV=$(/usr/bin/lslpp -Lqc bos.rte.libc | - awk -F: '{ print $3 }' | sed s/[0-9]*$/0/) + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \ + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else - IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" + IBM_REV=$UNAME_VERSION.$UNAME_RELEASE fi - echo "$IBM_ARCH"-ibm-aix"$IBM_REV" - exit ;; + GUESS=$IBM_ARCH-ibm-aix$IBM_REV + ;; *:AIX:*:*) - echo rs6000-ibm-aix - exit ;; + GUESS=rs6000-ibm-aix + ;; ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) - echo romp-ibm-bsd4.4 - exit ;; + GUESS=romp-ibm-bsd4.4 + ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to - exit ;; # report: romp-ibm BSD 4.3 + GUESS=romp-ibm-bsd$UNAME_RELEASE # 4.3 with uname added to + ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) - echo rs6000-bull-bosx - exit ;; + GUESS=rs6000-bull-bosx + ;; DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit ;; + GUESS=m68k-bull-sysv3 + ;; 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit ;; + GUESS=m68k-hp-bsd + ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit ;; + GUESS=m68k-hp-bsd4.4 + ;; 9000/[34678]??:HP-UX:*:*) - HPUX_REV=$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//') - case "$UNAME_MACHINE" in + HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` + case $UNAME_MACHINE in 9000/31?) HP_ARCH=m68000 ;; 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if test -x /usr/bin/getconf; then - sc_cpu_version=$(/usr/bin/getconf SC_CPU_VERSION 2>/dev/null) - sc_kernel_bits=$(/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null) - case "$sc_cpu_version" in + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case $sc_cpu_version in 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 - case "$sc_kernel_bits" in + case $sc_kernel_bits in 32) HP_ARCH=hppa2.0n ;; 64) HP_ARCH=hppa2.0w ;; '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 @@ -714,7 +739,7 @@ EOF exit (0); } EOF - (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=$("$dummy") + (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac @@ -739,12 +764,12 @@ EOF HP_ARCH=hppa64 fi fi - echo "$HP_ARCH"-hp-hpux"$HPUX_REV" - exit ;; + GUESS=$HP_ARCH-hp-hpux$HPUX_REV + ;; ia64:HP-UX:*:*) - HPUX_REV=$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//') - echo ia64-hp-hpux"$HPUX_REV" - exit ;; + HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` + GUESS=ia64-hp-hpux$HPUX_REV + ;; 3050*:HI-UX:*:*) set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" @@ -772,38 +797,38 @@ EOF exit (0); } EOF - $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=$("$dummy") && + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } - echo unknown-hitachi-hiuxwe2 - exit ;; + GUESS=unknown-hitachi-hiuxwe2 + ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) - echo hppa1.1-hp-bsd - exit ;; + GUESS=hppa1.1-hp-bsd + ;; 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit ;; + GUESS=hppa1.0-hp-bsd + ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit ;; + GUESS=hppa1.0-hp-mpeix + ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) - echo hppa1.1-hp-osf - exit ;; + GUESS=hppa1.1-hp-osf + ;; hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit ;; + GUESS=hppa1.0-hp-osf + ;; i*86:OSF1:*:*) if test -x /usr/sbin/sysversion ; then - echo "$UNAME_MACHINE"-unknown-osf1mk + GUESS=$UNAME_MACHINE-unknown-osf1mk else - echo "$UNAME_MACHINE"-unknown-osf1 + GUESS=$UNAME_MACHINE-unknown-osf1 fi - exit ;; + ;; parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit ;; + GUESS=hppa1.1-hp-lites + ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit ;; + GUESS=c1-convex-bsd + ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd @@ -811,17 +836,18 @@ EOF fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit ;; + GUESS=c34-convex-bsd + ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit ;; + GUESS=c38-convex-bsd + ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit ;; + GUESS=c4-convex-bsd + ;; CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' - exit ;; + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=ymp-cray-unicos$CRAY_REL + ;; CRAY*[A-Z]90:*:*:*) echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ @@ -829,114 +855,126 @@ EOF -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) - echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' - exit ;; + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=t90-cray-unicos$CRAY_REL + ;; CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' - exit ;; + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=alphaev5-cray-unicosmk$CRAY_REL + ;; CRAY*SV1:*:*:*) - echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' - exit ;; + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=sv1-cray-unicos$CRAY_REL + ;; *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' - exit ;; + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=craynv-cray-unicosmp$CRAY_REL + ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=$(uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz) - FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///') - FUJITSU_REL=$(echo "$UNAME_RELEASE" | sed -e 's/ /_/') - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` + GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} + ;; 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///') - FUJITSU_REL=$(echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/') - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` + GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} + ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE + ;; sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi"$UNAME_RELEASE" - exit ;; + GUESS=sparc-unknown-bsdi$UNAME_RELEASE + ;; *:BSD/OS:*:*) - echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE + ;; arm:FreeBSD:*:*) - UNAME_PROCESSOR=$(uname -p) + UNAME_PROCESSOR=`uname -p` set_cc_for_build if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then - echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabi + FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi else - echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabihf + FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf fi - exit ;; + ;; *:FreeBSD:*:*) - UNAME_PROCESSOR=$(/usr/bin/uname -p) - case "$UNAME_PROCESSOR" in + UNAME_PROCESSOR=`/usr/bin/uname -p` + case $UNAME_PROCESSOR in amd64) UNAME_PROCESSOR=x86_64 ;; i386) UNAME_PROCESSOR=i586 ;; esac - echo "$UNAME_PROCESSOR"-unknown-freebsd"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')" - exit ;; + FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL + ;; i*:CYGWIN*:*) - echo "$UNAME_MACHINE"-pc-cygwin - exit ;; + GUESS=$UNAME_MACHINE-pc-cygwin + ;; *:MINGW64*:*) - echo "$UNAME_MACHINE"-pc-mingw64 - exit ;; + GUESS=$UNAME_MACHINE-pc-mingw64 + ;; *:MINGW*:*) - echo "$UNAME_MACHINE"-pc-mingw32 - exit ;; + GUESS=$UNAME_MACHINE-pc-mingw32 + ;; *:MSYS*:*) - echo "$UNAME_MACHINE"-pc-msys - exit ;; + GUESS=$UNAME_MACHINE-pc-msys + ;; i*:PW*:*) - echo "$UNAME_MACHINE"-pc-pw32 - exit ;; + GUESS=$UNAME_MACHINE-pc-pw32 + ;; *:Interix*:*) - case "$UNAME_MACHINE" in + case $UNAME_MACHINE in x86) - echo i586-pc-interix"$UNAME_RELEASE" - exit ;; + GUESS=i586-pc-interix$UNAME_RELEASE + ;; authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix"$UNAME_RELEASE" - exit ;; + GUESS=x86_64-unknown-interix$UNAME_RELEASE + ;; IA64) - echo ia64-unknown-interix"$UNAME_RELEASE" - exit ;; + GUESS=ia64-unknown-interix$UNAME_RELEASE + ;; esac ;; i*:UWIN*:*) - echo "$UNAME_MACHINE"-pc-uwin - exit ;; + GUESS=$UNAME_MACHINE-pc-uwin + ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-pc-cygwin - exit ;; + GUESS=x86_64-pc-cygwin + ;; prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')" - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=powerpcle-unknown-solaris2$SUN_REL + ;; *:GNU:*:*) # the GNU system - echo "$(echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,')-unknown-$LIBC$(echo "$UNAME_RELEASE"|sed -e 's,/.*$,,')" - exit ;; + GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'` + GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'` + GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL + ;; *:GNU/*:*:*) # other systems with GNU libc and userland - echo "$UNAME_MACHINE-unknown-$(echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]")$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')-$LIBC" - exit ;; + GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"` + GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC + ;; *:Minix:*:*) - echo "$UNAME_MACHINE"-unknown-minix - exit ;; + GUESS=$UNAME_MACHINE-unknown-minix + ;; aarch64:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; alpha:Linux:*:*) - case $(sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null) in + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; @@ -947,63 +985,63 @@ EOF esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC=gnulibc1 ; fi - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - arc:Linux:*:* | arceb:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; arm*:Linux:*:*) set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi + GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi else - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf + GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf fi fi - exit ;; + ;; avr32*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; cris:Linux:*:*) - echo "$UNAME_MACHINE"-axis-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-axis-linux-$LIBC + ;; crisv32:Linux:*:*) - echo "$UNAME_MACHINE"-axis-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-axis-linux-$LIBC + ;; e2k:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; frv:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; hexagon:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; i*86:Linux:*:*) - echo "$UNAME_MACHINE"-pc-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-pc-linux-$LIBC + ;; ia64:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; k1om:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; m32r*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; m68*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; mips:Linux:*:* | mips64:Linux:*:*) set_cc_for_build IS_GLIBC=0 @@ -1048,65 +1086,66 @@ EOF #endif #endif EOF - eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI')" + cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'` + eval "$cc_set_vars" test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } ;; mips64el:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; openrisc*:Linux:*:*) - echo or1k-unknown-linux-"$LIBC" - exit ;; + GUESS=or1k-unknown-linux-$LIBC + ;; or32:Linux:*:* | or1k*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; padre:Linux:*:*) - echo sparc-unknown-linux-"$LIBC" - exit ;; + GUESS=sparc-unknown-linux-$LIBC + ;; parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-"$LIBC" - exit ;; + GUESS=hppa64-unknown-linux-$LIBC + ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level - case $(grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2) in - PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; - PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; - *) echo hppa-unknown-linux-"$LIBC" ;; + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;; + PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;; + *) GUESS=hppa-unknown-linux-$LIBC ;; esac - exit ;; + ;; ppc64:Linux:*:*) - echo powerpc64-unknown-linux-"$LIBC" - exit ;; + GUESS=powerpc64-unknown-linux-$LIBC + ;; ppc:Linux:*:*) - echo powerpc-unknown-linux-"$LIBC" - exit ;; + GUESS=powerpc-unknown-linux-$LIBC + ;; ppc64le:Linux:*:*) - echo powerpc64le-unknown-linux-"$LIBC" - exit ;; + GUESS=powerpc64le-unknown-linux-$LIBC + ;; ppcle:Linux:*:*) - echo powerpcle-unknown-linux-"$LIBC" - exit ;; + GUESS=powerpcle-unknown-linux-$LIBC + ;; riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; s390:Linux:*:* | s390x:Linux:*:*) - echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-ibm-linux-$LIBC + ;; sh64*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; sh*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; sparc:Linux:*:* | sparc64:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; tile*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; vax:Linux:*:*) - echo "$UNAME_MACHINE"-dec-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-dec-linux-$LIBC + ;; x86_64:Linux:*:*) set_cc_for_build LIBCABI=$LIBC @@ -1115,71 +1154,71 @@ EOF (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_X32 >/dev/null then - LIBCABI="$LIBC"x32 + LIBCABI=${LIBC}x32 fi fi - echo "$UNAME_MACHINE"-pc-linux-"$LIBCABI" - exit ;; + GUESS=$UNAME_MACHINE-pc-linux-$LIBCABI + ;; xtensa*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. - echo i386-sequent-sysv4 - exit ;; + GUESS=i386-sequent-sysv4 + ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. - echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" - exit ;; + GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION + ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. - echo "$UNAME_MACHINE"-pc-os2-emx - exit ;; + GUESS=$UNAME_MACHINE-pc-os2-emx + ;; i*86:XTS-300:*:STOP) - echo "$UNAME_MACHINE"-unknown-stop - exit ;; + GUESS=$UNAME_MACHINE-unknown-stop + ;; i*86:atheos:*:*) - echo "$UNAME_MACHINE"-unknown-atheos - exit ;; + GUESS=$UNAME_MACHINE-unknown-atheos + ;; i*86:syllable:*:*) - echo "$UNAME_MACHINE"-pc-syllable - exit ;; + GUESS=$UNAME_MACHINE-pc-syllable + ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos"$UNAME_RELEASE" - exit ;; + GUESS=i386-unknown-lynxos$UNAME_RELEASE + ;; i*86:*DOS:*:*) - echo "$UNAME_MACHINE"-pc-msdosdjgpp - exit ;; + GUESS=$UNAME_MACHINE-pc-msdosdjgpp + ;; i*86:*:4.*:*) - UNAME_REL=$(echo "$UNAME_RELEASE" | sed 's/\/MP$//') + UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" + GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL else - echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" + GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL fi - exit ;; + ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. - case $(/bin/uname -X | grep "^Machine") in + case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac - echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}" - exit ;; + GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then - UNAME_REL=$(sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=$( (/bin/uname -X|grep Release|sed -e 's/.*= //')) + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 @@ -1187,11 +1226,11 @@ EOF && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 - echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" + GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL else - echo "$UNAME_MACHINE"-pc-sysv32 + GUESS=$UNAME_MACHINE-pc-sysv32 fi - exit ;; + ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about @@ -1199,37 +1238,37 @@ EOF # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. - echo i586-pc-msdosdjgpp - exit ;; + GUESS=i586-pc-msdosdjgpp + ;; Intel:Mach:3*:*) - echo i386-pc-mach3 - exit ;; + GUESS=i386-pc-mach3 + ;; paragon:*:*:*) - echo i860-intel-osf1 - exit ;; + GUESS=i860-intel-osf1 + ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 + GUESS=i860-stardent-sysv$UNAME_RELEASE # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 + GUESS=i860-unknown-sysv$UNAME_RELEASE # Unknown i860-SVR4 fi - exit ;; + ;; mini*:CTIX:SYS*5:*) # "miniframe" - echo m68010-convergent-sysv - exit ;; + GUESS=m68010-convergent-sysv + ;; mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit ;; + GUESS=m68k-convergent-sysv + ;; M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit ;; + GUESS=m68k-diab-dnix + ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ - && OS_REL=.$(sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid) + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ @@ -1240,7 +1279,7 @@ EOF NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ - && OS_REL=.$(sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid) + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ @@ -1248,118 +1287,118 @@ EOF /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos"$UNAME_RELEASE" - exit ;; + GUESS=m68k-unknown-lynxos$UNAME_RELEASE + ;; mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit ;; + GUESS=m68k-atari-sysv4 + ;; TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos"$UNAME_RELEASE" - exit ;; + GUESS=sparc-unknown-lynxos$UNAME_RELEASE + ;; rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos"$UNAME_RELEASE" - exit ;; + GUESS=rs6000-unknown-lynxos$UNAME_RELEASE + ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos"$UNAME_RELEASE" - exit ;; + GUESS=powerpc-unknown-lynxos$UNAME_RELEASE + ;; SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv"$UNAME_RELEASE" - exit ;; + GUESS=mips-dde-sysv$UNAME_RELEASE + ;; RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit ;; + GUESS=mips-sni-sysv4 + ;; RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit ;; + GUESS=mips-sni-sysv4 + ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=$( (uname -p) 2>/dev/null) - echo "$UNAME_MACHINE"-sni-sysv4 + UNAME_MACHINE=`(uname -p) 2>/dev/null` + GUESS=$UNAME_MACHINE-sni-sysv4 else - echo ns32k-sni-sysv + GUESS=ns32k-sni-sysv fi - exit ;; + ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says - echo i586-unisys-sysv4 - exit ;; + GUESS=i586-unisys-sysv4 + ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit ;; + GUESS=hppa1.1-stratus-sysv4 + ;; *:*:*:FTX*) # From seanf at swdc.stratus.com. - echo i860-stratus-sysv4 - exit ;; + GUESS=i860-stratus-sysv4 + ;; i*86:VOS:*:*) # From Paul.Green at stratus.com. - echo "$UNAME_MACHINE"-stratus-vos - exit ;; + GUESS=$UNAME_MACHINE-stratus-vos + ;; *:VOS:*:*) # From Paul.Green at stratus.com. - echo hppa1.1-stratus-vos - exit ;; + GUESS=hppa1.1-stratus-vos + ;; mc68*:A/UX:*:*) - echo m68k-apple-aux"$UNAME_RELEASE" - exit ;; + GUESS=m68k-apple-aux$UNAME_RELEASE + ;; news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit ;; + GUESS=mips-sony-newsos6 + ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if test -d /usr/nec; then - echo mips-nec-sysv"$UNAME_RELEASE" + GUESS=mips-nec-sysv$UNAME_RELEASE else - echo mips-unknown-sysv"$UNAME_RELEASE" + GUESS=mips-unknown-sysv$UNAME_RELEASE fi - exit ;; + ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit ;; + GUESS=powerpc-be-beos + ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit ;; + GUESS=powerpc-apple-beos + ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit ;; + GUESS=i586-pc-beos + ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. - echo i586-pc-haiku - exit ;; + GUESS=i586-pc-haiku + ;; x86_64:Haiku:*:*) - echo x86_64-unknown-haiku - exit ;; + GUESS=x86_64-unknown-haiku + ;; SX-4:SUPER-UX:*:*) - echo sx4-nec-superux"$UNAME_RELEASE" - exit ;; + GUESS=sx4-nec-superux$UNAME_RELEASE + ;; SX-5:SUPER-UX:*:*) - echo sx5-nec-superux"$UNAME_RELEASE" - exit ;; + GUESS=sx5-nec-superux$UNAME_RELEASE + ;; SX-6:SUPER-UX:*:*) - echo sx6-nec-superux"$UNAME_RELEASE" - exit ;; + GUESS=sx6-nec-superux$UNAME_RELEASE + ;; SX-7:SUPER-UX:*:*) - echo sx7-nec-superux"$UNAME_RELEASE" - exit ;; + GUESS=sx7-nec-superux$UNAME_RELEASE + ;; SX-8:SUPER-UX:*:*) - echo sx8-nec-superux"$UNAME_RELEASE" - exit ;; + GUESS=sx8-nec-superux$UNAME_RELEASE + ;; SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux"$UNAME_RELEASE" - exit ;; + GUESS=sx8r-nec-superux$UNAME_RELEASE + ;; SX-ACE:SUPER-UX:*:*) - echo sxace-nec-superux"$UNAME_RELEASE" - exit ;; + GUESS=sxace-nec-superux$UNAME_RELEASE + ;; Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody"$UNAME_RELEASE" - exit ;; + GUESS=powerpc-apple-rhapsody$UNAME_RELEASE + ;; *:Rhapsody:*:*) - echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE + ;; arm64:Darwin:*:*) - echo aarch64-apple-darwin"$UNAME_RELEASE" - exit ;; + GUESS=aarch64-apple-darwin$UNAME_RELEASE + ;; *:Darwin:*:*) - UNAME_PROCESSOR=$(uname -p) + UNAME_PROCESSOR=`uname -p` case $UNAME_PROCESSOR in unknown) UNAME_PROCESSOR=powerpc ;; esac @@ -1393,109 +1432,116 @@ EOF # uname -m returns i386 or x86_64 UNAME_PROCESSOR=$UNAME_MACHINE fi - echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE + ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) - UNAME_PROCESSOR=$(uname -p) + UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi - echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE + ;; *:QNX:*:4*) - echo i386-pc-qnx - exit ;; + GUESS=i386-pc-qnx + ;; NEO-*:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk"$UNAME_RELEASE" - exit ;; + GUESS=neo-tandem-nsk$UNAME_RELEASE + ;; NSE-*:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk"$UNAME_RELEASE" - exit ;; + GUESS=nse-tandem-nsk$UNAME_RELEASE + ;; NSR-*:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk"$UNAME_RELEASE" - exit ;; + GUESS=nsr-tandem-nsk$UNAME_RELEASE + ;; NSV-*:NONSTOP_KERNEL:*:*) - echo nsv-tandem-nsk"$UNAME_RELEASE" - exit ;; + GUESS=nsv-tandem-nsk$UNAME_RELEASE + ;; NSX-*:NONSTOP_KERNEL:*:*) - echo nsx-tandem-nsk"$UNAME_RELEASE" - exit ;; + GUESS=nsx-tandem-nsk$UNAME_RELEASE + ;; *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit ;; + GUESS=mips-compaq-nonstopux + ;; BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit ;; + GUESS=bs2000-siemens-sysv + ;; DS/*:UNIX_System_V:*:*) - echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE + ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. - # shellcheck disable=SC2154 - if test "$cputype" = 386; then + if test "${cputype-}" = 386; then UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" + elif test "x${cputype-}" != x; then + UNAME_MACHINE=$cputype fi - echo "$UNAME_MACHINE"-unknown-plan9 - exit ;; + GUESS=$UNAME_MACHINE-unknown-plan9 + ;; *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit ;; + GUESS=pdp10-unknown-tops10 + ;; *:TENEX:*:*) - echo pdp10-unknown-tenex - exit ;; + GUESS=pdp10-unknown-tenex + ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit ;; + GUESS=pdp10-dec-tops20 + ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit ;; + GUESS=pdp10-xkl-tops20 + ;; *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit ;; + GUESS=pdp10-unknown-tops20 + ;; *:ITS:*:*) - echo pdp10-unknown-its - exit ;; + GUESS=pdp10-unknown-its + ;; SEI:*:*:SEIUX) - echo mips-sei-seiux"$UNAME_RELEASE" - exit ;; + GUESS=mips-sei-seiux$UNAME_RELEASE + ;; *:DragonFly:*:*) - echo "$UNAME_MACHINE"-unknown-dragonfly"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')" - exit ;; + DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL + ;; *:*VMS:*:*) - UNAME_MACHINE=$( (uname -p) 2>/dev/null) - case "$UNAME_MACHINE" in - A*) echo alpha-dec-vms ; exit ;; - I*) echo ia64-dec-vms ; exit ;; - V*) echo vax-dec-vms ; exit ;; + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case $UNAME_MACHINE in + A*) GUESS=alpha-dec-vms ;; + I*) GUESS=ia64-dec-vms ;; + V*) GUESS=vax-dec-vms ;; esac ;; *:XENIX:*:SysV) - echo i386-pc-xenix - exit ;; + GUESS=i386-pc-xenix + ;; i*86:skyos:*:*) - echo "$UNAME_MACHINE"-pc-skyos"$(echo "$UNAME_RELEASE" | sed -e 's/ .*$//')" - exit ;; + SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'` + GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL + ;; i*86:rdos:*:*) - echo "$UNAME_MACHINE"-pc-rdos - exit ;; + GUESS=$UNAME_MACHINE-pc-rdos + ;; *:AROS:*:*) - echo "$UNAME_MACHINE"-unknown-aros - exit ;; + GUESS=$UNAME_MACHINE-unknown-aros + ;; x86_64:VMkernel:*:*) - echo "$UNAME_MACHINE"-unknown-esx - exit ;; + GUESS=$UNAME_MACHINE-unknown-esx + ;; amd64:Isilon\ OneFS:*:*) - echo x86_64-unknown-onefs - exit ;; + GUESS=x86_64-unknown-onefs + ;; *:Unleashed:*:*) - echo "$UNAME_MACHINE"-unknown-unleashed"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE + ;; esac +# Do we have a guess based on uname results? +if test "x$GUESS" != x; then + echo "$GUESS" + exit +fi + # No uname command or uname output not recognized. set_cc_for_build cat > "$dummy.c" </dev/null); + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else @@ -1627,7 +1673,7 @@ main () } EOF -$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=$($dummy) && +$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. @@ -1635,7 +1681,7 @@ test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } echo "$0: unable to guess system type" >&2 -case "$UNAME_MACHINE:$UNAME_SYSTEM" in +case $UNAME_MACHINE:$UNAME_SYSTEM in mips:Linux | mips64:Linux) # If we got here on MIPS GNU/Linux, output extra information. cat >&2 <&2 </dev/null || echo unknown) -uname -r = $( (uname -r) 2>/dev/null || echo unknown) -uname -s = $( (uname -s) 2>/dev/null || echo unknown) -uname -v = $( (uname -v) 2>/dev/null || echo unknown) +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` -/usr/bin/uname -p = $( (/usr/bin/uname -p) 2>/dev/null) -/bin/uname -X = $( (/bin/uname -X) 2>/dev/null) +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` -hostinfo = $( (hostinfo) 2>/dev/null) -/bin/universe = $( (/bin/universe) 2>/dev/null) -/usr/bin/arch -k = $( (/usr/bin/arch -k) 2>/dev/null) -/bin/arch = $( (/bin/arch) 2>/dev/null) -/usr/bin/oslevel = $( (/usr/bin/oslevel) 2>/dev/null) -/usr/convex/getsysinfo = $( (/usr/convex/getsysinfo) 2>/dev/null) +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = "$UNAME_MACHINE" UNAME_RELEASE = "$UNAME_RELEASE" diff --git a/config.sub b/config.sub index 63c1f1c8b5e2d..d74fb6deac942 100755 --- a/config.sub +++ b/config.sub @@ -2,7 +2,9 @@ # Configuration validation subroutine script. # Copyright 1992-2021 Free Software Foundation, Inc. -timestamp='2021-01-08' +# shellcheck disable=SC2006,SC2268 # see below for rationale + +timestamp='2021-08-14' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -50,7 +52,14 @@ timestamp='2021-01-08' # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. -me=$(echo "$0" | sed -e 's,.*/,,') +# The "shellcheck disable" line above the timestamp inhibits complaints +# about features and limitations of the classic Bourne shell that were +# superseded or lifted in POSIX. However, this script identifies a wide +# variety of pre-POSIX systems that do not have POSIX shells at all, and +# even some reasonably current systems (Solaris 10 as case-in-point) still +# have a pre-POSIX /bin/sh. + +me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS @@ -112,9 +121,11 @@ esac # Split fields of configuration type # shellcheck disable=SC2162 +saved_IFS=$IFS IFS="-" read field1 field2 field3 field4 <&2 From webhook-mailer at python.org Thu Nov 25 15:24:50 2021 From: webhook-mailer at python.org (tiran) Date: Thu, 25 Nov 2021 20:24:50 -0000 Subject: [Python-checkins] bpo-40280: Add wasm cross build targets (GH-29771) Message-ID: https://github.com/python/cpython/commit/1052a39b7603e4d8401a5987af0c36f4a1d0b1e4 commit: 1052a39b7603e4d8401a5987af0c36f4a1d0b1e4 branch: main author: Christian Heimes committer: tiran date: 2021-11-25T21:24:40+01:00 summary: bpo-40280: Add wasm cross build targets (GH-29771) files: A Misc/NEWS.d/next/Build/2021-11-25-10-55-03.bpo-40280.E9-gsQ.rst M configure M configure.ac diff --git a/Misc/NEWS.d/next/Build/2021-11-25-10-55-03.bpo-40280.E9-gsQ.rst b/Misc/NEWS.d/next/Build/2021-11-25-10-55-03.bpo-40280.E9-gsQ.rst new file mode 100644 index 0000000000000..04579b4ecb71c --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-25-10-55-03.bpo-40280.E9-gsQ.rst @@ -0,0 +1,3 @@ +``configure`` now accepts machine ``wasm32`` or ``wasm64`` and OS ``wasi`` +or ``emscripten`` for cross building, e.g. ``wasm32-unknown-emscripten``, +``wasm32-wasi``, or ``wasm32-unknown-wasi``. diff --git a/configure b/configure index abfda2b00de74..944e97ccf9929 100755 --- a/configure +++ b/configure @@ -3717,6 +3717,12 @@ then *-*-vxworks*) ac_sys_system=VxWorks ;; + *-*-emscripten) + ac_sys_system=Emscripten + ;; + *-*-wasi) + ac_sys_system=WASI + ;; *) # for now, limit cross builds to known configurations MACHDEP="unknown" @@ -3767,6 +3773,9 @@ if test "$cross_compiling" = yes; then *-*-vxworks*) _host_cpu=$host_cpu ;; + wasm32-*-* | wasm64-*-*) + _host_cpu=$host_cpu + ;; *) # for now, limit cross builds to known configurations MACHDEP="unknown" @@ -10382,6 +10391,9 @@ fi # Dynamic linking for HP-UX + + + have_uuid=missing for ac_header in uuid.h @@ -10414,10 +10426,6 @@ fi done - - - - if test "x$have_uuid" = xmissing; then : diff --git a/configure.ac b/configure.ac index 1853baa5a8e8c..2140e3e43db82 100644 --- a/configure.ac +++ b/configure.ac @@ -465,6 +465,12 @@ then *-*-vxworks*) ac_sys_system=VxWorks ;; + *-*-emscripten) + ac_sys_system=Emscripten + ;; + *-*-wasi) + ac_sys_system=WASI + ;; *) # for now, limit cross builds to known configurations MACHDEP="unknown" @@ -514,6 +520,9 @@ if test "$cross_compiling" = yes; then *-*-vxworks*) _host_cpu=$host_cpu ;; + wasm32-*-* | wasm64-*-*) + _host_cpu=$host_cpu + ;; *) # for now, limit cross builds to known configurations MACHDEP="unknown" From webhook-mailer at python.org Thu Nov 25 15:49:57 2021 From: webhook-mailer at python.org (miss-islington) Date: Thu, 25 Nov 2021 20:49:57 -0000 Subject: [Python-checkins] bpo-43137: webbrowser: Replace gvfs-open and gnome-open with "gio open" (GH-29154) Message-ID: https://github.com/python/cpython/commit/97dcab783279444ff721a301e1faca6f29fdc600 commit: 97dcab783279444ff721a301e1faca6f29fdc600 branch: main author: Simon McVittie committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-25T12:49:48-08:00 summary: bpo-43137: webbrowser: Replace gvfs-open and gnome-open with "gio open" (GH-29154) * [bpo-43137](): webbrowser: Prefer gio open over gvfs-open gvfs-open(1) was superseded by gio(1) in 2015, and removed from GNOME releases in 2018. Debian and its derivatives like Ubuntu currently still have a compatibility shim for gvfs-open, but we plan to remove it. webbrowser prefers xdg-settings and xdg-open over gvfs-open, so this will only have any practical effect on systems where the xdg-utils package is not installed. Note that we don't check for GNOME_DESKTOP_SESSION_ID before using gio. gio does the right thing on any desktop environment that follows freedesktop.org specifications, similar to xdg-settings, so it's unnecessary to guard in this way. GNOME_DESKTOP_SESSION_ID was deprecated in 2008 and removed from upstream gnome-session in 2018 (it's still present in Debian/Ubuntu for backward compatibility, but probably shouldn't be). The replacement way to detect a desktop environment is the XDG_CURRENT_DESKTOP environment variable, which is a colon-separated sequence where the first item is the current desktop environment and the second and subsequent items (if present) are other desktop environments that it resembles or is based on. Resolves: * [bpo-43137](): webbrowser: Never invoke gnome-open gnome-open was part of GNOME 2, which was superseded in around 2010 and is unmaintained. The replacement was gvfs-open, which was subsequently replaced by gio(1) (as used in the previous commit). * [bpo-43137](): webbrowser: Don't run gvfs-open on GNOME gvfs-open was deprecated in 2015 and removed in 2018. The replacement is gio(1) (as used in a previous commit). GNOME_DESKTOP_SESSION_ID was deprecated in 2008 and removed in 2018. The replacement is XDG_CURRENT_DESKTOP (as mentioned in a previous commit). --- To test this on a typical modern Linux system, it is necessary to disable the `xdg-settings` and `xdg-open` code paths, for example with this hack:
Hack to disable use of xdg-settings and xdg-open ```diff diff --git a/Lib/webbrowser.py b/Lib/webbrowser.py index 3244f206aa..8f6c09d1d2 100755 --- a/Lib/webbrowser.py +++ b/Lib/webbrowser.py @@ -459,7 +459,7 @@ def open(self, url, new=0, autoraise=True): def register_X_browsers(): # use xdg-open if around - if shutil.which("xdg-open"): + if 0 and shutil.which("xdg-open"): register("xdg-open", None, BackgroundBrowser("xdg-open")) # Opens an appropriate browser for the URL scheme according to @@ -549,7 +549,7 @@ def register_standard_browsers(): # Prefer X browsers if present if os.environ.get("DISPLAY") or os.environ.get("WAYLAND_DISPLAY"): try: - cmd = "xdg-settings get default-web-browser".split() + cmd = "false xdg-settings get default-web-browser".split() raw_result = subprocess.check_output(cmd, stderr=subprocess.DEVNULL) result = raw_result.decode().strip() except (FileNotFoundError, subprocess.CalledProcessError, PermissionError, NotADirectoryError) : ```
I haven't attempted to assess which of the specific web browsers such as Galeon are still extant, and which ones disappeared years ago. They could almost certainly be cleaned up, but that's beyond the scope of this PR. files: A Misc/NEWS.d/next/Library/2021-10-25-12-51-02.bpo-43137.apo7jY.rst M Lib/webbrowser.py diff --git a/Lib/webbrowser.py b/Lib/webbrowser.py index d8a9915cac5f6..3244f206aade6 100755 --- a/Lib/webbrowser.py +++ b/Lib/webbrowser.py @@ -462,13 +462,10 @@ def register_X_browsers(): if shutil.which("xdg-open"): register("xdg-open", None, BackgroundBrowser("xdg-open")) - # The default GNOME3 browser - if "GNOME_DESKTOP_SESSION_ID" in os.environ and shutil.which("gvfs-open"): - register("gvfs-open", None, BackgroundBrowser("gvfs-open")) - - # The default GNOME browser - if "GNOME_DESKTOP_SESSION_ID" in os.environ and shutil.which("gnome-open"): - register("gnome-open", None, BackgroundBrowser("gnome-open")) + # Opens an appropriate browser for the URL scheme according to + # freedesktop.org settings (GNOME, KDE, XFCE, etc.) + if shutil.which("gio"): + register("gio", None, BackgroundBrowser(["gio", "open", "--", "%s"])) # The default KDE browser if "KDE_FULL_SESSION" in os.environ and shutil.which("kfmclient"): diff --git a/Misc/NEWS.d/next/Library/2021-10-25-12-51-02.bpo-43137.apo7jY.rst b/Misc/NEWS.d/next/Library/2021-10-25-12-51-02.bpo-43137.apo7jY.rst new file mode 100644 index 0000000000000..19287532e97f1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-10-25-12-51-02.bpo-43137.apo7jY.rst @@ -0,0 +1 @@ +Launch GNOME web browsers via gio tool instead of obsolete gvfs-open \ No newline at end of file From webhook-mailer at python.org Thu Nov 25 16:52:01 2021 From: webhook-mailer at python.org (tiran) Date: Thu, 25 Nov 2021 21:52:01 -0000 Subject: [Python-checkins] [3.9] bpo-33393: Update config.guess and config.sub (GH-29781) (GH-29783) Message-ID: https://github.com/python/cpython/commit/b5249349845c21a07e13888aa12c5b86c0f06c31 commit: b5249349845c21a07e13888aa12c5b86c0f06c31 branch: 3.9 author: Christian Heimes committer: tiran date: 2021-11-25T22:51:52+01:00 summary: [3.9] bpo-33393: Update config.guess and config.sub (GH-29781) (GH-29783) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Build/2021-11-25-20-26-06.bpo-33393.24YNtM.rst M Makefile.pre.in M config.guess M config.sub diff --git a/Makefile.pre.in b/Makefile.pre.in index 11230fa563d16..42b1ec622accc 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1946,6 +1946,12 @@ funny: patchcheck: @DEF_MAKE_RULE@ $(RUNSHARED) ./$(BUILDPYTHON) $(srcdir)/Tools/scripts/patchcheck.py +.PHONY: update-config +update-config: + curl -sL -o config.guess 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD' + curl -sL -o config.sub 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD' + chmod +x config.guess config.sub + # Dependencies Python/thread.o: @THREADHEADERS@ $(srcdir)/Python/condvar.h diff --git a/Misc/NEWS.d/next/Build/2021-11-25-20-26-06.bpo-33393.24YNtM.rst b/Misc/NEWS.d/next/Build/2021-11-25-20-26-06.bpo-33393.24YNtM.rst new file mode 100644 index 0000000000000..c27869c9b6ded --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-25-20-26-06.bpo-33393.24YNtM.rst @@ -0,0 +1,3 @@ +Update ``config.guess`` to 2021-06-03 and ``config.sub`` to 2021-08-14. +``Makefile`` now has an ``update-config`` target to make updating more +convenient. diff --git a/config.guess b/config.guess index 256083a70d359..e81d3ae7c210b 100755 --- a/config.guess +++ b/config.guess @@ -1,8 +1,10 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2018 Free Software Foundation, Inc. +# Copyright 1992-2021 Free Software Foundation, Inc. -timestamp='2018-03-08' +# shellcheck disable=SC2006,SC2268 # see below for rationale + +timestamp='2021-06-03' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -27,11 +29,19 @@ timestamp='2018-03-08' # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: -# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess # # Please send patches to . +# The "shellcheck disable" line above the timestamp inhibits complaints +# about features and limitations of the classic Bourne shell that were +# superseded or lifted in POSIX. However, this script identifies a wide +# variety of pre-POSIX systems that do not have POSIX shells at all, and +# even some reasonably current systems (Solaris 10 as case-in-point) still +# have a pre-POSIX /bin/sh. + + me=`echo "$0" | sed -e 's,.*/,,'` usage="\ @@ -50,7 +60,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2018 Free Software Foundation, Inc. +Copyright 1992-2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -84,7 +94,8 @@ if test $# != 0; then exit 1 fi -trap 'exit 1' 1 2 15 +# Just in case it came from the environment. +GUESS= # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires @@ -96,73 +107,90 @@ trap 'exit 1' 1 2 15 # Portable tmp directory creation inspired by the Autoconf team. -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > "$dummy.c" ; - for c in cc gcc c89 c99 ; do - if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' +tmp= +# shellcheck disable=SC2172 +trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 + +set_cc_for_build() { + # prevent multiple calls if $tmp is already set + test "$tmp" && return 0 + : "${TMPDIR=/tmp}" + # shellcheck disable=SC2039,SC3028 + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } + dummy=$tmp/dummy + case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in + ,,) echo "int x;" > "$dummy.c" + for driver in cc gcc c89 c99 ; do + if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then + CC_FOR_BUILD=$driver + break + fi + done + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; + esac +} # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi at noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then +if test -f /.attbin/uname ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown -case "$UNAME_SYSTEM" in +case $UNAME_SYSTEM in Linux|GNU|GNU/*) - # If the system lacks a compiler, then just pick glibc. - # We could probably try harder. - LIBC=gnu + LIBC=unknown - eval "$set_cc_for_build" + set_cc_for_build cat <<-EOF > "$dummy.c" #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc - #else + #elif defined(__GLIBC__) LIBC=gnu + #else + #include + /* First heuristic to detect musl libc. */ + #ifdef __DEFINED_va_list + LIBC=musl + #endif #endif EOF - eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" + cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + eval "$cc_set_libc" - # If ldd exists, use it to detect musl libc. - if command -v ldd >/dev/null && \ - ldd --version 2>&1 | grep -q ^musl - then - LIBC=musl + # Second heuristic to detect musl libc. + if [ "$LIBC" = unknown ] && + command -v ldd >/dev/null && + ldd --version 2>&1 | grep -q ^musl; then + LIBC=musl + fi + + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + if [ "$LIBC" = unknown ]; then + LIBC=gnu fi ;; esac # Note: order is significant - the case branches are not exclusive. -case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in +case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, @@ -174,12 +202,12 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". - sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ - "/sbin/$sysctl" 2>/dev/null || \ - "/usr/sbin/$sysctl" 2>/dev/null || \ + /sbin/sysctl -n hw.machine_arch 2>/dev/null || \ + /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \ echo unknown)` - case "$UNAME_MACHINE_ARCH" in + case $UNAME_MACHINE_ARCH in + aarch64eb) machine=aarch64_be-unknown ;; armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; @@ -188,18 +216,18 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in earmv*) arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` - machine="${arch}${endian}"-unknown + machine=${arch}${endian}-unknown ;; - *) machine="$UNAME_MACHINE_ARCH"-unknown ;; + *) machine=$UNAME_MACHINE_ARCH-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently (or will in the future) and ABI. - case "$UNAME_MACHINE_ARCH" in + case $UNAME_MACHINE_ARCH in earm*) os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval "$set_cc_for_build" + set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then @@ -215,7 +243,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in ;; esac # Determine ABI tags. - case "$UNAME_MACHINE_ARCH" in + case $UNAME_MACHINE_ARCH in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` @@ -226,7 +254,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. - case "$UNAME_VERSION" in + case $UNAME_VERSION in Debian*) release='-gnu' ;; @@ -237,45 +265,57 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "$machine-${os}${release}${abi}" - exit ;; + GUESS=$machine-${os}${release}${abi-} + ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` - echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE + ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE + ;; + *:SecBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'` + GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE + ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` - echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE + ;; *:MidnightBSD:*:*) - echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE + ;; *:ekkoBSD:*:*) - echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE + ;; *:SolidBSD:*:*) - echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE + ;; + *:OS108:*:*) + GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE + ;; macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd"$UNAME_RELEASE" - exit ;; + GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE + ;; *:MirBSD:*:*) - echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE + ;; *:Sortix:*:*) - echo "$UNAME_MACHINE"-unknown-sortix - exit ;; + GUESS=$UNAME_MACHINE-unknown-sortix + ;; + *:Twizzler:*:*) + GUESS=$UNAME_MACHINE-unknown-twizzler + ;; *:Redox:*:*) - echo "$UNAME_MACHINE"-unknown-redox - exit ;; + GUESS=$UNAME_MACHINE-unknown-redox + ;; mips:OSF1:*.*) - echo mips-dec-osf1 - exit ;; + GUESS=mips-dec-osf1 + ;; alpha:OSF1:*:*) + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + trap '' 0 case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` @@ -289,7 +329,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` - case "$ALPHA_CPU_TYPE" in + case $ALPHA_CPU_TYPE in "EV4 (21064)") UNAME_MACHINE=alpha ;; "EV4.5 (21064)") @@ -326,75 +366,76 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" - # Reset EXIT trap before exiting to avoid spurious non-zero exit code. - exitcode=$? - trap '' 0 - exit $exitcode ;; + OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + GUESS=$UNAME_MACHINE-dec-osf$OSF_REL + ;; Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit ;; + GUESS=m68k-unknown-sysv4 + ;; *:[Aa]miga[Oo][Ss]:*:*) - echo "$UNAME_MACHINE"-unknown-amigaos - exit ;; + GUESS=$UNAME_MACHINE-unknown-amigaos + ;; *:[Mm]orph[Oo][Ss]:*:*) - echo "$UNAME_MACHINE"-unknown-morphos - exit ;; + GUESS=$UNAME_MACHINE-unknown-morphos + ;; *:OS/390:*:*) - echo i370-ibm-openedition - exit ;; + GUESS=i370-ibm-openedition + ;; *:z/VM:*:*) - echo s390-ibm-zvmoe - exit ;; + GUESS=s390-ibm-zvmoe + ;; *:OS400:*:*) - echo powerpc-ibm-os400 - exit ;; + GUESS=powerpc-ibm-os400 + ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix"$UNAME_RELEASE" - exit ;; + GUESS=arm-acorn-riscix$UNAME_RELEASE + ;; arm*:riscos:*:*|arm*:RISCOS:*:*) - echo arm-unknown-riscos - exit ;; + GUESS=arm-unknown-riscos + ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit ;; + GUESS=hppa1.1-hitachi-hiuxmpp + ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee at wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit ;; + case `(/bin/universe) 2>/dev/null` in + att) GUESS=pyramid-pyramid-sysv3 ;; + *) GUESS=pyramid-pyramid-bsd ;; + esac + ;; NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit ;; + GUESS=pyramid-pyramid-svr4 + ;; DRS?6000:unix:4.0:6*) - echo sparc-icl-nx6 - exit ;; + GUESS=sparc-icl-nx6 + ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7; exit ;; - esac ;; + sparc) GUESS=sparc-icl-nx7 ;; + esac + ;; s390x:SunOS:*:*) - echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL + ;; sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=sparc-hal-solaris2$SUN_REL + ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=sparc-sun-solaris2$SUN_REL + ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux"$UNAME_RELEASE" - exit ;; + GUESS=i386-pc-auroraux$UNAME_RELEASE + ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval "$set_cc_for_build" + set_cc_for_build SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. - if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null @@ -402,41 +443,44 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in SUN_ARCH=x86_64 fi fi - echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=$SUN_ARCH-pc-solaris2$SUN_REL + ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=sparc-sun-solaris3$SUN_REL + ;; sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in + case `/usr/bin/arch -k` in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'` + GUESS=sparc-sun-sunos$SUN_REL + ;; sun3*:SunOS:*:*) - echo m68k-sun-sunos"$UNAME_RELEASE" - exit ;; + GUESS=m68k-sun-sunos$UNAME_RELEASE + ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 - case "`/bin/arch`" in + case `/bin/arch` in sun3) - echo m68k-sun-sunos"$UNAME_RELEASE" + GUESS=m68k-sun-sunos$UNAME_RELEASE ;; sun4) - echo sparc-sun-sunos"$UNAME_RELEASE" + GUESS=sparc-sun-sunos$UNAME_RELEASE ;; esac - exit ;; + ;; aushp:SunOS:*:*) - echo sparc-auspex-sunos"$UNAME_RELEASE" - exit ;; + GUESS=sparc-auspex-sunos$UNAME_RELEASE + ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor @@ -446,43 +490,43 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint"$UNAME_RELEASE" - exit ;; + GUESS=m68k-atari-mint$UNAME_RELEASE + ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint"$UNAME_RELEASE" - exit ;; + GUESS=m68k-atari-mint$UNAME_RELEASE + ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint"$UNAME_RELEASE" - exit ;; + GUESS=m68k-atari-mint$UNAME_RELEASE + ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint"$UNAME_RELEASE" - exit ;; + GUESS=m68k-milan-mint$UNAME_RELEASE + ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint"$UNAME_RELEASE" - exit ;; + GUESS=m68k-hades-mint$UNAME_RELEASE + ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint"$UNAME_RELEASE" - exit ;; + GUESS=m68k-unknown-mint$UNAME_RELEASE + ;; m68k:machten:*:*) - echo m68k-apple-machten"$UNAME_RELEASE" - exit ;; + GUESS=m68k-apple-machten$UNAME_RELEASE + ;; powerpc:machten:*:*) - echo powerpc-apple-machten"$UNAME_RELEASE" - exit ;; + GUESS=powerpc-apple-machten$UNAME_RELEASE + ;; RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit ;; + GUESS=mips-dec-mach_bsd4.3 + ;; RISC*:ULTRIX:*:*) - echo mips-dec-ultrix"$UNAME_RELEASE" - exit ;; + GUESS=mips-dec-ultrix$UNAME_RELEASE + ;; VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix"$UNAME_RELEASE" - exit ;; + GUESS=vax-dec-ultrix$UNAME_RELEASE + ;; 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix"$UNAME_RELEASE" - exit ;; + GUESS=clipper-intergraph-clix$UNAME_RELEASE + ;; mips:*:*:UMIPS | mips:*:*:RISCos) - eval "$set_cc_for_build" + set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include /* for printf() prototype */ @@ -508,78 +552,79 @@ EOF dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`"$dummy" "$dummyarg"` && { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos"$UNAME_RELEASE" - exit ;; + GUESS=mips-mips-riscos$UNAME_RELEASE + ;; Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit ;; + GUESS=powerpc-motorola-powermax + ;; Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit ;; + GUESS=powerpc-harris-powermax + ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - echo powerpc-harris-powermax - exit ;; + GUESS=powerpc-harris-powermax + ;; Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit ;; + GUESS=powerpc-harris-powerunix + ;; m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit ;; + GUESS=m88k-harris-cxux7 + ;; m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit ;; + GUESS=m88k-motorola-sysv4 + ;; m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit ;; + GUESS=m88k-motorola-sysv3 + ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] + if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110 then - if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ - [ "$TARGET_BINARY_INTERFACE"x = x ] + if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \ + test "$TARGET_BINARY_INTERFACE"x = x then - echo m88k-dg-dgux"$UNAME_RELEASE" + GUESS=m88k-dg-dgux$UNAME_RELEASE else - echo m88k-dg-dguxbcs"$UNAME_RELEASE" + GUESS=m88k-dg-dguxbcs$UNAME_RELEASE fi else - echo i586-dg-dgux"$UNAME_RELEASE" + GUESS=i586-dg-dgux$UNAME_RELEASE fi - exit ;; + ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit ;; + GUESS=m88k-dolphin-sysv3 + ;; M88*:*:R3*:*) # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit ;; + GUESS=m88k-motorola-sysv3 + ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit ;; + GUESS=m88k-tektronix-sysv3 + ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit ;; + GUESS=m68k-tektronix-bsd + ;; *:IRIX*:*:*) - echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" - exit ;; + IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'` + GUESS=mips-sgi-irix$IRIX_REL + ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + GUESS=romp-ibm-aix # uname -m gives an 8 hex-code CPU id + ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) - echo i386-ibm-aix - exit ;; + GUESS=i386-ibm-aix + ;; ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then + if test -x /usr/bin/oslevel ; then IBM_REV=`/usr/bin/oslevel` else - IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" + IBM_REV=$UNAME_VERSION.$UNAME_RELEASE fi - echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" - exit ;; + GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV + ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval "$set_cc_for_build" + set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include @@ -593,16 +638,16 @@ EOF EOF if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` then - echo "$SYSTEM_NAME" + GUESS=$SYSTEM_NAME else - echo rs6000-ibm-aix3.2.5 + GUESS=rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 + GUESS=rs6000-ibm-aix3.2.4 else - echo rs6000-ibm-aix3.2 + GUESS=rs6000-ibm-aix3.2 fi - exit ;; + ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then @@ -610,57 +655,57 @@ EOF else IBM_ARCH=powerpc fi - if [ -x /usr/bin/lslpp ] ; then - IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + if test -x /usr/bin/lslpp ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \ awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else - IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" + IBM_REV=$UNAME_VERSION.$UNAME_RELEASE fi - echo "$IBM_ARCH"-ibm-aix"$IBM_REV" - exit ;; + GUESS=$IBM_ARCH-ibm-aix$IBM_REV + ;; *:AIX:*:*) - echo rs6000-ibm-aix - exit ;; + GUESS=rs6000-ibm-aix + ;; ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) - echo romp-ibm-bsd4.4 - exit ;; + GUESS=romp-ibm-bsd4.4 + ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to - exit ;; # report: romp-ibm BSD 4.3 + GUESS=romp-ibm-bsd$UNAME_RELEASE # 4.3 with uname added to + ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) - echo rs6000-bull-bosx - exit ;; + GUESS=rs6000-bull-bosx + ;; DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit ;; + GUESS=m68k-bull-sysv3 + ;; 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit ;; + GUESS=m68k-hp-bsd + ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit ;; + GUESS=m68k-hp-bsd4.4 + ;; 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` - case "$UNAME_MACHINE" in + HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` + case $UNAME_MACHINE in 9000/31?) HP_ARCH=m68000 ;; 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) - if [ -x /usr/bin/getconf ]; then + if test -x /usr/bin/getconf; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "$sc_cpu_version" in + case $sc_cpu_version in 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 - case "$sc_kernel_bits" in + case $sc_kernel_bits in 32) HP_ARCH=hppa2.0n ;; 64) HP_ARCH=hppa2.0w ;; '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi - if [ "$HP_ARCH" = "" ]; then - eval "$set_cc_for_build" + if test "$HP_ARCH" = ""; then + set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #define _HPUX_SOURCE @@ -698,9 +743,9 @@ EOF test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac - if [ "$HP_ARCH" = hppa2.0w ] + if test "$HP_ARCH" = hppa2.0w then - eval "$set_cc_for_build" + set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler @@ -719,14 +764,14 @@ EOF HP_ARCH=hppa64 fi fi - echo "$HP_ARCH"-hp-hpux"$HPUX_REV" - exit ;; + GUESS=$HP_ARCH-hp-hpux$HPUX_REV + ;; ia64:HP-UX:*:*) - HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux"$HPUX_REV" - exit ;; + HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` + GUESS=ia64-hp-hpux$HPUX_REV + ;; 3050*:HI-UX:*:*) - eval "$set_cc_for_build" + set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include int @@ -754,36 +799,36 @@ EOF EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } - echo unknown-hitachi-hiuxwe2 - exit ;; + GUESS=unknown-hitachi-hiuxwe2 + ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) - echo hppa1.1-hp-bsd - exit ;; + GUESS=hppa1.1-hp-bsd + ;; 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit ;; + GUESS=hppa1.0-hp-bsd + ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit ;; + GUESS=hppa1.0-hp-mpeix + ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) - echo hppa1.1-hp-osf - exit ;; + GUESS=hppa1.1-hp-osf + ;; hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit ;; + GUESS=hppa1.0-hp-osf + ;; i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo "$UNAME_MACHINE"-unknown-osf1mk + if test -x /usr/sbin/sysversion ; then + GUESS=$UNAME_MACHINE-unknown-osf1mk else - echo "$UNAME_MACHINE"-unknown-osf1 + GUESS=$UNAME_MACHINE-unknown-osf1 fi - exit ;; + ;; parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit ;; + GUESS=hppa1.1-hp-lites + ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit ;; + GUESS=c1-convex-bsd + ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd @@ -791,17 +836,18 @@ EOF fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit ;; + GUESS=c34-convex-bsd + ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit ;; + GUESS=c38-convex-bsd + ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit ;; + GUESS=c4-convex-bsd + ;; CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' - exit ;; + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=ymp-cray-unicos$CRAY_REL + ;; CRAY*[A-Z]90:*:*:*) echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ @@ -809,103 +855,126 @@ EOF -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) - echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' - exit ;; + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=t90-cray-unicos$CRAY_REL + ;; CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' - exit ;; + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=alphaev5-cray-unicosmk$CRAY_REL + ;; CRAY*SV1:*:*:*) - echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' - exit ;; + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=sv1-cray-unicos$CRAY_REL + ;; *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' - exit ;; + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=craynv-cray-unicosmp$CRAY_REL + ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; + GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} + ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; + GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} + ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE + ;; sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi"$UNAME_RELEASE" - exit ;; + GUESS=sparc-unknown-bsdi$UNAME_RELEASE + ;; *:BSD/OS:*:*) - echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE + ;; + arm:FreeBSD:*:*) + UNAME_PROCESSOR=`uname -p` + set_cc_for_build + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi + else + FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf + fi + ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` - case "$UNAME_PROCESSOR" in + case $UNAME_PROCESSOR in amd64) UNAME_PROCESSOR=x86_64 ;; i386) UNAME_PROCESSOR=i586 ;; esac - echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" - exit ;; + FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL + ;; i*:CYGWIN*:*) - echo "$UNAME_MACHINE"-pc-cygwin - exit ;; + GUESS=$UNAME_MACHINE-pc-cygwin + ;; *:MINGW64*:*) - echo "$UNAME_MACHINE"-pc-mingw64 - exit ;; + GUESS=$UNAME_MACHINE-pc-mingw64 + ;; *:MINGW*:*) - echo "$UNAME_MACHINE"-pc-mingw32 - exit ;; + GUESS=$UNAME_MACHINE-pc-mingw32 + ;; *:MSYS*:*) - echo "$UNAME_MACHINE"-pc-msys - exit ;; + GUESS=$UNAME_MACHINE-pc-msys + ;; i*:PW*:*) - echo "$UNAME_MACHINE"-pc-pw32 - exit ;; + GUESS=$UNAME_MACHINE-pc-pw32 + ;; *:Interix*:*) - case "$UNAME_MACHINE" in + case $UNAME_MACHINE in x86) - echo i586-pc-interix"$UNAME_RELEASE" - exit ;; + GUESS=i586-pc-interix$UNAME_RELEASE + ;; authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix"$UNAME_RELEASE" - exit ;; + GUESS=x86_64-unknown-interix$UNAME_RELEASE + ;; IA64) - echo ia64-unknown-interix"$UNAME_RELEASE" - exit ;; + GUESS=ia64-unknown-interix$UNAME_RELEASE + ;; esac ;; i*:UWIN*:*) - echo "$UNAME_MACHINE"-pc-uwin - exit ;; + GUESS=$UNAME_MACHINE-pc-uwin + ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-unknown-cygwin - exit ;; + GUESS=x86_64-pc-cygwin + ;; prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=powerpcle-unknown-solaris2$SUN_REL + ;; *:GNU:*:*) # the GNU system - echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" - exit ;; + GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'` + GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'` + GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL + ;; *:GNU/*:*:*) # other systems with GNU libc and userland - echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" - exit ;; - i*86:Minix:*:*) - echo "$UNAME_MACHINE"-pc-minix - exit ;; + GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"` + GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC + ;; + *:Minix:*:*) + GUESS=$UNAME_MACHINE-unknown-minix + ;; aarch64:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; @@ -916,183 +985,225 @@ EOF esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC=gnulibc1 ; fi - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - arc:Linux:*:* | arceb:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; arm*:Linux:*:*) - eval "$set_cc_for_build" + set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi + GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi else - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf + GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf fi fi - exit ;; + ;; avr32*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; cris:Linux:*:*) - echo "$UNAME_MACHINE"-axis-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-axis-linux-$LIBC + ;; crisv32:Linux:*:*) - echo "$UNAME_MACHINE"-axis-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-axis-linux-$LIBC + ;; e2k:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; frv:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; hexagon:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; i*86:Linux:*:*) - echo "$UNAME_MACHINE"-pc-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-pc-linux-$LIBC + ;; ia64:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; k1om:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; m32r*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; m68*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; mips:Linux:*:* | mips64:Linux:*:*) - eval "$set_cc_for_build" + set_cc_for_build + IS_GLIBC=0 + test x"${LIBC}" = xgnu && IS_GLIBC=1 sed 's/^ //' << EOF > "$dummy.c" #undef CPU - #undef ${UNAME_MACHINE} - #undef ${UNAME_MACHINE}el + #undef mips + #undef mipsel + #undef mips64 + #undef mips64el + #if ${IS_GLIBC} && defined(_ABI64) + LIBCABI=gnuabi64 + #else + #if ${IS_GLIBC} && defined(_ABIN32) + LIBCABI=gnuabin32 + #else + LIBCABI=${LIBC} + #endif + #endif + + #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa64r6 + #else + #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa32r6 + #else + #if defined(__mips64) + CPU=mips64 + #else + CPU=mips + #endif + #endif + #endif + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=${UNAME_MACHINE}el + MIPS_ENDIAN=el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=${UNAME_MACHINE} + MIPS_ENDIAN= #else - CPU= + MIPS_ENDIAN= #endif #endif EOF - eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`" - test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; } + cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'` + eval "$cc_set_vars" + test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } ;; mips64el:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; openrisc*:Linux:*:*) - echo or1k-unknown-linux-"$LIBC" - exit ;; + GUESS=or1k-unknown-linux-$LIBC + ;; or32:Linux:*:* | or1k*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; padre:Linux:*:*) - echo sparc-unknown-linux-"$LIBC" - exit ;; + GUESS=sparc-unknown-linux-$LIBC + ;; parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-"$LIBC" - exit ;; + GUESS=hppa64-unknown-linux-$LIBC + ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; - PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; - *) echo hppa-unknown-linux-"$LIBC" ;; + PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;; + PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;; + *) GUESS=hppa-unknown-linux-$LIBC ;; esac - exit ;; + ;; ppc64:Linux:*:*) - echo powerpc64-unknown-linux-"$LIBC" - exit ;; + GUESS=powerpc64-unknown-linux-$LIBC + ;; ppc:Linux:*:*) - echo powerpc-unknown-linux-"$LIBC" - exit ;; + GUESS=powerpc-unknown-linux-$LIBC + ;; ppc64le:Linux:*:*) - echo powerpc64le-unknown-linux-"$LIBC" - exit ;; + GUESS=powerpc64le-unknown-linux-$LIBC + ;; ppcle:Linux:*:*) - echo powerpcle-unknown-linux-"$LIBC" - exit ;; - riscv32:Linux:*:* | riscv64:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=powerpcle-unknown-linux-$LIBC + ;; + riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; s390:Linux:*:* | s390x:Linux:*:*) - echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-ibm-linux-$LIBC + ;; sh64*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; sh*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; sparc:Linux:*:* | sparc64:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; tile*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; vax:Linux:*:*) - echo "$UNAME_MACHINE"-dec-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-dec-linux-$LIBC + ;; x86_64:Linux:*:*) - echo "$UNAME_MACHINE"-pc-linux-"$LIBC" - exit ;; + set_cc_for_build + LIBCABI=$LIBC + if test "$CC_FOR_BUILD" != no_compiler_found; then + if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_X32 >/dev/null + then + LIBCABI=${LIBC}x32 + fi + fi + GUESS=$UNAME_MACHINE-pc-linux-$LIBCABI + ;; xtensa*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. - echo i386-sequent-sysv4 - exit ;; + GUESS=i386-sequent-sysv4 + ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. - echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" - exit ;; + GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION + ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. - echo "$UNAME_MACHINE"-pc-os2-emx - exit ;; + GUESS=$UNAME_MACHINE-pc-os2-emx + ;; i*86:XTS-300:*:STOP) - echo "$UNAME_MACHINE"-unknown-stop - exit ;; + GUESS=$UNAME_MACHINE-unknown-stop + ;; i*86:atheos:*:*) - echo "$UNAME_MACHINE"-unknown-atheos - exit ;; + GUESS=$UNAME_MACHINE-unknown-atheos + ;; i*86:syllable:*:*) - echo "$UNAME_MACHINE"-pc-syllable - exit ;; + GUESS=$UNAME_MACHINE-pc-syllable + ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos"$UNAME_RELEASE" - exit ;; + GUESS=i386-unknown-lynxos$UNAME_RELEASE + ;; i*86:*DOS:*:*) - echo "$UNAME_MACHINE"-pc-msdosdjgpp - exit ;; + GUESS=$UNAME_MACHINE-pc-msdosdjgpp + ;; i*86:*:4.*:*) UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" + GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL else - echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" + GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL fi - exit ;; + ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in @@ -1100,12 +1211,12 @@ EOF *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac - echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}" - exit ;; + GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 @@ -1115,11 +1226,11 @@ EOF && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 - echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" + GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL else - echo "$UNAME_MACHINE"-pc-sysv32 + GUESS=$UNAME_MACHINE-pc-sysv32 fi - exit ;; + ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about @@ -1127,31 +1238,31 @@ EOF # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. - echo i586-pc-msdosdjgpp - exit ;; + GUESS=i586-pc-msdosdjgpp + ;; Intel:Mach:3*:*) - echo i386-pc-mach3 - exit ;; + GUESS=i386-pc-mach3 + ;; paragon:*:*:*) - echo i860-intel-osf1 - exit ;; + GUESS=i860-intel-osf1 + ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 + GUESS=i860-stardent-sysv$UNAME_RELEASE # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 + GUESS=i860-unknown-sysv$UNAME_RELEASE # Unknown i860-SVR4 fi - exit ;; + ;; mini*:CTIX:SYS*5:*) # "miniframe" - echo m68010-convergent-sysv - exit ;; + GUESS=m68010-convergent-sysv + ;; mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit ;; + GUESS=m68k-convergent-sysv + ;; M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit ;; + GUESS=m68k-diab-dnix + ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) @@ -1176,249 +1287,401 @@ EOF /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos"$UNAME_RELEASE" - exit ;; + GUESS=m68k-unknown-lynxos$UNAME_RELEASE + ;; mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit ;; + GUESS=m68k-atari-sysv4 + ;; TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos"$UNAME_RELEASE" - exit ;; + GUESS=sparc-unknown-lynxos$UNAME_RELEASE + ;; rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos"$UNAME_RELEASE" - exit ;; + GUESS=rs6000-unknown-lynxos$UNAME_RELEASE + ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos"$UNAME_RELEASE" - exit ;; + GUESS=powerpc-unknown-lynxos$UNAME_RELEASE + ;; SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv"$UNAME_RELEASE" - exit ;; + GUESS=mips-dde-sysv$UNAME_RELEASE + ;; RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit ;; + GUESS=mips-sni-sysv4 + ;; RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit ;; + GUESS=mips-sni-sysv4 + ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo "$UNAME_MACHINE"-sni-sysv4 + GUESS=$UNAME_MACHINE-sni-sysv4 else - echo ns32k-sni-sysv + GUESS=ns32k-sni-sysv fi - exit ;; + ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says - echo i586-unisys-sysv4 - exit ;; + GUESS=i586-unisys-sysv4 + ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit ;; + GUESS=hppa1.1-stratus-sysv4 + ;; *:*:*:FTX*) # From seanf at swdc.stratus.com. - echo i860-stratus-sysv4 - exit ;; + GUESS=i860-stratus-sysv4 + ;; i*86:VOS:*:*) # From Paul.Green at stratus.com. - echo "$UNAME_MACHINE"-stratus-vos - exit ;; + GUESS=$UNAME_MACHINE-stratus-vos + ;; *:VOS:*:*) # From Paul.Green at stratus.com. - echo hppa1.1-stratus-vos - exit ;; + GUESS=hppa1.1-stratus-vos + ;; mc68*:A/UX:*:*) - echo m68k-apple-aux"$UNAME_RELEASE" - exit ;; + GUESS=m68k-apple-aux$UNAME_RELEASE + ;; news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit ;; + GUESS=mips-sony-newsos6 + ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv"$UNAME_RELEASE" + if test -d /usr/nec; then + GUESS=mips-nec-sysv$UNAME_RELEASE else - echo mips-unknown-sysv"$UNAME_RELEASE" + GUESS=mips-unknown-sysv$UNAME_RELEASE fi - exit ;; + ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit ;; + GUESS=powerpc-be-beos + ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit ;; + GUESS=powerpc-apple-beos + ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit ;; + GUESS=i586-pc-beos + ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. - echo i586-pc-haiku - exit ;; + GUESS=i586-pc-haiku + ;; x86_64:Haiku:*:*) - echo x86_64-unknown-haiku - exit ;; + GUESS=x86_64-unknown-haiku + ;; SX-4:SUPER-UX:*:*) - echo sx4-nec-superux"$UNAME_RELEASE" - exit ;; + GUESS=sx4-nec-superux$UNAME_RELEASE + ;; SX-5:SUPER-UX:*:*) - echo sx5-nec-superux"$UNAME_RELEASE" - exit ;; + GUESS=sx5-nec-superux$UNAME_RELEASE + ;; SX-6:SUPER-UX:*:*) - echo sx6-nec-superux"$UNAME_RELEASE" - exit ;; + GUESS=sx6-nec-superux$UNAME_RELEASE + ;; SX-7:SUPER-UX:*:*) - echo sx7-nec-superux"$UNAME_RELEASE" - exit ;; + GUESS=sx7-nec-superux$UNAME_RELEASE + ;; SX-8:SUPER-UX:*:*) - echo sx8-nec-superux"$UNAME_RELEASE" - exit ;; + GUESS=sx8-nec-superux$UNAME_RELEASE + ;; SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux"$UNAME_RELEASE" - exit ;; + GUESS=sx8r-nec-superux$UNAME_RELEASE + ;; SX-ACE:SUPER-UX:*:*) - echo sxace-nec-superux"$UNAME_RELEASE" - exit ;; + GUESS=sxace-nec-superux$UNAME_RELEASE + ;; Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody"$UNAME_RELEASE" - exit ;; + GUESS=powerpc-apple-rhapsody$UNAME_RELEASE + ;; *:Rhapsody:*:*) - echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE + ;; + arm64:Darwin:*:*) + GUESS=aarch64-apple-darwin$UNAME_RELEASE + ;; *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - eval "$set_cc_for_build" - if test "$UNAME_PROCESSOR" = unknown ; then - UNAME_PROCESSOR=powerpc + UNAME_PROCESSOR=`uname -p` + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + if command -v xcode-select > /dev/null 2> /dev/null && \ + ! xcode-select --print-path > /dev/null 2> /dev/null ; then + # Avoid executing cc if there is no toolchain installed as + # cc will be a stub that puts up a graphical alert + # prompting the user to install developer tools. + CC_FOR_BUILD=no_compiler_found + else + set_cc_for_build fi - if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then - if [ "$CC_FOR_BUILD" != no_compiler_found ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - case $UNAME_PROCESSOR in - i386) UNAME_PROCESSOR=x86_64 ;; - powerpc) UNAME_PROCESSOR=powerpc64 ;; - esac - fi - # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc - if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_PPC >/dev/null - then - UNAME_PROCESSOR=powerpc - fi + if test "$CC_FOR_BUILD" != no_compiler_found; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc fi elif test "$UNAME_PROCESSOR" = i386 ; then - # Avoid executing cc on OS X 10.9, as it ships with a stub - # that puts up a graphical alert prompting to install - # developer tools. Any system running Mac OS X 10.7 or - # later (Darwin 11 and later) is required to have a 64-bit - # processor. This is not true of the ARM version of Darwin - # that Apple uses in portable devices. - UNAME_PROCESSOR=x86_64 + # uname -m returns i386 or x86_64 + UNAME_PROCESSOR=$UNAME_MACHINE fi - echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE + ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi - echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE + ;; *:QNX:*:4*) - echo i386-pc-qnx - exit ;; + GUESS=i386-pc-qnx + ;; NEO-*:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk"$UNAME_RELEASE" - exit ;; + GUESS=neo-tandem-nsk$UNAME_RELEASE + ;; NSE-*:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk"$UNAME_RELEASE" - exit ;; + GUESS=nse-tandem-nsk$UNAME_RELEASE + ;; NSR-*:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk"$UNAME_RELEASE" - exit ;; + GUESS=nsr-tandem-nsk$UNAME_RELEASE + ;; NSV-*:NONSTOP_KERNEL:*:*) - echo nsv-tandem-nsk"$UNAME_RELEASE" - exit ;; + GUESS=nsv-tandem-nsk$UNAME_RELEASE + ;; NSX-*:NONSTOP_KERNEL:*:*) - echo nsx-tandem-nsk"$UNAME_RELEASE" - exit ;; + GUESS=nsx-tandem-nsk$UNAME_RELEASE + ;; *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit ;; + GUESS=mips-compaq-nonstopux + ;; BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit ;; + GUESS=bs2000-siemens-sysv + ;; DS/*:UNIX_System_V:*:*) - echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE + ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. - if test "$cputype" = 386; then + if test "${cputype-}" = 386; then UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" + elif test "x${cputype-}" != x; then + UNAME_MACHINE=$cputype fi - echo "$UNAME_MACHINE"-unknown-plan9 - exit ;; + GUESS=$UNAME_MACHINE-unknown-plan9 + ;; *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit ;; + GUESS=pdp10-unknown-tops10 + ;; *:TENEX:*:*) - echo pdp10-unknown-tenex - exit ;; + GUESS=pdp10-unknown-tenex + ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit ;; + GUESS=pdp10-dec-tops20 + ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit ;; + GUESS=pdp10-xkl-tops20 + ;; *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit ;; + GUESS=pdp10-unknown-tops20 + ;; *:ITS:*:*) - echo pdp10-unknown-its - exit ;; + GUESS=pdp10-unknown-its + ;; SEI:*:*:SEIUX) - echo mips-sei-seiux"$UNAME_RELEASE" - exit ;; + GUESS=mips-sei-seiux$UNAME_RELEASE + ;; *:DragonFly:*:*) - echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" - exit ;; + DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL + ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "$UNAME_MACHINE" in - A*) echo alpha-dec-vms ; exit ;; - I*) echo ia64-dec-vms ; exit ;; - V*) echo vax-dec-vms ; exit ;; + case $UNAME_MACHINE in + A*) GUESS=alpha-dec-vms ;; + I*) GUESS=ia64-dec-vms ;; + V*) GUESS=vax-dec-vms ;; esac ;; *:XENIX:*:SysV) - echo i386-pc-xenix - exit ;; + GUESS=i386-pc-xenix + ;; i*86:skyos:*:*) - echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" - exit ;; + SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'` + GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL + ;; i*86:rdos:*:*) - echo "$UNAME_MACHINE"-pc-rdos - exit ;; - i*86:AROS:*:*) - echo "$UNAME_MACHINE"-pc-aros - exit ;; + GUESS=$UNAME_MACHINE-pc-rdos + ;; + *:AROS:*:*) + GUESS=$UNAME_MACHINE-unknown-aros + ;; x86_64:VMkernel:*:*) - echo "$UNAME_MACHINE"-unknown-esx - exit ;; + GUESS=$UNAME_MACHINE-unknown-esx + ;; amd64:Isilon\ OneFS:*:*) - echo x86_64-unknown-onefs - exit ;; + GUESS=x86_64-unknown-onefs + ;; + *:Unleashed:*:*) + GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE + ;; esac +# Do we have a guess based on uname results? +if test "x$GUESS" != x; then + echo "$GUESS" + exit +fi + +# No uname command or uname output not recognized. +set_cc_for_build +cat > "$dummy.c" < +#include +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#include +#if defined(_SIZE_T_) || defined(SIGLOST) +#include +#endif +#endif +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); +#endif + +#if defined (vax) +#if !defined (ultrix) +#include +#if defined (BSD) +#if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +#else +#if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#endif +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#else +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname un; + uname (&un); + printf ("vax-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("vax-dec-ultrix\n"); exit (0); +#endif +#endif +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname *un; + uname (&un); + printf ("mips-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("mips-dec-ultrix\n"); exit (0); +#endif +#endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. +test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } + echo "$0: unable to guess system type" >&2 -case "$UNAME_MACHINE:$UNAME_SYSTEM" in +case $UNAME_MACHINE:$UNAME_SYSTEM in mips:Linux | mips64:Linux) # If we got here on MIPS GNU/Linux, output extra information. cat >&2 <&2 <&2 exit 1 ;; *local*) @@ -110,1227 +119,1181 @@ case $# in exit 1;; esac -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ - kopensolaris*-gnu* | cloudabi*-eabi* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - android-linux) - os=-linux-android - basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown - ;; - *) - basic_machine=`echo "$1" | sed 's/-[^-]*$//'` - if [ "$basic_machine" != "$1" ] - then os=`echo "$1" | sed 's/.*-/-/'` - else os=; fi - ;; -esac +# Split fields of configuration type +# shellcheck disable=SC2162 +saved_IFS=$IFS +IFS="-" read field1 field2 field3 field4 <&2 + exit 1 ;; - -lynx*) - os=-lynxos + *-*-*-*) + basic_machine=$field1-$field2 + basic_os=$field3-$field4 ;; - -ptx*) - basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'` + *-*-*) + # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two + # parts + maybe_os=$field2-$field3 + case $maybe_os in + nto-qnx* | linux-* | uclinux-uclibc* \ + | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ + | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ + | storm-chaos* | os2-emx* | rtmk-nova*) + basic_machine=$field1 + basic_os=$maybe_os + ;; + android-linux) + basic_machine=$field1-unknown + basic_os=linux-android + ;; + *) + basic_machine=$field1-$field2 + basic_os=$field3 + ;; + esac ;; - -psos*) - os=-psos + *-*) + # A lone config we happen to match not fitting any pattern + case $field1-$field2 in + decstation-3100) + basic_machine=mips-dec + basic_os= + ;; + *-*) + # Second component is usually, but not always the OS + case $field2 in + # Prevent following clause from handling this valid os + sun*os*) + basic_machine=$field1 + basic_os=$field2 + ;; + zephyr*) + basic_machine=$field1-unknown + basic_os=$field2 + ;; + # Manufacturers + dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ + | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ + | unicom* | ibm* | next | hp | isi* | apollo | altos* \ + | convergent* | ncr* | news | 32* | 3600* | 3100* \ + | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ + | ultra | tti* | harris | dolphin | highlevel | gould \ + | cbm | ns | masscomp | apple | axis | knuth | cray \ + | microblaze* | sim | cisco \ + | oki | wec | wrs | winbond) + basic_machine=$field1-$field2 + basic_os= + ;; + *) + basic_machine=$field1 + basic_os=$field2 + ;; + esac + ;; + esac ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint + *) + # Convert single-component short-hands not valid as part of + # multi-component configurations. + case $field1 in + 386bsd) + basic_machine=i386-pc + basic_os=bsd + ;; + a29khif) + basic_machine=a29k-amd + basic_os=udi + ;; + adobe68k) + basic_machine=m68010-adobe + basic_os=scout + ;; + alliant) + basic_machine=fx80-alliant + basic_os= + ;; + altos | altos3068) + basic_machine=m68k-altos + basic_os= + ;; + am29k) + basic_machine=a29k-none + basic_os=bsd + ;; + amdahl) + basic_machine=580-amdahl + basic_os=sysv + ;; + amiga) + basic_machine=m68k-unknown + basic_os= + ;; + amigaos | amigados) + basic_machine=m68k-unknown + basic_os=amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + basic_os=sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + basic_os=sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + basic_os=bsd + ;; + aros) + basic_machine=i386-pc + basic_os=aros + ;; + aux) + basic_machine=m68k-apple + basic_os=aux + ;; + balance) + basic_machine=ns32k-sequent + basic_os=dynix + ;; + blackfin) + basic_machine=bfin-unknown + basic_os=linux + ;; + cegcc) + basic_machine=arm-unknown + basic_os=cegcc + ;; + convex-c1) + basic_machine=c1-convex + basic_os=bsd + ;; + convex-c2) + basic_machine=c2-convex + basic_os=bsd + ;; + convex-c32) + basic_machine=c32-convex + basic_os=bsd + ;; + convex-c34) + basic_machine=c34-convex + basic_os=bsd + ;; + convex-c38) + basic_machine=c38-convex + basic_os=bsd + ;; + cray) + basic_machine=j90-cray + basic_os=unicos + ;; + crds | unos) + basic_machine=m68k-crds + basic_os= + ;; + da30) + basic_machine=m68k-da30 + basic_os= + ;; + decstation | pmax | pmin | dec3100 | decstatn) + basic_machine=mips-dec + basic_os= + ;; + delta88) + basic_machine=m88k-motorola + basic_os=sysv3 + ;; + dicos) + basic_machine=i686-pc + basic_os=dicos + ;; + djgpp) + basic_machine=i586-pc + basic_os=msdosdjgpp + ;; + ebmon29k) + basic_machine=a29k-amd + basic_os=ebmon + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + basic_os=ose + ;; + gmicro) + basic_machine=tron-gmicro + basic_os=sysv + ;; + go32) + basic_machine=i386-pc + basic_os=go32 + ;; + h8300hms) + basic_machine=h8300-hitachi + basic_os=hms + ;; + h8300xray) + basic_machine=h8300-hitachi + basic_os=xray + ;; + h8500hms) + basic_machine=h8500-hitachi + basic_os=hms + ;; + harris) + basic_machine=m88k-harris + basic_os=sysv3 + ;; + hp300 | hp300hpux) + basic_machine=m68k-hp + basic_os=hpux + ;; + hp300bsd) + basic_machine=m68k-hp + basic_os=bsd + ;; + hppaosf) + basic_machine=hppa1.1-hp + basic_os=osf + ;; + hppro) + basic_machine=hppa1.1-hp + basic_os=proelf + ;; + i386mach) + basic_machine=i386-mach + basic_os=mach + ;; + isi68 | isi) + basic_machine=m68k-isi + basic_os=sysv + ;; + m68knommu) + basic_machine=m68k-unknown + basic_os=linux + ;; + magnum | m3230) + basic_machine=mips-mips + basic_os=sysv + ;; + merlin) + basic_machine=ns32k-utek + basic_os=sysv + ;; + mingw64) + basic_machine=x86_64-pc + basic_os=mingw64 + ;; + mingw32) + basic_machine=i686-pc + basic_os=mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + basic_os=mingw32ce + ;; + monitor) + basic_machine=m68k-rom68k + basic_os=coff + ;; + morphos) + basic_machine=powerpc-unknown + basic_os=morphos + ;; + moxiebox) + basic_machine=moxie-unknown + basic_os=moxiebox + ;; + msdos) + basic_machine=i386-pc + basic_os=msdos + ;; + msys) + basic_machine=i686-pc + basic_os=msys + ;; + mvs) + basic_machine=i370-ibm + basic_os=mvs + ;; + nacl) + basic_machine=le32-unknown + basic_os=nacl + ;; + ncr3000) + basic_machine=i486-ncr + basic_os=sysv4 + ;; + netbsd386) + basic_machine=i386-pc + basic_os=netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + basic_os=linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + basic_os=newsos + ;; + news1000) + basic_machine=m68030-sony + basic_os=newsos + ;; + necv70) + basic_machine=v70-nec + basic_os=sysv + ;; + nh3000) + basic_machine=m68k-harris + basic_os=cxux + ;; + nh[45]000) + basic_machine=m88k-harris + basic_os=cxux + ;; + nindy960) + basic_machine=i960-intel + basic_os=nindy + ;; + mon960) + basic_machine=i960-intel + basic_os=mon960 + ;; + nonstopux) + basic_machine=mips-compaq + basic_os=nonstopux + ;; + os400) + basic_machine=powerpc-ibm + basic_os=os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + basic_os=ose + ;; + os68k) + basic_machine=m68k-none + basic_os=os68k + ;; + paragon) + basic_machine=i860-intel + basic_os=osf + ;; + parisc) + basic_machine=hppa-unknown + basic_os=linux + ;; + psp) + basic_machine=mipsallegrexel-sony + basic_os=psp + ;; + pw32) + basic_machine=i586-unknown + basic_os=pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + basic_os=rdos + ;; + rdos32) + basic_machine=i386-pc + basic_os=rdos + ;; + rom68k) + basic_machine=m68k-rom68k + basic_os=coff + ;; + sa29200) + basic_machine=a29k-amd + basic_os=udi + ;; + sei) + basic_machine=mips-sei + basic_os=seiux + ;; + sequent) + basic_machine=i386-sequent + basic_os= + ;; + sps7) + basic_machine=m68k-bull + basic_os=sysv2 + ;; + st2000) + basic_machine=m68k-tandem + basic_os= + ;; + stratus) + basic_machine=i860-stratus + basic_os=sysv4 + ;; + sun2) + basic_machine=m68000-sun + basic_os= + ;; + sun2os3) + basic_machine=m68000-sun + basic_os=sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + basic_os=sunos4 + ;; + sun3) + basic_machine=m68k-sun + basic_os= + ;; + sun3os3) + basic_machine=m68k-sun + basic_os=sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + basic_os=sunos4 + ;; + sun4) + basic_machine=sparc-sun + basic_os= + ;; + sun4os3) + basic_machine=sparc-sun + basic_os=sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + basic_os=sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + basic_os=solaris2 + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + basic_os= + ;; + sv1) + basic_machine=sv1-cray + basic_os=unicos + ;; + symmetry) + basic_machine=i386-sequent + basic_os=dynix + ;; + t3e) + basic_machine=alphaev5-cray + basic_os=unicos + ;; + t90) + basic_machine=t90-cray + basic_os=unicos + ;; + toad1) + basic_machine=pdp10-xkl + basic_os=tops20 + ;; + tpf) + basic_machine=s390x-ibm + basic_os=tpf + ;; + udi29k) + basic_machine=a29k-amd + basic_os=udi + ;; + ultra3) + basic_machine=a29k-nyu + basic_os=sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + basic_os=none + ;; + vaxv) + basic_machine=vax-dec + basic_os=sysv + ;; + vms) + basic_machine=vax-dec + basic_os=vms + ;; + vsta) + basic_machine=i386-pc + basic_os=vsta + ;; + vxworks960) + basic_machine=i960-wrs + basic_os=vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + basic_os=vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + basic_os=vxworks + ;; + xbox) + basic_machine=i686-pc + basic_os=mingw32 + ;; + ymp) + basic_machine=ymp-cray + basic_os=unicos + ;; + *) + basic_machine=$1 + basic_os= + ;; + esac ;; esac -# Decode aliases for certain CPU-COMPANY combinations. +# Decode 1-component or ad-hoc basic machines case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | aarch64 | aarch64_be \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arceb \ - | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv6m | armv[78][arm] \ - | avr | avr32 \ - | ba \ - | be32 | be64 \ - | bfin \ - | c4x | c8051 | clipper | csky \ - | d10v | d30v | dlx | dsp16xx \ - | e2k | epiphany \ - | fido | fr30 | frv | ft32 \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | hexagon \ - | i370 | i860 | i960 | ia16 | ia64 \ - | ip2k | iq2000 \ - | k1om \ - | le32 | le64 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa32r6 | mipsisa32r6el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64r6 | mipsisa64r6el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipsr5900 | mipsr5900el \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ - | msp430 \ - | nds32 | nds32le | nds32be \ - | nios | nios2 | nios2eb | nios2el \ - | ns16k | ns32k \ - | open8 | or1k | or1knd | or32 \ - | pdp10 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pru \ - | pyramid \ - | riscv32 | riscv64 \ - | rl78 | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu \ - | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ - | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | visium \ - | wasm32 \ - | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown - ;; - c54x) - basic_machine=tic54x-unknown - ;; - c55x) - basic_machine=tic55x-unknown - ;; - c6x) - basic_machine=tic6x-unknown - ;; - leon|leon[3-9]) - basic_machine=sparc-$basic_machine - ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65) + # Here we handle the default manufacturer of certain CPU types. It is in + # some cases the only manufacturer, in others, it is the most popular. + w89k) + cpu=hppa1.1 + vendor=winbond ;; - m9s12z | m68hcs12z | hcs12z | s12z) - basic_machine=s12z-unknown - os=-none + op50n) + cpu=hppa1.1 + vendor=oki ;; - ms1) - basic_machine=mt-unknown + op60c) + cpu=hppa1.1 + vendor=oki ;; - - strongarm | thumb | xscale) - basic_machine=arm-unknown + ibm*) + cpu=i370 + vendor=ibm ;; - xgate) - basic_machine=$basic_machine-unknown - os=-none + orion105) + cpu=clipper + vendor=highlevel ;; - xscaleeb) - basic_machine=armeb-unknown + mac | mpw | mac-mpw) + cpu=m68k + vendor=apple ;; - - xscaleel) - basic_machine=armel-unknown + pmac | pmac-mpw) + cpu=powerpc + vendor=apple ;; - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | aarch64-* | aarch64_be-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | ba-* \ - | be32-* | be64-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | c8051-* | clipper-* | craynv-* | csky-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | e2k-* | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | hexagon-* \ - | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ - | ip2k-* | iq2000-* \ - | k1om-* \ - | le32-* | le64-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ - | microblaze-* | microblazeel-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64octeon-* | mips64octeonel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64r5900-* | mips64r5900el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa32r6-* | mipsisa32r6el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64r6-* | mipsisa64r6el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipsr5900-* | mipsr5900el-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* | nios2eb-* | nios2el-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | open8-* \ - | or1k*-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pru-* \ - | pyramid-* \ - | riscv32-* | riscv64-* \ - | rl78-* | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ - | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile*-* \ - | tron-* \ - | ubicom32-* \ - | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ - | vax-* \ - | visium-* \ - | wasm32-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown - ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-pc - os=-bsd - ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att + cpu=m68000 + vendor=att ;; 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aros) - basic_machine=i386-pc - os=-aros - ;; - asmjs) - basic_machine=asmjs-unknown - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - blackfin) - basic_machine=bfin-unknown - os=-linux - ;; - blackfin-*) - basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'` - os=-linux + cpu=we32k + vendor=att ;; bluegene*) - basic_machine=powerpc-ibm - os=-cnk - ;; - c54x-*) - basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - c55x-*) - basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - c6x-*) - basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - cegcc) - basic_machine=arm-unknown - os=-cegcc - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16 | cr16-*) - basic_machine=cr16-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec + cpu=powerpc + vendor=ibm + basic_os=cnk ;; decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 + cpu=pdp10 + vendor=dec + basic_os=tops10 ;; decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 + cpu=pdp10 + vendor=dec + basic_os=tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dicos) - basic_machine=i686-pc - os=-dicos - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx + cpu=m68k + vendor=motorola ;; dpx2*) - basic_machine=m68k-bull - os=-sysv3 - ;; - e500v[12]) - basic_machine=powerpc-unknown - os=$os"spe" - ;; - e500v[12]-*) - basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` - os=$os"spe" - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd + cpu=m68k + vendor=bull + basic_os=sysv3 ;; encore | umax | mmax) - basic_machine=ns32k-encore + cpu=ns32k + vendor=encore ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose + elxsi) + cpu=elxsi + vendor=elxsi + basic_os=${basic_os:-bsd} ;; fx2800) - basic_machine=i860-alliant + cpu=i860 + vendor=alliant ;; genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 + cpu=ns32k + vendor=ns ;; h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux + cpu=hppa1.1 + vendor=hitachi + basic_os=hiuxwe2 ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp + cpu=hppa1.0 + vendor=hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp + cpu=m68000 + vendor=hp ;; hp9k3[2-9][0-9]) - basic_machine=m68k-hp + cpu=m68k + vendor=hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp + cpu=hppa1.0 + vendor=hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm + cpu=hppa1.0 + vendor=hp ;; i*86v32) - basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` - os=-sysv32 + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=sysv32 ;; i*86v4*) - basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` - os=-sysv4 + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=sysv4 ;; i*86v) - basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` - os=-sysv + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=sysv ;; i*86sol2) - basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=solaris2 ;; - vsta) - basic_machine=i386-unknown - os=-vsta + j90 | j90-cray) + cpu=j90 + vendor=cray + basic_os=${basic_os:-unicos} ;; iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) + cpu=mips + vendor=sgi + case $basic_os in + irix*) ;; *) - os=-irix4 + basic_os=irix4 ;; esac ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - leon-*|leon[3-9]-*) - basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'` - ;; - m68knommu) - basic_machine=m68k-unknown - os=-linux - ;; - m68knommu-*) - basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'` - os=-linux - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - microblaze*) - basic_machine=microblaze-xilinx - ;; - mingw64) - basic_machine=x86_64-pc - os=-mingw64 - ;; - mingw32) - basic_machine=i686-pc - os=-mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=-mingw32ce - ;; miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - moxiebox) - basic_machine=moxie-unknown - os=-moxiebox + cpu=m68000 + vendor=convergent ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'` - ;; - msys) - basic_machine=i686-pc - os=-msys - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - nacl) - basic_machine=le32-unknown - os=-nacl - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos + *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) + cpu=m68k + vendor=atari + basic_os=mint ;; news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv + cpu=mips + vendor=sony + basic_os=newsos ;; next | m*-next) - basic_machine=m68k-next - case $os in - -nextstep* ) + cpu=m68k + vendor=next + case $basic_os in + openstep*) + ;; + nextstep*) ;; - -ns2*) - os=-nextstep2 + ns2*) + basic_os=nextstep2 ;; *) - os=-nextstep3 + basic_os=nextstep3 ;; esac ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; np1) - basic_machine=np1-gould - ;; - neo-tandem) - basic_machine=neo-tandem - ;; - nse-tandem) - basic_machine=nse-tandem - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - nsv-tandem) - basic_machine=nsv-tandem - ;; - nsx-tandem) - basic_machine=nsx-tandem + cpu=np1 + vendor=gould ;; op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k + cpu=hppa1.1 + vendor=oki + basic_os=proelf ;; pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - parisc) - basic_machine=hppa-unknown - os=-linux - ;; - parisc-*) - basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'` - os=-linux + cpu=hppa1.1 + vendor=hitachi + basic_os=hiuxwe2 ;; pbd) - basic_machine=sparc-tti + cpu=sparc + vendor=tti ;; pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pc98) - basic_machine=i386-pc + cpu=m68k + vendor=tti ;; - pc98-*) - basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'` + pc532) + cpu=ns32k + vendor=pc532 ;; pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc | ppcbe) basic_machine=powerpc-unknown + cpu=pn + vendor=gould ;; - ppc-* | ppcbe-*) - basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'` + power) + cpu=power + vendor=ibm ;; - ppc64) basic_machine=powerpc64-unknown + ps2) + cpu=i386 + vendor=ibm ;; - ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'` + rm[46]00) + cpu=mips + vendor=siemens ;; - ppc64le | powerpc64little) - basic_machine=powerpc64le-unknown + rtpc | rtpc-*) + cpu=romp + vendor=ibm ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'` + sde) + cpu=mipsisa32 + vendor=sde + basic_os=${basic_os:-elf} ;; - ps2) - basic_machine=i386-ibm + simso-wrs) + cpu=sparclite + vendor=wrs + basic_os=vxworks ;; - pw32) - basic_machine=i586-unknown - os=-pw32 + tower | tower-32) + cpu=m68k + vendor=ncr ;; - rdos | rdos64) - basic_machine=x86_64-pc - os=-rdos + vpp*|vx|vx-*) + cpu=f301 + vendor=fujitsu ;; - rdos32) - basic_machine=i386-pc - os=-rdos + w65) + cpu=w65 + vendor=wdc ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff + w89k-*) + cpu=hppa1.1 + vendor=winbond + basic_os=proelf ;; - rm[46]00) - basic_machine=mips-siemens + none) + cpu=none + vendor=none ;; - rtpc | rtpc-*) - basic_machine=romp-ibm + leon|leon[3-9]) + cpu=sparc + vendor=$basic_machine ;; - s390 | s390-*) - basic_machine=s390-ibm + leon-*|leon[3-9]-*) + cpu=sparc + vendor=`echo "$basic_machine" | sed 's/-.*//'` ;; - s390x | s390x-*) - basic_machine=s390x-ibm + + *-*) + # shellcheck disable=SC2162 + saved_IFS=$IFS + IFS="-" read cpu vendor <&2 - exit 1 + # Recognize the canonical CPU types that are allowed with any + # company name. + case $cpu in + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | abacus \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \ + | alphapca5[67] | alpha64pca5[67] \ + | am33_2.0 \ + | amdgcn \ + | arc | arceb | arc32 | arc64 \ + | arm | arm[lb]e | arme[lb] | armv* \ + | avr | avr32 \ + | asmjs \ + | ba \ + | be32 | be64 \ + | bfin | bpf | bs2000 \ + | c[123]* | c30 | [cjt]90 | c4x \ + | c8051 | clipper | craynv | csky | cydra \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | elxsi | epiphany \ + | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \ + | h8300 | h8500 \ + | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i*86 | i860 | i960 | ia16 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | loongarch32 | loongarch64 | loongarchx32 \ + | m32c | m32r | m32rle \ + | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \ + | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \ + | m88110 | m88k | maxq | mb | mcore | mep | metag \ + | microblaze | microblazeel \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64eb | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r3 | mipsisa32r3el \ + | mipsisa32r5 | mipsisa32r5el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r3 | mipsisa64r3el \ + | mipsisa64r5 | mipsisa64r5el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mmix \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nfp \ + | nios | nios2 | nios2eb | nios2el \ + | none | np1 | ns16k | ns32k | nvptx \ + | open8 \ + | or1k* \ + | or32 \ + | orion \ + | picochip \ + | pdp10 | pdp11 | pj | pjl | pn | power \ + | powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \ + | pru \ + | pyramid \ + | riscv | riscv32 | riscv32be | riscv64 | riscv64be \ + | rl78 | romp | rs6000 | rx \ + | s390 | s390x \ + | score \ + | sh | shl \ + | sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \ + | sh[1234]e[lb] | sh[12345][lb]e | sh[23]ele | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \ + | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \ + | spu \ + | tahoe \ + | thumbv7* \ + | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \ + | tron \ + | ubicom32 \ + | v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \ + | vax \ + | visium \ + | w65 \ + | wasm32 | wasm64 \ + | we32k \ + | x86 | x86_64 | xc16x | xgate | xps100 \ + | xstormy16 | xtensa* \ + | ymp \ + | z8k | z80) + ;; + + *) + echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2 + exit 1 + ;; + esac ;; esac # Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'` +case $vendor in + digital*) + vendor=dec ;; - *-commodore*) - basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'` + commodore*) + vendor=cbm ;; *) ;; @@ -1338,203 +1301,215 @@ esac # Decode manufacturer-specific aliases for certain operating systems. -if [ x"$os" != x"" ] +if test x$basic_os != x then + +# First recognize some ad-hoc caes, or perhaps split kernel-os, or else just +# set os. +case $basic_os in + gnu/linux*) + kernel=linux + os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'` + ;; + os2-emx) + kernel=os2 + os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'` + ;; + nto-qnx*) + kernel=nto + os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'` + ;; + *-*) + # shellcheck disable=SC2162 + saved_IFS=$IFS + IFS="-" read kernel os <&2 - exit 1 + # No normalization, but not necessarily accepted, that comes below. ;; esac + else # Here we handle the default operating systems that come with various machines. @@ -1547,254 +1522,358 @@ else # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. -case $basic_machine in +kernel= +case $cpu-$vendor in score-*) - os=-elf + os=elf ;; spu-*) - os=-elf + os=elf ;; *-acorn) - os=-riscix1.2 + os=riscix1.2 ;; arm*-rebel) - os=-linux + kernel=linux + os=gnu ;; arm*-semi) - os=-aout + os=aout ;; c4x-* | tic4x-*) - os=-coff + os=coff ;; c8051-*) - os=-elf + os=elf + ;; + clipper-intergraph) + os=clix ;; hexagon-*) - os=-elf + os=elf ;; tic54x-*) - os=-coff + os=coff ;; tic55x-*) - os=-coff + os=coff ;; tic6x-*) - os=-coff + os=coff ;; # This must come before the *-dec entry. pdp10-*) - os=-tops20 + os=tops20 ;; pdp11-*) - os=-none + os=none ;; *-dec | vax-*) - os=-ultrix4.2 + os=ultrix4.2 ;; m68*-apollo) - os=-domain + os=domain ;; i386-sun) - os=-sunos4.0.2 + os=sunos4.0.2 ;; m68000-sun) - os=-sunos3 + os=sunos3 ;; m68*-cisco) - os=-aout + os=aout ;; mep-*) - os=-elf + os=elf ;; mips*-cisco) - os=-elf + os=elf ;; mips*-*) - os=-elf + os=elf ;; or32-*) - os=-coff + os=coff ;; *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 + os=sysv3 ;; sparc-* | *-sun) - os=-sunos4.1.1 + os=sunos4.1.1 ;; pru-*) - os=-elf + os=elf ;; *-be) - os=-beos + os=beos ;; *-ibm) - os=-aix + os=aix ;; *-knuth) - os=-mmixware + os=mmixware ;; *-wec) - os=-proelf + os=proelf ;; *-winbond) - os=-proelf + os=proelf ;; *-oki) - os=-proelf + os=proelf ;; *-hp) - os=-hpux + os=hpux ;; *-hitachi) - os=-hiux + os=hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv + os=sysv ;; *-cbm) - os=-amigaos + os=amigaos ;; *-dg) - os=-dgux + os=dgux ;; *-dolphin) - os=-sysv3 + os=sysv3 ;; m68k-ccur) - os=-rtu + os=rtu ;; m88k-omron*) - os=-luna + os=luna ;; *-next) - os=-nextstep + os=nextstep ;; *-sequent) - os=-ptx + os=ptx ;; *-crds) - os=-unos + os=unos ;; *-ns) - os=-genix + os=genix ;; i370-*) - os=-mvs + os=mvs ;; *-gould) - os=-sysv + os=sysv ;; *-highlevel) - os=-bsd + os=bsd ;; *-encore) - os=-bsd + os=bsd ;; *-sgi) - os=-irix + os=irix ;; *-siemens) - os=-sysv4 + os=sysv4 ;; *-masscomp) - os=-rtu + os=rtu ;; f30[01]-fujitsu | f700-fujitsu) - os=-uxpv + os=uxpv ;; *-rom68k) - os=-coff + os=coff ;; *-*bug) - os=-coff + os=coff ;; *-apple) - os=-macos + os=macos ;; *-atari*) - os=-mint + os=mint + ;; + *-wrs) + os=vxworks ;; *) - os=-none + os=none ;; esac + fi +# Now, validate our (potentially fixed-up) OS. +case $os in + # Sometimes we do "kernel-libc", so those need to count as OSes. + musl* | newlib* | relibc* | uclibc*) + ;; + # Likewise for "kernel-abi" + eabi* | gnueabi*) + ;; + # VxWorks passes extra cpu info in the 4th filed. + simlinux | simwindows | spe) + ;; + # Now accept the basic system types. + # The portable systems comes first. + # Each alternative MUST end in a * to match a version number. + gnu* | android* | bsd* | mach* | minix* | genix* | ultrix* | irix* \ + | *vms* | esix* | aix* | cnk* | sunos | sunos[34]* \ + | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \ + | sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \ + | hiux* | abug | nacl* | netware* | windows* \ + | os9* | macos* | osx* | ios* \ + | mpw* | magic* | mmixware* | mon960* | lnews* \ + | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \ + | aos* | aros* | cloudabi* | sortix* | twizzler* \ + | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \ + | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \ + | mirbsd* | netbsd* | dicos* | openedition* | ose* \ + | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \ + | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \ + | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \ + | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \ + | udi* | lites* | ieee* | go32* | aux* | hcos* \ + | chorusrdb* | cegcc* | glidix* | serenity* \ + | cygwin* | msys* | pe* | moss* | proelf* | rtems* \ + | midipix* | mingw32* | mingw64* | mint* \ + | uxpv* | beos* | mpeix* | udk* | moxiebox* \ + | interix* | uwin* | mks* | rhapsody* | darwin* \ + | openstep* | oskit* | conix* | pw32* | nonstopux* \ + | storm-chaos* | tops10* | tenex* | tops20* | its* \ + | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \ + | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \ + | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \ + | skyos* | haiku* | rdos* | toppers* | drops* | es* \ + | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ + | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ + | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr*) + ;; + # This one is extra strict with allowed versions + sco3.2v2 | sco3.2v[4-9]* | sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + ;; + none) + ;; + *) + echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2 + exit 1 + ;; +esac + +# As a final step for OS-related things, validate the OS-kernel combination +# (given a valid OS), if there is a kernel. +case $kernel-$os in + linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \ + | linux-musl* | linux-relibc* | linux-uclibc* ) + ;; + uclinux-uclibc* ) + ;; + -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* ) + # These are just libc implementations, not actual OSes, and thus + # require a kernel. + echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2 + exit 1 + ;; + kfreebsd*-gnu* | kopensolaris*-gnu*) + ;; + vxworks-simlinux | vxworks-simwindows | vxworks-spe) + ;; + nto-qnx*) + ;; + os2-emx) + ;; + *-eabi* | *-gnueabi*) + ;; + -*) + # Blank kernel with real OS is always fine. + ;; + *-*) + echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2 + exit 1 + ;; +esac + # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) +case $vendor in + unknown) + case $cpu-$os in + *-riscix*) vendor=acorn ;; - -sunos*) + *-sunos*) vendor=sun ;; - -cnk*|-aix*) + *-cnk* | *-aix*) vendor=ibm ;; - -beos*) + *-beos*) vendor=be ;; - -hpux*) + *-hpux*) vendor=hp ;; - -mpeix*) + *-mpeix*) vendor=hp ;; - -hiux*) + *-hiux*) vendor=hitachi ;; - -unos*) + *-unos*) vendor=crds ;; - -dgux*) + *-dgux*) vendor=dg ;; - -luna*) + *-luna*) vendor=omron ;; - -genix*) + *-genix*) vendor=ns ;; - -mvs* | -opened*) + *-clix*) + vendor=intergraph + ;; + *-mvs* | *-opened*) + vendor=ibm + ;; + *-os400*) vendor=ibm ;; - -os400*) + s390-* | s390x-*) vendor=ibm ;; - -ptx*) + *-ptx*) vendor=sequent ;; - -tpf*) + *-tpf*) vendor=ibm ;; - -vxsim* | -vxworks* | -windiss*) + *-vxsim* | *-vxworks* | *-windiss*) vendor=wrs ;; - -aux*) + *-aux*) vendor=apple ;; - -hms*) + *-hms*) vendor=hitachi ;; - -mpw* | -macos*) + *-mpw* | *-macos*) vendor=apple ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*) vendor=atari ;; - -vos*) + *-vos*) vendor=stratus ;; esac - basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"` ;; esac -echo "$basic_machine$os" +echo "$cpu-$vendor-${kernel:+$kernel-}$os" exit # Local variables: From webhook-mailer at python.org Thu Nov 25 16:52:06 2021 From: webhook-mailer at python.org (tiran) Date: Thu, 25 Nov 2021 21:52:06 -0000 Subject: [Python-checkins] [3.10] bpo-33393: Update config.guess and config.sub (GH-29781) (GH-29782) Message-ID: https://github.com/python/cpython/commit/3f565f8edf84cfe8fa3e9cbf5da7c5911acaa6f9 commit: 3f565f8edf84cfe8fa3e9cbf5da7c5911acaa6f9 branch: 3.10 author: Christian Heimes committer: tiran date: 2021-11-25T22:52:02+01:00 summary: [3.10] bpo-33393: Update config.guess and config.sub (GH-29781) (GH-29782) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Build/2021-11-25-20-26-06.bpo-33393.24YNtM.rst M Makefile.pre.in M config.guess M config.sub diff --git a/Makefile.pre.in b/Makefile.pre.in index 86014227c3387..ee85f35b10da4 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -2002,6 +2002,12 @@ patchcheck: @DEF_MAKE_RULE@ check-limited-abi: all $(RUNSHARED) ./$(BUILDPYTHON) $(srcdir)/Tools/scripts/stable_abi.py --all $(srcdir)/Misc/stable_abi.txt +.PHONY: update-config +update-config: + curl -sL -o config.guess 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD' + curl -sL -o config.sub 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD' + chmod +x config.guess config.sub + # Dependencies Python/thread.o: @THREADHEADERS@ $(srcdir)/Python/condvar.h diff --git a/Misc/NEWS.d/next/Build/2021-11-25-20-26-06.bpo-33393.24YNtM.rst b/Misc/NEWS.d/next/Build/2021-11-25-20-26-06.bpo-33393.24YNtM.rst new file mode 100644 index 0000000000000..c27869c9b6ded --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-25-20-26-06.bpo-33393.24YNtM.rst @@ -0,0 +1,3 @@ +Update ``config.guess`` to 2021-06-03 and ``config.sub`` to 2021-08-14. +``Makefile`` now has an ``update-config`` target to make updating more +convenient. diff --git a/config.guess b/config.guess index 256083a70d359..e81d3ae7c210b 100755 --- a/config.guess +++ b/config.guess @@ -1,8 +1,10 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2018 Free Software Foundation, Inc. +# Copyright 1992-2021 Free Software Foundation, Inc. -timestamp='2018-03-08' +# shellcheck disable=SC2006,SC2268 # see below for rationale + +timestamp='2021-06-03' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -27,11 +29,19 @@ timestamp='2018-03-08' # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: -# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess # # Please send patches to . +# The "shellcheck disable" line above the timestamp inhibits complaints +# about features and limitations of the classic Bourne shell that were +# superseded or lifted in POSIX. However, this script identifies a wide +# variety of pre-POSIX systems that do not have POSIX shells at all, and +# even some reasonably current systems (Solaris 10 as case-in-point) still +# have a pre-POSIX /bin/sh. + + me=`echo "$0" | sed -e 's,.*/,,'` usage="\ @@ -50,7 +60,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2018 Free Software Foundation, Inc. +Copyright 1992-2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -84,7 +94,8 @@ if test $# != 0; then exit 1 fi -trap 'exit 1' 1 2 15 +# Just in case it came from the environment. +GUESS= # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires @@ -96,73 +107,90 @@ trap 'exit 1' 1 2 15 # Portable tmp directory creation inspired by the Autoconf team. -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > "$dummy.c" ; - for c in cc gcc c89 c99 ; do - if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' +tmp= +# shellcheck disable=SC2172 +trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 + +set_cc_for_build() { + # prevent multiple calls if $tmp is already set + test "$tmp" && return 0 + : "${TMPDIR=/tmp}" + # shellcheck disable=SC2039,SC3028 + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } + dummy=$tmp/dummy + case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in + ,,) echo "int x;" > "$dummy.c" + for driver in cc gcc c89 c99 ; do + if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then + CC_FOR_BUILD=$driver + break + fi + done + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; + esac +} # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi at noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then +if test -f /.attbin/uname ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown -case "$UNAME_SYSTEM" in +case $UNAME_SYSTEM in Linux|GNU|GNU/*) - # If the system lacks a compiler, then just pick glibc. - # We could probably try harder. - LIBC=gnu + LIBC=unknown - eval "$set_cc_for_build" + set_cc_for_build cat <<-EOF > "$dummy.c" #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc - #else + #elif defined(__GLIBC__) LIBC=gnu + #else + #include + /* First heuristic to detect musl libc. */ + #ifdef __DEFINED_va_list + LIBC=musl + #endif #endif EOF - eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" + cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + eval "$cc_set_libc" - # If ldd exists, use it to detect musl libc. - if command -v ldd >/dev/null && \ - ldd --version 2>&1 | grep -q ^musl - then - LIBC=musl + # Second heuristic to detect musl libc. + if [ "$LIBC" = unknown ] && + command -v ldd >/dev/null && + ldd --version 2>&1 | grep -q ^musl; then + LIBC=musl + fi + + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + if [ "$LIBC" = unknown ]; then + LIBC=gnu fi ;; esac # Note: order is significant - the case branches are not exclusive. -case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in +case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, @@ -174,12 +202,12 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". - sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ - "/sbin/$sysctl" 2>/dev/null || \ - "/usr/sbin/$sysctl" 2>/dev/null || \ + /sbin/sysctl -n hw.machine_arch 2>/dev/null || \ + /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \ echo unknown)` - case "$UNAME_MACHINE_ARCH" in + case $UNAME_MACHINE_ARCH in + aarch64eb) machine=aarch64_be-unknown ;; armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; @@ -188,18 +216,18 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in earmv*) arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` - machine="${arch}${endian}"-unknown + machine=${arch}${endian}-unknown ;; - *) machine="$UNAME_MACHINE_ARCH"-unknown ;; + *) machine=$UNAME_MACHINE_ARCH-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently (or will in the future) and ABI. - case "$UNAME_MACHINE_ARCH" in + case $UNAME_MACHINE_ARCH in earm*) os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval "$set_cc_for_build" + set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then @@ -215,7 +243,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in ;; esac # Determine ABI tags. - case "$UNAME_MACHINE_ARCH" in + case $UNAME_MACHINE_ARCH in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` @@ -226,7 +254,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. - case "$UNAME_VERSION" in + case $UNAME_VERSION in Debian*) release='-gnu' ;; @@ -237,45 +265,57 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "$machine-${os}${release}${abi}" - exit ;; + GUESS=$machine-${os}${release}${abi-} + ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` - echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE + ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE + ;; + *:SecBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'` + GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE + ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` - echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE + ;; *:MidnightBSD:*:*) - echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE + ;; *:ekkoBSD:*:*) - echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE + ;; *:SolidBSD:*:*) - echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE + ;; + *:OS108:*:*) + GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE + ;; macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd"$UNAME_RELEASE" - exit ;; + GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE + ;; *:MirBSD:*:*) - echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE + ;; *:Sortix:*:*) - echo "$UNAME_MACHINE"-unknown-sortix - exit ;; + GUESS=$UNAME_MACHINE-unknown-sortix + ;; + *:Twizzler:*:*) + GUESS=$UNAME_MACHINE-unknown-twizzler + ;; *:Redox:*:*) - echo "$UNAME_MACHINE"-unknown-redox - exit ;; + GUESS=$UNAME_MACHINE-unknown-redox + ;; mips:OSF1:*.*) - echo mips-dec-osf1 - exit ;; + GUESS=mips-dec-osf1 + ;; alpha:OSF1:*:*) + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + trap '' 0 case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` @@ -289,7 +329,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` - case "$ALPHA_CPU_TYPE" in + case $ALPHA_CPU_TYPE in "EV4 (21064)") UNAME_MACHINE=alpha ;; "EV4.5 (21064)") @@ -326,75 +366,76 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" - # Reset EXIT trap before exiting to avoid spurious non-zero exit code. - exitcode=$? - trap '' 0 - exit $exitcode ;; + OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + GUESS=$UNAME_MACHINE-dec-osf$OSF_REL + ;; Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit ;; + GUESS=m68k-unknown-sysv4 + ;; *:[Aa]miga[Oo][Ss]:*:*) - echo "$UNAME_MACHINE"-unknown-amigaos - exit ;; + GUESS=$UNAME_MACHINE-unknown-amigaos + ;; *:[Mm]orph[Oo][Ss]:*:*) - echo "$UNAME_MACHINE"-unknown-morphos - exit ;; + GUESS=$UNAME_MACHINE-unknown-morphos + ;; *:OS/390:*:*) - echo i370-ibm-openedition - exit ;; + GUESS=i370-ibm-openedition + ;; *:z/VM:*:*) - echo s390-ibm-zvmoe - exit ;; + GUESS=s390-ibm-zvmoe + ;; *:OS400:*:*) - echo powerpc-ibm-os400 - exit ;; + GUESS=powerpc-ibm-os400 + ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix"$UNAME_RELEASE" - exit ;; + GUESS=arm-acorn-riscix$UNAME_RELEASE + ;; arm*:riscos:*:*|arm*:RISCOS:*:*) - echo arm-unknown-riscos - exit ;; + GUESS=arm-unknown-riscos + ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit ;; + GUESS=hppa1.1-hitachi-hiuxmpp + ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee at wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit ;; + case `(/bin/universe) 2>/dev/null` in + att) GUESS=pyramid-pyramid-sysv3 ;; + *) GUESS=pyramid-pyramid-bsd ;; + esac + ;; NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit ;; + GUESS=pyramid-pyramid-svr4 + ;; DRS?6000:unix:4.0:6*) - echo sparc-icl-nx6 - exit ;; + GUESS=sparc-icl-nx6 + ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7; exit ;; - esac ;; + sparc) GUESS=sparc-icl-nx7 ;; + esac + ;; s390x:SunOS:*:*) - echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL + ;; sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=sparc-hal-solaris2$SUN_REL + ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=sparc-sun-solaris2$SUN_REL + ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux"$UNAME_RELEASE" - exit ;; + GUESS=i386-pc-auroraux$UNAME_RELEASE + ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval "$set_cc_for_build" + set_cc_for_build SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. - if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null @@ -402,41 +443,44 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in SUN_ARCH=x86_64 fi fi - echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=$SUN_ARCH-pc-solaris2$SUN_REL + ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=sparc-sun-solaris3$SUN_REL + ;; sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in + case `/usr/bin/arch -k` in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'` + GUESS=sparc-sun-sunos$SUN_REL + ;; sun3*:SunOS:*:*) - echo m68k-sun-sunos"$UNAME_RELEASE" - exit ;; + GUESS=m68k-sun-sunos$UNAME_RELEASE + ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 - case "`/bin/arch`" in + case `/bin/arch` in sun3) - echo m68k-sun-sunos"$UNAME_RELEASE" + GUESS=m68k-sun-sunos$UNAME_RELEASE ;; sun4) - echo sparc-sun-sunos"$UNAME_RELEASE" + GUESS=sparc-sun-sunos$UNAME_RELEASE ;; esac - exit ;; + ;; aushp:SunOS:*:*) - echo sparc-auspex-sunos"$UNAME_RELEASE" - exit ;; + GUESS=sparc-auspex-sunos$UNAME_RELEASE + ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor @@ -446,43 +490,43 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint"$UNAME_RELEASE" - exit ;; + GUESS=m68k-atari-mint$UNAME_RELEASE + ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint"$UNAME_RELEASE" - exit ;; + GUESS=m68k-atari-mint$UNAME_RELEASE + ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint"$UNAME_RELEASE" - exit ;; + GUESS=m68k-atari-mint$UNAME_RELEASE + ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint"$UNAME_RELEASE" - exit ;; + GUESS=m68k-milan-mint$UNAME_RELEASE + ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint"$UNAME_RELEASE" - exit ;; + GUESS=m68k-hades-mint$UNAME_RELEASE + ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint"$UNAME_RELEASE" - exit ;; + GUESS=m68k-unknown-mint$UNAME_RELEASE + ;; m68k:machten:*:*) - echo m68k-apple-machten"$UNAME_RELEASE" - exit ;; + GUESS=m68k-apple-machten$UNAME_RELEASE + ;; powerpc:machten:*:*) - echo powerpc-apple-machten"$UNAME_RELEASE" - exit ;; + GUESS=powerpc-apple-machten$UNAME_RELEASE + ;; RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit ;; + GUESS=mips-dec-mach_bsd4.3 + ;; RISC*:ULTRIX:*:*) - echo mips-dec-ultrix"$UNAME_RELEASE" - exit ;; + GUESS=mips-dec-ultrix$UNAME_RELEASE + ;; VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix"$UNAME_RELEASE" - exit ;; + GUESS=vax-dec-ultrix$UNAME_RELEASE + ;; 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix"$UNAME_RELEASE" - exit ;; + GUESS=clipper-intergraph-clix$UNAME_RELEASE + ;; mips:*:*:UMIPS | mips:*:*:RISCos) - eval "$set_cc_for_build" + set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include /* for printf() prototype */ @@ -508,78 +552,79 @@ EOF dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`"$dummy" "$dummyarg"` && { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos"$UNAME_RELEASE" - exit ;; + GUESS=mips-mips-riscos$UNAME_RELEASE + ;; Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit ;; + GUESS=powerpc-motorola-powermax + ;; Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit ;; + GUESS=powerpc-harris-powermax + ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - echo powerpc-harris-powermax - exit ;; + GUESS=powerpc-harris-powermax + ;; Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit ;; + GUESS=powerpc-harris-powerunix + ;; m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit ;; + GUESS=m88k-harris-cxux7 + ;; m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit ;; + GUESS=m88k-motorola-sysv4 + ;; m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit ;; + GUESS=m88k-motorola-sysv3 + ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] + if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110 then - if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ - [ "$TARGET_BINARY_INTERFACE"x = x ] + if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \ + test "$TARGET_BINARY_INTERFACE"x = x then - echo m88k-dg-dgux"$UNAME_RELEASE" + GUESS=m88k-dg-dgux$UNAME_RELEASE else - echo m88k-dg-dguxbcs"$UNAME_RELEASE" + GUESS=m88k-dg-dguxbcs$UNAME_RELEASE fi else - echo i586-dg-dgux"$UNAME_RELEASE" + GUESS=i586-dg-dgux$UNAME_RELEASE fi - exit ;; + ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit ;; + GUESS=m88k-dolphin-sysv3 + ;; M88*:*:R3*:*) # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit ;; + GUESS=m88k-motorola-sysv3 + ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit ;; + GUESS=m88k-tektronix-sysv3 + ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit ;; + GUESS=m68k-tektronix-bsd + ;; *:IRIX*:*:*) - echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" - exit ;; + IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'` + GUESS=mips-sgi-irix$IRIX_REL + ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + GUESS=romp-ibm-aix # uname -m gives an 8 hex-code CPU id + ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) - echo i386-ibm-aix - exit ;; + GUESS=i386-ibm-aix + ;; ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then + if test -x /usr/bin/oslevel ; then IBM_REV=`/usr/bin/oslevel` else - IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" + IBM_REV=$UNAME_VERSION.$UNAME_RELEASE fi - echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" - exit ;; + GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV + ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval "$set_cc_for_build" + set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include @@ -593,16 +638,16 @@ EOF EOF if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` then - echo "$SYSTEM_NAME" + GUESS=$SYSTEM_NAME else - echo rs6000-ibm-aix3.2.5 + GUESS=rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 + GUESS=rs6000-ibm-aix3.2.4 else - echo rs6000-ibm-aix3.2 + GUESS=rs6000-ibm-aix3.2 fi - exit ;; + ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then @@ -610,57 +655,57 @@ EOF else IBM_ARCH=powerpc fi - if [ -x /usr/bin/lslpp ] ; then - IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + if test -x /usr/bin/lslpp ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \ awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else - IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" + IBM_REV=$UNAME_VERSION.$UNAME_RELEASE fi - echo "$IBM_ARCH"-ibm-aix"$IBM_REV" - exit ;; + GUESS=$IBM_ARCH-ibm-aix$IBM_REV + ;; *:AIX:*:*) - echo rs6000-ibm-aix - exit ;; + GUESS=rs6000-ibm-aix + ;; ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) - echo romp-ibm-bsd4.4 - exit ;; + GUESS=romp-ibm-bsd4.4 + ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to - exit ;; # report: romp-ibm BSD 4.3 + GUESS=romp-ibm-bsd$UNAME_RELEASE # 4.3 with uname added to + ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) - echo rs6000-bull-bosx - exit ;; + GUESS=rs6000-bull-bosx + ;; DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit ;; + GUESS=m68k-bull-sysv3 + ;; 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit ;; + GUESS=m68k-hp-bsd + ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit ;; + GUESS=m68k-hp-bsd4.4 + ;; 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` - case "$UNAME_MACHINE" in + HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` + case $UNAME_MACHINE in 9000/31?) HP_ARCH=m68000 ;; 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) - if [ -x /usr/bin/getconf ]; then + if test -x /usr/bin/getconf; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "$sc_cpu_version" in + case $sc_cpu_version in 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 - case "$sc_kernel_bits" in + case $sc_kernel_bits in 32) HP_ARCH=hppa2.0n ;; 64) HP_ARCH=hppa2.0w ;; '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi - if [ "$HP_ARCH" = "" ]; then - eval "$set_cc_for_build" + if test "$HP_ARCH" = ""; then + set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #define _HPUX_SOURCE @@ -698,9 +743,9 @@ EOF test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac - if [ "$HP_ARCH" = hppa2.0w ] + if test "$HP_ARCH" = hppa2.0w then - eval "$set_cc_for_build" + set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler @@ -719,14 +764,14 @@ EOF HP_ARCH=hppa64 fi fi - echo "$HP_ARCH"-hp-hpux"$HPUX_REV" - exit ;; + GUESS=$HP_ARCH-hp-hpux$HPUX_REV + ;; ia64:HP-UX:*:*) - HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux"$HPUX_REV" - exit ;; + HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` + GUESS=ia64-hp-hpux$HPUX_REV + ;; 3050*:HI-UX:*:*) - eval "$set_cc_for_build" + set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include int @@ -754,36 +799,36 @@ EOF EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } - echo unknown-hitachi-hiuxwe2 - exit ;; + GUESS=unknown-hitachi-hiuxwe2 + ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) - echo hppa1.1-hp-bsd - exit ;; + GUESS=hppa1.1-hp-bsd + ;; 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit ;; + GUESS=hppa1.0-hp-bsd + ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit ;; + GUESS=hppa1.0-hp-mpeix + ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) - echo hppa1.1-hp-osf - exit ;; + GUESS=hppa1.1-hp-osf + ;; hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit ;; + GUESS=hppa1.0-hp-osf + ;; i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo "$UNAME_MACHINE"-unknown-osf1mk + if test -x /usr/sbin/sysversion ; then + GUESS=$UNAME_MACHINE-unknown-osf1mk else - echo "$UNAME_MACHINE"-unknown-osf1 + GUESS=$UNAME_MACHINE-unknown-osf1 fi - exit ;; + ;; parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit ;; + GUESS=hppa1.1-hp-lites + ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit ;; + GUESS=c1-convex-bsd + ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd @@ -791,17 +836,18 @@ EOF fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit ;; + GUESS=c34-convex-bsd + ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit ;; + GUESS=c38-convex-bsd + ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit ;; + GUESS=c4-convex-bsd + ;; CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' - exit ;; + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=ymp-cray-unicos$CRAY_REL + ;; CRAY*[A-Z]90:*:*:*) echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ @@ -809,103 +855,126 @@ EOF -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) - echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' - exit ;; + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=t90-cray-unicos$CRAY_REL + ;; CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' - exit ;; + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=alphaev5-cray-unicosmk$CRAY_REL + ;; CRAY*SV1:*:*:*) - echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' - exit ;; + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=sv1-cray-unicos$CRAY_REL + ;; *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' - exit ;; + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=craynv-cray-unicosmp$CRAY_REL + ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; + GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} + ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; + GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} + ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE + ;; sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi"$UNAME_RELEASE" - exit ;; + GUESS=sparc-unknown-bsdi$UNAME_RELEASE + ;; *:BSD/OS:*:*) - echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE + ;; + arm:FreeBSD:*:*) + UNAME_PROCESSOR=`uname -p` + set_cc_for_build + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi + else + FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf + fi + ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` - case "$UNAME_PROCESSOR" in + case $UNAME_PROCESSOR in amd64) UNAME_PROCESSOR=x86_64 ;; i386) UNAME_PROCESSOR=i586 ;; esac - echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" - exit ;; + FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL + ;; i*:CYGWIN*:*) - echo "$UNAME_MACHINE"-pc-cygwin - exit ;; + GUESS=$UNAME_MACHINE-pc-cygwin + ;; *:MINGW64*:*) - echo "$UNAME_MACHINE"-pc-mingw64 - exit ;; + GUESS=$UNAME_MACHINE-pc-mingw64 + ;; *:MINGW*:*) - echo "$UNAME_MACHINE"-pc-mingw32 - exit ;; + GUESS=$UNAME_MACHINE-pc-mingw32 + ;; *:MSYS*:*) - echo "$UNAME_MACHINE"-pc-msys - exit ;; + GUESS=$UNAME_MACHINE-pc-msys + ;; i*:PW*:*) - echo "$UNAME_MACHINE"-pc-pw32 - exit ;; + GUESS=$UNAME_MACHINE-pc-pw32 + ;; *:Interix*:*) - case "$UNAME_MACHINE" in + case $UNAME_MACHINE in x86) - echo i586-pc-interix"$UNAME_RELEASE" - exit ;; + GUESS=i586-pc-interix$UNAME_RELEASE + ;; authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix"$UNAME_RELEASE" - exit ;; + GUESS=x86_64-unknown-interix$UNAME_RELEASE + ;; IA64) - echo ia64-unknown-interix"$UNAME_RELEASE" - exit ;; + GUESS=ia64-unknown-interix$UNAME_RELEASE + ;; esac ;; i*:UWIN*:*) - echo "$UNAME_MACHINE"-pc-uwin - exit ;; + GUESS=$UNAME_MACHINE-pc-uwin + ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-unknown-cygwin - exit ;; + GUESS=x86_64-pc-cygwin + ;; prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" - exit ;; + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=powerpcle-unknown-solaris2$SUN_REL + ;; *:GNU:*:*) # the GNU system - echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" - exit ;; + GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'` + GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'` + GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL + ;; *:GNU/*:*:*) # other systems with GNU libc and userland - echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" - exit ;; - i*86:Minix:*:*) - echo "$UNAME_MACHINE"-pc-minix - exit ;; + GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"` + GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC + ;; + *:Minix:*:*) + GUESS=$UNAME_MACHINE-unknown-minix + ;; aarch64:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; @@ -916,183 +985,225 @@ EOF esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC=gnulibc1 ; fi - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; - arc:Linux:*:* | arceb:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; arm*:Linux:*:*) - eval "$set_cc_for_build" + set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi + GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi else - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf + GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf fi fi - exit ;; + ;; avr32*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; cris:Linux:*:*) - echo "$UNAME_MACHINE"-axis-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-axis-linux-$LIBC + ;; crisv32:Linux:*:*) - echo "$UNAME_MACHINE"-axis-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-axis-linux-$LIBC + ;; e2k:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; frv:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; hexagon:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; i*86:Linux:*:*) - echo "$UNAME_MACHINE"-pc-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-pc-linux-$LIBC + ;; ia64:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; k1om:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; m32r*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; m68*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; mips:Linux:*:* | mips64:Linux:*:*) - eval "$set_cc_for_build" + set_cc_for_build + IS_GLIBC=0 + test x"${LIBC}" = xgnu && IS_GLIBC=1 sed 's/^ //' << EOF > "$dummy.c" #undef CPU - #undef ${UNAME_MACHINE} - #undef ${UNAME_MACHINE}el + #undef mips + #undef mipsel + #undef mips64 + #undef mips64el + #if ${IS_GLIBC} && defined(_ABI64) + LIBCABI=gnuabi64 + #else + #if ${IS_GLIBC} && defined(_ABIN32) + LIBCABI=gnuabin32 + #else + LIBCABI=${LIBC} + #endif + #endif + + #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa64r6 + #else + #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa32r6 + #else + #if defined(__mips64) + CPU=mips64 + #else + CPU=mips + #endif + #endif + #endif + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=${UNAME_MACHINE}el + MIPS_ENDIAN=el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=${UNAME_MACHINE} + MIPS_ENDIAN= #else - CPU= + MIPS_ENDIAN= #endif #endif EOF - eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`" - test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; } + cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'` + eval "$cc_set_vars" + test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } ;; mips64el:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; openrisc*:Linux:*:*) - echo or1k-unknown-linux-"$LIBC" - exit ;; + GUESS=or1k-unknown-linux-$LIBC + ;; or32:Linux:*:* | or1k*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; padre:Linux:*:*) - echo sparc-unknown-linux-"$LIBC" - exit ;; + GUESS=sparc-unknown-linux-$LIBC + ;; parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-"$LIBC" - exit ;; + GUESS=hppa64-unknown-linux-$LIBC + ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; - PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; - *) echo hppa-unknown-linux-"$LIBC" ;; + PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;; + PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;; + *) GUESS=hppa-unknown-linux-$LIBC ;; esac - exit ;; + ;; ppc64:Linux:*:*) - echo powerpc64-unknown-linux-"$LIBC" - exit ;; + GUESS=powerpc64-unknown-linux-$LIBC + ;; ppc:Linux:*:*) - echo powerpc-unknown-linux-"$LIBC" - exit ;; + GUESS=powerpc-unknown-linux-$LIBC + ;; ppc64le:Linux:*:*) - echo powerpc64le-unknown-linux-"$LIBC" - exit ;; + GUESS=powerpc64le-unknown-linux-$LIBC + ;; ppcle:Linux:*:*) - echo powerpcle-unknown-linux-"$LIBC" - exit ;; - riscv32:Linux:*:* | riscv64:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=powerpcle-unknown-linux-$LIBC + ;; + riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; s390:Linux:*:* | s390x:Linux:*:*) - echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-ibm-linux-$LIBC + ;; sh64*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; sh*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; sparc:Linux:*:* | sparc64:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; tile*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; vax:Linux:*:*) - echo "$UNAME_MACHINE"-dec-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-dec-linux-$LIBC + ;; x86_64:Linux:*:*) - echo "$UNAME_MACHINE"-pc-linux-"$LIBC" - exit ;; + set_cc_for_build + LIBCABI=$LIBC + if test "$CC_FOR_BUILD" != no_compiler_found; then + if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_X32 >/dev/null + then + LIBCABI=${LIBC}x32 + fi + fi + GUESS=$UNAME_MACHINE-pc-linux-$LIBCABI + ;; xtensa*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. - echo i386-sequent-sysv4 - exit ;; + GUESS=i386-sequent-sysv4 + ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. - echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" - exit ;; + GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION + ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. - echo "$UNAME_MACHINE"-pc-os2-emx - exit ;; + GUESS=$UNAME_MACHINE-pc-os2-emx + ;; i*86:XTS-300:*:STOP) - echo "$UNAME_MACHINE"-unknown-stop - exit ;; + GUESS=$UNAME_MACHINE-unknown-stop + ;; i*86:atheos:*:*) - echo "$UNAME_MACHINE"-unknown-atheos - exit ;; + GUESS=$UNAME_MACHINE-unknown-atheos + ;; i*86:syllable:*:*) - echo "$UNAME_MACHINE"-pc-syllable - exit ;; + GUESS=$UNAME_MACHINE-pc-syllable + ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos"$UNAME_RELEASE" - exit ;; + GUESS=i386-unknown-lynxos$UNAME_RELEASE + ;; i*86:*DOS:*:*) - echo "$UNAME_MACHINE"-pc-msdosdjgpp - exit ;; + GUESS=$UNAME_MACHINE-pc-msdosdjgpp + ;; i*86:*:4.*:*) UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" + GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL else - echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" + GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL fi - exit ;; + ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in @@ -1100,12 +1211,12 @@ EOF *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac - echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}" - exit ;; + GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 @@ -1115,11 +1226,11 @@ EOF && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 - echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" + GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL else - echo "$UNAME_MACHINE"-pc-sysv32 + GUESS=$UNAME_MACHINE-pc-sysv32 fi - exit ;; + ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about @@ -1127,31 +1238,31 @@ EOF # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. - echo i586-pc-msdosdjgpp - exit ;; + GUESS=i586-pc-msdosdjgpp + ;; Intel:Mach:3*:*) - echo i386-pc-mach3 - exit ;; + GUESS=i386-pc-mach3 + ;; paragon:*:*:*) - echo i860-intel-osf1 - exit ;; + GUESS=i860-intel-osf1 + ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 + GUESS=i860-stardent-sysv$UNAME_RELEASE # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 + GUESS=i860-unknown-sysv$UNAME_RELEASE # Unknown i860-SVR4 fi - exit ;; + ;; mini*:CTIX:SYS*5:*) # "miniframe" - echo m68010-convergent-sysv - exit ;; + GUESS=m68010-convergent-sysv + ;; mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit ;; + GUESS=m68k-convergent-sysv + ;; M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit ;; + GUESS=m68k-diab-dnix + ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) @@ -1176,249 +1287,401 @@ EOF /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos"$UNAME_RELEASE" - exit ;; + GUESS=m68k-unknown-lynxos$UNAME_RELEASE + ;; mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit ;; + GUESS=m68k-atari-sysv4 + ;; TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos"$UNAME_RELEASE" - exit ;; + GUESS=sparc-unknown-lynxos$UNAME_RELEASE + ;; rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos"$UNAME_RELEASE" - exit ;; + GUESS=rs6000-unknown-lynxos$UNAME_RELEASE + ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos"$UNAME_RELEASE" - exit ;; + GUESS=powerpc-unknown-lynxos$UNAME_RELEASE + ;; SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv"$UNAME_RELEASE" - exit ;; + GUESS=mips-dde-sysv$UNAME_RELEASE + ;; RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit ;; + GUESS=mips-sni-sysv4 + ;; RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit ;; + GUESS=mips-sni-sysv4 + ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo "$UNAME_MACHINE"-sni-sysv4 + GUESS=$UNAME_MACHINE-sni-sysv4 else - echo ns32k-sni-sysv + GUESS=ns32k-sni-sysv fi - exit ;; + ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says - echo i586-unisys-sysv4 - exit ;; + GUESS=i586-unisys-sysv4 + ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit ;; + GUESS=hppa1.1-stratus-sysv4 + ;; *:*:*:FTX*) # From seanf at swdc.stratus.com. - echo i860-stratus-sysv4 - exit ;; + GUESS=i860-stratus-sysv4 + ;; i*86:VOS:*:*) # From Paul.Green at stratus.com. - echo "$UNAME_MACHINE"-stratus-vos - exit ;; + GUESS=$UNAME_MACHINE-stratus-vos + ;; *:VOS:*:*) # From Paul.Green at stratus.com. - echo hppa1.1-stratus-vos - exit ;; + GUESS=hppa1.1-stratus-vos + ;; mc68*:A/UX:*:*) - echo m68k-apple-aux"$UNAME_RELEASE" - exit ;; + GUESS=m68k-apple-aux$UNAME_RELEASE + ;; news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit ;; + GUESS=mips-sony-newsos6 + ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv"$UNAME_RELEASE" + if test -d /usr/nec; then + GUESS=mips-nec-sysv$UNAME_RELEASE else - echo mips-unknown-sysv"$UNAME_RELEASE" + GUESS=mips-unknown-sysv$UNAME_RELEASE fi - exit ;; + ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit ;; + GUESS=powerpc-be-beos + ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit ;; + GUESS=powerpc-apple-beos + ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit ;; + GUESS=i586-pc-beos + ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. - echo i586-pc-haiku - exit ;; + GUESS=i586-pc-haiku + ;; x86_64:Haiku:*:*) - echo x86_64-unknown-haiku - exit ;; + GUESS=x86_64-unknown-haiku + ;; SX-4:SUPER-UX:*:*) - echo sx4-nec-superux"$UNAME_RELEASE" - exit ;; + GUESS=sx4-nec-superux$UNAME_RELEASE + ;; SX-5:SUPER-UX:*:*) - echo sx5-nec-superux"$UNAME_RELEASE" - exit ;; + GUESS=sx5-nec-superux$UNAME_RELEASE + ;; SX-6:SUPER-UX:*:*) - echo sx6-nec-superux"$UNAME_RELEASE" - exit ;; + GUESS=sx6-nec-superux$UNAME_RELEASE + ;; SX-7:SUPER-UX:*:*) - echo sx7-nec-superux"$UNAME_RELEASE" - exit ;; + GUESS=sx7-nec-superux$UNAME_RELEASE + ;; SX-8:SUPER-UX:*:*) - echo sx8-nec-superux"$UNAME_RELEASE" - exit ;; + GUESS=sx8-nec-superux$UNAME_RELEASE + ;; SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux"$UNAME_RELEASE" - exit ;; + GUESS=sx8r-nec-superux$UNAME_RELEASE + ;; SX-ACE:SUPER-UX:*:*) - echo sxace-nec-superux"$UNAME_RELEASE" - exit ;; + GUESS=sxace-nec-superux$UNAME_RELEASE + ;; Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody"$UNAME_RELEASE" - exit ;; + GUESS=powerpc-apple-rhapsody$UNAME_RELEASE + ;; *:Rhapsody:*:*) - echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE + ;; + arm64:Darwin:*:*) + GUESS=aarch64-apple-darwin$UNAME_RELEASE + ;; *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - eval "$set_cc_for_build" - if test "$UNAME_PROCESSOR" = unknown ; then - UNAME_PROCESSOR=powerpc + UNAME_PROCESSOR=`uname -p` + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + if command -v xcode-select > /dev/null 2> /dev/null && \ + ! xcode-select --print-path > /dev/null 2> /dev/null ; then + # Avoid executing cc if there is no toolchain installed as + # cc will be a stub that puts up a graphical alert + # prompting the user to install developer tools. + CC_FOR_BUILD=no_compiler_found + else + set_cc_for_build fi - if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then - if [ "$CC_FOR_BUILD" != no_compiler_found ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - case $UNAME_PROCESSOR in - i386) UNAME_PROCESSOR=x86_64 ;; - powerpc) UNAME_PROCESSOR=powerpc64 ;; - esac - fi - # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc - if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_PPC >/dev/null - then - UNAME_PROCESSOR=powerpc - fi + if test "$CC_FOR_BUILD" != no_compiler_found; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc fi elif test "$UNAME_PROCESSOR" = i386 ; then - # Avoid executing cc on OS X 10.9, as it ships with a stub - # that puts up a graphical alert prompting to install - # developer tools. Any system running Mac OS X 10.7 or - # later (Darwin 11 and later) is required to have a 64-bit - # processor. This is not true of the ARM version of Darwin - # that Apple uses in portable devices. - UNAME_PROCESSOR=x86_64 + # uname -m returns i386 or x86_64 + UNAME_PROCESSOR=$UNAME_MACHINE fi - echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE + ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi - echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE + ;; *:QNX:*:4*) - echo i386-pc-qnx - exit ;; + GUESS=i386-pc-qnx + ;; NEO-*:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk"$UNAME_RELEASE" - exit ;; + GUESS=neo-tandem-nsk$UNAME_RELEASE + ;; NSE-*:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk"$UNAME_RELEASE" - exit ;; + GUESS=nse-tandem-nsk$UNAME_RELEASE + ;; NSR-*:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk"$UNAME_RELEASE" - exit ;; + GUESS=nsr-tandem-nsk$UNAME_RELEASE + ;; NSV-*:NONSTOP_KERNEL:*:*) - echo nsv-tandem-nsk"$UNAME_RELEASE" - exit ;; + GUESS=nsv-tandem-nsk$UNAME_RELEASE + ;; NSX-*:NONSTOP_KERNEL:*:*) - echo nsx-tandem-nsk"$UNAME_RELEASE" - exit ;; + GUESS=nsx-tandem-nsk$UNAME_RELEASE + ;; *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit ;; + GUESS=mips-compaq-nonstopux + ;; BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit ;; + GUESS=bs2000-siemens-sysv + ;; DS/*:UNIX_System_V:*:*) - echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" - exit ;; + GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE + ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. - if test "$cputype" = 386; then + if test "${cputype-}" = 386; then UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" + elif test "x${cputype-}" != x; then + UNAME_MACHINE=$cputype fi - echo "$UNAME_MACHINE"-unknown-plan9 - exit ;; + GUESS=$UNAME_MACHINE-unknown-plan9 + ;; *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit ;; + GUESS=pdp10-unknown-tops10 + ;; *:TENEX:*:*) - echo pdp10-unknown-tenex - exit ;; + GUESS=pdp10-unknown-tenex + ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit ;; + GUESS=pdp10-dec-tops20 + ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit ;; + GUESS=pdp10-xkl-tops20 + ;; *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit ;; + GUESS=pdp10-unknown-tops20 + ;; *:ITS:*:*) - echo pdp10-unknown-its - exit ;; + GUESS=pdp10-unknown-its + ;; SEI:*:*:SEIUX) - echo mips-sei-seiux"$UNAME_RELEASE" - exit ;; + GUESS=mips-sei-seiux$UNAME_RELEASE + ;; *:DragonFly:*:*) - echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" - exit ;; + DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL + ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "$UNAME_MACHINE" in - A*) echo alpha-dec-vms ; exit ;; - I*) echo ia64-dec-vms ; exit ;; - V*) echo vax-dec-vms ; exit ;; + case $UNAME_MACHINE in + A*) GUESS=alpha-dec-vms ;; + I*) GUESS=ia64-dec-vms ;; + V*) GUESS=vax-dec-vms ;; esac ;; *:XENIX:*:SysV) - echo i386-pc-xenix - exit ;; + GUESS=i386-pc-xenix + ;; i*86:skyos:*:*) - echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" - exit ;; + SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'` + GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL + ;; i*86:rdos:*:*) - echo "$UNAME_MACHINE"-pc-rdos - exit ;; - i*86:AROS:*:*) - echo "$UNAME_MACHINE"-pc-aros - exit ;; + GUESS=$UNAME_MACHINE-pc-rdos + ;; + *:AROS:*:*) + GUESS=$UNAME_MACHINE-unknown-aros + ;; x86_64:VMkernel:*:*) - echo "$UNAME_MACHINE"-unknown-esx - exit ;; + GUESS=$UNAME_MACHINE-unknown-esx + ;; amd64:Isilon\ OneFS:*:*) - echo x86_64-unknown-onefs - exit ;; + GUESS=x86_64-unknown-onefs + ;; + *:Unleashed:*:*) + GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE + ;; esac +# Do we have a guess based on uname results? +if test "x$GUESS" != x; then + echo "$GUESS" + exit +fi + +# No uname command or uname output not recognized. +set_cc_for_build +cat > "$dummy.c" < +#include +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#include +#if defined(_SIZE_T_) || defined(SIGLOST) +#include +#endif +#endif +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); +#endif + +#if defined (vax) +#if !defined (ultrix) +#include +#if defined (BSD) +#if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +#else +#if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#endif +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#else +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname un; + uname (&un); + printf ("vax-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("vax-dec-ultrix\n"); exit (0); +#endif +#endif +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname *un; + uname (&un); + printf ("mips-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("mips-dec-ultrix\n"); exit (0); +#endif +#endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. +test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } + echo "$0: unable to guess system type" >&2 -case "$UNAME_MACHINE:$UNAME_SYSTEM" in +case $UNAME_MACHINE:$UNAME_SYSTEM in mips:Linux | mips64:Linux) # If we got here on MIPS GNU/Linux, output extra information. cat >&2 <&2 <&2 exit 1 ;; *local*) @@ -110,1227 +119,1181 @@ case $# in exit 1;; esac -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ - kopensolaris*-gnu* | cloudabi*-eabi* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - android-linux) - os=-linux-android - basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown - ;; - *) - basic_machine=`echo "$1" | sed 's/-[^-]*$//'` - if [ "$basic_machine" != "$1" ] - then os=`echo "$1" | sed 's/.*-/-/'` - else os=; fi - ;; -esac +# Split fields of configuration type +# shellcheck disable=SC2162 +saved_IFS=$IFS +IFS="-" read field1 field2 field3 field4 <&2 + exit 1 ;; - -lynx*) - os=-lynxos + *-*-*-*) + basic_machine=$field1-$field2 + basic_os=$field3-$field4 ;; - -ptx*) - basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'` + *-*-*) + # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two + # parts + maybe_os=$field2-$field3 + case $maybe_os in + nto-qnx* | linux-* | uclinux-uclibc* \ + | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ + | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ + | storm-chaos* | os2-emx* | rtmk-nova*) + basic_machine=$field1 + basic_os=$maybe_os + ;; + android-linux) + basic_machine=$field1-unknown + basic_os=linux-android + ;; + *) + basic_machine=$field1-$field2 + basic_os=$field3 + ;; + esac ;; - -psos*) - os=-psos + *-*) + # A lone config we happen to match not fitting any pattern + case $field1-$field2 in + decstation-3100) + basic_machine=mips-dec + basic_os= + ;; + *-*) + # Second component is usually, but not always the OS + case $field2 in + # Prevent following clause from handling this valid os + sun*os*) + basic_machine=$field1 + basic_os=$field2 + ;; + zephyr*) + basic_machine=$field1-unknown + basic_os=$field2 + ;; + # Manufacturers + dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ + | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ + | unicom* | ibm* | next | hp | isi* | apollo | altos* \ + | convergent* | ncr* | news | 32* | 3600* | 3100* \ + | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ + | ultra | tti* | harris | dolphin | highlevel | gould \ + | cbm | ns | masscomp | apple | axis | knuth | cray \ + | microblaze* | sim | cisco \ + | oki | wec | wrs | winbond) + basic_machine=$field1-$field2 + basic_os= + ;; + *) + basic_machine=$field1 + basic_os=$field2 + ;; + esac + ;; + esac ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint + *) + # Convert single-component short-hands not valid as part of + # multi-component configurations. + case $field1 in + 386bsd) + basic_machine=i386-pc + basic_os=bsd + ;; + a29khif) + basic_machine=a29k-amd + basic_os=udi + ;; + adobe68k) + basic_machine=m68010-adobe + basic_os=scout + ;; + alliant) + basic_machine=fx80-alliant + basic_os= + ;; + altos | altos3068) + basic_machine=m68k-altos + basic_os= + ;; + am29k) + basic_machine=a29k-none + basic_os=bsd + ;; + amdahl) + basic_machine=580-amdahl + basic_os=sysv + ;; + amiga) + basic_machine=m68k-unknown + basic_os= + ;; + amigaos | amigados) + basic_machine=m68k-unknown + basic_os=amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + basic_os=sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + basic_os=sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + basic_os=bsd + ;; + aros) + basic_machine=i386-pc + basic_os=aros + ;; + aux) + basic_machine=m68k-apple + basic_os=aux + ;; + balance) + basic_machine=ns32k-sequent + basic_os=dynix + ;; + blackfin) + basic_machine=bfin-unknown + basic_os=linux + ;; + cegcc) + basic_machine=arm-unknown + basic_os=cegcc + ;; + convex-c1) + basic_machine=c1-convex + basic_os=bsd + ;; + convex-c2) + basic_machine=c2-convex + basic_os=bsd + ;; + convex-c32) + basic_machine=c32-convex + basic_os=bsd + ;; + convex-c34) + basic_machine=c34-convex + basic_os=bsd + ;; + convex-c38) + basic_machine=c38-convex + basic_os=bsd + ;; + cray) + basic_machine=j90-cray + basic_os=unicos + ;; + crds | unos) + basic_machine=m68k-crds + basic_os= + ;; + da30) + basic_machine=m68k-da30 + basic_os= + ;; + decstation | pmax | pmin | dec3100 | decstatn) + basic_machine=mips-dec + basic_os= + ;; + delta88) + basic_machine=m88k-motorola + basic_os=sysv3 + ;; + dicos) + basic_machine=i686-pc + basic_os=dicos + ;; + djgpp) + basic_machine=i586-pc + basic_os=msdosdjgpp + ;; + ebmon29k) + basic_machine=a29k-amd + basic_os=ebmon + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + basic_os=ose + ;; + gmicro) + basic_machine=tron-gmicro + basic_os=sysv + ;; + go32) + basic_machine=i386-pc + basic_os=go32 + ;; + h8300hms) + basic_machine=h8300-hitachi + basic_os=hms + ;; + h8300xray) + basic_machine=h8300-hitachi + basic_os=xray + ;; + h8500hms) + basic_machine=h8500-hitachi + basic_os=hms + ;; + harris) + basic_machine=m88k-harris + basic_os=sysv3 + ;; + hp300 | hp300hpux) + basic_machine=m68k-hp + basic_os=hpux + ;; + hp300bsd) + basic_machine=m68k-hp + basic_os=bsd + ;; + hppaosf) + basic_machine=hppa1.1-hp + basic_os=osf + ;; + hppro) + basic_machine=hppa1.1-hp + basic_os=proelf + ;; + i386mach) + basic_machine=i386-mach + basic_os=mach + ;; + isi68 | isi) + basic_machine=m68k-isi + basic_os=sysv + ;; + m68knommu) + basic_machine=m68k-unknown + basic_os=linux + ;; + magnum | m3230) + basic_machine=mips-mips + basic_os=sysv + ;; + merlin) + basic_machine=ns32k-utek + basic_os=sysv + ;; + mingw64) + basic_machine=x86_64-pc + basic_os=mingw64 + ;; + mingw32) + basic_machine=i686-pc + basic_os=mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + basic_os=mingw32ce + ;; + monitor) + basic_machine=m68k-rom68k + basic_os=coff + ;; + morphos) + basic_machine=powerpc-unknown + basic_os=morphos + ;; + moxiebox) + basic_machine=moxie-unknown + basic_os=moxiebox + ;; + msdos) + basic_machine=i386-pc + basic_os=msdos + ;; + msys) + basic_machine=i686-pc + basic_os=msys + ;; + mvs) + basic_machine=i370-ibm + basic_os=mvs + ;; + nacl) + basic_machine=le32-unknown + basic_os=nacl + ;; + ncr3000) + basic_machine=i486-ncr + basic_os=sysv4 + ;; + netbsd386) + basic_machine=i386-pc + basic_os=netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + basic_os=linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + basic_os=newsos + ;; + news1000) + basic_machine=m68030-sony + basic_os=newsos + ;; + necv70) + basic_machine=v70-nec + basic_os=sysv + ;; + nh3000) + basic_machine=m68k-harris + basic_os=cxux + ;; + nh[45]000) + basic_machine=m88k-harris + basic_os=cxux + ;; + nindy960) + basic_machine=i960-intel + basic_os=nindy + ;; + mon960) + basic_machine=i960-intel + basic_os=mon960 + ;; + nonstopux) + basic_machine=mips-compaq + basic_os=nonstopux + ;; + os400) + basic_machine=powerpc-ibm + basic_os=os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + basic_os=ose + ;; + os68k) + basic_machine=m68k-none + basic_os=os68k + ;; + paragon) + basic_machine=i860-intel + basic_os=osf + ;; + parisc) + basic_machine=hppa-unknown + basic_os=linux + ;; + psp) + basic_machine=mipsallegrexel-sony + basic_os=psp + ;; + pw32) + basic_machine=i586-unknown + basic_os=pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + basic_os=rdos + ;; + rdos32) + basic_machine=i386-pc + basic_os=rdos + ;; + rom68k) + basic_machine=m68k-rom68k + basic_os=coff + ;; + sa29200) + basic_machine=a29k-amd + basic_os=udi + ;; + sei) + basic_machine=mips-sei + basic_os=seiux + ;; + sequent) + basic_machine=i386-sequent + basic_os= + ;; + sps7) + basic_machine=m68k-bull + basic_os=sysv2 + ;; + st2000) + basic_machine=m68k-tandem + basic_os= + ;; + stratus) + basic_machine=i860-stratus + basic_os=sysv4 + ;; + sun2) + basic_machine=m68000-sun + basic_os= + ;; + sun2os3) + basic_machine=m68000-sun + basic_os=sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + basic_os=sunos4 + ;; + sun3) + basic_machine=m68k-sun + basic_os= + ;; + sun3os3) + basic_machine=m68k-sun + basic_os=sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + basic_os=sunos4 + ;; + sun4) + basic_machine=sparc-sun + basic_os= + ;; + sun4os3) + basic_machine=sparc-sun + basic_os=sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + basic_os=sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + basic_os=solaris2 + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + basic_os= + ;; + sv1) + basic_machine=sv1-cray + basic_os=unicos + ;; + symmetry) + basic_machine=i386-sequent + basic_os=dynix + ;; + t3e) + basic_machine=alphaev5-cray + basic_os=unicos + ;; + t90) + basic_machine=t90-cray + basic_os=unicos + ;; + toad1) + basic_machine=pdp10-xkl + basic_os=tops20 + ;; + tpf) + basic_machine=s390x-ibm + basic_os=tpf + ;; + udi29k) + basic_machine=a29k-amd + basic_os=udi + ;; + ultra3) + basic_machine=a29k-nyu + basic_os=sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + basic_os=none + ;; + vaxv) + basic_machine=vax-dec + basic_os=sysv + ;; + vms) + basic_machine=vax-dec + basic_os=vms + ;; + vsta) + basic_machine=i386-pc + basic_os=vsta + ;; + vxworks960) + basic_machine=i960-wrs + basic_os=vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + basic_os=vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + basic_os=vxworks + ;; + xbox) + basic_machine=i686-pc + basic_os=mingw32 + ;; + ymp) + basic_machine=ymp-cray + basic_os=unicos + ;; + *) + basic_machine=$1 + basic_os= + ;; + esac ;; esac -# Decode aliases for certain CPU-COMPANY combinations. +# Decode 1-component or ad-hoc basic machines case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | aarch64 | aarch64_be \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arceb \ - | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv6m | armv[78][arm] \ - | avr | avr32 \ - | ba \ - | be32 | be64 \ - | bfin \ - | c4x | c8051 | clipper | csky \ - | d10v | d30v | dlx | dsp16xx \ - | e2k | epiphany \ - | fido | fr30 | frv | ft32 \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | hexagon \ - | i370 | i860 | i960 | ia16 | ia64 \ - | ip2k | iq2000 \ - | k1om \ - | le32 | le64 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa32r6 | mipsisa32r6el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64r6 | mipsisa64r6el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipsr5900 | mipsr5900el \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ - | msp430 \ - | nds32 | nds32le | nds32be \ - | nios | nios2 | nios2eb | nios2el \ - | ns16k | ns32k \ - | open8 | or1k | or1knd | or32 \ - | pdp10 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pru \ - | pyramid \ - | riscv32 | riscv64 \ - | rl78 | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu \ - | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ - | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | visium \ - | wasm32 \ - | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown - ;; - c54x) - basic_machine=tic54x-unknown - ;; - c55x) - basic_machine=tic55x-unknown - ;; - c6x) - basic_machine=tic6x-unknown - ;; - leon|leon[3-9]) - basic_machine=sparc-$basic_machine - ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65) + # Here we handle the default manufacturer of certain CPU types. It is in + # some cases the only manufacturer, in others, it is the most popular. + w89k) + cpu=hppa1.1 + vendor=winbond ;; - m9s12z | m68hcs12z | hcs12z | s12z) - basic_machine=s12z-unknown - os=-none + op50n) + cpu=hppa1.1 + vendor=oki ;; - ms1) - basic_machine=mt-unknown + op60c) + cpu=hppa1.1 + vendor=oki ;; - - strongarm | thumb | xscale) - basic_machine=arm-unknown + ibm*) + cpu=i370 + vendor=ibm ;; - xgate) - basic_machine=$basic_machine-unknown - os=-none + orion105) + cpu=clipper + vendor=highlevel ;; - xscaleeb) - basic_machine=armeb-unknown + mac | mpw | mac-mpw) + cpu=m68k + vendor=apple ;; - - xscaleel) - basic_machine=armel-unknown + pmac | pmac-mpw) + cpu=powerpc + vendor=apple ;; - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | aarch64-* | aarch64_be-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | ba-* \ - | be32-* | be64-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | c8051-* | clipper-* | craynv-* | csky-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | e2k-* | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | hexagon-* \ - | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ - | ip2k-* | iq2000-* \ - | k1om-* \ - | le32-* | le64-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ - | microblaze-* | microblazeel-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64octeon-* | mips64octeonel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64r5900-* | mips64r5900el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa32r6-* | mipsisa32r6el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64r6-* | mipsisa64r6el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipsr5900-* | mipsr5900el-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* | nios2eb-* | nios2el-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | open8-* \ - | or1k*-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pru-* \ - | pyramid-* \ - | riscv32-* | riscv64-* \ - | rl78-* | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ - | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile*-* \ - | tron-* \ - | ubicom32-* \ - | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ - | vax-* \ - | visium-* \ - | wasm32-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown - ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-pc - os=-bsd - ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att + cpu=m68000 + vendor=att ;; 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aros) - basic_machine=i386-pc - os=-aros - ;; - asmjs) - basic_machine=asmjs-unknown - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - blackfin) - basic_machine=bfin-unknown - os=-linux - ;; - blackfin-*) - basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'` - os=-linux + cpu=we32k + vendor=att ;; bluegene*) - basic_machine=powerpc-ibm - os=-cnk - ;; - c54x-*) - basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - c55x-*) - basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - c6x-*) - basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - cegcc) - basic_machine=arm-unknown - os=-cegcc - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16 | cr16-*) - basic_machine=cr16-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec + cpu=powerpc + vendor=ibm + basic_os=cnk ;; decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 + cpu=pdp10 + vendor=dec + basic_os=tops10 ;; decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 + cpu=pdp10 + vendor=dec + basic_os=tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dicos) - basic_machine=i686-pc - os=-dicos - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx + cpu=m68k + vendor=motorola ;; dpx2*) - basic_machine=m68k-bull - os=-sysv3 - ;; - e500v[12]) - basic_machine=powerpc-unknown - os=$os"spe" - ;; - e500v[12]-*) - basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` - os=$os"spe" - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd + cpu=m68k + vendor=bull + basic_os=sysv3 ;; encore | umax | mmax) - basic_machine=ns32k-encore + cpu=ns32k + vendor=encore ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose + elxsi) + cpu=elxsi + vendor=elxsi + basic_os=${basic_os:-bsd} ;; fx2800) - basic_machine=i860-alliant + cpu=i860 + vendor=alliant ;; genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 + cpu=ns32k + vendor=ns ;; h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux + cpu=hppa1.1 + vendor=hitachi + basic_os=hiuxwe2 ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp + cpu=hppa1.0 + vendor=hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp + cpu=m68000 + vendor=hp ;; hp9k3[2-9][0-9]) - basic_machine=m68k-hp + cpu=m68k + vendor=hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp + cpu=hppa1.0 + vendor=hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm + cpu=hppa1.0 + vendor=hp ;; i*86v32) - basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` - os=-sysv32 + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=sysv32 ;; i*86v4*) - basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` - os=-sysv4 + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=sysv4 ;; i*86v) - basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` - os=-sysv + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=sysv ;; i*86sol2) - basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=solaris2 ;; - vsta) - basic_machine=i386-unknown - os=-vsta + j90 | j90-cray) + cpu=j90 + vendor=cray + basic_os=${basic_os:-unicos} ;; iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) + cpu=mips + vendor=sgi + case $basic_os in + irix*) ;; *) - os=-irix4 + basic_os=irix4 ;; esac ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - leon-*|leon[3-9]-*) - basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'` - ;; - m68knommu) - basic_machine=m68k-unknown - os=-linux - ;; - m68knommu-*) - basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'` - os=-linux - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - microblaze*) - basic_machine=microblaze-xilinx - ;; - mingw64) - basic_machine=x86_64-pc - os=-mingw64 - ;; - mingw32) - basic_machine=i686-pc - os=-mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=-mingw32ce - ;; miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - moxiebox) - basic_machine=moxie-unknown - os=-moxiebox + cpu=m68000 + vendor=convergent ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'` - ;; - msys) - basic_machine=i686-pc - os=-msys - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - nacl) - basic_machine=le32-unknown - os=-nacl - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos + *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) + cpu=m68k + vendor=atari + basic_os=mint ;; news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv + cpu=mips + vendor=sony + basic_os=newsos ;; next | m*-next) - basic_machine=m68k-next - case $os in - -nextstep* ) + cpu=m68k + vendor=next + case $basic_os in + openstep*) + ;; + nextstep*) ;; - -ns2*) - os=-nextstep2 + ns2*) + basic_os=nextstep2 ;; *) - os=-nextstep3 + basic_os=nextstep3 ;; esac ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; np1) - basic_machine=np1-gould - ;; - neo-tandem) - basic_machine=neo-tandem - ;; - nse-tandem) - basic_machine=nse-tandem - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - nsv-tandem) - basic_machine=nsv-tandem - ;; - nsx-tandem) - basic_machine=nsx-tandem + cpu=np1 + vendor=gould ;; op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k + cpu=hppa1.1 + vendor=oki + basic_os=proelf ;; pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - parisc) - basic_machine=hppa-unknown - os=-linux - ;; - parisc-*) - basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'` - os=-linux + cpu=hppa1.1 + vendor=hitachi + basic_os=hiuxwe2 ;; pbd) - basic_machine=sparc-tti + cpu=sparc + vendor=tti ;; pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pc98) - basic_machine=i386-pc + cpu=m68k + vendor=tti ;; - pc98-*) - basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'` + pc532) + cpu=ns32k + vendor=pc532 ;; pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc | ppcbe) basic_machine=powerpc-unknown + cpu=pn + vendor=gould ;; - ppc-* | ppcbe-*) - basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'` + power) + cpu=power + vendor=ibm ;; - ppc64) basic_machine=powerpc64-unknown + ps2) + cpu=i386 + vendor=ibm ;; - ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'` + rm[46]00) + cpu=mips + vendor=siemens ;; - ppc64le | powerpc64little) - basic_machine=powerpc64le-unknown + rtpc | rtpc-*) + cpu=romp + vendor=ibm ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'` + sde) + cpu=mipsisa32 + vendor=sde + basic_os=${basic_os:-elf} ;; - ps2) - basic_machine=i386-ibm + simso-wrs) + cpu=sparclite + vendor=wrs + basic_os=vxworks ;; - pw32) - basic_machine=i586-unknown - os=-pw32 + tower | tower-32) + cpu=m68k + vendor=ncr ;; - rdos | rdos64) - basic_machine=x86_64-pc - os=-rdos + vpp*|vx|vx-*) + cpu=f301 + vendor=fujitsu ;; - rdos32) - basic_machine=i386-pc - os=-rdos + w65) + cpu=w65 + vendor=wdc ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff + w89k-*) + cpu=hppa1.1 + vendor=winbond + basic_os=proelf ;; - rm[46]00) - basic_machine=mips-siemens + none) + cpu=none + vendor=none ;; - rtpc | rtpc-*) - basic_machine=romp-ibm + leon|leon[3-9]) + cpu=sparc + vendor=$basic_machine ;; - s390 | s390-*) - basic_machine=s390-ibm + leon-*|leon[3-9]-*) + cpu=sparc + vendor=`echo "$basic_machine" | sed 's/-.*//'` ;; - s390x | s390x-*) - basic_machine=s390x-ibm + + *-*) + # shellcheck disable=SC2162 + saved_IFS=$IFS + IFS="-" read cpu vendor <&2 - exit 1 + # Recognize the canonical CPU types that are allowed with any + # company name. + case $cpu in + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | abacus \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \ + | alphapca5[67] | alpha64pca5[67] \ + | am33_2.0 \ + | amdgcn \ + | arc | arceb | arc32 | arc64 \ + | arm | arm[lb]e | arme[lb] | armv* \ + | avr | avr32 \ + | asmjs \ + | ba \ + | be32 | be64 \ + | bfin | bpf | bs2000 \ + | c[123]* | c30 | [cjt]90 | c4x \ + | c8051 | clipper | craynv | csky | cydra \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | elxsi | epiphany \ + | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \ + | h8300 | h8500 \ + | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i*86 | i860 | i960 | ia16 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | loongarch32 | loongarch64 | loongarchx32 \ + | m32c | m32r | m32rle \ + | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \ + | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \ + | m88110 | m88k | maxq | mb | mcore | mep | metag \ + | microblaze | microblazeel \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64eb | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r3 | mipsisa32r3el \ + | mipsisa32r5 | mipsisa32r5el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r3 | mipsisa64r3el \ + | mipsisa64r5 | mipsisa64r5el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mmix \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nfp \ + | nios | nios2 | nios2eb | nios2el \ + | none | np1 | ns16k | ns32k | nvptx \ + | open8 \ + | or1k* \ + | or32 \ + | orion \ + | picochip \ + | pdp10 | pdp11 | pj | pjl | pn | power \ + | powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \ + | pru \ + | pyramid \ + | riscv | riscv32 | riscv32be | riscv64 | riscv64be \ + | rl78 | romp | rs6000 | rx \ + | s390 | s390x \ + | score \ + | sh | shl \ + | sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \ + | sh[1234]e[lb] | sh[12345][lb]e | sh[23]ele | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \ + | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \ + | spu \ + | tahoe \ + | thumbv7* \ + | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \ + | tron \ + | ubicom32 \ + | v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \ + | vax \ + | visium \ + | w65 \ + | wasm32 | wasm64 \ + | we32k \ + | x86 | x86_64 | xc16x | xgate | xps100 \ + | xstormy16 | xtensa* \ + | ymp \ + | z8k | z80) + ;; + + *) + echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2 + exit 1 + ;; + esac ;; esac # Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'` +case $vendor in + digital*) + vendor=dec ;; - *-commodore*) - basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'` + commodore*) + vendor=cbm ;; *) ;; @@ -1338,203 +1301,215 @@ esac # Decode manufacturer-specific aliases for certain operating systems. -if [ x"$os" != x"" ] +if test x$basic_os != x then + +# First recognize some ad-hoc caes, or perhaps split kernel-os, or else just +# set os. +case $basic_os in + gnu/linux*) + kernel=linux + os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'` + ;; + os2-emx) + kernel=os2 + os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'` + ;; + nto-qnx*) + kernel=nto + os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'` + ;; + *-*) + # shellcheck disable=SC2162 + saved_IFS=$IFS + IFS="-" read kernel os <&2 - exit 1 + # No normalization, but not necessarily accepted, that comes below. ;; esac + else # Here we handle the default operating systems that come with various machines. @@ -1547,254 +1522,358 @@ else # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. -case $basic_machine in +kernel= +case $cpu-$vendor in score-*) - os=-elf + os=elf ;; spu-*) - os=-elf + os=elf ;; *-acorn) - os=-riscix1.2 + os=riscix1.2 ;; arm*-rebel) - os=-linux + kernel=linux + os=gnu ;; arm*-semi) - os=-aout + os=aout ;; c4x-* | tic4x-*) - os=-coff + os=coff ;; c8051-*) - os=-elf + os=elf + ;; + clipper-intergraph) + os=clix ;; hexagon-*) - os=-elf + os=elf ;; tic54x-*) - os=-coff + os=coff ;; tic55x-*) - os=-coff + os=coff ;; tic6x-*) - os=-coff + os=coff ;; # This must come before the *-dec entry. pdp10-*) - os=-tops20 + os=tops20 ;; pdp11-*) - os=-none + os=none ;; *-dec | vax-*) - os=-ultrix4.2 + os=ultrix4.2 ;; m68*-apollo) - os=-domain + os=domain ;; i386-sun) - os=-sunos4.0.2 + os=sunos4.0.2 ;; m68000-sun) - os=-sunos3 + os=sunos3 ;; m68*-cisco) - os=-aout + os=aout ;; mep-*) - os=-elf + os=elf ;; mips*-cisco) - os=-elf + os=elf ;; mips*-*) - os=-elf + os=elf ;; or32-*) - os=-coff + os=coff ;; *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 + os=sysv3 ;; sparc-* | *-sun) - os=-sunos4.1.1 + os=sunos4.1.1 ;; pru-*) - os=-elf + os=elf ;; *-be) - os=-beos + os=beos ;; *-ibm) - os=-aix + os=aix ;; *-knuth) - os=-mmixware + os=mmixware ;; *-wec) - os=-proelf + os=proelf ;; *-winbond) - os=-proelf + os=proelf ;; *-oki) - os=-proelf + os=proelf ;; *-hp) - os=-hpux + os=hpux ;; *-hitachi) - os=-hiux + os=hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv + os=sysv ;; *-cbm) - os=-amigaos + os=amigaos ;; *-dg) - os=-dgux + os=dgux ;; *-dolphin) - os=-sysv3 + os=sysv3 ;; m68k-ccur) - os=-rtu + os=rtu ;; m88k-omron*) - os=-luna + os=luna ;; *-next) - os=-nextstep + os=nextstep ;; *-sequent) - os=-ptx + os=ptx ;; *-crds) - os=-unos + os=unos ;; *-ns) - os=-genix + os=genix ;; i370-*) - os=-mvs + os=mvs ;; *-gould) - os=-sysv + os=sysv ;; *-highlevel) - os=-bsd + os=bsd ;; *-encore) - os=-bsd + os=bsd ;; *-sgi) - os=-irix + os=irix ;; *-siemens) - os=-sysv4 + os=sysv4 ;; *-masscomp) - os=-rtu + os=rtu ;; f30[01]-fujitsu | f700-fujitsu) - os=-uxpv + os=uxpv ;; *-rom68k) - os=-coff + os=coff ;; *-*bug) - os=-coff + os=coff ;; *-apple) - os=-macos + os=macos ;; *-atari*) - os=-mint + os=mint + ;; + *-wrs) + os=vxworks ;; *) - os=-none + os=none ;; esac + fi +# Now, validate our (potentially fixed-up) OS. +case $os in + # Sometimes we do "kernel-libc", so those need to count as OSes. + musl* | newlib* | relibc* | uclibc*) + ;; + # Likewise for "kernel-abi" + eabi* | gnueabi*) + ;; + # VxWorks passes extra cpu info in the 4th filed. + simlinux | simwindows | spe) + ;; + # Now accept the basic system types. + # The portable systems comes first. + # Each alternative MUST end in a * to match a version number. + gnu* | android* | bsd* | mach* | minix* | genix* | ultrix* | irix* \ + | *vms* | esix* | aix* | cnk* | sunos | sunos[34]* \ + | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \ + | sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \ + | hiux* | abug | nacl* | netware* | windows* \ + | os9* | macos* | osx* | ios* \ + | mpw* | magic* | mmixware* | mon960* | lnews* \ + | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \ + | aos* | aros* | cloudabi* | sortix* | twizzler* \ + | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \ + | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \ + | mirbsd* | netbsd* | dicos* | openedition* | ose* \ + | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \ + | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \ + | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \ + | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \ + | udi* | lites* | ieee* | go32* | aux* | hcos* \ + | chorusrdb* | cegcc* | glidix* | serenity* \ + | cygwin* | msys* | pe* | moss* | proelf* | rtems* \ + | midipix* | mingw32* | mingw64* | mint* \ + | uxpv* | beos* | mpeix* | udk* | moxiebox* \ + | interix* | uwin* | mks* | rhapsody* | darwin* \ + | openstep* | oskit* | conix* | pw32* | nonstopux* \ + | storm-chaos* | tops10* | tenex* | tops20* | its* \ + | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \ + | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \ + | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \ + | skyos* | haiku* | rdos* | toppers* | drops* | es* \ + | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ + | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ + | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr*) + ;; + # This one is extra strict with allowed versions + sco3.2v2 | sco3.2v[4-9]* | sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + ;; + none) + ;; + *) + echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2 + exit 1 + ;; +esac + +# As a final step for OS-related things, validate the OS-kernel combination +# (given a valid OS), if there is a kernel. +case $kernel-$os in + linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \ + | linux-musl* | linux-relibc* | linux-uclibc* ) + ;; + uclinux-uclibc* ) + ;; + -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* ) + # These are just libc implementations, not actual OSes, and thus + # require a kernel. + echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2 + exit 1 + ;; + kfreebsd*-gnu* | kopensolaris*-gnu*) + ;; + vxworks-simlinux | vxworks-simwindows | vxworks-spe) + ;; + nto-qnx*) + ;; + os2-emx) + ;; + *-eabi* | *-gnueabi*) + ;; + -*) + # Blank kernel with real OS is always fine. + ;; + *-*) + echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2 + exit 1 + ;; +esac + # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) +case $vendor in + unknown) + case $cpu-$os in + *-riscix*) vendor=acorn ;; - -sunos*) + *-sunos*) vendor=sun ;; - -cnk*|-aix*) + *-cnk* | *-aix*) vendor=ibm ;; - -beos*) + *-beos*) vendor=be ;; - -hpux*) + *-hpux*) vendor=hp ;; - -mpeix*) + *-mpeix*) vendor=hp ;; - -hiux*) + *-hiux*) vendor=hitachi ;; - -unos*) + *-unos*) vendor=crds ;; - -dgux*) + *-dgux*) vendor=dg ;; - -luna*) + *-luna*) vendor=omron ;; - -genix*) + *-genix*) vendor=ns ;; - -mvs* | -opened*) + *-clix*) + vendor=intergraph + ;; + *-mvs* | *-opened*) + vendor=ibm + ;; + *-os400*) vendor=ibm ;; - -os400*) + s390-* | s390x-*) vendor=ibm ;; - -ptx*) + *-ptx*) vendor=sequent ;; - -tpf*) + *-tpf*) vendor=ibm ;; - -vxsim* | -vxworks* | -windiss*) + *-vxsim* | *-vxworks* | *-windiss*) vendor=wrs ;; - -aux*) + *-aux*) vendor=apple ;; - -hms*) + *-hms*) vendor=hitachi ;; - -mpw* | -macos*) + *-mpw* | *-macos*) vendor=apple ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*) vendor=atari ;; - -vos*) + *-vos*) vendor=stratus ;; esac - basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"` ;; esac -echo "$basic_machine$os" +echo "$cpu-$vendor-${kernel:+$kernel-}$os" exit # Local variables: From webhook-mailer at python.org Thu Nov 25 23:55:24 2021 From: webhook-mailer at python.org (gvanrossum) Date: Fri, 26 Nov 2021 04:55:24 -0000 Subject: [Python-checkins] bpo-44353: Correct docstring for `NewType` (#29785) Message-ID: https://github.com/python/cpython/commit/93c65df83cef71a4bc77d71afecdec8744c4f73a commit: 93c65df83cef71a4bc77d71afecdec8744c4f73a branch: main author: Alex Waygood committer: gvanrossum date: 2021-11-25T20:55:15-08:00 summary: bpo-44353: Correct docstring for `NewType` (#29785) The docstring for `typing.NewType` is no longer strictly accurate, now that `NewType` is a class, rather than a function files: M Lib/typing.py diff --git a/Lib/typing.py b/Lib/typing.py index 031aa24eaf442..bdd19cadb471a 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -2427,7 +2427,7 @@ class NewType: """NewType creates simple unique types with almost zero runtime overhead. NewType(name, tp) is considered a subtype of tp by static type checkers. At runtime, NewType(name, tp) returns - a dummy function that simply returns its argument. Usage:: + a dummy callable that simply returns its argument. Usage:: UserId = NewType('UserId', int) From webhook-mailer at python.org Fri Nov 26 00:19:15 2021 From: webhook-mailer at python.org (gvanrossum) Date: Fri, 26 Nov 2021 05:19:15 -0000 Subject: [Python-checkins] bpo-45619: documentation of execution model: clarify and update binding summary (#29232) Message-ID: https://github.com/python/cpython/commit/cd876c84932ecc2f7a6c41f3fc800a34d5b06b95 commit: cd876c84932ecc2f7a6c41f3fc800a34d5b06b95 branch: main author: Arthur Milchior committer: gvanrossum date: 2021-11-25T21:19:06-08:00 summary: bpo-45619: documentation of execution model: clarify and update binding summary (#29232) This does two changes that are quite related. 0. it add that variable binding can occur in pattern matching, an update of 3.10 which seems to have been omitted from the list of bindings 1. Given how long the sentence already was, with even subcases in the middle of the sentence, the commit breaks the sentence into an actual list. files: M Doc/reference/executionmodel.rst diff --git a/Doc/reference/executionmodel.rst b/Doc/reference/executionmodel.rst index 5c85dd7052d67..e652915bd271c 100644 --- a/Doc/reference/executionmodel.rst +++ b/Doc/reference/executionmodel.rst @@ -56,15 +56,25 @@ Binding of names .. index:: single: from; import statement -The following constructs bind names: formal parameters to functions, -:keyword:`import` statements, class and function definitions (these bind the -class or function name in the defining block), and targets that are identifiers -if occurring in an assignment, :keyword:`for` loop header, or after -:keyword:`!as` in a :keyword:`with` statement or :keyword:`except` clause. -The :keyword:`!import` statement -of the form ``from ... import *`` binds all names defined in the imported -module, except those beginning with an underscore. This form may only be used -at the module level. +The following constructs bind names: + +* formal parameters to functions, +* class definitions, +* function definitions, +* assignment expressions, +* :ref:`targets ` that are identifiers if occurring in + an assignment: + + + :keyword:`for` loop header, + + after :keyword:`!as` in a :keyword:`with` statement, :keyword:`except` + clause or in the as-pattern in structural pattern matching, + + in a capture pattern in structural pattern matching + +* :keyword:`import` statements. + +The :keyword:`!import` statement of the form ``from ... import *`` binds all +names defined in the imported module, except those beginning with an underscore. +This form may only be used at the module level. A target occurring in a :keyword:`del` statement is also considered bound for this purpose (though the actual semantics are to unbind the name). From webhook-mailer at python.org Fri Nov 26 00:36:45 2021 From: webhook-mailer at python.org (miss-islington) Date: Fri, 26 Nov 2021 05:36:45 -0000 Subject: [Python-checkins] bpo-45619: documentation of execution model: clarify and update binding summary (GH-29232) Message-ID: https://github.com/python/cpython/commit/7842aed7a7938df20b652177458407683e7f1a0b commit: 7842aed7a7938df20b652177458407683e7f1a0b branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-25T21:36:37-08:00 summary: bpo-45619: documentation of execution model: clarify and update binding summary (GH-29232) This does two changes that are quite related. 0. it add that variable binding can occur in pattern matching, an update of 3.10 which seems to have been omitted from the list of bindings 1. Given how long the sentence already was, with even subcases in the middle of the sentence, the commit breaks the sentence into an actual list. (cherry picked from commit cd876c84932ecc2f7a6c41f3fc800a34d5b06b95) Co-authored-by: Arthur Milchior files: M Doc/reference/executionmodel.rst diff --git a/Doc/reference/executionmodel.rst b/Doc/reference/executionmodel.rst index 5c85dd7052d67..e652915bd271c 100644 --- a/Doc/reference/executionmodel.rst +++ b/Doc/reference/executionmodel.rst @@ -56,15 +56,25 @@ Binding of names .. index:: single: from; import statement -The following constructs bind names: formal parameters to functions, -:keyword:`import` statements, class and function definitions (these bind the -class or function name in the defining block), and targets that are identifiers -if occurring in an assignment, :keyword:`for` loop header, or after -:keyword:`!as` in a :keyword:`with` statement or :keyword:`except` clause. -The :keyword:`!import` statement -of the form ``from ... import *`` binds all names defined in the imported -module, except those beginning with an underscore. This form may only be used -at the module level. +The following constructs bind names: + +* formal parameters to functions, +* class definitions, +* function definitions, +* assignment expressions, +* :ref:`targets ` that are identifiers if occurring in + an assignment: + + + :keyword:`for` loop header, + + after :keyword:`!as` in a :keyword:`with` statement, :keyword:`except` + clause or in the as-pattern in structural pattern matching, + + in a capture pattern in structural pattern matching + +* :keyword:`import` statements. + +The :keyword:`!import` statement of the form ``from ... import *`` binds all +names defined in the imported module, except those beginning with an underscore. +This form may only be used at the module level. A target occurring in a :keyword:`del` statement is also considered bound for this purpose (though the actual semantics are to unbind the name). From webhook-mailer at python.org Fri Nov 26 02:26:59 2021 From: webhook-mailer at python.org (tiran) Date: Fri, 26 Nov 2021 07:26:59 -0000 Subject: [Python-checkins] bpo-40280: Use Setup.stdlib static for wasm builds (GH-29784) Message-ID: https://github.com/python/cpython/commit/ee1e2c604c8a66a407116d9c3e589ab0b9580c54 commit: ee1e2c604c8a66a407116d9c3e589ab0b9580c54 branch: main author: Christian Heimes committer: tiran date: 2021-11-26T08:26:49+01:00 summary: bpo-40280: Use Setup.stdlib static for wasm builds (GH-29784) ``Modules/Setup.stdlib`` contains ``Setup`` lines for all stdlib extension modules for which ``configure`` has detected their dependencies. The file is not used yet and still under development. To use the file, do ``ln -sfr Modules/Setup.stdlib Modules/Setup.local``. files: M Modules/Setup.stdlib.in M configure M configure.ac diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index eadd1619a3b38..03295400f638c 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -22,8 +22,8 @@ # Build modules statically or as shared extensions -*shared* -# *static* +# *shared* / *static* +*@MODULE_BUILDTYPE@* ############################################################################ diff --git a/configure b/configure index 944e97ccf9929..1aaa13abd6816 100755 --- a/configure +++ b/configure @@ -770,6 +770,7 @@ MODULE_TIME_FALSE MODULE_TIME_TRUE MODULE__IO_FALSE MODULE__IO_TRUE +MODULE_BUILDTYPE TEST_MODULES LIBRARY_DEPS STATIC_LIBPYTHON @@ -21012,6 +21013,15 @@ case $ac_sys_system in #( ;; esac +case $host_cpu in #( + wasm32|wasm64) : + MODULE_BUILDTYPE=static ;; #( + *) : + MODULE_BUILDTYPE=${MODULE_BUILDTYPE:-shared} + ;; +esac + + MODULE_BLOCK= diff --git a/configure.ac b/configure.ac index 2140e3e43db82..7963f9ccaf80a 100644 --- a/configure.ac +++ b/configure.ac @@ -6185,6 +6185,13 @@ AS_CASE([$ac_sys_system], [py_stdlib_not_available="_scproxy"] ) +dnl Default value for Modules/Setup.stdlib build type +AS_CASE([$host_cpu], + [wasm32|wasm64], [MODULE_BUILDTYPE=static], + [MODULE_BUILDTYPE=${MODULE_BUILDTYPE:-shared}] +) +AC_SUBST([MODULE_BUILDTYPE]) + dnl _MODULE_BLOCK_ADD([VAR], [VALUE]) dnl internal: adds $1=quote($2) to MODULE_BLOCK AC_DEFUN([_MODULE_BLOCK_ADD], [AS_VAR_APPEND([MODULE_BLOCK], ["$1=_AS_QUOTE([$2])$as_nl"])]) From webhook-mailer at python.org Fri Nov 26 04:59:41 2021 From: webhook-mailer at python.org (vstinner) Date: Fri, 26 Nov 2021 09:59:41 -0000 Subject: [Python-checkins] bpo-39026: Fix Python.h when building with Xcode (GH-29488) (GH-29776) Message-ID: https://github.com/python/cpython/commit/92631a4144fba041a5fb6578620db784821dfdc5 commit: 92631a4144fba041a5fb6578620db784821dfdc5 branch: 3.9 author: Victor Stinner committer: vstinner date: 2021-11-26T10:59:31+01:00 summary: bpo-39026: Fix Python.h when building with Xcode (GH-29488) (GH-29776) Fix Python.h to build C extensions with Xcode: remove a relative include from Include/cpython/pystate.h. (cherry picked from commit 4ae26b9c1d0c33e3db92c6f305293f9240dea358) files: A Misc/NEWS.d/next/C API/2021-11-09-15-42-11.bpo-39026.sUnYWn.rst M Include/Python.h M Include/cpython/pystate.h diff --git a/Include/Python.h b/Include/Python.h index 6ee52e7492837..7f7ed5981c5c7 100644 --- a/Include/Python.h +++ b/Include/Python.h @@ -116,6 +116,7 @@ #include "sliceobject.h" #include "cellobject.h" #include "iterobject.h" +#include "cpython/initconfig.h" #include "genobject.h" #include "descrobject.h" #include "genericaliasobject.h" @@ -127,8 +128,6 @@ #include "codecs.h" #include "pyerrors.h" - -#include "cpython/initconfig.h" #include "pythread.h" #include "pystate.h" #include "context.h" diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index f292da1d3c6c5..0eb601fd7c55e 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -6,8 +6,6 @@ extern "C" { #endif -#include "cpython/initconfig.h" - PyAPI_FUNC(int) _PyInterpreterState_RequiresIDRef(PyInterpreterState *); PyAPI_FUNC(void) _PyInterpreterState_RequireIDRef(PyInterpreterState *, int); diff --git a/Misc/NEWS.d/next/C API/2021-11-09-15-42-11.bpo-39026.sUnYWn.rst b/Misc/NEWS.d/next/C API/2021-11-09-15-42-11.bpo-39026.sUnYWn.rst new file mode 100644 index 0000000000000..77a0119792152 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2021-11-09-15-42-11.bpo-39026.sUnYWn.rst @@ -0,0 +1,2 @@ +Fix Python.h to build C extensions with Xcode: remove a relative include +from ``Include/cpython/pystate.h``. From webhook-mailer at python.org Fri Nov 26 05:50:38 2021 From: webhook-mailer at python.org (vstinner) Date: Fri, 26 Nov 2021 10:50:38 -0000 Subject: [Python-checkins] bpo-45866: pegen strips directory of "generated from" header (GH-29777) Message-ID: https://github.com/python/cpython/commit/253b7a0a9fef1d72a4cb87b837885576e68e917c commit: 253b7a0a9fef1d72a4cb87b837885576e68e917c branch: main author: Victor Stinner committer: vstinner date: 2021-11-26T11:50:34+01:00 summary: bpo-45866: pegen strips directory of "generated from" header (GH-29777) "make regen-all" now produces the same output when run from a directory other than the source tree: when building Python out of the source tree. files: A Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst M Parser/parser.c M Tools/peg_generator/pegen/c_generator.py M Tools/peg_generator/pegen/grammar_parser.py M Tools/peg_generator/pegen/python_generator.py diff --git a/Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst b/Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst new file mode 100644 index 0000000000000..efa046d91e08e --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst @@ -0,0 +1,4 @@ +``make regen-all`` now produces the same output when run from a directory +other than the source tree: when building Python out of the source tree. +pegen now strips directory of the "generated by pygen from None: def generate(self, filename: str) -> None: self.collect_rules() - self.print(f"// @generated by pegen from {filename}") + basename = os.path.basename(filename) + self.print(f"// @generated by pegen from {basename}") header = self.grammar.metas.get("header", EXTENSION_PREFIX) if header: self.print(header.rstrip("\n")) diff --git a/Tools/peg_generator/pegen/grammar_parser.py b/Tools/peg_generator/pegen/grammar_parser.py index 6e9f7d3d11d29..bf31fe5326364 100644 --- a/Tools/peg_generator/pegen/grammar_parser.py +++ b/Tools/peg_generator/pegen/grammar_parser.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3.8 -# @generated by pegen from ./Tools/peg_generator/pegen/metagrammar.gram +# @generated by pegen from metagrammar.gram import ast import sys diff --git a/Tools/peg_generator/pegen/python_generator.py b/Tools/peg_generator/pegen/python_generator.py index 25a48bfab5d6c..5329d0ebe5e64 100644 --- a/Tools/peg_generator/pegen/python_generator.py +++ b/Tools/peg_generator/pegen/python_generator.py @@ -1,3 +1,4 @@ +import os.path import token from typing import IO, Any, Dict, Optional, Sequence, Set, Text, Tuple @@ -212,7 +213,8 @@ def generate(self, filename: str) -> None: self.collect_rules() header = self.grammar.metas.get("header", MODULE_PREFIX) if header is not None: - self.print(header.rstrip("\n").format(filename=filename)) + basename = os.path.basename(filename) + self.print(header.rstrip("\n").format(filename=basename)) subheader = self.grammar.metas.get("subheader", "") if subheader: self.print(subheader) From webhook-mailer at python.org Fri Nov 26 08:30:01 2021 From: webhook-mailer at python.org (tiran) Date: Fri, 26 Nov 2021 13:30:01 -0000 Subject: [Python-checkins] bpo-40280: clean and ignore .wasm files (GH-29794) Message-ID: https://github.com/python/cpython/commit/d224e769b83a6a027bec8e21ee62db2b96d5af8e commit: d224e769b83a6a027bec8e21ee62db2b96d5af8e branch: main author: Christian Heimes committer: tiran date: 2021-11-26T14:29:46+01:00 summary: bpo-40280: clean and ignore .wasm files (GH-29794) files: M .gitignore M Makefile.pre.in diff --git a/.gitignore b/.gitignore index 0831c58d36748..cfd3163cd1818 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ *.so.* *.dylib *.dll +*.wasm *.orig *.pyc *.pyd diff --git a/Makefile.pre.in b/Makefile.pre.in index be9f68d4e0285..75d3bce946f42 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -2284,6 +2284,7 @@ clean-retain-profile: pycremoval find . -name '*.[oa]' -exec rm -f {} ';' find . -name '*.s[ol]' -exec rm -f {} ';' find . -name '*.so.[0-9]*.[0-9]*' -exec rm -f {} ';' + find . -name '*.wasm' -exec rm -f {} ';' find . -name '*.lst' -exec rm -f {} ';' find build -name 'fficonfig.h' -exec rm -f {} ';' || true find build -name '*.py' -exec rm -f {} ';' || true From webhook-mailer at python.org Fri Nov 26 09:10:19 2021 From: webhook-mailer at python.org (corona10) Date: Fri, 26 Nov 2021 14:10:19 -0000 Subject: [Python-checkins] bpo-45760: Remove PyNumber_InMatrixMultiply (GH-29751) Message-ID: https://github.com/python/cpython/commit/db671b010cb4662011c6e6567a1f4fcd509102b8 commit: db671b010cb4662011c6e6567a1f4fcd509102b8 branch: main author: Dong-hee Na committer: corona10 date: 2021-11-26T23:10:10+09:00 summary: bpo-45760: Remove PyNumber_InMatrixMultiply (GH-29751) files: M Objects/abstract.c diff --git a/Objects/abstract.c b/Objects/abstract.c index 82599dd6eca23..5c533bf03292d 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -1248,21 +1248,10 @@ INPLACE_BINOP(PyNumber_InPlaceAnd, nb_inplace_and, nb_and, "&=") INPLACE_BINOP(PyNumber_InPlaceLshift, nb_inplace_lshift, nb_lshift, "<<=") INPLACE_BINOP(PyNumber_InPlaceRshift, nb_inplace_rshift, nb_rshift, ">>=") INPLACE_BINOP(PyNumber_InPlaceSubtract, nb_inplace_subtract, nb_subtract, "-=") -INPLACE_BINOP(PyNumber_InMatrixMultiply, nb_inplace_matrix_multiply, nb_matrix_multiply, "@=") - -PyObject * -PyNumber_InPlaceFloorDivide(PyObject *v, PyObject *w) -{ - return binary_iop(v, w, NB_SLOT(nb_inplace_floor_divide), - NB_SLOT(nb_floor_divide), "//="); -} - -PyObject * -PyNumber_InPlaceTrueDivide(PyObject *v, PyObject *w) -{ - return binary_iop(v, w, NB_SLOT(nb_inplace_true_divide), - NB_SLOT(nb_true_divide), "/="); -} +INPLACE_BINOP(PyNumber_InPlaceMatrixMultiply, nb_inplace_matrix_multiply, nb_matrix_multiply, "@=") +INPLACE_BINOP(PyNumber_InPlaceFloorDivide, nb_inplace_floor_divide, nb_floor_divide, "//=") +INPLACE_BINOP(PyNumber_InPlaceTrueDivide, nb_inplace_true_divide, nb_true_divide, "/=") +INPLACE_BINOP(PyNumber_InPlaceRemainder, nb_inplace_remainder, nb_remainder, "%=") PyObject * PyNumber_InPlaceAdd(PyObject *v, PyObject *w) @@ -1316,20 +1305,6 @@ PyNumber_InPlaceMultiply(PyObject *v, PyObject *w) return result; } -PyObject * -PyNumber_InPlaceMatrixMultiply(PyObject *v, PyObject *w) -{ - return binary_iop(v, w, NB_SLOT(nb_inplace_matrix_multiply), - NB_SLOT(nb_matrix_multiply), "@="); -} - -PyObject * -PyNumber_InPlaceRemainder(PyObject *v, PyObject *w) -{ - return binary_iop(v, w, NB_SLOT(nb_inplace_remainder), - NB_SLOT(nb_remainder), "%="); -} - PyObject * PyNumber_InPlacePower(PyObject *v, PyObject *w, PyObject *z) { From webhook-mailer at python.org Fri Nov 26 09:17:04 2021 From: webhook-mailer at python.org (tiran) Date: Fri, 26 Nov 2021 14:17:04 -0000 Subject: [Python-checkins] bpo-40280: Add configure check for socket shutdown (GH-29795) Message-ID: https://github.com/python/cpython/commit/8caceb7a474bf32cddfd25fba25b531ff65f4365 commit: 8caceb7a474bf32cddfd25fba25b531ff65f4365 branch: main author: Christian Heimes committer: tiran date: 2021-11-26T15:16:54+01:00 summary: bpo-40280: Add configure check for socket shutdown (GH-29795) files: A Misc/NEWS.d/next/Build/2021-11-26-14-09-04.bpo-40280.ZLpwQf.rst M Modules/socketmodule.c M PC/pyconfig.h M configure M configure.ac M pyconfig.h.in diff --git a/Misc/NEWS.d/next/Build/2021-11-26-14-09-04.bpo-40280.ZLpwQf.rst b/Misc/NEWS.d/next/Build/2021-11-26-14-09-04.bpo-40280.ZLpwQf.rst new file mode 100644 index 0000000000000..ce75febd25bd2 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-26-14-09-04.bpo-40280.ZLpwQf.rst @@ -0,0 +1,3 @@ +``configure`` now checks for socket ``shutdown`` function. The check makes +it possible to disable ``SYS_shutdown`` with ``ac_cv_func_shutdown=no`` in +CONFIG_SITE. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index ed1043c0c43a5..89e93c58187c9 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -4788,6 +4788,7 @@ Set operation mode, IV and length of associated data for an AF_ALG\n\ operation socket."); #endif +#ifdef HAVE_SHUTDOWN /* s.shutdown(how) method */ static PyObject * @@ -4812,6 +4813,7 @@ PyDoc_STRVAR(shutdown_doc, \n\ Shut down the reading side of the socket (flag == SHUT_RD), the writing side\n\ of the socket (flag == SHUT_WR), or both ends (flag == SHUT_RDWR)."); +#endif #if defined(MS_WINDOWS) && defined(SIO_RCVALL) static PyObject* @@ -4957,8 +4959,10 @@ static PyMethodDef sock_methods[] = { gettimeout_doc}, {"setsockopt", (PyCFunction)sock_setsockopt, METH_VARARGS, setsockopt_doc}, +#ifdef HAVE_SHUTDOWN {"shutdown", (PyCFunction)sock_shutdown, METH_O, shutdown_doc}, +#endif #ifdef CMSG_LEN {"recvmsg", (PyCFunction)sock_recvmsg, METH_VARARGS, recvmsg_doc}, diff --git a/PC/pyconfig.h b/PC/pyconfig.h index b3e73d4dabefe..5d8d9f3618454 100644 --- a/PC/pyconfig.h +++ b/PC/pyconfig.h @@ -517,6 +517,9 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ /* Define if you have siginterrupt. */ /* #undef HAVE_SIGINTERRUPT */ +/* Define to 1 if you have the `shutdown' function. */ +#define HAVE_SHUTDOWN 1 + /* Define if you have symlink. */ /* #undef HAVE_SYMLINK */ diff --git a/configure b/configure index 1aaa13abd6816..5f8b11c9415f7 100755 --- a/configure +++ b/configure @@ -13395,7 +13395,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \ setgid sethostname \ setlocale setregid setreuid setresuid setresgid setsid setpgid setpgrp setpriority setuid setvbuf \ sched_get_priority_max sched_setaffinity sched_setscheduler sched_setparam \ - sched_rr_get_interval \ + sched_rr_get_interval shutdown \ sigaction sigaltstack sigfillset siginterrupt sigpending sigrelse \ sigtimedwait sigwait sigwaitinfo snprintf splice strftime strlcpy strsignal symlinkat sync \ sysconf tcgetpgrp tcsetpgrp tempnam timegm times tmpfile tmpnam tmpnam_r \ diff --git a/configure.ac b/configure.ac index 7963f9ccaf80a..447a9c85099c4 100644 --- a/configure.ac +++ b/configure.ac @@ -3956,7 +3956,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \ setgid sethostname \ setlocale setregid setreuid setresuid setresgid setsid setpgid setpgrp setpriority setuid setvbuf \ sched_get_priority_max sched_setaffinity sched_setscheduler sched_setparam \ - sched_rr_get_interval \ + sched_rr_get_interval shutdown \ sigaction sigaltstack sigfillset siginterrupt sigpending sigrelse \ sigtimedwait sigwait sigwaitinfo snprintf splice strftime strlcpy strsignal symlinkat sync \ sysconf tcgetpgrp tcsetpgrp tempnam timegm times tmpfile tmpnam tmpnam_r \ diff --git a/pyconfig.h.in b/pyconfig.h.in index 842759fb213ae..b837b9ad2e2db 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -992,6 +992,9 @@ /* Define to 1 if you have the `shm_unlink' function. */ #undef HAVE_SHM_UNLINK +/* Define to 1 if you have the `shutdown' function. */ +#undef HAVE_SHUTDOWN + /* Define to 1 if you have the `sigaction' function. */ #undef HAVE_SIGACTION From webhook-mailer at python.org Fri Nov 26 09:58:18 2021 From: webhook-mailer at python.org (miss-islington) Date: Fri, 26 Nov 2021 14:58:18 -0000 Subject: [Python-checkins] bpo-44353: Correct docstring for `NewType` (GH-29785) Message-ID: https://github.com/python/cpython/commit/3f024e27c29a57dd4f805aa2431d713ed0fe57b2 commit: 3f024e27c29a57dd4f805aa2431d713ed0fe57b2 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-26T06:58:13-08:00 summary: bpo-44353: Correct docstring for `NewType` (GH-29785) The docstring for `typing.NewType` is no longer strictly accurate, now that `NewType` is a class, rather than a function (cherry picked from commit 93c65df83cef71a4bc77d71afecdec8744c4f73a) Co-authored-by: Alex Waygood files: M Lib/typing.py diff --git a/Lib/typing.py b/Lib/typing.py index 21caabb5d3e67..b743d400c0e5f 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -2427,7 +2427,7 @@ class NewType: """NewType creates simple unique types with almost zero runtime overhead. NewType(name, tp) is considered a subtype of tp by static type checkers. At runtime, NewType(name, tp) returns - a dummy function that simply returns its argument. Usage:: + a dummy callable that simply returns its argument. Usage:: UserId = NewType('UserId', int) From webhook-mailer at python.org Fri Nov 26 10:38:58 2021 From: webhook-mailer at python.org (vstinner) Date: Fri, 26 Nov 2021 15:38:58 -0000 Subject: [Python-checkins] bpo-45866: pegen strips directory of "generated from" header (GH-29777) (GH-29792) Message-ID: https://github.com/python/cpython/commit/b6defde2afe656db830d6fedf74ca5f6225f5928 commit: b6defde2afe656db830d6fedf74ca5f6225f5928 branch: 3.10 author: Victor Stinner committer: vstinner date: 2021-11-26T16:38:50+01:00 summary: bpo-45866: pegen strips directory of "generated from" header (GH-29777) (GH-29792) "make regen-all" now produces the same output when run from a directory other than the source tree: when building Python out of the source tree. (cherry picked from commit 253b7a0a9fef1d72a4cb87b837885576e68e917c) files: A Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst M Parser/parser.c M Tools/peg_generator/pegen/c_generator.py M Tools/peg_generator/pegen/grammar_parser.py M Tools/peg_generator/pegen/python_generator.py diff --git a/Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst b/Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst new file mode 100644 index 0000000000000..efa046d91e08e --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst @@ -0,0 +1,4 @@ +``make regen-all`` now produces the same output when run from a directory +other than the source tree: when building Python out of the source tree. +pegen now strips directory of the "generated by pygen from None: def generate(self, filename: str) -> None: self.collect_todo() - self.print(f"// @generated by pegen.py from {filename}") + basename = os.path.basename(filename) + self.print(f"// @generated by pegen.py from {basename}") header = self.grammar.metas.get("header", EXTENSION_PREFIX) if header: self.print(header.rstrip("\n")) diff --git a/Tools/peg_generator/pegen/grammar_parser.py b/Tools/peg_generator/pegen/grammar_parser.py index 70fa5b001b5c1..892df5cf8ccca 100644 --- a/Tools/peg_generator/pegen/grammar_parser.py +++ b/Tools/peg_generator/pegen/grammar_parser.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3.8 -# @generated by pegen from ./Tools/peg_generator/pegen/metagrammar.gram +# @generated by pegen from metagrammar.gram import ast from typing import Optional, Any diff --git a/Tools/peg_generator/pegen/python_generator.py b/Tools/peg_generator/pegen/python_generator.py index b500e3e204a5d..4b270aa1e9741 100644 --- a/Tools/peg_generator/pegen/python_generator.py +++ b/Tools/peg_generator/pegen/python_generator.py @@ -1,3 +1,4 @@ +import os.path import token from typing import Any, Dict, Optional, IO, Text, Tuple @@ -139,7 +140,8 @@ def __init__( def generate(self, filename: str) -> None: header = self.grammar.metas.get("header", MODULE_PREFIX) if header is not None: - self.print(header.rstrip("\n").format(filename=filename)) + basename = os.path.basename(filename) + self.print(header.rstrip("\n").format(filename=basename)) subheader = self.grammar.metas.get("subheader", "") if subheader: self.print(subheader.format(filename=filename)) From webhook-mailer at python.org Fri Nov 26 11:05:25 2021 From: webhook-mailer at python.org (tiran) Date: Fri, 26 Nov 2021 16:05:25 -0000 Subject: [Python-checkins] bpo-45886: Fix OOT build when srcdir has frozen module headers (GH-29793) Message-ID: https://github.com/python/cpython/commit/765b2a3ad2e8abf9a06d5e9b3802b575ec115d76 commit: 765b2a3ad2e8abf9a06d5e9b3802b575ec115d76 branch: main author: Christian Heimes committer: tiran date: 2021-11-26T17:05:16+01:00 summary: bpo-45886: Fix OOT build when srcdir has frozen module headers (GH-29793) The presence of frozen module headers in srcdir interfers with OOT build. Make considers headers in srcdir up to date, but later builds do not use VPATH to locate files. make clean now removes the headers, too. Also remove stale ``_bootstrap_python`` from .gitignore. files: M .gitignore M Makefile.pre.in diff --git a/.gitignore b/.gitignore index cfd3163cd1818..0363244bdaf63 100644 --- a/.gitignore +++ b/.gitignore @@ -60,7 +60,6 @@ Lib/distutils/command/*.pdb Lib/lib2to3/*.pickle Lib/test/data/* !Lib/test/data/README -/_bootstrap_python /Makefile /Makefile.pre Mac/Makefile diff --git a/Makefile.pre.in b/Makefile.pre.in index 75d3bce946f42..fc8ab99babcdb 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -587,7 +587,10 @@ build_all: check-clean-src $(BUILDPYTHON) oldsharedmods sharedmods gdbhooks \ # Check that the source is clean when building out of source. check-clean-src: - @if test -n "$(VPATH)" -a -f "$(srcdir)/Programs/python.o"; then \ + @if test -n "$(VPATH)" -a \( \ + -f "$(srcdir)/Programs/python.o" \ + -o -f "$(srcdir)\Python/frozen_modules/importlib._bootstrap.h" \ + \); then \ echo "Error: The source directory ($(srcdir)) is not clean" ; \ echo "Building Python out of the source tree (in $(abs_builddir)) requires a clean source tree ($(abs_srcdir))" ; \ echo "Try to run: make -C \"$(srcdir)\" clean" ; \ @@ -2293,6 +2296,8 @@ clean-retain-profile: pycremoval -rm -f Lib/lib2to3/*Grammar*.pickle -rm -f Programs/_testembed Programs/_freeze_module -rm -f Python/deepfreeze/*.[co] + -rm -f Python/frozen_modules/*.h + -rm -f Python/frozen_modules/MANIFEST -find build -type f -a ! -name '*.gc??' -exec rm -f {} ';' -rm -f Include/pydtrace_probes.h -rm -f profile-gen-stamp @@ -2330,8 +2335,6 @@ distclean: clobber Modules/Setup.stdlib Modules/ld_so_aix Modules/python.exp Misc/python.pc \ Misc/python-embed.pc Misc/python-config.sh -rm -f python*-gdb.py - -rm -f Python/frozen_modules/*.h - -rm -f Python/frozen_modules/MANIFEST # Issue #28258: set LC_ALL to avoid issues with Estonian locale. # Expansion is performed here by shell (spawned by make) itself before # arguments are passed to find. So LC_ALL=C must be set as a separate From webhook-mailer at python.org Fri Nov 26 11:23:51 2021 From: webhook-mailer at python.org (vstinner) Date: Fri, 26 Nov 2021 16:23:51 -0000 Subject: [Python-checkins] bpo-45866: pegen strips directory of "generated from" header (GH-29777) (GH-29792) (GH-29797) Message-ID: https://github.com/python/cpython/commit/93a540d74c654819ad04d72fcdcf827d0e259999 commit: 93a540d74c654819ad04d72fcdcf827d0e259999 branch: 3.9 author: Victor Stinner committer: vstinner date: 2021-11-26T17:23:41+01:00 summary: bpo-45866: pegen strips directory of "generated from" header (GH-29777) (GH-29792) (GH-29797) "make regen-all" now produces the same output when run from a directory other than the source tree: when building Python out of the source tree. (cherry picked from commit 253b7a0a9fef1d72a4cb87b837885576e68e917c) (cherry picked from commit b6defde2afe656db830d6fedf74ca5f6225f5928) files: A Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst M Parser/pegen/parse.c M Tools/peg_generator/pegen/c_generator.py M Tools/peg_generator/pegen/grammar_parser.py M Tools/peg_generator/pegen/python_generator.py diff --git a/Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst b/Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst new file mode 100644 index 0000000000000..efa046d91e08e --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst @@ -0,0 +1,4 @@ +``make regen-all`` now produces the same output when run from a directory +other than the source tree: when building Python out of the source tree. +pegen now strips directory of the "generated by pygen from None: def generate(self, filename: str) -> None: self.collect_todo() - self.print(f"// @generated by pegen.py from {filename}") + basename = os.path.basename(filename) + self.print(f"// @generated by pegen.py from {basename}") header = self.grammar.metas.get("header", EXTENSION_PREFIX) if header: self.print(header.rstrip("\n")) diff --git a/Tools/peg_generator/pegen/grammar_parser.py b/Tools/peg_generator/pegen/grammar_parser.py index c784cfdf3b266..50a2153d15e5c 100644 --- a/Tools/peg_generator/pegen/grammar_parser.py +++ b/Tools/peg_generator/pegen/grammar_parser.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3.8 -# @generated by pegen from ./Tools/peg_generator/pegen/metagrammar.gram +# @generated by pegen from metagrammar.gram import ast import sys diff --git a/Tools/peg_generator/pegen/python_generator.py b/Tools/peg_generator/pegen/python_generator.py index b786de7fee5b4..530cf111023c7 100644 --- a/Tools/peg_generator/pegen/python_generator.py +++ b/Tools/peg_generator/pegen/python_generator.py @@ -1,3 +1,4 @@ +import os.path import token from typing import Any, Dict, Optional, IO, Text, Tuple @@ -142,7 +143,8 @@ def __init__( def generate(self, filename: str) -> None: header = self.grammar.metas.get("header", MODULE_PREFIX) if header is not None: - self.print(header.rstrip("\n").format(filename=filename)) + basename = os.path.basename(filename) + self.print(header.rstrip("\n").format(filename=basename)) subheader = self.grammar.metas.get("subheader", "") if subheader: self.print(subheader.format(filename=filename)) From webhook-mailer at python.org Fri Nov 26 11:51:23 2021 From: webhook-mailer at python.org (gvanrossum) Date: Fri, 26 Nov 2021 16:51:23 -0000 Subject: [Python-checkins] bpo-45019: Cleanup module freezing and deepfreeze (#29772) Message-ID: https://github.com/python/cpython/commit/b0b10e146b1cbf9c5dfa44af116a2eeb0f210e8b commit: b0b10e146b1cbf9c5dfa44af116a2eeb0f210e8b branch: main author: Kumar Aditya committer: gvanrossum date: 2021-11-26T08:50:54-08:00 summary: bpo-45019: Cleanup module freezing and deepfreeze (#29772) files: M Tools/scripts/freeze_modules.py diff --git a/Tools/scripts/freeze_modules.py b/Tools/scripts/freeze_modules.py index 74b2c4857d088..7496b6c868407 100644 --- a/Tools/scripts/freeze_modules.py +++ b/Tools/scripts/freeze_modules.py @@ -8,12 +8,9 @@ import os import ntpath import posixpath -import platform -import subprocess import sys -import time -from update_file import updating_file_with_tmpfile, update_file_with_tmpfile +from update_file import updating_file_with_tmpfile ROOT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) @@ -21,9 +18,10 @@ FROZEN_ONLY = os.path.join(ROOT_DIR, 'Tools', 'freeze', 'flag.py') STDLIB_DIR = os.path.join(ROOT_DIR, 'Lib') -# If MODULES_DIR is changed then the .gitattributes and .gitignore files -# need to be updated. -MODULES_DIR = os.path.join(ROOT_DIR, 'Python', 'frozen_modules') +# If FROZEN_MODULES_DIR or DEEPFROZEN_MODULES_DIR is changed then the +# .gitattributes and .gitignore files needs to be updated. +FROZEN_MODULES_DIR = os.path.join(ROOT_DIR, 'Python', 'frozen_modules') +DEEPFROZEN_MODULES_DIR = os.path.join(ROOT_DIR, 'Python', 'deepfreeze') FROZEN_FILE = os.path.join(ROOT_DIR, 'Python', 'frozen.c') MAKEFILE = os.path.join(ROOT_DIR, 'Makefile.pre.in') @@ -111,16 +109,16 @@ def relpath_for_posix_display(path, base): ####################################### # specs -def parse_frozen_specs(sectionalspecs=FROZEN, destdir=None): +def parse_frozen_specs(): seen = {} - for section, specs in sectionalspecs: + for section, specs in FROZEN: parsed = _parse_specs(specs, section, seen) for item in parsed: frozenid, pyfile, modname, ispkg, section = item try: source = seen[frozenid] except KeyError: - source = FrozenSource.from_id(frozenid, pyfile, destdir) + source = FrozenSource.from_id(frozenid, pyfile) seen[frozenid] = source else: assert not pyfile or pyfile == source.pyfile, item @@ -225,15 +223,16 @@ def iter_subs(): ####################################### # frozen source files -class FrozenSource(namedtuple('FrozenSource', 'id pyfile frozenfile')): +class FrozenSource(namedtuple('FrozenSource', 'id pyfile frozenfile deepfreezefile')): @classmethod - def from_id(cls, frozenid, pyfile=None, destdir=MODULES_DIR): + def from_id(cls, frozenid, pyfile=None): if not pyfile: pyfile = os.path.join(STDLIB_DIR, *frozenid.split('.')) + '.py' #assert os.path.exists(pyfile), (frozenid, pyfile) - frozenfile = resolve_frozen_file(frozenid, destdir) - return cls(frozenid, pyfile, frozenfile) + frozenfile = resolve_frozen_file(frozenid, FROZEN_MODULES_DIR) + deepfreezefile = resolve_frozen_file(frozenid, DEEPFROZEN_MODULES_DIR) + return cls(frozenid, pyfile, frozenfile, deepfreezefile) @property def frozenid(self): @@ -261,7 +260,7 @@ def ispkg(self): return os.path.basename(self.pyfile) == '__init__.py' -def resolve_frozen_file(frozenid, destdir=MODULES_DIR): +def resolve_frozen_file(frozenid, destdir): """Return the filename corresponding to the given frozen ID. For stdlib modules the ID will always be the full name @@ -570,41 +569,30 @@ def regen_makefile(modules): deepfreezefiles = [] rules = [''] deepfreezerules = [''] - - # TODO: Merge the two loops for src in _iter_sources(modules): - header = relpath_for_posix_display(src.frozenfile, ROOT_DIR) - relfile = header.replace('\\', '/') - _pyfile = relpath_for_posix_display(src.pyfile, ROOT_DIR) - - # TODO: This is a bit hackish - xfile = relfile.replace("/frozen_modules/", "/deepfreeze/") - cfile = xfile[:-2] + ".c" - ofile = xfile[:-2] + ".o" + frozen_header = relpath_for_posix_display(src.frozenfile, ROOT_DIR) + deepfreeze_header = relpath_for_posix_display(src.deepfreezefile, ROOT_DIR) + frozenfiles.append(f'\t\t{frozen_header} \\') + cfile = deepfreeze_header[:-2] + ".c" + ofile = deepfreeze_header[:-2] + ".o" deepfreezefiles.append(f"\t\t{ofile} \\") - # Also add a deepfreeze rule. - deepfreezerules.append(f'{cfile}: {header} $(DEEPFREEZE_DEPS)') - deepfreezerules.append( - f"\t$(PYTHON_FOR_REGEN) " - f"$(srcdir)/Tools/scripts/deepfreeze.py " - f"{header} -m {src.frozenid} -o {cfile}") - deepfreezerules.append('') - - for src in _iter_sources(modules): - header = relpath_for_posix_display(src.frozenfile, ROOT_DIR) - frozenfiles.append(f'\t\t{header} \\') - pyfile = relpath_for_posix_display(src.pyfile, ROOT_DIR) pyfiles.append(f'\t\t{pyfile} \\') freeze = (f'$(FREEZE_MODULE) {src.frozenid} ' - f'$(srcdir)/{pyfile} {header}') + f'$(srcdir)/{pyfile} {frozen_header}') rules.extend([ - f'{header}: $(FREEZE_MODULE) {pyfile}', + f'{frozen_header}: $(FREEZE_MODULE) {pyfile}', f'\t{freeze}', '', ]) + deepfreezerules.append(f'{cfile}: {frozen_header} $(DEEPFREEZE_DEPS)') + deepfreezerules.append( + f"\t$(PYTHON_FOR_REGEN) " + f"$(srcdir)/Tools/scripts/deepfreeze.py " + f"{frozen_header} -m {src.frozenid} -o {cfile}") + deepfreezerules.append('') pyfiles[-1] = pyfiles[-1].rstrip(" \\") frozenfiles[-1] = frozenfiles[-1].rstrip(" \\") deepfreezefiles[-1] = deepfreezefiles[-1].rstrip(" \\") @@ -715,7 +703,7 @@ def regen_pcbuild(modules): def main(): # Expand the raw specs, preserving order. - modules = list(parse_frozen_specs(destdir=MODULES_DIR)) + modules = list(parse_frozen_specs()) # Regen build-related files. regen_makefile(modules) From webhook-mailer at python.org Fri Nov 26 13:36:59 2021 From: webhook-mailer at python.org (tiran) Date: Fri, 26 Nov 2021 18:36:59 -0000 Subject: [Python-checkins] bpo-40280: Move hard-coded feature checks to configure (GH-29789) Message-ID: https://github.com/python/cpython/commit/4ebde73b8e416eeb1fd5d2ca3283f7ddb534c5b1 commit: 4ebde73b8e416eeb1fd5d2ca3283f7ddb534c5b1 branch: main author: Christian Heimes committer: tiran date: 2021-11-26T19:36:48+01:00 summary: bpo-40280: Move hard-coded feature checks to configure (GH-29789) Co-authored-by: Erlend Egeberg Aasland files: A Misc/NEWS.d/next/Build/2021-11-26-09-10-19.bpo-40280.xmiMJl.rst M Modules/posixmodule.c M configure M configure.ac M pyconfig.h.in diff --git a/Misc/NEWS.d/next/Build/2021-11-26-09-10-19.bpo-40280.xmiMJl.rst b/Misc/NEWS.d/next/Build/2021-11-26-09-10-19.bpo-40280.xmiMJl.rst new file mode 100644 index 0000000000000..5d1be17c682b1 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-26-09-10-19.bpo-40280.xmiMJl.rst @@ -0,0 +1,3 @@ +``configure`` now checks for functions ``fork1, getegid, +geteuid, getgid, getppid, getuid, opendir, pipe, system, wait, +ttyname``. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index c29d9fc2a7087..a89cff7295163 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -320,26 +320,6 @@ corresponding Unix manual entries for more information on calls."); # define HAVE_CWAIT 1 # define HAVE_FSYNC 1 # define fsync _commit -# else - /* Unix functions that the configure script doesn't check for */ -# ifndef __VXWORKS__ -# define HAVE_EXECV 1 -# define HAVE_FORK 1 -# if defined(__USLC__) && defined(__SCO_VERSION__) /* SCO UDK Compiler */ -# define HAVE_FORK1 1 -# endif -# endif -# define HAVE_GETEGID 1 -# define HAVE_GETEUID 1 -# define HAVE_GETGID 1 -# define HAVE_GETPPID 1 -# define HAVE_GETUID 1 -# define HAVE_KILL 1 -# define HAVE_OPENDIR 1 -# define HAVE_PIPE 1 -# define HAVE_SYSTEM 1 -# define HAVE_WAIT 1 -# define HAVE_TTYNAME 1 # endif /* _MSC_VER */ #endif /* ! __WATCOMC__ || __QNX__ */ diff --git a/configure b/configure index 5f8b11c9415f7..1c398929c962d 100755 --- a/configure +++ b/configure @@ -13376,31 +13376,32 @@ $as_echo "$MACHDEP_OBJS" >&6; } fi # checks for library functions -for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \ - clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \ - explicit_memset faccessat fchmod fchmodat fchown fchownat \ - fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \ - futimens futimes gai_strerror getentropy \ - getgrgid getgrgid_r getgrnam_r \ - getgrouplist getgroups getlogin getloadavg getpeername getpgid getpid \ - getpriority getresuid getresgid getpwent getpwnam_r getpwuid_r getspnam getspent getsid getwd \ - if_nameindex \ - initgroups kill killpg lchown lockf linkat lstat lutimes mmap \ - memrchr mbrtowc mkdirat mkfifo \ - madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \ - posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \ - pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \ - readlink readlinkat readv realpath renameat \ - sem_open sem_timedwait sem_clockwait sem_getvalue sem_unlink sendfile setegid seteuid \ - setgid sethostname \ - setlocale setregid setreuid setresuid setresgid setsid setpgid setpgrp setpriority setuid setvbuf \ - sched_get_priority_max sched_setaffinity sched_setscheduler sched_setparam \ - sched_rr_get_interval shutdown \ - sigaction sigaltstack sigfillset siginterrupt sigpending sigrelse \ - sigtimedwait sigwait sigwaitinfo snprintf splice strftime strlcpy strsignal symlinkat sync \ - sysconf tcgetpgrp tcsetpgrp tempnam timegm times tmpfile tmpnam tmpnam_r \ - truncate uname unlinkat utimensat utimes vfork waitid waitpid wait3 wait4 \ - wcscoll wcsftime wcsxfrm wmemcmp writev _getpty rtpSpawn +for ac_func in \ + accept4 alarm bind_textdomain_codeset chown clock close_range confstr \ + copy_file_range ctermid dup3 execv explicit_bzero explicit_memset \ + faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \ + fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \ + gai_strerror getegid getentropy geteuid getgid getgrgid getgrgid_r \ + getgrnam_r getgrouplist getgroups getitimer getloadavg getlogin \ + getpeername getpgid getpid getppid getpriority _getpty \ + getpwent getpwnam_r getpwuid_r getresgid getresuid getsid getspent \ + getspnam getuid getwd if_nameindex initgroups kill killpg lchown linkat \ + lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \ + mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \ + pipe2 plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \ + pread preadv preadv2 pthread_condattr_setclock pthread_init pthread_kill \ + pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \ + rtpSpawn sched_get_priority_max sched_rr_get_interval sched_setaffinity \ + sched_setparam sched_setscheduler sem_clockwait sem_getvalue sem_open \ + sem_timedwait sem_unlink sendfile setegid seteuid setgid sethostname \ + setitimer setlocale setpgid setpgrp setpriority setregid setresgid \ + setresuid setreuid setsid setuid setvbuf shutdown sigaction sigaltstack \ + sigfillset siginterrupt sigpending sigrelse sigtimedwait sigwait \ + sigwaitinfo snprintf splice strftime strlcpy strsignal symlinkat sync \ + sysconf system tcgetpgrp tcsetpgrp tempnam timegm times tmpfile \ + tmpnam tmpnam_r truncate ttyname uname unlinkat utimensat utimes vfork \ + wait wait3 wait4 waitid waitpid wcscoll wcsftime wcsxfrm wmemcmp writev \ + do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" diff --git a/configure.ac b/configure.ac index 447a9c85099c4..e96d88fb8c811 100644 --- a/configure.ac +++ b/configure.ac @@ -3937,31 +3937,32 @@ else fi # checks for library functions -AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \ - clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \ - explicit_memset faccessat fchmod fchmodat fchown fchownat \ - fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \ - futimens futimes gai_strerror getentropy \ - getgrgid getgrgid_r getgrnam_r \ - getgrouplist getgroups getlogin getloadavg getpeername getpgid getpid \ - getpriority getresuid getresgid getpwent getpwnam_r getpwuid_r getspnam getspent getsid getwd \ - if_nameindex \ - initgroups kill killpg lchown lockf linkat lstat lutimes mmap \ - memrchr mbrtowc mkdirat mkfifo \ - madvise mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \ - posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \ - pthread_condattr_setclock pthread_init pthread_kill pwrite pwritev pwritev2 \ - readlink readlinkat readv realpath renameat \ - sem_open sem_timedwait sem_clockwait sem_getvalue sem_unlink sendfile setegid seteuid \ - setgid sethostname \ - setlocale setregid setreuid setresuid setresgid setsid setpgid setpgrp setpriority setuid setvbuf \ - sched_get_priority_max sched_setaffinity sched_setscheduler sched_setparam \ - sched_rr_get_interval shutdown \ - sigaction sigaltstack sigfillset siginterrupt sigpending sigrelse \ - sigtimedwait sigwait sigwaitinfo snprintf splice strftime strlcpy strsignal symlinkat sync \ - sysconf tcgetpgrp tcsetpgrp tempnam timegm times tmpfile tmpnam tmpnam_r \ - truncate uname unlinkat utimensat utimes vfork waitid waitpid wait3 wait4 \ - wcscoll wcsftime wcsxfrm wmemcmp writev _getpty rtpSpawn) +AC_CHECK_FUNCS([ \ + accept4 alarm bind_textdomain_codeset chown clock close_range confstr \ + copy_file_range ctermid dup3 execv explicit_bzero explicit_memset \ + faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \ + fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \ + gai_strerror getegid getentropy geteuid getgid getgrgid getgrgid_r \ + getgrnam_r getgrouplist getgroups getitimer getloadavg getlogin \ + getpeername getpgid getpid getppid getpriority _getpty \ + getpwent getpwnam_r getpwuid_r getresgid getresuid getsid getspent \ + getspnam getuid getwd if_nameindex initgroups kill killpg lchown linkat \ + lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \ + mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \ + pipe2 plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \ + pread preadv preadv2 pthread_condattr_setclock pthread_init pthread_kill \ + pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \ + rtpSpawn sched_get_priority_max sched_rr_get_interval sched_setaffinity \ + sched_setparam sched_setscheduler sem_clockwait sem_getvalue sem_open \ + sem_timedwait sem_unlink sendfile setegid seteuid setgid sethostname \ + setitimer setlocale setpgid setpgrp setpriority setregid setresgid \ + setresuid setreuid setsid setuid setvbuf shutdown sigaction sigaltstack \ + sigfillset siginterrupt sigpending sigrelse sigtimedwait sigwait \ + sigwaitinfo snprintf splice strftime strlcpy strsignal symlinkat sync \ + sysconf system tcgetpgrp tcsetpgrp tempnam timegm times tmpfile \ + tmpnam tmpnam_r truncate ttyname uname unlinkat utimensat utimes vfork \ + wait wait3 wait4 waitid waitpid wcscoll wcsftime wcsxfrm wmemcmp writev \ +]) # Force lchmod off for Linux. Linux disallows changing the mode of symbolic # links. Some libc implementations have a stub lchmod implementation that always diff --git a/pyconfig.h.in b/pyconfig.h.in index b837b9ad2e2db..27bed56084684 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -362,6 +362,9 @@ /* Define to 1 if you have the `fork' function. */ #undef HAVE_FORK +/* Define to 1 if you have the `fork1' function. */ +#undef HAVE_FORK1 + /* Define to 1 if you have the `forkpty' function. */ #undef HAVE_FORKPTY @@ -435,9 +438,18 @@ /* Define this if you have flockfile(), getc_unlocked(), and funlockfile() */ #undef HAVE_GETC_UNLOCKED +/* Define to 1 if you have the `getegid' function. */ +#undef HAVE_GETEGID + /* Define to 1 if you have the `getentropy' function. */ #undef HAVE_GETENTROPY +/* Define to 1 if you have the `geteuid' function. */ +#undef HAVE_GETEUID + +/* Define to 1 if you have the `getgid' function. */ +#undef HAVE_GETGID + /* Define to 1 if you have the `getgrgid' function. */ #undef HAVE_GETGRGID @@ -495,6 +507,9 @@ /* Define to 1 if you have the `getpid' function. */ #undef HAVE_GETPID +/* Define to 1 if you have the `getppid' function. */ +#undef HAVE_GETPPID + /* Define to 1 if you have the `getpriority' function. */ #undef HAVE_GETPRIORITY @@ -528,6 +543,9 @@ /* Define to 1 if you have the `getspnam' function. */ #undef HAVE_GETSPNAM +/* Define to 1 if you have the `getuid' function. */ +#undef HAVE_GETUID + /* Define to 1 if you have the `getwd' function. */ #undef HAVE_GETWD @@ -767,6 +785,9 @@ /* Define to 1 if you have the `openat' function. */ #undef HAVE_OPENAT +/* Define to 1 if you have the `opendir' function. */ +#undef HAVE_OPENDIR + /* Define to 1 if you have the `openpty' function. */ #undef HAVE_OPENPTY @@ -776,6 +797,9 @@ /* Define to 1 if you have the `pause' function. */ #undef HAVE_PAUSE +/* Define to 1 if you have the `pipe' function. */ +#undef HAVE_PIPE + /* Define to 1 if you have the `pipe2' function. */ #undef HAVE_PIPE2 @@ -1137,6 +1161,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYSLOG_H +/* Define to 1 if you have the `system' function. */ +#undef HAVE_SYSTEM + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_AUDIOIO_H @@ -1296,6 +1323,9 @@ /* Define to 1 if you have the `truncate' function. */ #undef HAVE_TRUNCATE +/* Define to 1 if you have the `ttyname' function. */ +#undef HAVE_TTYNAME + /* Define to 1 if you don't have `tm_zone' but do have the external array `tzname'. */ #undef HAVE_TZNAME @@ -1347,6 +1377,9 @@ /* Define to 1 if you have the `vfork' function. */ #undef HAVE_VFORK +/* Define to 1 if you have the `wait' function. */ +#undef HAVE_WAIT + /* Define to 1 if you have the `wait3' function. */ #undef HAVE_WAIT3 From webhook-mailer at python.org Fri Nov 26 16:56:33 2021 From: webhook-mailer at python.org (vstinner) Date: Fri, 26 Nov 2021 21:56:33 -0000 Subject: [Python-checkins] bpo-45866: Fix typo in the NEWS entry (GH-29798) Message-ID: https://github.com/python/cpython/commit/9a7611a7c4da6406383f8ffcea272ded6f890f1e commit: 9a7611a7c4da6406383f8ffcea272ded6f890f1e branch: main author: Victor Stinner committer: vstinner date: 2021-11-26T22:56:25+01:00 summary: bpo-45866: Fix typo in the NEWS entry (GH-29798) files: M Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst diff --git a/Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst b/Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst index efa046d91e08e..e87b93932ffa1 100644 --- a/Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst +++ b/Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst @@ -1,4 +1,4 @@ ``make regen-all`` now produces the same output when run from a directory other than the source tree: when building Python out of the source tree. -pegen now strips directory of the "generated by pygen from " header Patch by Victor Stinner. From webhook-mailer at python.org Fri Nov 26 17:10:17 2021 From: webhook-mailer at python.org (gvanrossum) Date: Fri, 26 Nov 2021 22:10:17 -0000 Subject: [Python-checkins] Fix markup buglet in Doc/howto/annotations.rst (#29802) Message-ID: https://github.com/python/cpython/commit/94daf39b2f7e9b50e7ae7a16caeef804f8e37ae3 commit: 94daf39b2f7e9b50e7ae7a16caeef804f8e37ae3 branch: main author: Guido van Rossum committer: gvanrossum date: 2021-11-26T14:10:01-08:00 summary: Fix markup buglet in Doc/howto/annotations.rst (#29802) files: M Doc/howto/annotations.rst diff --git a/Doc/howto/annotations.rst b/Doc/howto/annotations.rst index 3e61103e99c9a..2bc2f2d4c839e 100644 --- a/Doc/howto/annotations.rst +++ b/Doc/howto/annotations.rst @@ -156,7 +156,7 @@ Manually Un-Stringizing Stringized Annotations require annotating with string values that specifically *can't* be evaluated. For example: - * :pep:`604` union types using `|`, before support for this + * :pep:`604` union types using ``|``, before support for this was added to Python 3.10. * Definitions that aren't needed at runtime, only imported when :const:`typing.TYPE_CHECKING` is true. From webhook-mailer at python.org Fri Nov 26 17:19:19 2021 From: webhook-mailer at python.org (miss-islington) Date: Fri, 26 Nov 2021 22:19:19 -0000 Subject: [Python-checkins] bpo-45866: Fix typo in the NEWS entry (GH-29798) Message-ID: https://github.com/python/cpython/commit/fc16ea9c8b8769af8a4c0c16fed7eba2e8bf4019 commit: fc16ea9c8b8769af8a4c0c16fed7eba2e8bf4019 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-26T14:18:54-08:00 summary: bpo-45866: Fix typo in the NEWS entry (GH-29798) (cherry picked from commit 9a7611a7c4da6406383f8ffcea272ded6f890f1e) Co-authored-by: Victor Stinner files: M Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst diff --git a/Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst b/Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst index efa046d91e08e..e87b93932ffa1 100644 --- a/Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst +++ b/Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst @@ -1,4 +1,4 @@ ``make regen-all`` now produces the same output when run from a directory other than the source tree: when building Python out of the source tree. -pegen now strips directory of the "generated by pygen from " header Patch by Victor Stinner. From webhook-mailer at python.org Fri Nov 26 17:20:25 2021 From: webhook-mailer at python.org (miss-islington) Date: Fri, 26 Nov 2021 22:20:25 -0000 Subject: [Python-checkins] bpo-45866: Fix typo in the NEWS entry (GH-29798) Message-ID: https://github.com/python/cpython/commit/b3f14dacfea54332e2ddde792142d818b3554dbc commit: b3f14dacfea54332e2ddde792142d818b3554dbc branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-26T14:20:14-08:00 summary: bpo-45866: Fix typo in the NEWS entry (GH-29798) (cherry picked from commit 9a7611a7c4da6406383f8ffcea272ded6f890f1e) Co-authored-by: Victor Stinner files: M Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst diff --git a/Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst b/Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst index efa046d91e08e..e87b93932ffa1 100644 --- a/Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst +++ b/Misc/NEWS.d/next/Build/2021-11-25-13-53-36.bpo-45866.ZH1W8N.rst @@ -1,4 +1,4 @@ ``make regen-all`` now produces the same output when run from a directory other than the source tree: when building Python out of the source tree. -pegen now strips directory of the "generated by pygen from " header Patch by Victor Stinner. From webhook-mailer at python.org Fri Nov 26 18:08:29 2021 From: webhook-mailer at python.org (zooba) Date: Fri, 26 Nov 2021 23:08:29 -0000 Subject: [Python-checkins] bpo-45901: Fixes argument passing when invoking .py files directly through the Store package (GH-29799) Message-ID: https://github.com/python/cpython/commit/4841e694ee1686f8c933ddfcb8c854915867ce17 commit: 4841e694ee1686f8c933ddfcb8c854915867ce17 branch: main author: Steve Dower committer: zooba date: 2021-11-26T23:08:20Z summary: bpo-45901: Fixes argument passing when invoking .py files directly through the Store package (GH-29799) files: A Misc/NEWS.d/next/Windows/2021-11-26-18-17-41.bpo-45901.c5IBqM.rst M PC/layout/support/appxmanifest.py diff --git a/Misc/NEWS.d/next/Windows/2021-11-26-18-17-41.bpo-45901.c5IBqM.rst b/Misc/NEWS.d/next/Windows/2021-11-26-18-17-41.bpo-45901.c5IBqM.rst new file mode 100644 index 0000000000000..2cb872bffe072 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2021-11-26-18-17-41.bpo-45901.c5IBqM.rst @@ -0,0 +1,4 @@ +When installed through the Microsoft Store and set as the default app for +:file:`*.py` files, command line arguments will now be passed to Python when +invoking a script without explicitly launching Python (that is, ``script.py +args`` rather than ``python script.py args``). diff --git a/PC/layout/support/appxmanifest.py b/PC/layout/support/appxmanifest.py index 747c97a00699d..15119b02a802a 100644 --- a/PC/layout/support/appxmanifest.py +++ b/PC/layout/support/appxmanifest.py @@ -430,7 +430,7 @@ def get_appxmanifest(ns): ["python", "python{}".format(VER_MAJOR), "python{}".format(VER_DOT)], PYTHON_VE_DATA, "console", - ("python.file", [".py"], '"%1"', "Python File", PY_PNG), + ("python.file", [".py"], '"%1" %*', "Python File", PY_PNG), ) add_application( @@ -441,7 +441,7 @@ def get_appxmanifest(ns): ["pythonw", "pythonw{}".format(VER_MAJOR), "pythonw{}".format(VER_DOT)], PYTHONW_VE_DATA, "windows", - ("python.windowedfile", [".pyw"], '"%1"', "Python File (no console)", PY_PNG), + ("python.windowedfile", [".pyw"], '"%1" %*', "Python File (no console)", PY_PNG), ) if ns.include_pip and ns.include_launchers: From webhook-mailer at python.org Fri Nov 26 18:30:48 2021 From: webhook-mailer at python.org (miss-islington) Date: Fri, 26 Nov 2021 23:30:48 -0000 Subject: [Python-checkins] bpo-45901: Fixes argument passing when invoking .py files directly through the Store package (GH-29799) Message-ID: https://github.com/python/cpython/commit/3dcbe01dc5236fb77d8c0133fb7e6bdd0754768a commit: 3dcbe01dc5236fb77d8c0133fb7e6bdd0754768a branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-26T15:30:39-08:00 summary: bpo-45901: Fixes argument passing when invoking .py files directly through the Store package (GH-29799) (cherry picked from commit 4841e694ee1686f8c933ddfcb8c854915867ce17) Co-authored-by: Steve Dower files: A Misc/NEWS.d/next/Windows/2021-11-26-18-17-41.bpo-45901.c5IBqM.rst M PC/layout/support/appxmanifest.py diff --git a/Misc/NEWS.d/next/Windows/2021-11-26-18-17-41.bpo-45901.c5IBqM.rst b/Misc/NEWS.d/next/Windows/2021-11-26-18-17-41.bpo-45901.c5IBqM.rst new file mode 100644 index 0000000000000..2cb872bffe072 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2021-11-26-18-17-41.bpo-45901.c5IBqM.rst @@ -0,0 +1,4 @@ +When installed through the Microsoft Store and set as the default app for +:file:`*.py` files, command line arguments will now be passed to Python when +invoking a script without explicitly launching Python (that is, ``script.py +args`` rather than ``python script.py args``). diff --git a/PC/layout/support/appxmanifest.py b/PC/layout/support/appxmanifest.py index 747c97a00699d..15119b02a802a 100644 --- a/PC/layout/support/appxmanifest.py +++ b/PC/layout/support/appxmanifest.py @@ -430,7 +430,7 @@ def get_appxmanifest(ns): ["python", "python{}".format(VER_MAJOR), "python{}".format(VER_DOT)], PYTHON_VE_DATA, "console", - ("python.file", [".py"], '"%1"', "Python File", PY_PNG), + ("python.file", [".py"], '"%1" %*', "Python File", PY_PNG), ) add_application( @@ -441,7 +441,7 @@ def get_appxmanifest(ns): ["pythonw", "pythonw{}".format(VER_MAJOR), "pythonw{}".format(VER_DOT)], PYTHONW_VE_DATA, "windows", - ("python.windowedfile", [".pyw"], '"%1"', "Python File (no console)", PY_PNG), + ("python.windowedfile", [".pyw"], '"%1" %*', "Python File (no console)", PY_PNG), ) if ns.include_pip and ns.include_launchers: From webhook-mailer at python.org Fri Nov 26 18:43:21 2021 From: webhook-mailer at python.org (zooba) Date: Fri, 26 Nov 2021 23:43:21 -0000 Subject: [Python-checkins] bpo-45901: Fixes argument passing when invoking .py files directly through the Store package (GH-29799) Message-ID: https://github.com/python/cpython/commit/133fb267f437f9bd568738d0e0e59e574fc82b02 commit: 133fb267f437f9bd568738d0e0e59e574fc82b02 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: zooba date: 2021-11-26T23:43:12Z summary: bpo-45901: Fixes argument passing when invoking .py files directly through the Store package (GH-29799) files: A Misc/NEWS.d/next/Windows/2021-11-26-18-17-41.bpo-45901.c5IBqM.rst M PC/layout/support/appxmanifest.py diff --git a/Misc/NEWS.d/next/Windows/2021-11-26-18-17-41.bpo-45901.c5IBqM.rst b/Misc/NEWS.d/next/Windows/2021-11-26-18-17-41.bpo-45901.c5IBqM.rst new file mode 100644 index 0000000000000..2cb872bffe072 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2021-11-26-18-17-41.bpo-45901.c5IBqM.rst @@ -0,0 +1,4 @@ +When installed through the Microsoft Store and set as the default app for +:file:`*.py` files, command line arguments will now be passed to Python when +invoking a script without explicitly launching Python (that is, ``script.py +args`` rather than ``python script.py args``). diff --git a/PC/layout/support/appxmanifest.py b/PC/layout/support/appxmanifest.py index 747c97a00699d..15119b02a802a 100644 --- a/PC/layout/support/appxmanifest.py +++ b/PC/layout/support/appxmanifest.py @@ -430,7 +430,7 @@ def get_appxmanifest(ns): ["python", "python{}".format(VER_MAJOR), "python{}".format(VER_DOT)], PYTHON_VE_DATA, "console", - ("python.file", [".py"], '"%1"', "Python File", PY_PNG), + ("python.file", [".py"], '"%1" %*', "Python File", PY_PNG), ) add_application( @@ -441,7 +441,7 @@ def get_appxmanifest(ns): ["pythonw", "pythonw{}".format(VER_MAJOR), "pythonw{}".format(VER_DOT)], PYTHONW_VE_DATA, "windows", - ("python.windowedfile", [".pyw"], '"%1"', "Python File (no console)", PY_PNG), + ("python.windowedfile", [".pyw"], '"%1" %*', "Python File (no console)", PY_PNG), ) if ns.include_pip and ns.include_launchers: From webhook-mailer at python.org Fri Nov 26 19:18:26 2021 From: webhook-mailer at python.org (gpshead) Date: Sat, 27 Nov 2021 00:18:26 -0000 Subject: [Python-checkins] bpo-41735: Fix thread lock in zlib.Decompress.flush() may go wrong (GH-29587) Message-ID: https://github.com/python/cpython/commit/7edb6270a78c695e4c2ae2432797dc18105374fc commit: 7edb6270a78c695e4c2ae2432797dc18105374fc branch: main author: Ma Lin committer: gpshead date: 2021-11-26T16:18:17-08:00 summary: bpo-41735: Fix thread lock in zlib.Decompress.flush() may go wrong (GH-29587) * Fix thread lock in zlib.Decompress.flush() may go wrong Getting `.unconsumed_tail` before acquiring the thread lock may mix up decompress state. files: A Misc/NEWS.d/next/Library/2021-11-16-18-13-49.bpo-41735.D72UY1.rst M Modules/zlibmodule.c diff --git a/Misc/NEWS.d/next/Library/2021-11-16-18-13-49.bpo-41735.D72UY1.rst b/Misc/NEWS.d/next/Library/2021-11-16-18-13-49.bpo-41735.D72UY1.rst new file mode 100644 index 0000000000000..101da0e9ce648 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-16-18-13-49.bpo-41735.D72UY1.rst @@ -0,0 +1 @@ +Fix thread lock in ``zlib.Decompress.flush()`` method before ``PyObject_GetBuffer``. diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c index 67bde701fa608..f9646568d7e01 100644 --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -1269,12 +1269,13 @@ zlib_Decompress_flush_impl(compobject *self, PyTypeObject *cls, return NULL; } + ENTER_ZLIB(self); + if (PyObject_GetBuffer(self->unconsumed_tail, &data, PyBUF_SIMPLE) == -1) { + LEAVE_ZLIB(self); return NULL; } - ENTER_ZLIB(self); - self->zst.next_in = data.buf; ibuflen = data.len; From webhook-mailer at python.org Fri Nov 26 19:21:31 2021 From: webhook-mailer at python.org (gpshead) Date: Sat, 27 Nov 2021 00:21:31 -0000 Subject: [Python-checkins] [3.9] bpo-41735: Fix thread lock in zlib.Decompress.flush() may go wrong (GH-29588) Message-ID: https://github.com/python/cpython/commit/86c1265cdc64030c8921e0da5fcae2ac64299c26 commit: 86c1265cdc64030c8921e0da5fcae2ac64299c26 branch: 3.9 author: Ma Lin committer: gpshead date: 2021-11-26T16:21:22-08:00 summary: [3.9] bpo-41735: Fix thread lock in zlib.Decompress.flush() may go wrong (GH-29588) * Fix thread lock in zlib.Decompress.flush() may go wrong Getting `.unconsumed_tail` before acquiring the thread lock may mix up decompress state. backport of https://github.com/python/cpython/pull/29587 to 3.9/3.8. files: A Misc/NEWS.d/next/Library/2021-11-17-11-38-30.bpo-41735.2feh9v.rst M Modules/zlibmodule.c diff --git a/Misc/NEWS.d/next/Library/2021-11-17-11-38-30.bpo-41735.2feh9v.rst b/Misc/NEWS.d/next/Library/2021-11-17-11-38-30.bpo-41735.2feh9v.rst new file mode 100644 index 0000000000000..101da0e9ce648 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-17-11-38-30.bpo-41735.2feh9v.rst @@ -0,0 +1 @@ +Fix thread lock in ``zlib.Decompress.flush()`` method before ``PyObject_GetBuffer``. diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c index 8f8bcd85f2c16..4dfd4ae672200 100644 --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -1134,11 +1134,13 @@ zlib_Decompress_flush_impl(compobject *self, Py_ssize_t length) return NULL; } - if (PyObject_GetBuffer(self->unconsumed_tail, &data, PyBUF_SIMPLE) == -1) - return NULL; - ENTER_ZLIB(self); + if (PyObject_GetBuffer(self->unconsumed_tail, &data, PyBUF_SIMPLE) == -1) { + LEAVE_ZLIB(self); + return NULL; + } + self->zst.next_in = data.buf; ibuflen = data.len; From webhook-mailer at python.org Fri Nov 26 19:26:54 2021 From: webhook-mailer at python.org (zooba) Date: Sat, 27 Nov 2021 00:26:54 -0000 Subject: [Python-checkins] bpo-44530: Reverts a change to the 'code.__new__' audit event (GH-29809) Message-ID: https://github.com/python/cpython/commit/db55f3fabafc046e4fca907210ced4ce16bf58d6 commit: db55f3fabafc046e4fca907210ced4ce16bf58d6 branch: main author: Steve Dower committer: zooba date: 2021-11-27T00:26:45Z summary: bpo-44530: Reverts a change to the 'code.__new__' audit event (GH-29809) files: A Misc/NEWS.d/next/Core and Builtins/2021-11-26-23-26-25.bpo-44530.EZ0gel.rst M Objects/codeobject.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-26-23-26-25.bpo-44530.EZ0gel.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-26-23-26-25.bpo-44530.EZ0gel.rst new file mode 100644 index 0000000000000..f3c3a94dbf1ae --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-26-23-26-25.bpo-44530.EZ0gel.rst @@ -0,0 +1,2 @@ +Reverts a change to the ``code.__new__`` :ref:`audit event ` +from an earlier prerelease. diff --git a/Objects/codeobject.c b/Objects/codeobject.c index 8de5c4d9c8a9d..5ab8641a17caa 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -1254,8 +1254,8 @@ code_new_impl(PyTypeObject *type, int argcount, int posonlyargcount, PyObject *ourfreevars = NULL; PyObject *ourcellvars = NULL; - if (PySys_Audit("code.__new__", "OOOOiiiiii", - code, filename, name, qualname, argcount, posonlyargcount, + if (PySys_Audit("code.__new__", "OOOiiiiii", + code, filename, name, argcount, posonlyargcount, kwonlyargcount, nlocals, stacksize, flags) < 0) { goto cleanup; } @@ -1638,8 +1638,8 @@ code_replace_impl(PyCodeObject *self, int co_argcount, #undef CHECK_INT_ARG - if (PySys_Audit("code.__new__", "OOOOiiiiii", - co_code, co_filename, co_name, co_qualname, co_argcount, + if (PySys_Audit("code.__new__", "OOOiiiiii", + co_code, co_filename, co_name, co_argcount, co_posonlyargcount, co_kwonlyargcount, co_nlocals, co_stacksize, co_flags) < 0) { return NULL; From webhook-mailer at python.org Fri Nov 26 19:42:09 2021 From: webhook-mailer at python.org (miss-islington) Date: Sat, 27 Nov 2021 00:42:09 -0000 Subject: [Python-checkins] [3.10] bpo-41735: Fix thread lock in zlib.Decompress.flush() may go wrong (GH-29587) (GH-29811) Message-ID: https://github.com/python/cpython/commit/57100c86baa8451a568348646834380cd425b858 commit: 57100c86baa8451a568348646834380cd425b858 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-26T16:42:00-08:00 summary: [3.10] bpo-41735: Fix thread lock in zlib.Decompress.flush() may go wrong (GH-29587) (GH-29811) * Fix thread lock in zlib.Decompress.flush() may go wrong Getting `.unconsumed_tail` before acquiring the thread lock may mix up decompress state. (cherry picked from commit 7edb6270a78c695e4c2ae2432797dc18105374fc) Co-authored-by: Ma Lin Automerge-Triggered-By: GH:gpshead files: A Misc/NEWS.d/next/Library/2021-11-16-18-13-49.bpo-41735.D72UY1.rst M Modules/zlibmodule.c diff --git a/Misc/NEWS.d/next/Library/2021-11-16-18-13-49.bpo-41735.D72UY1.rst b/Misc/NEWS.d/next/Library/2021-11-16-18-13-49.bpo-41735.D72UY1.rst new file mode 100644 index 0000000000000..101da0e9ce648 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-16-18-13-49.bpo-41735.D72UY1.rst @@ -0,0 +1 @@ +Fix thread lock in ``zlib.Decompress.flush()`` method before ``PyObject_GetBuffer``. diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c index 68de701efa45f..a6940f2fd43a3 100644 --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -1266,12 +1266,13 @@ zlib_Decompress_flush_impl(compobject *self, PyTypeObject *cls, return NULL; } + ENTER_ZLIB(self); + if (PyObject_GetBuffer(self->unconsumed_tail, &data, PyBUF_SIMPLE) == -1) { + LEAVE_ZLIB(self); return NULL; } - ENTER_ZLIB(self); - self->zst.next_in = data.buf; ibuflen = data.len; From webhook-mailer at python.org Sat Nov 27 00:55:17 2021 From: webhook-mailer at python.org (rhettinger) Date: Sat, 27 Nov 2021 05:55:17 -0000 Subject: [Python-checkins] bpo-45876: Improve accuracy for stdev() and pstdev() in statistics (GH-29736) Message-ID: https://github.com/python/cpython/commit/af9ee57b96cb872df6574e36027cc753417605f9 commit: af9ee57b96cb872df6574e36027cc753417605f9 branch: main author: Raymond Hettinger committer: rhettinger date: 2021-11-26T22:54:50-07:00 summary: bpo-45876: Improve accuracy for stdev() and pstdev() in statistics (GH-29736) * Inlined code from variance functions * Added helper functions for the float square root of a fraction * Call helper functions * Add blurb * Fix over-specified test * Add a test for the _sqrt_frac() helper function * Increase the tested range * Add type hints to the internal function. * Fix test for correct rounding * Simplify ??(n/m)? calculation Co-authored-by: Mark Dickinson * Add comment and beef-up tests * Test for zero denominator * Add algorithmic references * Add test for the _isqrt_frac_rto() helper function. * Compute the 109 instead of hard-wiring it * Stronger test for _isqrt_frac_rto() * Bigger range * Bigger range * Replace float() call with int/int division to be parallel with the other code path. * Factor out division. Update proof link. Remove internal type declaration Co-authored-by: Mark Dickinson files: A Misc/NEWS.d/next/Library/2021-11-23-15-36-56.bpo-45876.NO8Yaj.rst M Lib/statistics.py M Lib/test/test_statistics.py diff --git a/Lib/statistics.py b/Lib/statistics.py index 5c3f77df1549d..cf8eaa0a61e62 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -130,6 +130,7 @@ import math import numbers import random +import sys from fractions import Fraction from decimal import Decimal @@ -304,6 +305,27 @@ def _fail_neg(values, errmsg='negative value'): raise StatisticsError(errmsg) yield x +def _isqrt_frac_rto(n: int, m: int) -> float: + """Square root of n/m, rounded to the nearest integer using round-to-odd.""" + # Reference: https://www.lri.fr/~melquion/doc/05-imacs17_1-expose.pdf + a = math.isqrt(n // m) + return a | (a*a*m != n) + +# For 53 bit precision floats, the _sqrt_frac() shift is 109. +_sqrt_shift: int = 2 * sys.float_info.mant_dig + 3 + +def _sqrt_frac(n: int, m: int) -> float: + """Square root of n/m as a float, correctly rounded.""" + # See principle and proof sketch at: https://bugs.python.org/msg407078 + q = (n.bit_length() - m.bit_length() - _sqrt_shift) // 2 + if q >= 0: + numerator = _isqrt_frac_rto(n, m << 2 * q) << q + denominator = 1 + else: + numerator = _isqrt_frac_rto(n << -2 * q, m) + denominator = 1 << -q + return numerator / denominator # Convert to float + # === Measures of central tendency (averages) === @@ -837,14 +859,17 @@ def stdev(data, xbar=None): 1.0810874155219827 """ - # Fixme: Despite the exact sum of squared deviations, some inaccuracy - # remain because there are two rounding steps. The first occurs in - # the _convert() step for variance(), the second occurs in math.sqrt(). - var = variance(data, xbar) - try: + if iter(data) is data: + data = list(data) + n = len(data) + if n < 2: + raise StatisticsError('stdev requires at least two data points') + T, ss = _ss(data, xbar) + mss = ss / (n - 1) + if hasattr(T, 'sqrt'): + var = _convert(mss, T) return var.sqrt() - except AttributeError: - return math.sqrt(var) + return _sqrt_frac(mss.numerator, mss.denominator) def pstdev(data, mu=None): @@ -856,14 +881,17 @@ def pstdev(data, mu=None): 0.986893273527251 """ - # Fixme: Despite the exact sum of squared deviations, some inaccuracy - # remain because there are two rounding steps. The first occurs in - # the _convert() step for pvariance(), the second occurs in math.sqrt(). - var = pvariance(data, mu) - try: + if iter(data) is data: + data = list(data) + n = len(data) + if n < 1: + raise StatisticsError('pstdev requires at least one data point') + T, ss = _ss(data, mu) + mss = ss / n + if hasattr(T, 'sqrt'): + var = _convert(mss, T) return var.sqrt() - except AttributeError: - return math.sqrt(var) + return _sqrt_frac(mss.numerator, mss.denominator) # === Statistics for relations between two inputs === diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py index c0e427d9355f2..771a03e707ee0 100644 --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -9,13 +9,14 @@ import copy import decimal import doctest +import itertools import math import pickle import random import sys import unittest from test import support -from test.support import import_helper +from test.support import import_helper, requires_IEEE_754 from decimal import Decimal from fractions import Fraction @@ -2161,6 +2162,66 @@ def test_center_not_at_mean(self): self.assertEqual(self.func(data), 2.5) self.assertEqual(self.func(data, mu=0.5), 6.5) +class TestSqrtHelpers(unittest.TestCase): + + def test_isqrt_frac_rto(self): + for n, m in itertools.product(range(100), range(1, 1000)): + r = statistics._isqrt_frac_rto(n, m) + self.assertIsInstance(r, int) + if r*r*m == n: + # Root is exact + continue + # Inexact, so the root should be odd + self.assertEqual(r&1, 1) + # Verify correct rounding + self.assertTrue(m * (r - 1)**2 < n < m * (r + 1)**2) + + @requires_IEEE_754 + def test_sqrt_frac(self): + + def is_root_correctly_rounded(x: Fraction, root: float) -> bool: + if not x: + return root == 0.0 + + # Extract adjacent representable floats + r_up: float = math.nextafter(root, math.inf) + r_down: float = math.nextafter(root, -math.inf) + assert r_down < root < r_up + + # Convert to fractions for exact arithmetic + frac_root: Fraction = Fraction(root) + half_way_up: Fraction = (frac_root + Fraction(r_up)) / 2 + half_way_down: Fraction = (frac_root + Fraction(r_down)) / 2 + + # Check a closed interval. + # Does not test for a midpoint rounding rule. + return half_way_down ** 2 <= x <= half_way_up ** 2 + + randrange = random.randrange + + for i in range(60_000): + numerator: int = randrange(10 ** randrange(50)) + denonimator: int = randrange(10 ** randrange(50)) + 1 + with self.subTest(numerator=numerator, denonimator=denonimator): + x: Fraction = Fraction(numerator, denonimator) + root: float = statistics._sqrt_frac(numerator, denonimator) + self.assertTrue(is_root_correctly_rounded(x, root)) + + # Verify that corner cases and error handling match math.sqrt() + self.assertEqual(statistics._sqrt_frac(0, 1), 0.0) + with self.assertRaises(ValueError): + statistics._sqrt_frac(-1, 1) + with self.assertRaises(ValueError): + statistics._sqrt_frac(1, -1) + + # Error handling for zero denominator matches that for Fraction(1, 0) + with self.assertRaises(ZeroDivisionError): + statistics._sqrt_frac(1, 0) + + # The result is well defined if both inputs are negative + self.assertAlmostEqual(statistics._sqrt_frac(-2, -1), math.sqrt(2.0)) + + class TestStdev(VarianceStdevMixin, NumericTestCase): # Tests for sample standard deviation. def setUp(self): @@ -2175,7 +2236,7 @@ def test_compare_to_variance(self): # Test that stdev is, in fact, the square root of variance. data = [random.uniform(-2, 9) for _ in range(1000)] expected = math.sqrt(statistics.variance(data)) - self.assertEqual(self.func(data), expected) + self.assertAlmostEqual(self.func(data), expected) def test_center_not_at_mean(self): data = (1.0, 2.0) diff --git a/Misc/NEWS.d/next/Library/2021-11-23-15-36-56.bpo-45876.NO8Yaj.rst b/Misc/NEWS.d/next/Library/2021-11-23-15-36-56.bpo-45876.NO8Yaj.rst new file mode 100644 index 0000000000000..889ed6ce3ffb2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-23-15-36-56.bpo-45876.NO8Yaj.rst @@ -0,0 +1,2 @@ +Improve the accuracy of stdev() and pstdev() in the statistics module. When +the inputs are floats or fractions, the output is a correctly rounded float From webhook-mailer at python.org Sat Nov 27 13:04:35 2021 From: webhook-mailer at python.org (pablogsal) Date: Sat, 27 Nov 2021 18:04:35 -0000 Subject: [Python-checkins] bpo-42268: Fail the configure step if the selected compiler doesn't support memory sanitizer (GH-29806) Message-ID: https://github.com/python/cpython/commit/e71c12efcddc1076d5367461a5b416092267aa77 commit: e71c12efcddc1076d5367461a5b416092267aa77 branch: main author: Pablo Galindo Salgado committer: pablogsal date: 2021-11-27T18:04:06Z summary: bpo-42268: Fail the configure step if the selected compiler doesn't support memory sanitizer (GH-29806) files: A Misc/NEWS.d/next/Core and Builtins/2021-11-26-22-31-22.bpo-42268.3wl-09.rst M configure M configure.ac diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-26-22-31-22.bpo-42268.3wl-09.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-26-22-31-22.bpo-42268.3wl-09.rst new file mode 100644 index 0000000000000..615bbb22ae2eb --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-26-22-31-22.bpo-42268.3wl-09.rst @@ -0,0 +1,2 @@ +Fail the configure step if the selected compiler doesn't support memory +sanitizer. Patch by Pablo Galindo diff --git a/configure b/configure index 1c398929c962d..958007288a165 100755 --- a/configure +++ b/configure @@ -9920,8 +9920,44 @@ if test "${with_memory_sanitizer+set}" = set; then : withval=$with_memory_sanitizer; { $as_echo "$as_me:${as_lineno-$LINENO}: result: $withval" >&5 $as_echo "$withval" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fsanitize=memory" >&5 +$as_echo_n "checking whether C compiler accepts -fsanitize=memory... " >&6; } +if ${ax_cv_check_cflags___fsanitize_memory+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS -fsanitize=memory" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ax_cv_check_cflags___fsanitize_memory=yes +else + ax_cv_check_cflags___fsanitize_memory=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___fsanitize_memory" >&5 +$as_echo "$ax_cv_check_cflags___fsanitize_memory" >&6; } +if test "x$ax_cv_check_cflags___fsanitize_memory" = xyes; then : + BASECFLAGS="-fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer $BASECFLAGS" LDFLAGS="-fsanitize=memory -fsanitize-memory-track-origins=2 $LDFLAGS" + +else + as_fn_error $? "The selected compiler doesn't support memory sanitizer" "$LINENO" 5 +fi + # MSan works by controlling memory allocation, our own malloc interferes. with_pymalloc="no" diff --git a/configure.ac b/configure.ac index e96d88fb8c811..0fce3f61f5a50 100644 --- a/configure.ac +++ b/configure.ac @@ -2565,8 +2565,10 @@ AC_ARG_WITH(memory_sanitizer, [enable MemorySanitizer allocation error detector, 'msan' (default is no)]), [ AC_MSG_RESULT($withval) +AX_CHECK_COMPILE_FLAG([-fsanitize=memory],[ BASECFLAGS="-fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer $BASECFLAGS" LDFLAGS="-fsanitize=memory -fsanitize-memory-track-origins=2 $LDFLAGS" +],[AC_MSG_ERROR([The selected compiler doesn't support memory sanitizer])]) # MSan works by controlling memory allocation, our own malloc interferes. with_pymalloc="no" ], From webhook-mailer at python.org Sat Nov 27 15:14:13 2021 From: webhook-mailer at python.org (tiran) Date: Sat, 27 Nov 2021 20:14:13 -0000 Subject: [Python-checkins] [3.10] bpo-45881: Use CC from env first for cross building (GH-29752). (GH-29753) Message-ID: https://github.com/python/cpython/commit/545aebd2ecef9f6c3b2ca1973e3e0515d8355ce3 commit: 545aebd2ecef9f6c3b2ca1973e3e0515d8355ce3 branch: 3.10 author: Christian Heimes committer: tiran date: 2021-11-27T21:14:05+01:00 summary: [3.10] bpo-45881: Use CC from env first for cross building (GH-29752). (GH-29753) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Build/2021-11-24-17-14-06.bpo-45881.GTXXLk.rst M setup.py diff --git a/Misc/NEWS.d/next/Build/2021-11-24-17-14-06.bpo-45881.GTXXLk.rst b/Misc/NEWS.d/next/Build/2021-11-24-17-14-06.bpo-45881.GTXXLk.rst new file mode 100644 index 0000000000000..b697658cf3aaa --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-24-17-14-06.bpo-45881.GTXXLk.rst @@ -0,0 +1,2 @@ +``setup.py`` now uses ``CC`` from environment first to discover multiarch +and cross compile paths. diff --git a/setup.py b/setup.py index 4802b6dd3e5e6..43e807f20d989 100644 --- a/setup.py +++ b/setup.py @@ -86,6 +86,9 @@ def get_platform(): MACOS = (HOST_PLATFORM == 'darwin') AIX = (HOST_PLATFORM.startswith('aix')) VXWORKS = ('vxworks' in HOST_PLATFORM) +CC = os.environ.get("CC") +if not CC: + CC = sysconfig.get_config_var("CC") SUMMARY = """ @@ -467,6 +470,9 @@ def set_compiler_executables(self): def build_extensions(self): self.set_srcdir() + self.set_compiler_executables() + self.configure_compiler() + self.init_inc_lib_dirs() # Detect which modules should be compiled self.detect_modules() @@ -476,7 +482,6 @@ def build_extensions(self): self.update_sources_depends() mods_built, mods_disabled = self.remove_configured_extensions() - self.set_compiler_executables() if LIST_MODULE_NAMES: for ext in self.extensions: @@ -662,12 +667,11 @@ def check_extension_import(self, ext): def add_multiarch_paths(self): # Debian/Ubuntu multiarch support. # https://wiki.ubuntu.com/MultiarchSpec - cc = sysconfig.get_config_var('CC') tmpfile = os.path.join(self.build_temp, 'multiarch') if not os.path.exists(self.build_temp): os.makedirs(self.build_temp) ret = run_command( - '%s -print-multiarch > %s 2> /dev/null' % (cc, tmpfile)) + '%s -print-multiarch > %s 2> /dev/null' % (CC, tmpfile)) multiarch_path_component = '' try: if ret == 0: @@ -729,11 +733,10 @@ def add_search_path(line): d = os.path.normpath(d) add_dir_to_list(self.compiler.library_dirs, d) - cc = sysconfig.get_config_var('CC') tmpfile = os.path.join(self.build_temp, 'wrccpaths') os.makedirs(self.build_temp, exist_ok=True) try: - ret = run_command('%s --print-search-dirs >%s' % (cc, tmpfile)) + ret = run_command('%s --print-search-dirs >%s' % (CC, tmpfile)) if ret: return with open(tmpfile) as fp: @@ -751,11 +754,10 @@ def add_search_path(line): pass def add_cross_compiling_paths(self): - cc = sysconfig.get_config_var('CC') tmpfile = os.path.join(self.build_temp, 'ccpaths') if not os.path.exists(self.build_temp): os.makedirs(self.build_temp) - ret = run_command('%s -E -v - %s 1>/dev/null' % (cc, tmpfile)) + ret = run_command('%s -E -v - %s 1>/dev/null' % (CC, tmpfile)) is_gcc = False is_clang = False in_incdirs = False @@ -1876,9 +1878,6 @@ def detect_uuid(self): self.missing.append('_uuid') def detect_modules(self): - self.configure_compiler() - self.init_inc_lib_dirs() - self.detect_simple_extensions() if TEST_EXTENSIONS: self.detect_test_extensions() From webhook-mailer at python.org Sat Nov 27 17:00:21 2021 From: webhook-mailer at python.org (iritkatriel) Date: Sat, 27 Nov 2021 22:00:21 -0000 Subject: [Python-checkins] bpo-45614: Fix traceback display for exceptions with invalid module name (GH-29726) Message-ID: https://github.com/python/cpython/commit/4dfae6f38e1720ddafcdd68043e476ecb41cb4d5 commit: 4dfae6f38e1720ddafcdd68043e476ecb41cb4d5 branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-11-27T22:00:10Z summary: bpo-45614: Fix traceback display for exceptions with invalid module name (GH-29726) files: A Misc/NEWS.d/next/Core and Builtins/2021-11-23-12-06-41.bpo-45614.fIekgI.rst M Lib/test/test_traceback.py M Lib/traceback.py M Python/pythonrun.c diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index d88851ddda431..cde35f5dacb2d 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -1254,6 +1254,17 @@ def __str__(self): exp = "%s: %s\n" % (str_name, str_value) self.assertEqual(exp, err) + def test_exception_modulename_not_unicode(self): + class X(Exception): + def __str__(self): + return "I am X" + + X.__module__ = 42 + + err = self.get_report(X()) + exp = f'.{X.__qualname__}: I am X\n' + self.assertEqual(exp, err) + def test_exception_bad__str__(self): class X(Exception): def __str__(self): diff --git a/Lib/traceback.py b/Lib/traceback.py index 97caa1372f478..77f8590719eb8 100644 --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -808,6 +808,8 @@ def format_exception_only(self): stype = self.exc_type.__qualname__ smod = self.exc_type.__module__ if smod not in ("__main__", "builtins"): + if not isinstance(smod, str): + smod = "" stype = smod + '.' + stype if not issubclass(self.exc_type, SyntaxError): diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-23-12-06-41.bpo-45614.fIekgI.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-23-12-06-41.bpo-45614.fIekgI.rst new file mode 100644 index 0000000000000..4255e1885ad67 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-23-12-06-41.bpo-45614.fIekgI.rst @@ -0,0 +1 @@ +Fix :mod:`traceback` display for exceptions with invalid module name. \ No newline at end of file diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 2c0950ee17e8a..2f68b214603e1 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1022,7 +1022,7 @@ print_exception(struct exception_print_context *ctx, PyObject *value) { Py_XDECREF(modulename); PyErr_Clear(); - err = PyFile_WriteString("", f); + err = PyFile_WriteString(".", f); } else { if (!_PyUnicode_EqualToASCIIId(modulename, &PyId_builtins) && From webhook-mailer at python.org Sun Nov 28 04:24:46 2021 From: webhook-mailer at python.org (asvetlov) Date: Sun, 28 Nov 2021 09:24:46 -0000 Subject: [Python-checkins] bpo-19460: Add test for MIMENonMultipart (GH-29817) Message-ID: https://github.com/python/cpython/commit/46c8d915715aa2bd4d697482aa051fe974d440e1 commit: 46c8d915715aa2bd4d697482aa051fe974d440e1 branch: main author: 180909 committer: asvetlov date: 2021-11-28T11:24:41+02:00 summary: bpo-19460: Add test for MIMENonMultipart (GH-29817) files: A Misc/NEWS.d/next/Tests/2021-11-28-15-25-02.bpo-19460.lr0aWs.rst M Lib/test/test_email/test_email.py diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py index 54ffcdc544e8b..a3ccbbbabfb32 100644 --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -2743,6 +2743,20 @@ def test_multipart_custom_policy(self): self.assertEqual(str(cm.exception), 'There may be at most 1 To headers in a message') + +# Test the NonMultipart class +class TestNonMultipart(TestEmailBase): + def test_nonmultipart_is_not_multipart(self): + msg = MIMENonMultipart('text', 'plain') + self.assertFalse(msg.is_multipart()) + + def test_attach_raises_exception(self): + msg = Message() + msg['Subject'] = 'subpart 1' + r = MIMENonMultipart('text', 'plain') + self.assertRaises(errors.MultipartConversionError, r.attach, msg) + + # A general test of parser->model->generator idempotency. IOW, read a message # in, parse it into a message object tree, then without touching the tree, # regenerate the plain text. The original text and the transformed text diff --git a/Misc/NEWS.d/next/Tests/2021-11-28-15-25-02.bpo-19460.lr0aWs.rst b/Misc/NEWS.d/next/Tests/2021-11-28-15-25-02.bpo-19460.lr0aWs.rst new file mode 100644 index 0000000000000..e2d3d9526ecab --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-11-28-15-25-02.bpo-19460.lr0aWs.rst @@ -0,0 +1 @@ +Add new Test for ``Lib/email/mime/nonmultipart.py::MIMENonMultipart``. From webhook-mailer at python.org Sun Nov 28 05:57:15 2021 From: webhook-mailer at python.org (asvetlov) Date: Sun, 28 Nov 2021 10:57:15 -0000 Subject: [Python-checkins] [3.10] bpo-19460: Add test for MIMENonMultipart (GH-29817) (GH-29818) Message-ID: https://github.com/python/cpython/commit/2c398a5acf85d1bbc5796f3385972d0759b90e54 commit: 2c398a5acf85d1bbc5796f3385972d0759b90e54 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: asvetlov date: 2021-11-28T12:57:10+02:00 summary: [3.10] bpo-19460: Add test for MIMENonMultipart (GH-29817) (GH-29818) Co-authored-by: 180909 Co-authored-by: Andrew Svetlov files: A Misc/NEWS.d/next/Tests/2021-11-28-15-25-02.bpo-19460.lr0aWs.rst M Lib/test/test_email/test_email.py diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py index 54ffcdc544e8b..a3ccbbbabfb32 100644 --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -2743,6 +2743,20 @@ def test_multipart_custom_policy(self): self.assertEqual(str(cm.exception), 'There may be at most 1 To headers in a message') + +# Test the NonMultipart class +class TestNonMultipart(TestEmailBase): + def test_nonmultipart_is_not_multipart(self): + msg = MIMENonMultipart('text', 'plain') + self.assertFalse(msg.is_multipart()) + + def test_attach_raises_exception(self): + msg = Message() + msg['Subject'] = 'subpart 1' + r = MIMENonMultipart('text', 'plain') + self.assertRaises(errors.MultipartConversionError, r.attach, msg) + + # A general test of parser->model->generator idempotency. IOW, read a message # in, parse it into a message object tree, then without touching the tree, # regenerate the plain text. The original text and the transformed text diff --git a/Misc/NEWS.d/next/Tests/2021-11-28-15-25-02.bpo-19460.lr0aWs.rst b/Misc/NEWS.d/next/Tests/2021-11-28-15-25-02.bpo-19460.lr0aWs.rst new file mode 100644 index 0000000000000..b082d6de20c07 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-11-28-15-25-02.bpo-19460.lr0aWs.rst @@ -0,0 +1 @@ +Add new Test for :class:`email.mime.nonmultipart.MIMENonMultipart`. From webhook-mailer at python.org Sun Nov 28 07:00:58 2021 From: webhook-mailer at python.org (tiran) Date: Sun, 28 Nov 2021 12:00:58 -0000 Subject: [Python-checkins] bpo-45847: Port _multiprocessing to PY_STDLIB_MOD (GH-29768) Message-ID: https://github.com/python/cpython/commit/aaf42222cfd5774d23ca48ff304ace1f64426201 commit: aaf42222cfd5774d23ca48ff304ace1f64426201 branch: main author: Erlend Egeberg Aasland committer: tiran date: 2021-11-28T13:00:51+01:00 summary: bpo-45847: Port _multiprocessing to PY_STDLIB_MOD (GH-29768) files: M Modules/Setup.stdlib.in M configure M configure.ac M setup.py diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 03295400f638c..9dfe918d05a09 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -124,6 +124,7 @@ # multiprocessing @MODULE__POSIXSHMEM_TRUE at _posixshmem _multiprocessing/posixshmem.c + at MODULE__MULTIPROCESSING_TRUE@_multiprocessing _multiprocessing/multiprocessing.c _multiprocessing/semaphore.c ############################################################################ diff --git a/configure b/configure index 958007288a165..32aed7e49f2c0 100755 --- a/configure +++ b/configure @@ -712,8 +712,6 @@ MODULE_OSSAUDIODEV_FALSE MODULE_OSSAUDIODEV_TRUE MODULE_GRP_FALSE MODULE_GRP_TRUE -MODULE__POSIXSHMEM_FALSE -MODULE__POSIXSHMEM_TRUE MODULE_MMAP_FALSE MODULE_MMAP_TRUE MODULE_FCNTL_FALSE @@ -728,6 +726,10 @@ MODULE__STATISTICS_FALSE MODULE__STATISTICS_TRUE MODULE_AUDIOOP_FALSE MODULE_AUDIOOP_TRUE +MODULE__POSIXSHMEM_FALSE +MODULE__POSIXSHMEM_TRUE +MODULE__MULTIPROCESSING_FALSE +MODULE__MULTIPROCESSING_TRUE MODULE__ZONEINFO_FALSE MODULE__ZONEINFO_TRUE MODULE__XXSUBINTERPRETERS_FALSE @@ -17647,11 +17649,6 @@ done LIBS=$LIBS_SAVE -# For multiprocessing module, check that sem_open -# actually works. For FreeBSD versions <= 7.2, -# the kernel module that provides POSIX semaphores -# isn't loaded by default, so an attempt to call -# sem_open results in a 'Signal 12' error. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether POSIX semaphores are enabled" >&5 $as_echo_n "checking whether POSIX semaphores are enabled... " >&6; } if ${ac_cv_posix_semaphores_enabled+:} false; then : @@ -17663,22 +17660,24 @@ else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include -#include -#include -#include -#include -int main(void) { - sem_t *a = sem_open("/autoconf", O_CREAT, S_IRUSR|S_IWUSR, 0); - if (a == SEM_FAILED) { - perror("sem_open"); - return 1; - } - sem_close(a); - sem_unlink("/autoconf"); - return 0; -} + #include + #include + #include + #include + #include + + int main(void) { + sem_t *a = sem_open("/autoconf", O_CREAT, S_IRUSR|S_IWUSR, 0); + if (a == SEM_FAILED) { + perror("sem_open"); + return 1; + } + sem_close(a); + sem_unlink("/autoconf"); + return 0; + } + _ACEOF if ac_fn_c_try_run "$LINENO"; then : @@ -17694,14 +17693,14 @@ fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_posix_semaphores_enabled" >&5 $as_echo "$ac_cv_posix_semaphores_enabled" >&6; } -if test $ac_cv_posix_semaphores_enabled = no -then +if test "x$ac_cv_posix_semaphores_enabled" = xno; then : + $as_echo "#define POSIX_SEMAPHORES_NOT_ENABLED 1" >>confdefs.h + fi -# Multiprocessing check for broken sem_getvalue { $as_echo "$as_me:${as_lineno-$LINENO}: checking for broken sem_getvalue" >&5 $as_echo_n "checking for broken sem_getvalue... " >&6; } if ${ac_cv_broken_sem_getvalue+:} false; then : @@ -17713,26 +17712,28 @@ else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include -#include -#include -#include -#include -int main(void){ - sem_t *a = sem_open("/autocftw", O_CREAT, S_IRUSR|S_IWUSR, 0); - int count; - int res; - if(a==SEM_FAILED){ - perror("sem_open"); - return 1; + #include + #include + #include + #include + #include + + int main(void){ + sem_t *a = sem_open("/autocftw", O_CREAT, S_IRUSR|S_IWUSR, 0); + int count; + int res; + if(a==SEM_FAILED){ + perror("sem_open"); + return 1; + + } + res = sem_getvalue(a, &count); + sem_close(a); + sem_unlink("/autocftw"); + return res==-1 ? 1 : 0; + } - } - res = sem_getvalue(a, &count); - sem_close(a); - sem_unlink("/autocftw"); - return res==-1 ? 1 : 0; -} _ACEOF if ac_fn_c_try_run "$LINENO"; then : @@ -17748,11 +17749,12 @@ fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_broken_sem_getvalue" >&5 $as_echo "$ac_cv_broken_sem_getvalue" >&6; } -if test $ac_cv_broken_sem_getvalue = yes -then +if test "x$ac_cv_broken_sem_getvalue" = xyes; then : + $as_echo "#define HAVE_BROKEN_SEM_GETVALUE 1" >>confdefs.h + fi ac_fn_c_check_decl "$LINENO" "RTLD_LAZY" "ac_cv_have_decl_RTLD_LAZY" "#include @@ -21262,6 +21264,54 @@ fi as_fn_append MODULE_BLOCK "MODULE__ZONEINFO=yes$as_nl" + if true; then + MODULE__MULTIPROCESSING_TRUE= + MODULE__MULTIPROCESSING_FALSE='#' +else + MODULE__MULTIPROCESSING_TRUE='#' + MODULE__MULTIPROCESSING_FALSE= +fi + as_fn_append MODULE_BLOCK "MODULE__MULTIPROCESSING=yes$as_nl" + as_fn_append MODULE_BLOCK "MODULE__MULTIPROCESSING_CFLAGS=-I\$(srcdir)/Modules/_multiprocessing$as_nl" + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _posixshmem" >&5 +$as_echo_n "checking for stdlib extension module _posixshmem... " >&6; } + case $py_stdlib_not_available in #( + *_posixshmem*) : + py_cv_module__posixshmem=n/a ;; #( + *) : + if true; then : + if test "$have_posix_shmem" = "yes"; then : + py_cv_module__posixshmem=yes +else + py_cv_module__posixshmem=missing +fi +else + py_cv_module__posixshmem=disabled +fi + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__POSIXSHMEM=$py_cv_module__posixshmem$as_nl" + if test "x$py_cv_module__posixshmem" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE__POSIXSHMEM_CFLAGS=$POSIXSHMEM_CFLAGS$as_nl" + as_fn_append MODULE_BLOCK "MODULE__POSIXSHMEM_LDFLAGS=$POSIXSHMEM_LIBS$as_nl" + +fi + if test "$py_cv_module__posixshmem" = yes; then + MODULE__POSIXSHMEM_TRUE= + MODULE__POSIXSHMEM_FALSE='#' +else + MODULE__POSIXSHMEM_TRUE='#' + MODULE__POSIXSHMEM_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__posixshmem" >&5 +$as_echo "$py_cv_module__posixshmem" >&6; } + + + if true; then MODULE_AUDIOOP_TRUE= MODULE_AUDIOOP_FALSE='#' @@ -21391,42 +21441,6 @@ fi $as_echo "$py_cv_module_mmap" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _posixshmem" >&5 -$as_echo_n "checking for stdlib extension module _posixshmem... " >&6; } - case $py_stdlib_not_available in #( - *_posixshmem*) : - py_cv_module__posixshmem=n/a ;; #( - *) : - if true; then : - if test "$have_posix_shmem" = "yes"; then : - py_cv_module__posixshmem=yes -else - py_cv_module__posixshmem=missing -fi -else - py_cv_module__posixshmem=disabled -fi - ;; -esac - as_fn_append MODULE_BLOCK "MODULE__POSIXSHMEM=$py_cv_module__posixshmem$as_nl" - if test "x$py_cv_module__posixshmem" = xyes; then : - - as_fn_append MODULE_BLOCK "MODULE__POSIXSHMEM_CFLAGS=$POSIXSHMEM_CFLAGS$as_nl" - as_fn_append MODULE_BLOCK "MODULE__POSIXSHMEM_LDFLAGS=$POSIXSHMEM_LIBS$as_nl" - -fi - if test "$py_cv_module__posixshmem" = yes; then - MODULE__POSIXSHMEM_TRUE= - MODULE__POSIXSHMEM_FALSE='#' -else - MODULE__POSIXSHMEM_TRUE='#' - MODULE__POSIXSHMEM_FALSE= -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__posixshmem" >&5 -$as_echo "$py_cv_module__posixshmem" >&6; } - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module grp" >&5 $as_echo_n "checking for stdlib extension module grp... " >&6; } @@ -22984,6 +22998,14 @@ if test -z "${MODULE__ZONEINFO_TRUE}" && test -z "${MODULE__ZONEINFO_FALSE}"; th as_fn_error $? "conditional \"MODULE__ZONEINFO\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__MULTIPROCESSING_TRUE}" && test -z "${MODULE__MULTIPROCESSING_FALSE}"; then + as_fn_error $? "conditional \"MODULE__MULTIPROCESSING\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MODULE__POSIXSHMEM_TRUE}" && test -z "${MODULE__POSIXSHMEM_FALSE}"; then + as_fn_error $? "conditional \"MODULE__POSIXSHMEM\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE_AUDIOOP_TRUE}" && test -z "${MODULE_AUDIOOP_FALSE}"; then as_fn_error $? "conditional \"MODULE_AUDIOOP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -23012,10 +23034,6 @@ if test -z "${MODULE_MMAP_TRUE}" && test -z "${MODULE_MMAP_FALSE}"; then as_fn_error $? "conditional \"MODULE_MMAP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${MODULE__POSIXSHMEM_TRUE}" && test -z "${MODULE__POSIXSHMEM_FALSE}"; then - as_fn_error $? "conditional \"MODULE__POSIXSHMEM\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${MODULE_GRP_TRUE}" && test -z "${MODULE_GRP_FALSE}"; then as_fn_error $? "conditional \"MODULE_GRP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index 0fce3f61f5a50..ec71470a74e02 100644 --- a/configure.ac +++ b/configure.ac @@ -4832,73 +4832,79 @@ AC_CHECK_FUNCS( ) LIBS=$LIBS_SAVE -# For multiprocessing module, check that sem_open -# actually works. For FreeBSD versions <= 7.2, -# the kernel module that provides POSIX semaphores -# isn't loaded by default, so an attempt to call -# sem_open results in a 'Signal 12' error. +dnl For multiprocessing module, check that sem_open +dnl actually works. For FreeBSD versions <= 7.2, +dnl the kernel module that provides POSIX semaphores +dnl isn't loaded by default, so an attempt to call +dnl sem_open results in a 'Signal 12' error. AC_CACHE_CHECK([whether POSIX semaphores are enabled], [ac_cv_posix_semaphores_enabled], -AC_RUN_IFELSE([AC_LANG_SOURCE([[ -#include -#include -#include -#include -#include - -int main(void) { - sem_t *a = sem_open("/autoconf", O_CREAT, S_IRUSR|S_IWUSR, 0); - if (a == SEM_FAILED) { - perror("sem_open"); - return 1; - } - sem_close(a); - sem_unlink("/autoconf"); - return 0; -} -]])], -[ac_cv_posix_semaphores_enabled=yes], -[ac_cv_posix_semaphores_enabled=no], -[ac_cv_posix_semaphores_enabled=yes]) + AC_RUN_IFELSE([ + AC_LANG_SOURCE([ + #include + #include + #include + #include + #include + + int main(void) { + sem_t *a = sem_open("/autoconf", O_CREAT, S_IRUSR|S_IWUSR, 0); + if (a == SEM_FAILED) { + perror("sem_open"); + return 1; + } + sem_close(a); + sem_unlink("/autoconf"); + return 0; + } + ]) + ], + [ac_cv_posix_semaphores_enabled=yes], + [ac_cv_posix_semaphores_enabled=no], + [ac_cv_posix_semaphores_enabled=yes]) ) -if test $ac_cv_posix_semaphores_enabled = no -then - AC_DEFINE(POSIX_SEMAPHORES_NOT_ENABLED, 1, - [Define if POSIX semaphores aren't enabled on your system]) -fi +AS_VAR_IF([ac_cv_posix_semaphores_enabled], [no], [ + AC_DEFINE( + [POSIX_SEMAPHORES_NOT_ENABLED], [1], + [Define if POSIX semaphores aren't enabled on your system] + ) +]) -# Multiprocessing check for broken sem_getvalue +dnl Multiprocessing check for broken sem_getvalue AC_CACHE_CHECK([for broken sem_getvalue], [ac_cv_broken_sem_getvalue], -AC_RUN_IFELSE([AC_LANG_SOURCE([[ -#include -#include -#include -#include -#include + AC_RUN_IFELSE([ + AC_LANG_SOURCE([ + #include + #include + #include + #include + #include -int main(void){ - sem_t *a = sem_open("/autocftw", O_CREAT, S_IRUSR|S_IWUSR, 0); - int count; - int res; - if(a==SEM_FAILED){ - perror("sem_open"); - return 1; + int main(void){ + sem_t *a = sem_open("/autocftw", O_CREAT, S_IRUSR|S_IWUSR, 0); + int count; + int res; + if(a==SEM_FAILED){ + perror("sem_open"); + return 1; - } - res = sem_getvalue(a, &count); - sem_close(a); - sem_unlink("/autocftw"); - return res==-1 ? 1 : 0; -} -]])], -[ac_cv_broken_sem_getvalue=no], -[ac_cv_broken_sem_getvalue=yes], -[ac_cv_broken_sem_getvalue=yes]) + } + res = sem_getvalue(a, &count); + sem_close(a); + sem_unlink("/autocftw"); + return res==-1 ? 1 : 0; + } + ]) + ], + [ac_cv_broken_sem_getvalue=no], + [ac_cv_broken_sem_getvalue=yes], + [ac_cv_broken_sem_getvalue=yes]) ) -if test $ac_cv_broken_sem_getvalue = yes -then - AC_DEFINE(HAVE_BROKEN_SEM_GETVALUE, 1, - [define to 1 if your sem_getvalue is broken.]) -fi +AS_VAR_IF([ac_cv_broken_sem_getvalue], [yes], [ + AC_DEFINE( + [HAVE_BROKEN_SEM_GETVALUE], [1], + [define to 1 if your sem_getvalue is broken.] + ) +]) AC_CHECK_DECLS([RTLD_LAZY, RTLD_NOW, RTLD_GLOBAL, RTLD_LOCAL, RTLD_NODELETE, RTLD_NOLOAD, RTLD_DEEPBIND, RTLD_MEMBER], [], [], [[#include ]]) @@ -6272,6 +6278,12 @@ PY_STDLIB_MOD_SIMPLE([_typing]) PY_STDLIB_MOD_SIMPLE([_xxsubinterpreters]) PY_STDLIB_MOD_SIMPLE([_zoneinfo]) +dnl multiprocessing modules +PY_STDLIB_MOD_SIMPLE([_multiprocessing], [-I\$(srcdir)/Modules/_multiprocessing]) +PY_STDLIB_MOD([_posixshmem], + [], [test "$have_posix_shmem" = "yes"], + [$POSIXSHMEM_CFLAGS], [$POSIXSHMEM_LIBS]) + dnl needs libm PY_STDLIB_MOD_SIMPLE([audioop], [], [$LIBM]) PY_STDLIB_MOD_SIMPLE([_statistics], [], [$LIBM]) @@ -6287,9 +6299,6 @@ PY_STDLIB_MOD([fcntl], [], [$FCNTL_LIBS]) PY_STDLIB_MOD([mmap], [], [test "$ac_cv_header_sys_mman_h" = "yes" -a "$ac_cv_header_sys_stat_h" = "yes"]) -PY_STDLIB_MOD([_posixshmem], - [], [test "$have_posix_shmem" = "yes"], - [$POSIXSHMEM_CFLAGS], [$POSIXSHMEM_LIBS]) dnl platform specific extensions PY_STDLIB_MOD([grp], [], [test "$ac_cv_func_getgrgid" = yes -o "$ac_cv_func_getgrgid_r" = yes]) diff --git a/setup.py b/setup.py index 79f8f4ef50817..572f2ac1783b8 100644 --- a/setup.py +++ b/setup.py @@ -1388,17 +1388,13 @@ def detect_multibytecodecs(self): def detect_multiprocessing(self): # Richard Oudkerk's multiprocessing module - if MS_WINDOWS: - multiprocessing_srcs = ['_multiprocessing/multiprocessing.c', - '_multiprocessing/semaphore.c'] - else: - multiprocessing_srcs = ['_multiprocessing/multiprocessing.c'] - if (sysconfig.get_config_var('HAVE_SEM_OPEN') and not - sysconfig.get_config_var('POSIX_SEMAPHORES_NOT_ENABLED')): - multiprocessing_srcs.append('_multiprocessing/semaphore.c') - self.add(Extension('_multiprocessing', multiprocessing_srcs, - include_dirs=["Modules/_multiprocessing"])) - + multiprocessing_srcs = ['_multiprocessing/multiprocessing.c'] + if ( + sysconfig.get_config_var('HAVE_SEM_OPEN') and not + sysconfig.get_config_var('POSIX_SEMAPHORES_NOT_ENABLED') + ): + multiprocessing_srcs.append('_multiprocessing/semaphore.c') + self.addext(Extension('_multiprocessing', multiprocessing_srcs)) self.addext(Extension('_posixshmem', ['_multiprocessing/posixshmem.c'])) def detect_uuid(self): From webhook-mailer at python.org Sun Nov 28 09:33:59 2021 From: webhook-mailer at python.org (asvetlov) Date: Sun, 28 Nov 2021 14:33:59 -0000 Subject: [Python-checkins] [3.9] bpo-19460: Add test for MIMENonMultipart (GH-29817) (#29819) Message-ID: https://github.com/python/cpython/commit/209cec8a2a2e845df5af764a9171af05a2a4c8e3 commit: 209cec8a2a2e845df5af764a9171af05a2a4c8e3 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: asvetlov date: 2021-11-28T16:33:50+02:00 summary: [3.9] bpo-19460: Add test for MIMENonMultipart (GH-29817) (#29819) * bpo-19460: Add test for MIMENonMultipart (GH-29817) (cherry picked from commit 46c8d915715aa2bd4d697482aa051fe974d440e1) Co-authored-by: 180909 * Update 2021-11-28-15-25-02.bpo-19460.lr0aWs.rst Co-authored-by: 180909 Co-authored-by: Andrew Svetlov files: A Misc/NEWS.d/next/Tests/2021-11-28-15-25-02.bpo-19460.lr0aWs.rst M Lib/test/test_email/test_email.py diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py index bc062b5cb0c59..489cd05be4dd5 100644 --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -2742,6 +2742,20 @@ def test_multipart_custom_policy(self): self.assertEqual(str(cm.exception), 'There may be at most 1 To headers in a message') + +# Test the NonMultipart class +class TestNonMultipart(TestEmailBase): + def test_nonmultipart_is_not_multipart(self): + msg = MIMENonMultipart('text', 'plain') + self.assertFalse(msg.is_multipart()) + + def test_attach_raises_exception(self): + msg = Message() + msg['Subject'] = 'subpart 1' + r = MIMENonMultipart('text', 'plain') + self.assertRaises(errors.MultipartConversionError, r.attach, msg) + + # A general test of parser->model->generator idempotency. IOW, read a message # in, parse it into a message object tree, then without touching the tree, # regenerate the plain text. The original text and the transformed text diff --git a/Misc/NEWS.d/next/Tests/2021-11-28-15-25-02.bpo-19460.lr0aWs.rst b/Misc/NEWS.d/next/Tests/2021-11-28-15-25-02.bpo-19460.lr0aWs.rst new file mode 100644 index 0000000000000..b082d6de20c07 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-11-28-15-25-02.bpo-19460.lr0aWs.rst @@ -0,0 +1 @@ +Add new Test for :class:`email.mime.nonmultipart.MIMENonMultipart`. From webhook-mailer at python.org Sun Nov 28 13:40:40 2021 From: webhook-mailer at python.org (tiran) Date: Sun, 28 Nov 2021 18:40:40 -0000 Subject: [Python-checkins] bpo-45915: use fcntl(fd, F_GETFD) in is_valid_fd() (GH-29821) Message-ID: https://github.com/python/cpython/commit/f87ea0350286837e9e96de03f8bfa215176c2928 commit: f87ea0350286837e9e96de03f8bfa215176c2928 branch: main author: Christian Heimes committer: tiran date: 2021-11-28T19:40:27+01:00 summary: bpo-45915: use fcntl(fd, F_GETFD) in is_valid_fd() (GH-29821) files: A Misc/NEWS.d/next/Core and Builtins/2021-11-28-11-25-08.bpo-45915.TSGcLF.rst M Python/pylifecycle.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-28-11-25-08.bpo-45915.TSGcLF.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-28-11-25-08.bpo-45915.TSGcLF.rst new file mode 100644 index 0000000000000..aa268f4533310 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-28-11-25-08.bpo-45915.TSGcLF.rst @@ -0,0 +1 @@ +``is_valid_fd`` now uses faster ``fcntl(fd, F_GETFD)`` on Linux, macOS, and Windows. diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 7e6060e4ebcf7..74d269b7a5646 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -30,6 +30,10 @@ # include // nl_langinfo(CODESET) #endif +#ifdef HAVE_FCNTL_H +# include // F_GETFD +#endif + #ifdef MS_WINDOWS # undef BYTE # include "windows.h" @@ -2129,18 +2133,26 @@ is_valid_fd(int fd) startup. Problem: dup() doesn't check if the file descriptor is valid on some platforms. + fcntl(fd, F_GETFD) is even faster, because it only checks the process table. + bpo-30225: On macOS Tiger, when stdout is redirected to a pipe and the other side of the pipe is closed, dup(1) succeed, whereas fstat(1, &st) fails with EBADF. FreeBSD has similar issue (bpo-32849). Only use dup() on platforms where dup() is enough to detect invalid FD in - corner cases: on Linux and Windows (bpo-32849). */ -#if defined(__linux__) || defined(MS_WINDOWS) + corner cases: on Linux and Windows (bpo-32849). +*/ if (fd < 0) { return 0; } +#if defined(F_GETFD) && (defined(__linux__) || defined(__APPLE__) || defined(MS_WINDOWS)) + int res; + _Py_BEGIN_SUPPRESS_IPH + res = fcntl(fd, F_GETFD); + _Py_END_SUPPRESS_IPH + return res >= 0; +#elif defined(__linux__) || defined(MS_WINDOWS) int fd2; - _Py_BEGIN_SUPPRESS_IPH fd2 = dup(fd); if (fd2 >= 0) { From webhook-mailer at python.org Sun Nov 28 16:23:48 2021 From: webhook-mailer at python.org (pablogsal) Date: Sun, 28 Nov 2021 21:23:48 -0000 Subject: [Python-checkins] [3.10] bpo-42268: Fail the configure step if the selected compiler doesn't support memory sanitizer (GH-29806) (GH-29815) Message-ID: https://github.com/python/cpython/commit/8d1a5800645575ec876932bbb9aed3aa65d18f46 commit: 8d1a5800645575ec876932bbb9aed3aa65d18f46 branch: 3.10 author: Pablo Galindo Salgado committer: pablogsal date: 2021-11-28T21:23:39Z summary: [3.10] bpo-42268: Fail the configure step if the selected compiler doesn't support memory sanitizer (GH-29806) (GH-29815) (cherry picked from commit e71c12efcddc1076d5367461a5b416092267aa77) Co-authored-by: Pablo Galindo Salgado files: A Misc/NEWS.d/next/Core and Builtins/2021-11-26-22-31-22.bpo-42268.3wl-09.rst M configure M configure.ac M pyconfig.h.in diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-26-22-31-22.bpo-42268.3wl-09.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-26-22-31-22.bpo-42268.3wl-09.rst new file mode 100644 index 0000000000000..615bbb22ae2eb --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-26-22-31-22.bpo-42268.3wl-09.rst @@ -0,0 +1,2 @@ +Fail the configure step if the selected compiler doesn't support memory +sanitizer. Patch by Pablo Galindo diff --git a/configure b/configure index b344445a80541..2e7e0b7e0a75e 100755 --- a/configure +++ b/configure @@ -9605,8 +9605,44 @@ if test "${with_memory_sanitizer+set}" = set; then : withval=$with_memory_sanitizer; { $as_echo "$as_me:${as_lineno-$LINENO}: result: $withval" >&5 $as_echo "$withval" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fsanitize=memory" >&5 +$as_echo_n "checking whether C compiler accepts -fsanitize=memory... " >&6; } +if ${ax_cv_check_cflags___fsanitize_memory+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS -fsanitize=memory" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ax_cv_check_cflags___fsanitize_memory=yes +else + ax_cv_check_cflags___fsanitize_memory=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___fsanitize_memory" >&5 +$as_echo "$ax_cv_check_cflags___fsanitize_memory" >&6; } +if test "x$ax_cv_check_cflags___fsanitize_memory" = xyes; then : + BASECFLAGS="-fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer $BASECFLAGS" LDFLAGS="-fsanitize=memory -fsanitize-memory-track-origins=2 $LDFLAGS" + +else + as_fn_error $? "The selected compiler doesn't support memory sanitizer" "$LINENO" 5 +fi + # MSan works by controlling memory allocation, our own malloc interferes. with_pymalloc="no" @@ -10120,13 +10156,15 @@ $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# check for libuuid from util-linux save_LIBS=$LIBS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing uuid_generate_time_safe" >&5 -$as_echo_n "checking for library containing uuid_generate_time_safe... " >&6; } -if ${ac_cv_search_uuid_generate_time_safe+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time in -luuid" >&5 +$as_echo_n "checking for uuid_generate_time in -luuid... " >&6; } +if ${ac_cv_lib_uuid_uuid_generate_time+:} false; then : $as_echo_n "(cached) " >&6 else - ac_func_search_save_LIBS=$LIBS + ac_check_lib_save_LIBS=$LIBS +LIBS="-luuid $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -10136,61 +10174,39 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext #ifdef __cplusplus extern "C" #endif -char uuid_generate_time_safe (); +char uuid_generate_time (); int main () { -return uuid_generate_time_safe (); +return uuid_generate_time (); ; return 0; } _ACEOF -for ac_lib in '' uuid; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_uuid_generate_time_safe=$ac_res -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_uuid_generate_time_safe+:} false; then : - break -fi -done -if ${ac_cv_search_uuid_generate_time_safe+:} false; then : - +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_uuid_uuid_generate_time=yes else - ac_cv_search_uuid_generate_time_safe=no + ac_cv_lib_uuid_uuid_generate_time=no fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_uuid_generate_time_safe" >&5 -$as_echo "$ac_cv_search_uuid_generate_time_safe" >&6; } -ac_res=$ac_cv_search_uuid_generate_time_safe -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - - -$as_echo "#define HAVE_LIBUUID 1" >>confdefs.h -, - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_uuid_uuid_generate_time" >&5 +$as_echo "$ac_cv_lib_uuid_uuid_generate_time" >&6; } +if test "x$ac_cv_lib_uuid_uuid_generate_time" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBUUID 1 +_ACEOF -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + LIBS="-luuid $LIBS" fi LIBS=$save_LIBS # AIX provides support for RFC4122 (uuid) in libc.a starting with AIX 6.1 (anno 2007) -# FreeBSD and OpenBSD provides support as well +# FreeBSD and OpenBSD provides support in libc as well. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_create" >&5 $as_echo_n "checking for uuid_create... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext diff --git a/configure.ac b/configure.ac index c0db1f41d3b7d..0c06914147854 100644 --- a/configure.ac +++ b/configure.ac @@ -2583,8 +2583,10 @@ AC_ARG_WITH(memory_sanitizer, [enable MemorySanitizer allocation error detector, 'msan' (default is no)]), [ AC_MSG_RESULT($withval) +AX_CHECK_COMPILE_FLAG([-fsanitize=memory],[ BASECFLAGS="-fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer $BASECFLAGS" LDFLAGS="-fsanitize=memory -fsanitize-memory-track-origins=2 $LDFLAGS" +],[AC_MSG_ERROR([The selected compiler doesn't support memory sanitizer])]) # MSan works by controlling memory allocation, our own malloc interferes. with_pymalloc="no" ], diff --git a/pyconfig.h.in b/pyconfig.h.in index 41d3abbf536ca..b97b8f8bf8b4a 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -628,7 +628,7 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LIBUTIL_H -/* Define you have libuuid. */ +/* Define to 1 if you have the `uuid' library (-luuid). */ #undef HAVE_LIBUUID /* Define if you have the 'link' function. */ From webhook-mailer at python.org Mon Nov 29 03:13:14 2021 From: webhook-mailer at python.org (asvetlov) Date: Mon, 29 Nov 2021 08:13:14 -0000 Subject: [Python-checkins] bpo-37658: Actually return result in race condition (GH-29202) Message-ID: https://github.com/python/cpython/commit/934a82623793e9d52b85f74d5395d65927a52205 commit: 934a82623793e9d52b85f74d5395d65927a52205 branch: main author: Sam Bull committer: asvetlov date: 2021-11-29T10:12:57+02:00 summary: bpo-37658: Actually return result in race condition (GH-29202) files: A Misc/NEWS.d/next/Library/2021-11-28-15-30-34.bpo-37658.8Hno7d.rst M Lib/asyncio/tasks.py M Lib/test/test_asyncio/test_tasks.py diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 9a9d0d6e3cc26..53eef84427be1 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -415,11 +415,9 @@ async def wait_for(fut, timeout): await _cancel_and_wait(fut, loop=loop) try: - fut.result() + return fut.result() except exceptions.CancelledError as exc: raise exceptions.TimeoutError() from exc - else: - raise exceptions.TimeoutError() waiter = loop.create_future() timeout_handle = loop.call_later(timeout, _release_waiter, waiter) @@ -455,11 +453,9 @@ async def wait_for(fut, timeout): # exception, we should re-raise it # See https://bugs.python.org/issue40607 try: - fut.result() + return fut.result() except exceptions.CancelledError as exc: raise exceptions.TimeoutError() from exc - else: - raise exceptions.TimeoutError() finally: timeout_handle.cancel() diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 362fbf8df08ca..a88cb89e4e6ee 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -1009,20 +1009,16 @@ def gen(): self.assertEqual(res, "ok") def test_wait_for_cancellation_race_condition(self): - def gen(): - yield 0.1 - yield 0.1 - yield 0.1 - yield 0.1 + async def inner(): + with contextlib.suppress(asyncio.CancelledError): + await asyncio.sleep(1) + return 1 - loop = self.new_test_loop(gen) + async def main(): + result = await asyncio.wait_for(inner(), timeout=.01) + assert result == 1 - fut = self.new_future(loop) - loop.call_later(0.1, fut.set_result, "ok") - task = loop.create_task(asyncio.wait_for(fut, timeout=1)) - loop.call_later(0.1, task.cancel) - res = loop.run_until_complete(task) - self.assertEqual(res, "ok") + asyncio.run(main()) def test_wait_for_waits_for_task_cancellation(self): loop = asyncio.new_event_loop() @@ -1101,24 +1097,6 @@ async def inner(): with self.assertRaises(FooException): loop.run_until_complete(foo()) - def test_wait_for_raises_timeout_error_if_returned_during_cancellation(self): - loop = asyncio.new_event_loop() - self.addCleanup(loop.close) - - async def foo(): - async def inner(): - try: - await asyncio.sleep(0.2) - except asyncio.CancelledError: - return 42 - - inner_task = self.new_task(loop, inner()) - - await asyncio.wait_for(inner_task, timeout=_EPSILON) - - with self.assertRaises(asyncio.TimeoutError): - loop.run_until_complete(foo()) - def test_wait_for_self_cancellation(self): loop = asyncio.new_event_loop() self.addCleanup(loop.close) diff --git a/Misc/NEWS.d/next/Library/2021-11-28-15-30-34.bpo-37658.8Hno7d.rst b/Misc/NEWS.d/next/Library/2021-11-28-15-30-34.bpo-37658.8Hno7d.rst new file mode 100644 index 0000000000000..97d1e961ac2be --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-28-15-30-34.bpo-37658.8Hno7d.rst @@ -0,0 +1,3 @@ +Fix issue when on certain conditions ``asyncio.wait_for()`` may allow a +coroutine to complete successfully, but fail to return the result, +potentially causing memory leaks or other issues. From webhook-mailer at python.org Mon Nov 29 03:20:15 2021 From: webhook-mailer at python.org (isidentical) Date: Mon, 29 Nov 2021 08:20:15 -0000 Subject: [Python-checkins] Remove misleading comment in the AST optimizer (#29825) Message-ID: https://github.com/python/cpython/commit/87d5180b7abbb8cf6213361f6bdd57cb605894d2 commit: 87d5180b7abbb8cf6213361f6bdd57cb605894d2 branch: main author: Serhiy Storchaka committer: isidentical date: 2021-11-29T11:19:59+03:00 summary: Remove misleading comment in the AST optimizer (#29825) files: M Python/ast_opt.c diff --git a/Python/ast_opt.c b/Python/ast_opt.c index 356f60e2d5399..5f219c6f4bbf7 100644 --- a/Python/ast_opt.c +++ b/Python/ast_opt.c @@ -618,7 +618,6 @@ fold_compare(expr_ty node, PyArena *arena, _PyASTOptimizeState *state) ops = node->v.Compare.ops; args = node->v.Compare.comparators; - /* TODO: optimize cases with literal arguments. */ /* Change literal list or set in 'in' or 'not in' into tuple or frozenset respectively. */ i = asdl_seq_LEN(ops) - 1; From webhook-mailer at python.org Mon Nov 29 03:37:47 2021 From: webhook-mailer at python.org (miss-islington) Date: Mon, 29 Nov 2021 08:37:47 -0000 Subject: [Python-checkins] bpo-37658: Actually return result in race condition (GH-29202) Message-ID: https://github.com/python/cpython/commit/305236e03a274850be8ed399ea3390ee71519ef4 commit: 305236e03a274850be8ed399ea3390ee71519ef4 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-29T00:37:34-08:00 summary: bpo-37658: Actually return result in race condition (GH-29202) (cherry picked from commit 934a82623793e9d52b85f74d5395d65927a52205) Co-authored-by: Sam Bull files: A Misc/NEWS.d/next/Library/2021-11-28-15-30-34.bpo-37658.8Hno7d.rst M Lib/asyncio/tasks.py M Lib/test/test_asyncio/test_tasks.py diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 9a9d0d6e3cc26..53eef84427be1 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -415,11 +415,9 @@ async def wait_for(fut, timeout): await _cancel_and_wait(fut, loop=loop) try: - fut.result() + return fut.result() except exceptions.CancelledError as exc: raise exceptions.TimeoutError() from exc - else: - raise exceptions.TimeoutError() waiter = loop.create_future() timeout_handle = loop.call_later(timeout, _release_waiter, waiter) @@ -455,11 +453,9 @@ async def wait_for(fut, timeout): # exception, we should re-raise it # See https://bugs.python.org/issue40607 try: - fut.result() + return fut.result() except exceptions.CancelledError as exc: raise exceptions.TimeoutError() from exc - else: - raise exceptions.TimeoutError() finally: timeout_handle.cancel() diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index ff627a6980ea0..773d5057fe4b2 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -1148,20 +1148,16 @@ def gen(): self.assertEqual(res, "ok") def test_wait_for_cancellation_race_condition(self): - def gen(): - yield 0.1 - yield 0.1 - yield 0.1 - yield 0.1 + async def inner(): + with contextlib.suppress(asyncio.CancelledError): + await asyncio.sleep(1) + return 1 - loop = self.new_test_loop(gen) + async def main(): + result = await asyncio.wait_for(inner(), timeout=.01) + assert result == 1 - fut = self.new_future(loop) - loop.call_later(0.1, fut.set_result, "ok") - task = loop.create_task(asyncio.wait_for(fut, timeout=1)) - loop.call_later(0.1, task.cancel) - res = loop.run_until_complete(task) - self.assertEqual(res, "ok") + asyncio.run(main()) def test_wait_for_waits_for_task_cancellation(self): loop = asyncio.new_event_loop() @@ -1240,24 +1236,6 @@ async def inner(): with self.assertRaises(FooException): loop.run_until_complete(foo()) - def test_wait_for_raises_timeout_error_if_returned_during_cancellation(self): - loop = asyncio.new_event_loop() - self.addCleanup(loop.close) - - async def foo(): - async def inner(): - try: - await asyncio.sleep(0.2) - except asyncio.CancelledError: - return 42 - - inner_task = self.new_task(loop, inner()) - - await asyncio.wait_for(inner_task, timeout=_EPSILON) - - with self.assertRaises(asyncio.TimeoutError): - loop.run_until_complete(foo()) - def test_wait_for_self_cancellation(self): loop = asyncio.new_event_loop() self.addCleanup(loop.close) diff --git a/Misc/NEWS.d/next/Library/2021-11-28-15-30-34.bpo-37658.8Hno7d.rst b/Misc/NEWS.d/next/Library/2021-11-28-15-30-34.bpo-37658.8Hno7d.rst new file mode 100644 index 0000000000000..97d1e961ac2be --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-28-15-30-34.bpo-37658.8Hno7d.rst @@ -0,0 +1,3 @@ +Fix issue when on certain conditions ``asyncio.wait_for()`` may allow a +coroutine to complete successfully, but fail to return the result, +potentially causing memory leaks or other issues. From webhook-mailer at python.org Mon Nov 29 04:36:15 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 29 Nov 2021 09:36:15 -0000 Subject: [Python-checkins] bpo-45847: Fix _multiprocessing on platforms without sem_open (GH-29833) Message-ID: https://github.com/python/cpython/commit/4dc198dedd66e3247aa934fb91c9a158c3eea15a commit: 4dc198dedd66e3247aa934fb91c9a158c3eea15a branch: main author: Christian Heimes committer: tiran date: 2021-11-29T10:36:10+01:00 summary: bpo-45847: Fix _multiprocessing on platforms without sem_open (GH-29833) files: M Modules/_multiprocessing/clinic/semaphore.c.h M Modules/_multiprocessing/multiprocessing.c M Modules/_multiprocessing/multiprocessing.h M Modules/_multiprocessing/semaphore.c diff --git a/Modules/_multiprocessing/clinic/semaphore.c.h b/Modules/_multiprocessing/clinic/semaphore.c.h index e1b9309e9f280..018447ad137ba 100644 --- a/Modules/_multiprocessing/clinic/semaphore.c.h +++ b/Modules/_multiprocessing/clinic/semaphore.c.h @@ -2,7 +2,7 @@ preserve [clinic start generated code]*/ -#if defined(MS_WINDOWS) +#if defined(HAVE_MP_SEMAPHORE) && defined(MS_WINDOWS) PyDoc_STRVAR(_multiprocessing_SemLock_acquire__doc__, "acquire($self, /, block=True, timeout=None)\n" @@ -52,9 +52,9 @@ _multiprocessing_SemLock_acquire(SemLockObject *self, PyObject *const *args, Py_ return return_value; } -#endif /* defined(MS_WINDOWS) */ +#endif /* defined(HAVE_MP_SEMAPHORE) && defined(MS_WINDOWS) */ -#if defined(MS_WINDOWS) +#if defined(HAVE_MP_SEMAPHORE) && defined(MS_WINDOWS) PyDoc_STRVAR(_multiprocessing_SemLock_release__doc__, "release($self, /)\n" @@ -74,9 +74,9 @@ _multiprocessing_SemLock_release(SemLockObject *self, PyObject *Py_UNUSED(ignore return _multiprocessing_SemLock_release_impl(self); } -#endif /* defined(MS_WINDOWS) */ +#endif /* defined(HAVE_MP_SEMAPHORE) && defined(MS_WINDOWS) */ -#if !defined(MS_WINDOWS) +#if defined(HAVE_MP_SEMAPHORE) && !defined(MS_WINDOWS) PyDoc_STRVAR(_multiprocessing_SemLock_acquire__doc__, "acquire($self, /, block=True, timeout=None)\n" @@ -126,9 +126,9 @@ _multiprocessing_SemLock_acquire(SemLockObject *self, PyObject *const *args, Py_ return return_value; } -#endif /* !defined(MS_WINDOWS) */ +#endif /* defined(HAVE_MP_SEMAPHORE) && !defined(MS_WINDOWS) */ -#if !defined(MS_WINDOWS) +#if defined(HAVE_MP_SEMAPHORE) && !defined(MS_WINDOWS) PyDoc_STRVAR(_multiprocessing_SemLock_release__doc__, "release($self, /)\n" @@ -148,7 +148,9 @@ _multiprocessing_SemLock_release(SemLockObject *self, PyObject *Py_UNUSED(ignore return _multiprocessing_SemLock_release_impl(self); } -#endif /* !defined(MS_WINDOWS) */ +#endif /* defined(HAVE_MP_SEMAPHORE) && !defined(MS_WINDOWS) */ + +#if defined(HAVE_MP_SEMAPHORE) static PyObject * _multiprocessing_SemLock_impl(PyTypeObject *type, int kind, int value, @@ -208,6 +210,10 @@ _multiprocessing_SemLock(PyTypeObject *type, PyObject *args, PyObject *kwargs) return return_value; } +#endif /* defined(HAVE_MP_SEMAPHORE) */ + +#if defined(HAVE_MP_SEMAPHORE) + PyDoc_STRVAR(_multiprocessing_SemLock__rebuild__doc__, "_rebuild($type, handle, kind, maxvalue, name, /)\n" "--\n" @@ -240,6 +246,10 @@ _multiprocessing_SemLock__rebuild(PyTypeObject *type, PyObject *const *args, Py_ return return_value; } +#endif /* defined(HAVE_MP_SEMAPHORE) */ + +#if defined(HAVE_MP_SEMAPHORE) + PyDoc_STRVAR(_multiprocessing_SemLock__count__doc__, "_count($self, /)\n" "--\n" @@ -258,6 +268,10 @@ _multiprocessing_SemLock__count(SemLockObject *self, PyObject *Py_UNUSED(ignored return _multiprocessing_SemLock__count_impl(self); } +#endif /* defined(HAVE_MP_SEMAPHORE) */ + +#if defined(HAVE_MP_SEMAPHORE) + PyDoc_STRVAR(_multiprocessing_SemLock__is_mine__doc__, "_is_mine($self, /)\n" "--\n" @@ -276,6 +290,10 @@ _multiprocessing_SemLock__is_mine(SemLockObject *self, PyObject *Py_UNUSED(ignor return _multiprocessing_SemLock__is_mine_impl(self); } +#endif /* defined(HAVE_MP_SEMAPHORE) */ + +#if defined(HAVE_MP_SEMAPHORE) + PyDoc_STRVAR(_multiprocessing_SemLock__get_value__doc__, "_get_value($self, /)\n" "--\n" @@ -294,6 +312,10 @@ _multiprocessing_SemLock__get_value(SemLockObject *self, PyObject *Py_UNUSED(ign return _multiprocessing_SemLock__get_value_impl(self); } +#endif /* defined(HAVE_MP_SEMAPHORE) */ + +#if defined(HAVE_MP_SEMAPHORE) + PyDoc_STRVAR(_multiprocessing_SemLock__is_zero__doc__, "_is_zero($self, /)\n" "--\n" @@ -312,6 +334,10 @@ _multiprocessing_SemLock__is_zero(SemLockObject *self, PyObject *Py_UNUSED(ignor return _multiprocessing_SemLock__is_zero_impl(self); } +#endif /* defined(HAVE_MP_SEMAPHORE) */ + +#if defined(HAVE_MP_SEMAPHORE) + PyDoc_STRVAR(_multiprocessing_SemLock__after_fork__doc__, "_after_fork($self, /)\n" "--\n" @@ -330,6 +356,10 @@ _multiprocessing_SemLock__after_fork(SemLockObject *self, PyObject *Py_UNUSED(ig return _multiprocessing_SemLock__after_fork_impl(self); } +#endif /* defined(HAVE_MP_SEMAPHORE) */ + +#if defined(HAVE_MP_SEMAPHORE) + PyDoc_STRVAR(_multiprocessing_SemLock___enter____doc__, "__enter__($self, /)\n" "--\n" @@ -348,6 +378,10 @@ _multiprocessing_SemLock___enter__(SemLockObject *self, PyObject *Py_UNUSED(igno return _multiprocessing_SemLock___enter___impl(self); } +#endif /* defined(HAVE_MP_SEMAPHORE) */ + +#if defined(HAVE_MP_SEMAPHORE) + PyDoc_STRVAR(_multiprocessing_SemLock___exit____doc__, "__exit__($self, exc_type=None, exc_value=None, exc_tb=None, /)\n" "--\n" @@ -392,6 +426,8 @@ _multiprocessing_SemLock___exit__(SemLockObject *self, PyObject *const *args, Py return return_value; } +#endif /* defined(HAVE_MP_SEMAPHORE) */ + #ifndef _MULTIPROCESSING_SEMLOCK_ACQUIRE_METHODDEF #define _MULTIPROCESSING_SEMLOCK_ACQUIRE_METHODDEF #endif /* !defined(_MULTIPROCESSING_SEMLOCK_ACQUIRE_METHODDEF) */ @@ -399,4 +435,36 @@ _multiprocessing_SemLock___exit__(SemLockObject *self, PyObject *const *args, Py #ifndef _MULTIPROCESSING_SEMLOCK_RELEASE_METHODDEF #define _MULTIPROCESSING_SEMLOCK_RELEASE_METHODDEF #endif /* !defined(_MULTIPROCESSING_SEMLOCK_RELEASE_METHODDEF) */ -/*[clinic end generated code: output=e7fd938150601fe5 input=a9049054013a1b77]*/ + +#ifndef _MULTIPROCESSING_SEMLOCK__REBUILD_METHODDEF + #define _MULTIPROCESSING_SEMLOCK__REBUILD_METHODDEF +#endif /* !defined(_MULTIPROCESSING_SEMLOCK__REBUILD_METHODDEF) */ + +#ifndef _MULTIPROCESSING_SEMLOCK__COUNT_METHODDEF + #define _MULTIPROCESSING_SEMLOCK__COUNT_METHODDEF +#endif /* !defined(_MULTIPROCESSING_SEMLOCK__COUNT_METHODDEF) */ + +#ifndef _MULTIPROCESSING_SEMLOCK__IS_MINE_METHODDEF + #define _MULTIPROCESSING_SEMLOCK__IS_MINE_METHODDEF +#endif /* !defined(_MULTIPROCESSING_SEMLOCK__IS_MINE_METHODDEF) */ + +#ifndef _MULTIPROCESSING_SEMLOCK__GET_VALUE_METHODDEF + #define _MULTIPROCESSING_SEMLOCK__GET_VALUE_METHODDEF +#endif /* !defined(_MULTIPROCESSING_SEMLOCK__GET_VALUE_METHODDEF) */ + +#ifndef _MULTIPROCESSING_SEMLOCK__IS_ZERO_METHODDEF + #define _MULTIPROCESSING_SEMLOCK__IS_ZERO_METHODDEF +#endif /* !defined(_MULTIPROCESSING_SEMLOCK__IS_ZERO_METHODDEF) */ + +#ifndef _MULTIPROCESSING_SEMLOCK__AFTER_FORK_METHODDEF + #define _MULTIPROCESSING_SEMLOCK__AFTER_FORK_METHODDEF +#endif /* !defined(_MULTIPROCESSING_SEMLOCK__AFTER_FORK_METHODDEF) */ + +#ifndef _MULTIPROCESSING_SEMLOCK___ENTER___METHODDEF + #define _MULTIPROCESSING_SEMLOCK___ENTER___METHODDEF +#endif /* !defined(_MULTIPROCESSING_SEMLOCK___ENTER___METHODDEF) */ + +#ifndef _MULTIPROCESSING_SEMLOCK___EXIT___METHODDEF + #define _MULTIPROCESSING_SEMLOCK___EXIT___METHODDEF +#endif /* !defined(_MULTIPROCESSING_SEMLOCK___EXIT___METHODDEF) */ +/*[clinic end generated code: output=fde05a081b5bdba4 input=a9049054013a1b77]*/ diff --git a/Modules/_multiprocessing/multiprocessing.c b/Modules/_multiprocessing/multiprocessing.c index bec23517fca51..0809c2455dbeb 100644 --- a/Modules/_multiprocessing/multiprocessing.c +++ b/Modules/_multiprocessing/multiprocessing.c @@ -186,8 +186,7 @@ static PyMethodDef module_methods[] = { static int multiprocessing_exec(PyObject *module) { -#if defined(MS_WINDOWS) || \ - (defined(HAVE_SEM_OPEN) && !defined(POSIX_SEMAPHORES_NOT_ENABLED)) +#ifdef HAVE_MP_SEMAPHORE /* Add _PyMp_SemLock type to module */ if (PyModule_AddType(module, &_PyMp_SemLockType) < 0) { diff --git a/Modules/_multiprocessing/multiprocessing.h b/Modules/_multiprocessing/multiprocessing.h index 277963bc1575b..3a8314b1db833 100644 --- a/Modules/_multiprocessing/multiprocessing.h +++ b/Modules/_multiprocessing/multiprocessing.h @@ -21,9 +21,11 @@ # endif # define SEM_HANDLE HANDLE # define SEM_VALUE_MAX LONG_MAX +# define HAVE_MP_SEMAPHORE #else # include /* O_CREAT and O_EXCL */ # if defined(HAVE_SEM_OPEN) && !defined(POSIX_SEMAPHORES_NOT_ENABLED) +# define HAVE_MP_SEMAPHORE # include typedef sem_t *SEM_HANDLE; # endif diff --git a/Modules/_multiprocessing/semaphore.c b/Modules/_multiprocessing/semaphore.c index 9a2d1f85c92fa..8607476aff10f 100644 --- a/Modules/_multiprocessing/semaphore.c +++ b/Modules/_multiprocessing/semaphore.c @@ -9,6 +9,8 @@ #include "multiprocessing.h" +#ifdef HAVE_MP_SEMAPHORE + enum { RECURSIVE_MUTEX, SEMAPHORE }; typedef struct { @@ -794,3 +796,5 @@ _PyMp_sem_unlink(const char *name) Py_RETURN_NONE; } + +#endif // HAVE_MP_SEMAPHORE From webhook-mailer at python.org Mon Nov 29 05:08:02 2021 From: webhook-mailer at python.org (iritkatriel) Date: Mon, 29 Nov 2021 10:08:02 -0000 Subject: [Python-checkins] bpo-45614: Fix traceback display for exceptions with invalid module name (GH-29726) (GH-29826) Message-ID: https://github.com/python/cpython/commit/4d2cc3ed46d2453bad92243128e237e7febca714 commit: 4d2cc3ed46d2453bad92243128e237e7febca714 branch: 3.10 author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-11-29T10:07:24Z summary: bpo-45614: Fix traceback display for exceptions with invalid module name (GH-29726) (GH-29826) (cherry picked from commit 4dfae6f38e1720ddafcdd68043e476ecb41cb4d5) files: A Misc/NEWS.d/next/Core and Builtins/2021-11-23-12-06-41.bpo-45614.fIekgI.rst M Lib/test/test_traceback.py M Lib/traceback.py M Python/pythonrun.c diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index ba03ce46294c5..18cd4aba24af2 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -785,6 +785,17 @@ def test_message_none(self): err = self.get_report(Exception('')) self.assertIn('Exception\n', err) + def test_exception_modulename_not_unicode(self): + class X(Exception): + def __str__(self): + return "I am X" + + X.__module__ = 42 + + err = self.get_report(X()) + exp = f'.{X.__qualname__}: I am X\n' + self.assertEqual(exp, err) + def test_syntax_error_various_offsets(self): for offset in range(-5, 10): for add in [0, 2]: diff --git a/Lib/traceback.py b/Lib/traceback.py index 901b99476aaf8..d6a010f415758 100644 --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -604,6 +604,8 @@ def format_exception_only(self): stype = self.exc_type.__qualname__ smod = self.exc_type.__module__ if smod not in ("__main__", "builtins"): + if not isinstance(smod, str): + smod = "" stype = smod + '.' + stype if not issubclass(self.exc_type, SyntaxError): diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-23-12-06-41.bpo-45614.fIekgI.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-23-12-06-41.bpo-45614.fIekgI.rst new file mode 100644 index 0000000000000..4255e1885ad67 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-23-12-06-41.bpo-45614.fIekgI.rst @@ -0,0 +1 @@ +Fix :mod:`traceback` display for exceptions with invalid module name. \ No newline at end of file diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 5704bcc7589f3..0f1794acec73a 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -972,7 +972,7 @@ print_exception(PyObject *f, PyObject *value) { Py_XDECREF(modulename); PyErr_Clear(); - err = PyFile_WriteString("", f); + err = PyFile_WriteString(".", f); } else { if (!_PyUnicode_EqualToASCIIId(modulename, &PyId_builtins)) From webhook-mailer at python.org Mon Nov 29 05:11:53 2021 From: webhook-mailer at python.org (iritkatriel) Date: Mon, 29 Nov 2021 10:11:53 -0000 Subject: [Python-checkins] bpo-45614: Fix traceback display for exceptions with invalid module name (GH-29726) (GH-29827) Message-ID: https://github.com/python/cpython/commit/5b6aa6ce20b5b3b45dec2ebd6355e248cdf2fbcc commit: 5b6aa6ce20b5b3b45dec2ebd6355e248cdf2fbcc branch: 3.9 author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-11-29T10:11:48Z summary: bpo-45614: Fix traceback display for exceptions with invalid module name (GH-29726) (GH-29827) (cherry picked from commit 4dfae6f38e1720ddafcdd68043e476ecb41cb4d5) files: A Misc/NEWS.d/next/Core and Builtins/2021-11-23-12-06-41.bpo-45614.fIekgI.rst M Lib/test/test_traceback.py M Lib/traceback.py M Python/pythonrun.c diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index 8d9d514d8deaa..c0b3388b2d363 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -740,6 +740,17 @@ def test_message_none(self): err = self.get_report(Exception('')) self.assertIn('Exception\n', err) + def test_exception_modulename_not_unicode(self): + class X(Exception): + def __str__(self): + return "I am X" + + X.__module__ = 42 + + err = self.get_report(X()) + exp = f'.{X.__qualname__}: I am X\n' + self.assertEqual(exp, err) + def test_syntax_error_various_offsets(self): for offset in range(-5, 10): for add in [0, 2]: diff --git a/Lib/traceback.py b/Lib/traceback.py index d65a6098cc621..c771a137cd9e8 100644 --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -574,6 +574,8 @@ def format_exception_only(self): stype = self.exc_type.__qualname__ smod = self.exc_type.__module__ if smod not in ("__main__", "builtins"): + if not isinstance(smod, str): + smod = "" stype = smod + '.' + stype if not issubclass(self.exc_type, SyntaxError): diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-23-12-06-41.bpo-45614.fIekgI.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-23-12-06-41.bpo-45614.fIekgI.rst new file mode 100644 index 0000000000000..4255e1885ad67 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-23-12-06-41.bpo-45614.fIekgI.rst @@ -0,0 +1 @@ +Fix :mod:`traceback` display for exceptions with invalid module name. \ No newline at end of file diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 50c59b69f31fc..364101e99de2d 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -903,7 +903,7 @@ print_exception(PyObject *f, PyObject *value) { Py_XDECREF(modulename); PyErr_Clear(); - err = PyFile_WriteString("", f); + err = PyFile_WriteString(".", f); } else { if (!_PyUnicode_EqualToASCIIId(modulename, &PyId_builtins)) From webhook-mailer at python.org Mon Nov 29 06:39:39 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 29 Nov 2021 11:39:39 -0000 Subject: [Python-checkins] bpo-40280: Disable unusable core extension modules on emscripten (GH-29834) Message-ID: https://github.com/python/cpython/commit/b3f443a35e08a473d52868621e9b268259139cb2 commit: b3f443a35e08a473d52868621e9b268259139cb2 branch: main author: Erlend Egeberg Aasland committer: tiran date: 2021-11-29T12:39:14+01:00 summary: bpo-40280: Disable unusable core extension modules on emscripten (GH-29834) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Build/2021-11-29-11-24-45.bpo-40280.Knx7d7.rst M configure M configure.ac diff --git a/Misc/NEWS.d/next/Build/2021-11-29-11-24-45.bpo-40280.Knx7d7.rst b/Misc/NEWS.d/next/Build/2021-11-29-11-24-45.bpo-40280.Knx7d7.rst new file mode 100644 index 0000000000000..28bcb4423ceb2 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-29-11-24-45.bpo-40280.Knx7d7.rst @@ -0,0 +1 @@ +Disable unusable core extension modules on WASM/Emscripten targets. diff --git a/configure b/configure index 32aed7e49f2c0..0f96171264940 100755 --- a/configure +++ b/configure @@ -21047,6 +21047,10 @@ case $ac_sys_system in #( py_stdlib_not_available="_scproxy nis" ;; #( FreeBSD*) : py_stdlib_not_available="_scproxy spwd" ;; #( + Emscripten) : + + py_stdlib_not_available="_curses _curses_panel _dbm _gdbm _multiprocessing _posixshmem _posixsubprocess _scproxy _xxsubinterpreters grp nis ossaudiodev resource spwd syslog termios" + ;; #( *) : py_stdlib_not_available="_scproxy" ;; diff --git a/configure.ac b/configure.ac index ec71470a74e02..21429470ebacb 100644 --- a/configure.ac +++ b/configure.ac @@ -6191,6 +6191,26 @@ AS_CASE([$ac_sys_system], [CYGWIN*], [py_stdlib_not_available="_scproxy nis"], [QNX*], [py_stdlib_not_available="_scproxy nis"], [FreeBSD*], [py_stdlib_not_available="_scproxy spwd"], + [Emscripten], [ + py_stdlib_not_available="m4_normalize([ + _curses + _curses_panel + _dbm + _gdbm + _multiprocessing + _posixshmem + _posixsubprocess + _scproxy + _xxsubinterpreters + grp + nis + ossaudiodev + resource + spwd + syslog + termios + ])" + ], [py_stdlib_not_available="_scproxy"] ) From webhook-mailer at python.org Mon Nov 29 07:03:05 2021 From: webhook-mailer at python.org (asvetlov) Date: Mon, 29 Nov 2021 12:03:05 -0000 Subject: [Python-checkins] bpo-43498: Fix dictionary iteration error in _ExecutorManagerThread (GH-24868) Message-ID: https://github.com/python/cpython/commit/7431448b817d3bf87f71661cf8f3d537807ab2e2 commit: 7431448b817d3bf87f71661cf8f3d537807ab2e2 branch: main author: Jakub Kul?k committer: asvetlov date: 2021-11-29T14:02:56+02:00 summary: bpo-43498: Fix dictionary iteration error in _ExecutorManagerThread (GH-24868) files: A Misc/NEWS.d/next/Library/2021-04-20-14-14-16.bpo-43498.L_Hq-8.rst M Lib/concurrent/futures/process.py diff --git a/Lib/concurrent/futures/process.py b/Lib/concurrent/futures/process.py index 19e93a608b276..695f7733305ed 100644 --- a/Lib/concurrent/futures/process.py +++ b/Lib/concurrent/futures/process.py @@ -400,7 +400,7 @@ def wait_result_broken_or_wakeup(self): assert not self.thread_wakeup._closed wakeup_reader = self.thread_wakeup._reader readers = [result_reader, wakeup_reader] - worker_sentinels = [p.sentinel for p in self.processes.values()] + worker_sentinels = [p.sentinel for p in list(self.processes.values())] ready = mp.connection.wait(readers + worker_sentinels) cause = None diff --git a/Misc/NEWS.d/next/Library/2021-04-20-14-14-16.bpo-43498.L_Hq-8.rst b/Misc/NEWS.d/next/Library/2021-04-20-14-14-16.bpo-43498.L_Hq-8.rst new file mode 100644 index 0000000000000..4713d1427ccd3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-04-20-14-14-16.bpo-43498.L_Hq-8.rst @@ -0,0 +1,2 @@ +Avoid a possible *"RuntimeError: dictionary changed size during iteration"* +when adjusting the process count of :class:`ProcessPoolExecutor`. From webhook-mailer at python.org Mon Nov 29 07:24:44 2021 From: webhook-mailer at python.org (miss-islington) Date: Mon, 29 Nov 2021 12:24:44 -0000 Subject: [Python-checkins] bpo-43498: Fix dictionary iteration error in _ExecutorManagerThread (GH-24868) Message-ID: https://github.com/python/cpython/commit/4b11d7118561a12322d3cfa76c5941690b241149 commit: 4b11d7118561a12322d3cfa76c5941690b241149 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-29T04:24:08-08:00 summary: bpo-43498: Fix dictionary iteration error in _ExecutorManagerThread (GH-24868) (cherry picked from commit 7431448b817d3bf87f71661cf8f3d537807ab2e2) Co-authored-by: Jakub Kul?k files: A Misc/NEWS.d/next/Library/2021-04-20-14-14-16.bpo-43498.L_Hq-8.rst M Lib/concurrent/futures/process.py diff --git a/Lib/concurrent/futures/process.py b/Lib/concurrent/futures/process.py index 764719859f7ce..6ee2ce626e456 100644 --- a/Lib/concurrent/futures/process.py +++ b/Lib/concurrent/futures/process.py @@ -373,7 +373,7 @@ def wait_result_broken_or_wakeup(self): assert not self.thread_wakeup._closed wakeup_reader = self.thread_wakeup._reader readers = [result_reader, wakeup_reader] - worker_sentinels = [p.sentinel for p in self.processes.values()] + worker_sentinels = [p.sentinel for p in list(self.processes.values())] ready = mp.connection.wait(readers + worker_sentinels) cause = None diff --git a/Misc/NEWS.d/next/Library/2021-04-20-14-14-16.bpo-43498.L_Hq-8.rst b/Misc/NEWS.d/next/Library/2021-04-20-14-14-16.bpo-43498.L_Hq-8.rst new file mode 100644 index 0000000000000..4713d1427ccd3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-04-20-14-14-16.bpo-43498.L_Hq-8.rst @@ -0,0 +1,2 @@ +Avoid a possible *"RuntimeError: dictionary changed size during iteration"* +when adjusting the process count of :class:`ProcessPoolExecutor`. From webhook-mailer at python.org Mon Nov 29 07:28:55 2021 From: webhook-mailer at python.org (miss-islington) Date: Mon, 29 Nov 2021 12:28:55 -0000 Subject: [Python-checkins] bpo-43498: Fix dictionary iteration error in _ExecutorManagerThread (GH-24868) Message-ID: https://github.com/python/cpython/commit/3b9d886567c4fc6279c2198b6711f0590dbf3336 commit: 3b9d886567c4fc6279c2198b6711f0590dbf3336 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-29T04:28:46-08:00 summary: bpo-43498: Fix dictionary iteration error in _ExecutorManagerThread (GH-24868) (cherry picked from commit 7431448b817d3bf87f71661cf8f3d537807ab2e2) Co-authored-by: Jakub Kul?k files: A Misc/NEWS.d/next/Library/2021-04-20-14-14-16.bpo-43498.L_Hq-8.rst M Lib/concurrent/futures/process.py diff --git a/Lib/concurrent/futures/process.py b/Lib/concurrent/futures/process.py index 90bc98bf2ecd1..a29e5247ab85c 100644 --- a/Lib/concurrent/futures/process.py +++ b/Lib/concurrent/futures/process.py @@ -373,7 +373,7 @@ def wait_result_broken_or_wakeup(self): assert not self.thread_wakeup._closed wakeup_reader = self.thread_wakeup._reader readers = [result_reader, wakeup_reader] - worker_sentinels = [p.sentinel for p in self.processes.values()] + worker_sentinels = [p.sentinel for p in list(self.processes.values())] ready = mp.connection.wait(readers + worker_sentinels) cause = None diff --git a/Misc/NEWS.d/next/Library/2021-04-20-14-14-16.bpo-43498.L_Hq-8.rst b/Misc/NEWS.d/next/Library/2021-04-20-14-14-16.bpo-43498.L_Hq-8.rst new file mode 100644 index 0000000000000..4713d1427ccd3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-04-20-14-14-16.bpo-43498.L_Hq-8.rst @@ -0,0 +1,2 @@ +Avoid a possible *"RuntimeError: dictionary changed size during iteration"* +when adjusting the process count of :class:`ProcessPoolExecutor`. From webhook-mailer at python.org Mon Nov 29 07:35:09 2021 From: webhook-mailer at python.org (markshannon) Date: Mon, 29 Nov 2021 12:35:09 -0000 Subject: [Python-checkins] bpo-45786: Allocate space for frame in frame object. (GH-29729) Message-ID: https://github.com/python/cpython/commit/60929576e40038ec71d896230f69e4411c82be4b commit: 60929576e40038ec71d896230f69e4411c82be4b branch: main author: Mark Shannon committer: markshannon date: 2021-11-29T12:34:59Z summary: bpo-45786: Allocate space for frame in frame object. (GH-29729) files: A Misc/NEWS.d/next/Core and Builtins/2021-11-23-15-25-00.bpo-45786.UdEciD.rst M Include/cpython/frameobject.h M Include/internal/pycore_frame.h M Include/internal/pycore_gc.h M Include/internal/pycore_interp.h M Lib/test/test_exceptions.py M Lib/test/test_sys.py M Modules/gcmodule.c M Objects/frameobject.c M Objects/genobject.c M Python/ceval.c M Python/frame.c diff --git a/Include/cpython/frameobject.h b/Include/cpython/frameobject.h index e4cfac518bb58..67f98a7642beb 100644 --- a/Include/cpython/frameobject.h +++ b/Include/cpython/frameobject.h @@ -12,7 +12,9 @@ struct _frame { int f_lineno; /* Current line number. Only valid if non-zero */ char f_trace_lines; /* Emit per-line trace events? */ char f_trace_opcodes; /* Emit per-opcode trace events? */ - char f_own_locals_memory; /* This frame owns the memory for the locals */ + char f_owns_frame; /* This frame owns the frame */ + /* The frame data, if this frame object owns the frame */ + PyObject *_f_frame_data[1]; }; /* Standard object interface */ @@ -26,7 +28,7 @@ PyAPI_FUNC(PyFrameObject *) PyFrame_New(PyThreadState *, PyCodeObject *, /* only internal use */ PyFrameObject* -_PyFrame_New_NoTrack(struct _interpreter_frame *, int); +_PyFrame_New_NoTrack(PyCodeObject *code); /* The rest of the interface is specific for frame objects */ diff --git a/Include/internal/pycore_frame.h b/Include/internal/pycore_frame.h index e36241f4a6a65..0015de8f8fcb4 100644 --- a/Include/internal/pycore_frame.h +++ b/Include/internal/pycore_frame.h @@ -69,8 +69,7 @@ static inline void _PyFrame_StackPush(InterpreterFrame *f, PyObject *value) { #define FRAME_SPECIALS_SIZE ((sizeof(InterpreterFrame)-1)/sizeof(PyObject *)) -InterpreterFrame * -_PyInterpreterFrame_HeapAlloc(PyFunctionObject *func, PyObject *locals); +InterpreterFrame *_PyFrame_Copy(InterpreterFrame *frame); static inline void _PyFrame_InitializeSpecials( @@ -139,8 +138,8 @@ _PyFrame_GetFrameObject(InterpreterFrame *frame) * take should be set to 1 for heap allocated * frames like the ones in generators and coroutines. */ -int -_PyFrame_Clear(InterpreterFrame * frame, int take); +void +_PyFrame_Clear(InterpreterFrame * frame); int _PyFrame_Traverse(InterpreterFrame *frame, visitproc visit, void *arg); diff --git a/Include/internal/pycore_gc.h b/Include/internal/pycore_gc.h index 45e85b54c2ec2..129d53921dc49 100644 --- a/Include/internal/pycore_gc.h +++ b/Include/internal/pycore_gc.h @@ -167,7 +167,6 @@ extern Py_ssize_t _PyGC_CollectNoFail(PyThreadState *tstate); // Functions to clear types free lists -extern void _PyFrame_ClearFreeList(PyInterpreterState *interp); extern void _PyTuple_ClearFreeList(PyInterpreterState *interp); extern void _PyFloat_ClearFreeList(PyInterpreterState *interp); extern void _PyList_ClearFreeList(PyInterpreterState *interp); diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index 18f21432008d9..f52ee594106f9 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -93,7 +93,6 @@ struct _Py_unicode_state { # define PyTuple_MAXFREELIST 1 # define PyList_MAXFREELIST 0 # define PyDict_MAXFREELIST 0 -# define PyFrame_MAXFREELIST 0 # define _PyAsyncGen_MAXFREELIST 0 # define PyContext_MAXFREELIST 0 #endif @@ -158,18 +157,6 @@ struct _Py_dict_state { #endif }; -#ifndef PyFrame_MAXFREELIST -# define PyFrame_MAXFREELIST 200 -#endif - -struct _Py_frame_state { -#if PyFrame_MAXFREELIST > 0 - PyFrameObject *free_list; - /* number of frames currently in free_list */ - int numfree; -#endif -}; - #ifndef _PyAsyncGen_MAXFREELIST # define _PyAsyncGen_MAXFREELIST 80 #endif @@ -332,7 +319,6 @@ struct _is { struct _Py_tuple_state tuple; struct _Py_list_state list; struct _Py_dict_state dict_state; - struct _Py_frame_state frame; struct _Py_async_gen_state async_gen; struct _Py_context_state context; struct _Py_exc_state exc_state; diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 7f087d085a810..c6660043c805f 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -209,7 +209,7 @@ def check(self, src, lineno, offset, encoding='utf-8'): src = src.decode(encoding, 'replace') line = src.split('\n')[lineno-1] self.assertIn(line, cm.exception.text) - + def test_error_offset_continuation_characters(self): check = self.check check('"\\\n"(1 for c in I,\\\n\\', 2, 2) @@ -1342,9 +1342,7 @@ def recurse(cnt): """ with SuppressCrashReport(): rc, out, err = script_helper.assert_python_failure("-c", code) - self.assertIn(b'Fatal Python error: _PyErr_NormalizeException: ' - b'Cannot recover from MemoryErrors while ' - b'normalizing exceptions.', err) + self.assertIn(b'MemoryError', err) @cpython_only def test_MemoryError(self): diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index b0688e1e605fe..db8d0082085cb 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1320,9 +1320,10 @@ class C(object): pass # sys.floatinfo check(sys.float_info, vsize('') + self.P * len(sys.float_info)) # frame - import inspect - x = inspect.currentframe() - check(x, size('3Pi3c')) + def func(): + return sys._getframe() + x = func() + check(x, size('3Pi3c8P2iciP')) # function def func(): pass check(func, size('14Pi')) diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-23-15-25-00.bpo-45786.UdEciD.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-23-15-25-00.bpo-45786.UdEciD.rst new file mode 100644 index 0000000000000..c88f1165a045e --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-23-15-25-00.bpo-45786.UdEciD.rst @@ -0,0 +1,2 @@ +Allocate space for the interpreter frame in the frame object, to avoid an +additional allocation when the frame object outlives the frame activation. diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 7d1a45bcaeabf..b505676636d38 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -1038,7 +1038,6 @@ delete_garbage(PyThreadState *tstate, GCState *gcstate, static void clear_freelists(PyInterpreterState *interp) { - _PyFrame_ClearFreeList(interp); _PyTuple_ClearFreeList(interp); _PyFloat_ClearFreeList(interp); _PyList_ClearFreeList(interp); diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 2a283b3113cb5..926a32a5100bd 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -610,7 +610,7 @@ static PyGetSetDef frame_getsetlist[] = { f_back next item on free list, or NULL */ -static void _Py_HOT_FUNCTION +static void frame_dealloc(PyFrameObject *f) { if (_PyObject_GC_IS_TRACKED(f)) { @@ -621,9 +621,10 @@ frame_dealloc(PyFrameObject *f) PyCodeObject *co = NULL; /* Kill all local variables including specials, if we own them */ - if (f->f_own_locals_memory) { - f->f_own_locals_memory = 0; - InterpreterFrame *frame = f->f_frame; + if (f->f_owns_frame) { + f->f_owns_frame = 0; + assert(f->f_frame == (InterpreterFrame *)f->_f_frame_data); + InterpreterFrame *frame = (InterpreterFrame *)f->_f_frame_data; /* Don't clear code object until the end */ co = frame->f_code; frame->f_code = NULL; @@ -633,27 +634,10 @@ frame_dealloc(PyFrameObject *f) for (int i = 0; i < frame->stacktop; i++) { Py_CLEAR(locals[i]); } - PyMem_Free(frame); } Py_CLEAR(f->f_back); Py_CLEAR(f->f_trace); -#if PyFrame_MAXFREELIST > 0 - struct _Py_frame_state *state = get_frame_state(); -#ifdef Py_DEBUG - // frame_dealloc() must not be called after _PyFrame_Fini() - assert(state->numfree != -1); -#endif - if (state->numfree < PyFrame_MAXFREELIST) { - ++state->numfree; - f->f_back = state->free_list; - state->free_list = f; - } - else -#endif - { - PyObject_GC_Del(f); - } - + PyObject_GC_Del(f); Py_XDECREF(co); Py_TRASHCAN_END; } @@ -663,7 +647,7 @@ frame_traverse(PyFrameObject *f, visitproc visit, void *arg) { Py_VISIT(f->f_back); Py_VISIT(f->f_trace); - if (f->f_own_locals_memory == 0) { + if (f->f_owns_frame == 0) { return 0; } assert(f->f_frame->frame_obj == NULL); @@ -715,11 +699,9 @@ static PyObject * frame_sizeof(PyFrameObject *f, PyObject *Py_UNUSED(ignored)) { Py_ssize_t res; - res = sizeof(PyFrameObject); - if (f->f_own_locals_memory) { - PyCodeObject *code = f->f_frame->f_code; - res += (code->co_nlocalsplus+code->co_stacksize) * sizeof(PyObject *); - } + res = offsetof(PyFrameObject, _f_frame_data) + offsetof(InterpreterFrame, localsplus); + PyCodeObject *code = f->f_frame->f_code; + res += (code->co_nlocalsplus+code->co_stacksize) * sizeof(PyObject *); return PyLong_FromSsize_t(res); } @@ -747,7 +729,8 @@ static PyMethodDef frame_methods[] = { PyTypeObject PyFrame_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "frame", - sizeof(PyFrameObject), + offsetof(PyFrameObject, _f_frame_data) + + offsetof(InterpreterFrame, localsplus), sizeof(PyObject *), (destructor)frame_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ @@ -781,67 +764,21 @@ PyTypeObject PyFrame_Type = { _Py_IDENTIFIER(__builtins__); -static InterpreterFrame * -allocate_heap_frame(PyFunctionObject *func, PyObject *locals) +static void +init_frame(InterpreterFrame *frame, PyFunctionObject *func, PyObject *locals) { PyCodeObject *code = (PyCodeObject *)func->func_code; - int size = code->co_nlocalsplus+code->co_stacksize + FRAME_SPECIALS_SIZE; - InterpreterFrame *frame = (InterpreterFrame *)PyMem_Malloc(sizeof(PyObject *)*size); - if (frame == NULL) { - PyErr_NoMemory(); - return NULL; - } _PyFrame_InitializeSpecials(frame, func, locals, code->co_nlocalsplus); for (Py_ssize_t i = 0; i < code->co_nlocalsplus; i++) { frame->localsplus[i] = NULL; } - return frame; } -static inline PyFrameObject* -frame_alloc(InterpreterFrame *frame, int owns) -{ - PyFrameObject *f; -#if PyFrame_MAXFREELIST > 0 - struct _Py_frame_state *state = get_frame_state(); - if (state->free_list == NULL) -#endif - { - f = PyObject_GC_New(PyFrameObject, &PyFrame_Type); - if (f == NULL) { - if (owns) { - Py_XDECREF(frame->f_code); - Py_XDECREF(frame->f_builtins); - Py_XDECREF(frame->f_globals); - Py_XDECREF(frame->f_locals); - PyMem_Free(frame); - } - return NULL; - } - } -#if PyFrame_MAXFREELIST > 0 - else - { -#ifdef Py_DEBUG - // frame_alloc() must not be called after _PyFrame_Fini() - assert(state->numfree != -1); -#endif - assert(state->numfree > 0); - --state->numfree; - f = state->free_list; - state->free_list = state->free_list->f_back; - _Py_NewReference((PyObject *)f); - } -#endif - f->f_frame = frame; - f->f_own_locals_memory = owns; - return f; -} - -PyFrameObject* _Py_HOT_FUNCTION -_PyFrame_New_NoTrack(InterpreterFrame *frame, int owns) +PyFrameObject* +_PyFrame_New_NoTrack(PyCodeObject *code) { - PyFrameObject *f = frame_alloc(frame, owns); + int slots = code->co_nlocalsplus + code->co_stacksize; + PyFrameObject *f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type, slots); if (f == NULL) { return NULL; } @@ -876,15 +813,16 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, if (func == NULL) { return NULL; } - InterpreterFrame *frame = allocate_heap_frame(func, locals); - Py_DECREF(func); - if (frame == NULL) { + PyFrameObject *f = _PyFrame_New_NoTrack(code); + if (f == NULL) { + Py_DECREF(func); return NULL; } - PyFrameObject *f = _PyFrame_New_NoTrack(frame, 1); - if (f) { - _PyObject_GC_TRACK(f); - } + init_frame((InterpreterFrame *)f->_f_frame_data, func, locals); + f->f_frame = (InterpreterFrame *)f->_f_frame_data; + f->f_owns_frame = 1; + Py_DECREF(func); + _PyObject_GC_TRACK(f); return f; } @@ -1087,42 +1025,15 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear) _PyFrame_LocalsToFast(f->f_frame, clear); } -/* Clear out the free list */ -void -_PyFrame_ClearFreeList(PyInterpreterState *interp) -{ -#if PyFrame_MAXFREELIST > 0 - struct _Py_frame_state *state = &interp->frame; - while (state->free_list != NULL) { - PyFrameObject *f = state->free_list; - state->free_list = state->free_list->f_back; - PyObject_GC_Del(f); - --state->numfree; - } - assert(state->numfree == 0); -#endif -} - void _PyFrame_Fini(PyInterpreterState *interp) { - _PyFrame_ClearFreeList(interp); -#if defined(Py_DEBUG) && PyFrame_MAXFREELIST > 0 - struct _Py_frame_state *state = &interp->frame; - state->numfree = -1; -#endif } /* Print summary info about the state of the optimized allocator */ void _PyFrame_DebugMallocStats(FILE *out) { -#if PyFrame_MAXFREELIST > 0 - struct _Py_frame_state *state = get_frame_state(); - _PyDebugAllocatorStats(out, - "free PyFrameObject", - state->numfree, sizeof(PyFrameObject)); -#endif } diff --git a/Objects/genobject.c b/Objects/genobject.c index 24d5f3579cbf2..04d98a2b4edf1 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -38,7 +38,7 @@ gen_traverse(PyGenObject *gen, visitproc visit, void *arg) Py_VISIT(gen->gi_qualname); InterpreterFrame *frame = gen->gi_xframe; if (frame != NULL) { - assert(frame->frame_obj == NULL || frame->frame_obj->f_own_locals_memory == 0); + assert(frame->frame_obj == NULL || frame->frame_obj->f_owns_frame == 0); int err = _PyFrame_Traverse(frame, visit, arg); if (err) { return err; @@ -136,7 +136,8 @@ gen_dealloc(PyGenObject *gen) gen->gi_xframe = NULL; frame->generator = NULL; frame->previous = NULL; - _PyFrame_Clear(frame, 1); + _PyFrame_Clear(frame); + PyMem_Free(frame); } if (((PyCodeObject *)gen->gi_code)->co_flags & CO_COROUTINE) { Py_CLEAR(((PyCoroObject *)gen)->cr_origin); @@ -254,7 +255,8 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, frame->generator = NULL; gen->gi_xframe = NULL; - _PyFrame_Clear(frame, 1); + _PyFrame_Clear(frame); + PyMem_Free(frame); *presult = result; return result ? PYGEN_RETURN : PYGEN_ERROR; } @@ -845,7 +847,8 @@ make_gen(PyTypeObject *type, PyFunctionObject *func, InterpreterFrame *frame) PyGenObject *gen = PyObject_GC_New(PyGenObject, type); if (gen == NULL) { assert(frame->frame_obj == NULL); - _PyFrame_Clear(frame, 1); + _PyFrame_Clear(frame); + PyMem_Free(frame); return NULL; } gen->gi_xframe = frame; @@ -929,10 +932,15 @@ gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f, /* Take ownership of the frame */ assert(f->f_frame->frame_obj == NULL); - assert(f->f_own_locals_memory); - gen->gi_xframe = f->f_frame; + assert(f->f_owns_frame); + gen->gi_xframe = _PyFrame_Copy((InterpreterFrame *)f->_f_frame_data); + if (gen->gi_xframe == NULL) { + Py_DECREF(f); + Py_DECREF(gen); + return NULL; + } gen->gi_xframe->frame_obj = f; - f->f_own_locals_memory = 0; + f->f_owns_frame = 0; gen->gi_xframe->generator = (PyObject *) gen; assert(PyObject_GC_IsTracked((PyObject *)f)); diff --git a/Python/ceval.c b/Python/ceval.c index 9beb1a4368226..0427361a03a8b 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -5694,7 +5694,8 @@ make_coro_frame(PyThreadState *tstate, } assert(frame->frame_obj == NULL); if (initialize_locals(tstate, func, frame->localsplus, args, argcount, kwnames)) { - _PyFrame_Clear(frame, 1); + _PyFrame_Clear(frame); + PyMem_Free(frame); return NULL; } return frame; @@ -5750,7 +5751,7 @@ _PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func, localsarray[i] = NULL; } if (initialize_locals(tstate, func, localsarray, args, argcount, kwnames)) { - _PyFrame_Clear(frame, 0); + _PyFrame_Clear(frame); return NULL; } return frame; @@ -5773,11 +5774,8 @@ static int _PyEvalFrameClearAndPop(PyThreadState *tstate, InterpreterFrame * frame) { --tstate->recursion_remaining; - assert(frame->frame_obj == NULL || frame->frame_obj->f_own_locals_memory == 0); - if (_PyFrame_Clear(frame, 0)) { - ++tstate->recursion_remaining; - return -1; - } + assert(frame->frame_obj == NULL || frame->frame_obj->f_owns_frame == 0); + _PyFrame_Clear(frame); ++tstate->recursion_remaining; _PyThreadState_PopFrame(tstate, frame); return 0; diff --git a/Python/frame.c b/Python/frame.c index 79b0f77a0657e..21f2ced959d80 100644 --- a/Python/frame.c +++ b/Python/frame.c @@ -27,22 +27,24 @@ _PyFrame_MakeAndSetFrameObject(InterpreterFrame *frame) assert(frame->frame_obj == NULL); PyObject *error_type, *error_value, *error_traceback; PyErr_Fetch(&error_type, &error_value, &error_traceback); - PyFrameObject *f = _PyFrame_New_NoTrack(frame, 0); + + PyFrameObject *f = _PyFrame_New_NoTrack(frame->f_code); if (f == NULL) { Py_XDECREF(error_type); Py_XDECREF(error_value); Py_XDECREF(error_traceback); } else { + f->f_owns_frame = 0; + f->f_frame = frame; + frame->frame_obj = f; PyErr_Restore(error_type, error_value, error_traceback); } - frame->frame_obj = f; return f; } - -static InterpreterFrame * -copy_frame_to_heap(InterpreterFrame *frame) +InterpreterFrame * +_PyFrame_Copy(InterpreterFrame *frame) { assert(frame->stacktop >= frame->f_code->co_nlocalsplus); Py_ssize_t size = ((char*)&frame->localsplus[frame->stacktop]) - (char *)frame; @@ -68,10 +70,11 @@ clear_specials(InterpreterFrame *frame) static void take_ownership(PyFrameObject *f, InterpreterFrame *frame) { - assert(f->f_own_locals_memory == 0); - assert(frame->frame_obj == NULL); - - f->f_own_locals_memory = 1; + assert(f->f_owns_frame == 0); + Py_ssize_t size = ((char*)&frame->localsplus[frame->stacktop]) - (char *)frame; + memcpy((InterpreterFrame *)f->_f_frame_data, frame, size); + frame = (InterpreterFrame *)f->_f_frame_data; + f->f_owns_frame = 1; f->f_frame = frame; assert(f->f_back == NULL); if (frame->previous != NULL) { @@ -82,7 +85,6 @@ take_ownership(PyFrameObject *f, InterpreterFrame *frame) assert(PyErr_ExceptionMatches(PyExc_MemoryError)); /* Nothing we can do about it */ PyErr_Clear(); - _PyErr_WriteUnraisableMsg("Out of memory lazily allocating frame->f_back", NULL); } else { f->f_back = (PyFrameObject *)Py_NewRef(back); @@ -94,8 +96,8 @@ take_ownership(PyFrameObject *f, InterpreterFrame *frame) } } -int -_PyFrame_Clear(InterpreterFrame * frame, int take) +void +_PyFrame_Clear(InterpreterFrame * frame) { /* It is the responsibility of the owning generator/coroutine * to have cleared the generator pointer */ @@ -104,15 +106,9 @@ _PyFrame_Clear(InterpreterFrame * frame, int take) PyFrameObject *f = frame->frame_obj; frame->frame_obj = NULL; if (Py_REFCNT(f) > 1) { - if (!take) { - frame = copy_frame_to_heap(frame); - if (frame == NULL) { - return -1; - } - } take_ownership(f, frame); Py_DECREF(f); - return 0; + return; } Py_DECREF(f); } @@ -121,8 +117,4 @@ _PyFrame_Clear(InterpreterFrame * frame, int take) Py_XDECREF(frame->localsplus[i]); } clear_specials(frame); - if (take) { - PyMem_Free(frame); - } - return 0; } From webhook-mailer at python.org Mon Nov 29 08:06:57 2021 From: webhook-mailer at python.org (vsajip) Date: Mon, 29 Nov 2021 13:06:57 -0000 Subject: [Python-checkins] =?utf-8?q?=5BDoc=5D_Add_info_to_logging_cookbo?= =?utf-8?q?ok_about_running_logging_socket_listeners_i=E2=80=A6_=28GH-2983?= =?utf-8?q?8=29?= Message-ID: https://github.com/python/cpython/commit/39b60ceae820a86d730ebdd1ee8cf5370bf5dff8 commit: 39b60ceae820a86d730ebdd1ee8cf5370bf5dff8 branch: main author: Vinay Sajip committer: vsajip date: 2021-11-29T13:06:52Z summary: [Doc] Add info to logging cookbook about running logging socket listeners i? (GH-29838) files: M Doc/howto/logging-cookbook.rst diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst index 5a8d92ad5120b..f0d944940fc28 100644 --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -541,6 +541,17 @@ alternative there, as well as adapting the above script to use your alternative serialization. +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. + + .. _context-info: Adding contextual information to your logging output @@ -982,6 +993,17 @@ to this (remembering to first import :mod:`concurrent.futures`):: for i in range(10): executor.submit(worker_process, queue, worker_configurer) +Deploying Web applications using Gunicorn and uWSGI +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When deploying Web applications using `Gunicorn `_ or `uWSGI +`_ (or similar), multiple worker +processes are created to handle client requests. In such environments, avoid creating +file-based handlers directly in your web application. Instead, use a +:class:`SocketHandler` to log from the web application to a listener in a separate +process. This can be set up using a process management tool such as Supervisor - see +`Running a logging socket listener in production`_ for more details. + Using file rotation ------------------- From webhook-mailer at python.org Mon Nov 29 08:28:25 2021 From: webhook-mailer at python.org (vsajip) Date: Mon, 29 Nov 2021 13:28:25 -0000 Subject: [Python-checkins] =?utf-8?b?WzMuMTBdIFtEb2NdIEFkZCBpbmZvIHRvIGxv?= =?utf-8?q?gging_cookbook_about_running_logging_socket_listeners_i?= =?utf-8?b?4oCmIChHSC0yOTgzOCkgKEdILTI5ODM5KQ==?= Message-ID: https://github.com/python/cpython/commit/efe2a2306bcc96357d4b885ca73c73d0e6e73cd6 commit: efe2a2306bcc96357d4b885ca73c73d0e6e73cd6 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: vsajip date: 2021-11-29T13:28:05Z summary: [3.10] [Doc] Add info to logging cookbook about running logging socket listeners i? (GH-29838) (GH-29839) files: M Doc/howto/logging-cookbook.rst diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst index 2ab8c52e23ea1..f82150a4f2e02 100644 --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -541,6 +541,17 @@ alternative there, as well as adapting the above script to use your alternative serialization. +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. + + .. _context-info: Adding contextual information to your logging output @@ -982,6 +993,17 @@ to this (remembering to first import :mod:`concurrent.futures`):: for i in range(10): executor.submit(worker_process, queue, worker_configurer) +Deploying Web applications using Gunicorn and uWSGI +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When deploying Web applications using `Gunicorn `_ or `uWSGI +`_ (or similar), multiple worker +processes are created to handle client requests. In such environments, avoid creating +file-based handlers directly in your web application. Instead, use a +:class:`SocketHandler` to log from the web application to a listener in a separate +process. This can be set up using a process management tool such as Supervisor - see +`Running a logging socket listener in production`_ for more details. + Using file rotation ------------------- From webhook-mailer at python.org Mon Nov 29 08:49:37 2021 From: webhook-mailer at python.org (vsajip) Date: Mon, 29 Nov 2021 13:49:37 -0000 Subject: [Python-checkins] =?utf-8?b?WzMuOV0gW0RvY10gQWRkIGluZm8gdG8gbG9n?= =?utf-8?q?ging_cookbook_about_running_logging_socket_listeners_i=E2=80=A6?= =?utf-8?q?_=28GH-29838=29_=28GH-29840=29?= Message-ID: https://github.com/python/cpython/commit/da3e9ddde7861d29ab465e8ab1e112693f689a79 commit: da3e9ddde7861d29ab465e8ab1e112693f689a79 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: vsajip date: 2021-11-29T13:49:20Z summary: [3.9] [Doc] Add info to logging cookbook about running logging socket listeners i? (GH-29838) (GH-29840) files: M Doc/howto/logging-cookbook.rst diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst index 20b02c838f328..bc9b2499224ca 100644 --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -541,6 +541,17 @@ alternative there, as well as adapting the above script to use your alternative serialization. +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. + + .. _context-info: Adding contextual information to your logging output @@ -982,6 +993,17 @@ to this (remembering to first import :mod:`concurrent.futures`):: for i in range(10): executor.submit(worker_process, queue, worker_configurer) +Deploying Web applications using Gunicorn and uWSGI +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When deploying Web applications using `Gunicorn `_ or `uWSGI +`_ (or similar), multiple worker +processes are created to handle client requests. In such environments, avoid creating +file-based handlers directly in your web application. Instead, use a +:class:`SocketHandler` to log from the web application to a listener in a separate +process. This can be set up using a process management tool such as Supervisor - see +`Running a logging socket listener in production`_ for more details. + Using file rotation ------------------- From webhook-mailer at python.org Mon Nov 29 08:57:45 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 29 Nov 2021 13:57:45 -0000 Subject: [Python-checkins] bpo-45847: Make socket module conditional (GH-29769) Message-ID: https://github.com/python/cpython/commit/f7a62f24053c82cf38c3db5848d9ff014470fa40 commit: f7a62f24053c82cf38c3db5848d9ff014470fa40 branch: main author: Erlend Egeberg Aasland committer: tiran date: 2021-11-29T14:57:36+01:00 summary: bpo-45847: Make socket module conditional (GH-29769) files: M configure M configure.ac M pyconfig.h.in diff --git a/configure b/configure index 0f96171264940..c670878c9ed42 100755 --- a/configure +++ b/configure @@ -712,6 +712,8 @@ MODULE_OSSAUDIODEV_FALSE MODULE_OSSAUDIODEV_TRUE MODULE_GRP_FALSE MODULE_GRP_TRUE +MODULE__SOCKET_FALSE +MODULE__SOCKET_TRUE MODULE_MMAP_FALSE MODULE_MMAP_TRUE MODULE_FCNTL_FALSE @@ -738,8 +740,6 @@ MODULE__TYPING_FALSE MODULE__TYPING_TRUE MODULE__STRUCT_FALSE MODULE__STRUCT_TRUE -MODULE__SOCKET_FALSE -MODULE__SOCKET_TRUE MODULE_SELECT_FALSE MODULE_SELECT_TRUE MODULE__RANDOM_FALSE @@ -8371,7 +8371,7 @@ sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h \ libutil.h sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \ linux/tipc.h linux/random.h spawn.h util.h alloca.h endian.h \ sys/endian.h sys/sysmacros.h linux/memfd.h linux/wait.h sys/memfd.h \ -sys/mman.h sys/eventfd.h linux/soundcard.h sys/soundcard.h syslog.h +sys/mman.h sys/eventfd.h linux/soundcard.h sys/soundcard.h syslog.h netinet/in.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" @@ -21222,15 +21222,6 @@ else fi as_fn_append MODULE_BLOCK "MODULE_SELECT=yes$as_nl" - if true; then - MODULE__SOCKET_TRUE= - MODULE__SOCKET_FALSE='#' -else - MODULE__SOCKET_TRUE='#' - MODULE__SOCKET_FALSE= -fi - as_fn_append MODULE_BLOCK "MODULE__SOCKET=yes$as_nl" - if true; then MODULE__STRUCT_TRUE= MODULE__STRUCT_FALSE='#' @@ -21445,6 +21436,42 @@ fi $as_echo "$py_cv_module_mmap" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _socket" >&5 +$as_echo_n "checking for stdlib extension module _socket... " >&6; } + case $py_stdlib_not_available in #( + *_socket*) : + py_cv_module__socket=n/a ;; #( + *) : + if true; then : + if test "$ac_cv_header_sys_socket_h" = "yes" -a "$ac_cv_header_sys_types_h" = "yes" -a "$ac_cv_header_netinet_in_h" = "yes"; then : + py_cv_module__socket=yes +else + py_cv_module__socket=missing +fi +else + py_cv_module__socket=disabled +fi + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__SOCKET=$py_cv_module__socket$as_nl" + if test "x$py_cv_module__socket" = xyes; then : + + + + +fi + if test "$py_cv_module__socket" = yes; then + MODULE__SOCKET_TRUE= + MODULE__SOCKET_FALSE='#' +else + MODULE__SOCKET_TRUE='#' + MODULE__SOCKET_FALSE= +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__socket" >&5 +$as_echo "$py_cv_module__socket" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module grp" >&5 $as_echo_n "checking for stdlib extension module grp... " >&6; } @@ -22982,10 +23009,6 @@ if test -z "${MODULE_SELECT_TRUE}" && test -z "${MODULE_SELECT_FALSE}"; then as_fn_error $? "conditional \"MODULE_SELECT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${MODULE__SOCKET_TRUE}" && test -z "${MODULE__SOCKET_FALSE}"; then - as_fn_error $? "conditional \"MODULE__SOCKET\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${MODULE__STRUCT_TRUE}" && test -z "${MODULE__STRUCT_FALSE}"; then as_fn_error $? "conditional \"MODULE__STRUCT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -23038,6 +23061,10 @@ if test -z "${MODULE_MMAP_TRUE}" && test -z "${MODULE_MMAP_FALSE}"; then as_fn_error $? "conditional \"MODULE_MMAP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MODULE__SOCKET_TRUE}" && test -z "${MODULE__SOCKET_FALSE}"; then + as_fn_error $? "conditional \"MODULE__SOCKET\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MODULE_GRP_TRUE}" && test -z "${MODULE_GRP_FALSE}"; then as_fn_error $? "conditional \"MODULE_GRP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index 21429470ebacb..ada3e4ba097fd 100644 --- a/configure.ac +++ b/configure.ac @@ -2206,7 +2206,7 @@ sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h \ libutil.h sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \ linux/tipc.h linux/random.h spawn.h util.h alloca.h endian.h \ sys/endian.h sys/sysmacros.h linux/memfd.h linux/wait.h sys/memfd.h \ -sys/mman.h sys/eventfd.h linux/soundcard.h sys/soundcard.h syslog.h) +sys/mman.h sys/eventfd.h linux/soundcard.h sys/soundcard.h syslog.h netinet/in.h) AC_HEADER_DIRENT AC_HEADER_MAJOR @@ -6292,7 +6292,6 @@ PY_STDLIB_MOD_SIMPLE([_posixsubprocess]) PY_STDLIB_MOD_SIMPLE([_queue]) PY_STDLIB_MOD_SIMPLE([_random]) PY_STDLIB_MOD_SIMPLE([select]) -PY_STDLIB_MOD_SIMPLE([_socket]) PY_STDLIB_MOD_SIMPLE([_struct]) PY_STDLIB_MOD_SIMPLE([_typing]) PY_STDLIB_MOD_SIMPLE([_xxsubinterpreters]) @@ -6319,6 +6318,10 @@ PY_STDLIB_MOD([fcntl], [], [$FCNTL_LIBS]) PY_STDLIB_MOD([mmap], [], [test "$ac_cv_header_sys_mman_h" = "yes" -a "$ac_cv_header_sys_stat_h" = "yes"]) +PY_STDLIB_MOD([_socket], + [], m4_flatten([test "$ac_cv_header_sys_socket_h" = "yes" + -a "$ac_cv_header_sys_types_h" = "yes" + -a "$ac_cv_header_netinet_in_h" = "yes"])) dnl platform specific extensions PY_STDLIB_MOD([grp], [], [test "$ac_cv_func_getgrgid" = yes -o "$ac_cv_func_getgrgid_r" = yes]) diff --git a/pyconfig.h.in b/pyconfig.h.in index 27bed56084684..efad243d0af8a 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -769,6 +769,9 @@ /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_NDIR_H +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + /* Define to 1 if you have the header file. */ #undef HAVE_NETPACKET_PACKET_H From webhook-mailer at python.org Mon Nov 29 09:41:23 2021 From: webhook-mailer at python.org (miss-islington) Date: Mon, 29 Nov 2021 14:41:23 -0000 Subject: [Python-checkins] bpo-45723: Sort the grand AC_CHECK_HEADERS check (GH-29846) Message-ID: https://github.com/python/cpython/commit/c1dec9540ab04691f8d4a131671e069913e6eee3 commit: c1dec9540ab04691f8d4a131671e069913e6eee3 branch: main author: Erlend Egeberg Aasland committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-29T06:41:11-08:00 summary: bpo-45723: Sort the grand AC_CHECK_HEADERS check (GH-29846) Automerge-Triggered-By: GH:tiran files: M configure M configure.ac diff --git a/configure b/configure index c670878c9ed42..c675923131df9 100755 --- a/configure +++ b/configure @@ -8357,21 +8357,18 @@ $as_echo "#define STDC_HEADERS 1" >>confdefs.h # checks for header files -for ac_header in asm/types.h crypt.h conio.h direct.h dlfcn.h errno.h \ -fcntl.h grp.h \ -ieeefp.h io.h langinfo.h libintl.h process.h pthread.h \ -sched.h shadow.h signal.h stropts.h termios.h \ -utime.h \ -poll.h sys/devpoll.h sys/epoll.h sys/poll.h \ -sys/audioio.h sys/xattr.h sys/bsdtty.h sys/event.h sys/file.h sys/ioctl.h \ -sys/kern_control.h sys/loadavg.h sys/lock.h sys/mkdev.h sys/modem.h \ -sys/param.h sys/random.h sys/select.h sys/sendfile.h sys/socket.h sys/statvfs.h \ -sys/stat.h sys/syscall.h sys/sys_domain.h sys/termio.h sys/time.h \ -sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h \ -libutil.h sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \ -linux/tipc.h linux/random.h spawn.h util.h alloca.h endian.h \ -sys/endian.h sys/sysmacros.h linux/memfd.h linux/wait.h sys/memfd.h \ -sys/mman.h sys/eventfd.h linux/soundcard.h sys/soundcard.h syslog.h netinet/in.h +for ac_header in \ + alloca.h asm/types.h bluetooth.h conio.h crypt.h direct.h dlfcn.h endian.h errno.h fcntl.h grp.h \ + ieeefp.h io.h langinfo.h libintl.h libutil.h linux/memfd.h linux/random.h linux/soundcard.h \ + linux/tipc.h linux/wait.h netinet/in.h netpacket/packet.h poll.h process.h pthread.h pty.h \ + sched.h shadow.h signal.h spawn.h stropts.h sys/audioio.h sys/bsdtty.h sys/devpoll.h \ + sys/endian.h sys/epoll.h sys/event.h sys/eventfd.h sys/file.h sys/ioctl.h sys/kern_control.h \ + sys/loadavg.h sys/lock.h sys/memfd.h sys/mkdev.h sys/mman.h sys/modem.h sys/param.h sys/poll.h \ + sys/random.h sys/resource.h sys/select.h sys/sendfile.h sys/socket.h sys/soundcard.h sys/stat.h \ + sys/statvfs.h sys/sys_domain.h sys/syscall.h sys/sysmacros.h sys/termio.h sys/time.h sys/times.h \ + sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h sys/xattr.h sysexits.h syslog.h \ + termios.h util.h utime.h \ + do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" diff --git a/configure.ac b/configure.ac index ada3e4ba097fd..7b80c2d8923f6 100644 --- a/configure.ac +++ b/configure.ac @@ -2192,21 +2192,18 @@ dnl assume C99 compilers provide ANSI C headers AC_DEFINE(STDC_HEADERS, 1, [Define to 1 if you have the ANSI C header files.]) # checks for header files -AC_CHECK_HEADERS(asm/types.h crypt.h conio.h direct.h dlfcn.h errno.h \ -fcntl.h grp.h \ -ieeefp.h io.h langinfo.h libintl.h process.h pthread.h \ -sched.h shadow.h signal.h stropts.h termios.h \ -utime.h \ -poll.h sys/devpoll.h sys/epoll.h sys/poll.h \ -sys/audioio.h sys/xattr.h sys/bsdtty.h sys/event.h sys/file.h sys/ioctl.h \ -sys/kern_control.h sys/loadavg.h sys/lock.h sys/mkdev.h sys/modem.h \ -sys/param.h sys/random.h sys/select.h sys/sendfile.h sys/socket.h sys/statvfs.h \ -sys/stat.h sys/syscall.h sys/sys_domain.h sys/termio.h sys/time.h \ -sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h \ -libutil.h sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \ -linux/tipc.h linux/random.h spawn.h util.h alloca.h endian.h \ -sys/endian.h sys/sysmacros.h linux/memfd.h linux/wait.h sys/memfd.h \ -sys/mman.h sys/eventfd.h linux/soundcard.h sys/soundcard.h syslog.h netinet/in.h) +AC_CHECK_HEADERS([ \ + alloca.h asm/types.h bluetooth.h conio.h crypt.h direct.h dlfcn.h endian.h errno.h fcntl.h grp.h \ + ieeefp.h io.h langinfo.h libintl.h libutil.h linux/memfd.h linux/random.h linux/soundcard.h \ + linux/tipc.h linux/wait.h netinet/in.h netpacket/packet.h poll.h process.h pthread.h pty.h \ + sched.h shadow.h signal.h spawn.h stropts.h sys/audioio.h sys/bsdtty.h sys/devpoll.h \ + sys/endian.h sys/epoll.h sys/event.h sys/eventfd.h sys/file.h sys/ioctl.h sys/kern_control.h \ + sys/loadavg.h sys/lock.h sys/memfd.h sys/mkdev.h sys/mman.h sys/modem.h sys/param.h sys/poll.h \ + sys/random.h sys/resource.h sys/select.h sys/sendfile.h sys/socket.h sys/soundcard.h sys/stat.h \ + sys/statvfs.h sys/sys_domain.h sys/syscall.h sys/sysmacros.h sys/termio.h sys/time.h sys/times.h \ + sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h sys/xattr.h sysexits.h syslog.h \ + termios.h util.h utime.h \ +]) AC_HEADER_DIRENT AC_HEADER_MAJOR From webhook-mailer at python.org Mon Nov 29 10:02:04 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 29 Nov 2021 15:02:04 -0000 Subject: [Python-checkins] bpo-40280: Emscripten systems use .wasm suffix by default (GH-29842) Message-ID: https://github.com/python/cpython/commit/6ac3c8a3140c17bd71ba98dfc5250c371101e77c commit: 6ac3c8a3140c17bd71ba98dfc5250c371101e77c branch: main author: Christian Heimes committer: tiran date: 2021-11-29T16:01:55+01:00 summary: bpo-40280: Emscripten systems use .wasm suffix by default (GH-29842) files: A Misc/NEWS.d/next/Build/2021-11-29-14-37-29.bpo-40280.UlTMR8.rst M Doc/using/configure.rst M configure M configure.ac diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index f00766dfc4f76..c6aa4af73f4d3 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -53,7 +53,11 @@ General Options Set the Python executable suffix to *SUFFIX*. The default suffix is ``.exe`` on Windows and macOS (``python.exe`` - executable), and an empty string on other platforms (``python`` executable). + executable), ``.wasm`` on Emscripten (``python.wasm`` executable), and + an empty string on other platforms (``python`` executable). + + .. versionchanged:: 3.11 + The default suffix on Emscripten platform is ``.wasm``. .. cmdoption:: --with-tzpath= diff --git a/Misc/NEWS.d/next/Build/2021-11-29-14-37-29.bpo-40280.UlTMR8.rst b/Misc/NEWS.d/next/Build/2021-11-29-14-37-29.bpo-40280.UlTMR8.rst new file mode 100644 index 0000000000000..d3ac7b37af8a7 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-29-14-37-29.bpo-40280.UlTMR8.rst @@ -0,0 +1 @@ +Emscripten platform now uses ``.wasm`` suffix by default. diff --git a/configure b/configure index c675923131df9..12c8d108b6528 100755 --- a/configure +++ b/configure @@ -1738,7 +1738,8 @@ Optional Packages: --with-cxx-main[=COMPILER] compile main() and link Python executable with C++ compiler specified in COMPILER (default is $CXX) - --with-suffix=SUFFIX set executable suffix to SUFFIX (default is '.exe') + --with-suffix=SUFFIX set executable suffix to SUFFIX (default is empty, + yes is mapped to '.exe') --with-pydebug build with Py_DEBUG defined (default is no) --with-trace-refs enable tracing references for debugging purpose (default is no) @@ -6136,11 +6137,26 @@ $as_echo_n "checking for --with-suffix... " >&6; } # Check whether --with-suffix was given. if test "${with_suffix+set}" = set; then : withval=$with_suffix; - case $withval in - no) EXEEXT=;; - yes) EXEEXT=.exe;; - *) EXEEXT=$withval;; - esac + case $with_suffix in #( + no) : + EXEEXT= ;; #( + yes) : + EXEEXT=.exe ;; #( + *) : + EXEEXT=$with_suffix + ;; +esac + +else + + case $ac_sys_system in #( + Emscripten) : + EXEEXT=.wasm ;; #( + *) : + EXEEXT= + ;; +esac + fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $EXEEXT" >&5 diff --git a/configure.ac b/configure.ac index 7b80c2d8923f6..5c89b9c241d74 100644 --- a/configure.ac +++ b/configure.ac @@ -1018,16 +1018,22 @@ atheos*|Linux*/1*) exit 1;; esac -AC_MSG_CHECKING(for --with-suffix) -AC_ARG_WITH(suffix, - AS_HELP_STRING([--with-suffix=SUFFIX], [set executable suffix to SUFFIX (default is '.exe')]), +AC_MSG_CHECKING([for --with-suffix]) +AC_ARG_WITH([suffix], + [AS_HELP_STRING([--with-suffix=SUFFIX], [set executable suffix to SUFFIX (default is empty, yes is mapped to '.exe')])], [ - case $withval in - no) EXEEXT=;; - yes) EXEEXT=.exe;; - *) EXEEXT=$withval;; - esac]) -AC_MSG_RESULT($EXEEXT) + AS_CASE([$with_suffix], + [no], [EXEEXT=], + [yes], [EXEEXT=.exe], + [EXEEXT=$with_suffix] + ) +], [ + AS_CASE([$ac_sys_system], + [Emscripten], [EXEEXT=.wasm], + [EXEEXT=] + ) +]) +AC_MSG_RESULT([$EXEEXT]) # Test whether we're running on a non-case-sensitive system, in which # case we give a warning if no ext is given From webhook-mailer at python.org Mon Nov 29 10:22:37 2021 From: webhook-mailer at python.org (pablogsal) Date: Mon, 29 Nov 2021 15:22:37 -0000 Subject: [Python-checkins] bpo-45828: Use unraisable exceptions within sqlite3 callbacks (FH-29591) Message-ID: https://github.com/python/cpython/commit/c4a69a4ad035513ada1c0d41a46723606b538e13 commit: c4a69a4ad035513ada1c0d41a46723606b538e13 branch: main author: Erlend Egeberg Aasland committer: pablogsal date: 2021-11-29T15:22:32Z summary: bpo-45828: Use unraisable exceptions within sqlite3 callbacks (FH-29591) files: A Misc/NEWS.d/next/Library/2021-11-17-11-40-21.bpo-45828.kQU35U.rst M Doc/library/sqlite3.rst M Doc/whatsnew/3.11.rst M Lib/test/test_sqlite3/test_hooks.py M Lib/test/test_sqlite3/test_userfunctions.py M Modules/_sqlite/connection.c diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index 9fffe4da901a8..fb38182370ea9 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -329,9 +329,27 @@ Module functions and constants By default you will not get any tracebacks in user-defined functions, aggregates, converters, authorizer callbacks etc. If you want to debug them, - you can call this function with *flag* set to ``True``. Afterwards, you will - get tracebacks from callbacks on ``sys.stderr``. Use :const:`False` to - disable the feature again. + you can call this function with *flag* set to :const:`True`. Afterwards, you + will get tracebacks from callbacks on :data:`sys.stderr`. Use :const:`False` + to disable the feature again. + + Register an :func:`unraisable hook handler ` for an + improved debug experience:: + + >>> import sqlite3 + >>> sqlite3.enable_callback_tracebacks(True) + >>> cx = sqlite3.connect(":memory:") + >>> cx.set_trace_callback(lambda stmt: 5/0) + >>> cx.execute("select 1") + Exception ignored in: at 0x10b4e3ee0> + Traceback (most recent call last): + File "", line 1, in + ZeroDivisionError: division by zero + >>> import sys + >>> sys.unraisablehook = lambda unraisable: print(unraisable) + >>> cx.execute("select 1") + UnraisableHookArgs(exc_type=, exc_value=ZeroDivisionError('division by zero'), exc_traceback=, err_msg=None, object= at 0x10b4e3ee0>) + .. _sqlite3-connection-objects: diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 9751f894f9a9a..3b65921a92619 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -248,7 +248,6 @@ sqlite3 (Contributed by Aviv Palivoda, Daniel Shahaf, and Erlend E. Aasland in :issue:`16379` and :issue:`24139`.) - * Add :meth:`~sqlite3.Connection.setlimit` and :meth:`~sqlite3.Connection.getlimit` to :class:`sqlite3.Connection` for setting and getting SQLite limits by connection basis. @@ -258,6 +257,12 @@ sqlite3 threading mode the underlying SQLite library has been compiled with. (Contributed by Erlend E. Aasland in :issue:`45613`.) +* :mod:`sqlite3` C callbacks now use unraisable exceptions if callback + tracebacks are enabled. Users can now register an + :func:`unraisable hook handler ` to improve their debug + experience. + (Contributed by Erlend E. Aasland in :issue:`45828`.) + threading --------- diff --git a/Lib/test/test_sqlite3/test_hooks.py b/Lib/test/test_sqlite3/test_hooks.py index bf454b2aa887f..9e5e53ad223f0 100644 --- a/Lib/test/test_sqlite3/test_hooks.py +++ b/Lib/test/test_sqlite3/test_hooks.py @@ -197,7 +197,7 @@ def progress(): con.execute("select 1 union select 2 union select 3").fetchall() self.assertEqual(action, 0, "progress handler was not cleared") - @with_tracebacks(['bad_progress', 'ZeroDivisionError']) + @with_tracebacks(ZeroDivisionError, name="bad_progress") def test_error_in_progress_handler(self): con = sqlite.connect(":memory:") def bad_progress(): @@ -208,7 +208,7 @@ def bad_progress(): create table foo(a, b) """) - @with_tracebacks(['__bool__', 'ZeroDivisionError']) + @with_tracebacks(ZeroDivisionError, name="bad_progress") def test_error_in_progress_handler_result(self): con = sqlite.connect(":memory:") class BadBool: diff --git a/Lib/test/test_sqlite3/test_userfunctions.py b/Lib/test/test_sqlite3/test_userfunctions.py index 62a11a5431b7b..996437b1a4bee 100644 --- a/Lib/test/test_sqlite3/test_userfunctions.py +++ b/Lib/test/test_sqlite3/test_userfunctions.py @@ -25,46 +25,52 @@ import functools import gc import io +import re import sys import unittest import unittest.mock import sqlite3 as sqlite -from test.support import bigmemtest +from test.support import bigmemtest, catch_unraisable_exception from .test_dbapi import cx_limit -def with_tracebacks(strings, traceback=True): +def with_tracebacks(exc, regex="", name=""): """Convenience decorator for testing callback tracebacks.""" - if traceback: - strings.append('Traceback') - def decorator(func): + _regex = re.compile(regex) if regex else None @functools.wraps(func) def wrapper(self, *args, **kwargs): - # First, run the test with traceback enabled. - with check_tracebacks(self, strings): - func(self, *args, **kwargs) + with catch_unraisable_exception() as cm: + # First, run the test with traceback enabled. + with check_tracebacks(self, cm, exc, _regex, name): + func(self, *args, **kwargs) # Then run the test with traceback disabled. func(self, *args, **kwargs) return wrapper return decorator + @contextlib.contextmanager -def check_tracebacks(self, strings): +def check_tracebacks(self, cm, exc, regex, obj_name): """Convenience context manager for testing callback tracebacks.""" sqlite.enable_callback_tracebacks(True) try: buf = io.StringIO() with contextlib.redirect_stderr(buf): yield - tb = buf.getvalue() - for s in strings: - self.assertIn(s, tb) + + self.assertEqual(cm.unraisable.exc_type, exc) + if regex: + msg = str(cm.unraisable.exc_value) + self.assertIsNotNone(regex.search(msg)) + if obj_name: + self.assertEqual(cm.unraisable.object.__name__, obj_name) finally: sqlite.enable_callback_tracebacks(False) + def func_returntext(): return "foo" def func_returntextwithnull(): @@ -299,7 +305,7 @@ def test_func_return_long_long(self): val = cur.fetchone()[0] self.assertEqual(val, 1<<31) - @with_tracebacks(['func_raiseexception', '5/0', 'ZeroDivisionError']) + @with_tracebacks(ZeroDivisionError, name="func_raiseexception") def test_func_exception(self): cur = self.con.cursor() with self.assertRaises(sqlite.OperationalError) as cm: @@ -307,14 +313,14 @@ def test_func_exception(self): cur.fetchone() self.assertEqual(str(cm.exception), 'user-defined function raised exception') - @with_tracebacks(['func_memoryerror', 'MemoryError']) + @with_tracebacks(MemoryError, name="func_memoryerror") def test_func_memory_error(self): cur = self.con.cursor() with self.assertRaises(MemoryError): cur.execute("select memoryerror()") cur.fetchone() - @with_tracebacks(['func_overflowerror', 'OverflowError']) + @with_tracebacks(OverflowError, name="func_overflowerror") def test_func_overflow_error(self): cur = self.con.cursor() with self.assertRaises(sqlite.DataError): @@ -426,22 +432,21 @@ def md5sum(t): del x,y gc.collect() + @with_tracebacks(OverflowError) def test_func_return_too_large_int(self): cur = self.con.cursor() for value in 2**63, -2**63-1, 2**64: self.con.create_function("largeint", 0, lambda value=value: value) - with check_tracebacks(self, ['OverflowError']): - with self.assertRaises(sqlite.DataError): - cur.execute("select largeint()") + with self.assertRaises(sqlite.DataError): + cur.execute("select largeint()") + @with_tracebacks(UnicodeEncodeError, "surrogates not allowed", "chr") def test_func_return_text_with_surrogates(self): cur = self.con.cursor() self.con.create_function("pychr", 1, chr) for value in 0xd8ff, 0xdcff: - with check_tracebacks(self, - ['UnicodeEncodeError', 'surrogates not allowed']): - with self.assertRaises(sqlite.OperationalError): - cur.execute("select pychr(?)", (value,)) + with self.assertRaises(sqlite.OperationalError): + cur.execute("select pychr(?)", (value,)) @unittest.skipUnless(sys.maxsize > 2**32, 'requires 64bit platform') @bigmemtest(size=2**31, memuse=3, dry_run=False) @@ -510,7 +515,7 @@ def test_aggr_no_finalize(self): val = cur.fetchone()[0] self.assertEqual(str(cm.exception), "user-defined aggregate's 'finalize' method raised error") - @with_tracebacks(['__init__', '5/0', 'ZeroDivisionError']) + @with_tracebacks(ZeroDivisionError, name="AggrExceptionInInit") def test_aggr_exception_in_init(self): cur = self.con.cursor() with self.assertRaises(sqlite.OperationalError) as cm: @@ -518,7 +523,7 @@ def test_aggr_exception_in_init(self): val = cur.fetchone()[0] self.assertEqual(str(cm.exception), "user-defined aggregate's '__init__' method raised error") - @with_tracebacks(['step', '5/0', 'ZeroDivisionError']) + @with_tracebacks(ZeroDivisionError, name="AggrExceptionInStep") def test_aggr_exception_in_step(self): cur = self.con.cursor() with self.assertRaises(sqlite.OperationalError) as cm: @@ -526,7 +531,7 @@ def test_aggr_exception_in_step(self): val = cur.fetchone()[0] self.assertEqual(str(cm.exception), "user-defined aggregate's 'step' method raised error") - @with_tracebacks(['finalize', '5/0', 'ZeroDivisionError']) + @with_tracebacks(ZeroDivisionError, name="AggrExceptionInFinalize") def test_aggr_exception_in_finalize(self): cur = self.con.cursor() with self.assertRaises(sqlite.OperationalError) as cm: @@ -643,11 +648,11 @@ def authorizer_cb(action, arg1, arg2, dbname, source): raise ValueError return sqlite.SQLITE_OK - @with_tracebacks(['authorizer_cb', 'ValueError']) + @with_tracebacks(ValueError, name="authorizer_cb") def test_table_access(self): super().test_table_access() - @with_tracebacks(['authorizer_cb', 'ValueError']) + @with_tracebacks(ValueError, name="authorizer_cb") def test_column_access(self): super().test_table_access() diff --git a/Misc/NEWS.d/next/Library/2021-11-17-11-40-21.bpo-45828.kQU35U.rst b/Misc/NEWS.d/next/Library/2021-11-17-11-40-21.bpo-45828.kQU35U.rst new file mode 100644 index 0000000000000..07ec273ef06b1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-17-11-40-21.bpo-45828.kQU35U.rst @@ -0,0 +1,2 @@ +:mod:`sqlite` C callbacks now use unraisable exceptions if callback +tracebacks are enabled. Patch by Erlend E. Aasland. diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 0bc9d1d0eeda5..4f0baa649e1d0 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -691,7 +691,7 @@ print_or_clear_traceback(callback_context *ctx) assert(ctx != NULL); assert(ctx->state != NULL); if (ctx->state->enable_callback_tracebacks) { - PyErr_Print(); + PyErr_WriteUnraisable(ctx->callable); } else { PyErr_Clear(); From webhook-mailer at python.org Mon Nov 29 10:34:25 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 29 Nov 2021 15:34:25 -0000 Subject: [Python-checkins] bpo-45847: PY_STDLIB_MOD_SIMPLE now checks py_stdlib_not_available (GH-29844) Message-ID: https://github.com/python/cpython/commit/b394af13f69c1a2ac0e7d32dabf6d86443606ab2 commit: b394af13f69c1a2ac0e7d32dabf6d86443606ab2 branch: main author: Christian Heimes committer: tiran date: 2021-11-29T16:34:16+01:00 summary: bpo-45847: PY_STDLIB_MOD_SIMPLE now checks py_stdlib_not_available (GH-29844) files: M configure M configure.ac diff --git a/configure b/configure index 12c8d108b6528..29c65a6bc94a4 100755 --- a/configure +++ b/configure @@ -21062,7 +21062,7 @@ case $ac_sys_system in #( py_stdlib_not_available="_scproxy spwd" ;; #( Emscripten) : - py_stdlib_not_available="_curses _curses_panel _dbm _gdbm _multiprocessing _posixshmem _posixsubprocess _scproxy _xxsubinterpreters grp nis ossaudiodev resource spwd syslog termios" + py_stdlib_not_available="_curses _curses_panel _dbm _gdbm _multiprocessing _posixshmem _posixsubprocess _scproxy _xxsubinterpreters fcntl grp nis ossaudiodev resource spwd syslog termios" ;; #( *) : py_stdlib_not_available="_scproxy" @@ -21086,201 +21086,522 @@ MODULE_BLOCK= - if true; then + case $py_stdlib_not_available in #( + *_io*) : + py_cv_module__io=n/a ;; #( + *) : + py_cv_module__io=yes + ;; +esac + if test "$py_cv_module__io" = yes; then MODULE__IO_TRUE= MODULE__IO_FALSE='#' else MODULE__IO_TRUE='#' MODULE__IO_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__IO=yes$as_nl" + + as_fn_append MODULE_BLOCK "MODULE__IO=$py_cv_module__io$as_nl" + if test "x$py_cv_module__io" = xyes; then : + as_fn_append MODULE_BLOCK "MODULE__IO_CFLAGS=-I\$(srcdir)/Modules/_io$as_nl" - if true; then +fi + + + case $py_stdlib_not_available in #( + *time*) : + py_cv_module_time=n/a ;; #( + *) : + py_cv_module_time=yes + ;; +esac + if test "$py_cv_module_time" = yes; then MODULE_TIME_TRUE= MODULE_TIME_FALSE='#' else MODULE_TIME_TRUE='#' MODULE_TIME_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE_TIME=yes$as_nl" + + as_fn_append MODULE_BLOCK "MODULE_TIME=$py_cv_module_time$as_nl" + if test "x$py_cv_module_time" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE_TIME_LDFLAGS=$TIMEMODULE_LIB$as_nl" +fi + - if true; then + case $py_stdlib_not_available in #( + *array*) : + py_cv_module_array=n/a ;; #( + *) : + py_cv_module_array=yes + ;; +esac + if test "$py_cv_module_array" = yes; then MODULE_ARRAY_TRUE= MODULE_ARRAY_FALSE='#' else MODULE_ARRAY_TRUE='#' MODULE_ARRAY_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE_ARRAY=yes$as_nl" - if true; then + as_fn_append MODULE_BLOCK "MODULE_ARRAY=$py_cv_module_array$as_nl" + if test "x$py_cv_module_array" = xyes; then : + + + + +fi + + + case $py_stdlib_not_available in #( + *_asyncio*) : + py_cv_module__asyncio=n/a ;; #( + *) : + py_cv_module__asyncio=yes + ;; +esac + if test "$py_cv_module__asyncio" = yes; then MODULE__ASYNCIO_TRUE= MODULE__ASYNCIO_FALSE='#' else MODULE__ASYNCIO_TRUE='#' MODULE__ASYNCIO_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__ASYNCIO=yes$as_nl" - if true; then + as_fn_append MODULE_BLOCK "MODULE__ASYNCIO=$py_cv_module__asyncio$as_nl" + if test "x$py_cv_module__asyncio" = xyes; then : + + + + +fi + + + case $py_stdlib_not_available in #( + *_bisect*) : + py_cv_module__bisect=n/a ;; #( + *) : + py_cv_module__bisect=yes + ;; +esac + if test "$py_cv_module__bisect" = yes; then MODULE__BISECT_TRUE= MODULE__BISECT_FALSE='#' else MODULE__BISECT_TRUE='#' MODULE__BISECT_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__BISECT=yes$as_nl" - if true; then + as_fn_append MODULE_BLOCK "MODULE__BISECT=$py_cv_module__bisect$as_nl" + if test "x$py_cv_module__bisect" = xyes; then : + + + + +fi + + + case $py_stdlib_not_available in #( + *_contextvars*) : + py_cv_module__contextvars=n/a ;; #( + *) : + py_cv_module__contextvars=yes + ;; +esac + if test "$py_cv_module__contextvars" = yes; then MODULE__CONTEXTVARS_TRUE= MODULE__CONTEXTVARS_FALSE='#' else MODULE__CONTEXTVARS_TRUE='#' MODULE__CONTEXTVARS_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__CONTEXTVARS=yes$as_nl" - if true; then + as_fn_append MODULE_BLOCK "MODULE__CONTEXTVARS=$py_cv_module__contextvars$as_nl" + if test "x$py_cv_module__contextvars" = xyes; then : + + + + +fi + + + case $py_stdlib_not_available in #( + *_csv*) : + py_cv_module__csv=n/a ;; #( + *) : + py_cv_module__csv=yes + ;; +esac + if test "$py_cv_module__csv" = yes; then MODULE__CSV_TRUE= MODULE__CSV_FALSE='#' else MODULE__CSV_TRUE='#' MODULE__CSV_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__CSV=yes$as_nl" - if true; then + as_fn_append MODULE_BLOCK "MODULE__CSV=$py_cv_module__csv$as_nl" + if test "x$py_cv_module__csv" = xyes; then : + + + + +fi + + + case $py_stdlib_not_available in #( + *_heapq*) : + py_cv_module__heapq=n/a ;; #( + *) : + py_cv_module__heapq=yes + ;; +esac + if test "$py_cv_module__heapq" = yes; then MODULE__HEAPQ_TRUE= MODULE__HEAPQ_FALSE='#' else MODULE__HEAPQ_TRUE='#' MODULE__HEAPQ_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__HEAPQ=yes$as_nl" - if true; then + as_fn_append MODULE_BLOCK "MODULE__HEAPQ=$py_cv_module__heapq$as_nl" + if test "x$py_cv_module__heapq" = xyes; then : + + + + +fi + + + case $py_stdlib_not_available in #( + *_json*) : + py_cv_module__json=n/a ;; #( + *) : + py_cv_module__json=yes + ;; +esac + if test "$py_cv_module__json" = yes; then MODULE__JSON_TRUE= MODULE__JSON_FALSE='#' else MODULE__JSON_TRUE='#' MODULE__JSON_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__JSON=yes$as_nl" - if true; then + as_fn_append MODULE_BLOCK "MODULE__JSON=$py_cv_module__json$as_nl" + if test "x$py_cv_module__json" = xyes; then : + + + + +fi + + + case $py_stdlib_not_available in #( + *_lsprof*) : + py_cv_module__lsprof=n/a ;; #( + *) : + py_cv_module__lsprof=yes + ;; +esac + if test "$py_cv_module__lsprof" = yes; then MODULE__LSPROF_TRUE= MODULE__LSPROF_FALSE='#' else MODULE__LSPROF_TRUE='#' MODULE__LSPROF_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__LSPROF=yes$as_nl" - if true; then + as_fn_append MODULE_BLOCK "MODULE__LSPROF=$py_cv_module__lsprof$as_nl" + if test "x$py_cv_module__lsprof" = xyes; then : + + + + +fi + + + case $py_stdlib_not_available in #( + *_opcode*) : + py_cv_module__opcode=n/a ;; #( + *) : + py_cv_module__opcode=yes + ;; +esac + if test "$py_cv_module__opcode" = yes; then MODULE__OPCODE_TRUE= MODULE__OPCODE_FALSE='#' else MODULE__OPCODE_TRUE='#' MODULE__OPCODE_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__OPCODE=yes$as_nl" - if true; then + as_fn_append MODULE_BLOCK "MODULE__OPCODE=$py_cv_module__opcode$as_nl" + if test "x$py_cv_module__opcode" = xyes; then : + + + + +fi + + + case $py_stdlib_not_available in #( + *_pickle*) : + py_cv_module__pickle=n/a ;; #( + *) : + py_cv_module__pickle=yes + ;; +esac + if test "$py_cv_module__pickle" = yes; then MODULE__PICKLE_TRUE= MODULE__PICKLE_FALSE='#' else MODULE__PICKLE_TRUE='#' MODULE__PICKLE_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__PICKLE=yes$as_nl" - if true; then + as_fn_append MODULE_BLOCK "MODULE__PICKLE=$py_cv_module__pickle$as_nl" + if test "x$py_cv_module__pickle" = xyes; then : + + + + +fi + + + case $py_stdlib_not_available in #( + *_posixsubprocess*) : + py_cv_module__posixsubprocess=n/a ;; #( + *) : + py_cv_module__posixsubprocess=yes + ;; +esac + if test "$py_cv_module__posixsubprocess" = yes; then MODULE__POSIXSUBPROCESS_TRUE= MODULE__POSIXSUBPROCESS_FALSE='#' else MODULE__POSIXSUBPROCESS_TRUE='#' MODULE__POSIXSUBPROCESS_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__POSIXSUBPROCESS=yes$as_nl" - if true; then + as_fn_append MODULE_BLOCK "MODULE__POSIXSUBPROCESS=$py_cv_module__posixsubprocess$as_nl" + if test "x$py_cv_module__posixsubprocess" = xyes; then : + + + + +fi + + + case $py_stdlib_not_available in #( + *_queue*) : + py_cv_module__queue=n/a ;; #( + *) : + py_cv_module__queue=yes + ;; +esac + if test "$py_cv_module__queue" = yes; then MODULE__QUEUE_TRUE= MODULE__QUEUE_FALSE='#' else MODULE__QUEUE_TRUE='#' MODULE__QUEUE_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__QUEUE=yes$as_nl" - if true; then + as_fn_append MODULE_BLOCK "MODULE__QUEUE=$py_cv_module__queue$as_nl" + if test "x$py_cv_module__queue" = xyes; then : + + + + +fi + + + case $py_stdlib_not_available in #( + *_random*) : + py_cv_module__random=n/a ;; #( + *) : + py_cv_module__random=yes + ;; +esac + if test "$py_cv_module__random" = yes; then MODULE__RANDOM_TRUE= MODULE__RANDOM_FALSE='#' else MODULE__RANDOM_TRUE='#' MODULE__RANDOM_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__RANDOM=yes$as_nl" - if true; then + as_fn_append MODULE_BLOCK "MODULE__RANDOM=$py_cv_module__random$as_nl" + if test "x$py_cv_module__random" = xyes; then : + + + + +fi + + + case $py_stdlib_not_available in #( + *select*) : + py_cv_module_select=n/a ;; #( + *) : + py_cv_module_select=yes + ;; +esac + if test "$py_cv_module_select" = yes; then MODULE_SELECT_TRUE= MODULE_SELECT_FALSE='#' else MODULE_SELECT_TRUE='#' MODULE_SELECT_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE_SELECT=yes$as_nl" - if true; then + as_fn_append MODULE_BLOCK "MODULE_SELECT=$py_cv_module_select$as_nl" + if test "x$py_cv_module_select" = xyes; then : + + + + +fi + + + case $py_stdlib_not_available in #( + *_struct*) : + py_cv_module__struct=n/a ;; #( + *) : + py_cv_module__struct=yes + ;; +esac + if test "$py_cv_module__struct" = yes; then MODULE__STRUCT_TRUE= MODULE__STRUCT_FALSE='#' else MODULE__STRUCT_TRUE='#' MODULE__STRUCT_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__STRUCT=yes$as_nl" - if true; then + as_fn_append MODULE_BLOCK "MODULE__STRUCT=$py_cv_module__struct$as_nl" + if test "x$py_cv_module__struct" = xyes; then : + + + + +fi + + + case $py_stdlib_not_available in #( + *_typing*) : + py_cv_module__typing=n/a ;; #( + *) : + py_cv_module__typing=yes + ;; +esac + if test "$py_cv_module__typing" = yes; then MODULE__TYPING_TRUE= MODULE__TYPING_FALSE='#' else MODULE__TYPING_TRUE='#' MODULE__TYPING_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__TYPING=yes$as_nl" - if true; then + as_fn_append MODULE_BLOCK "MODULE__TYPING=$py_cv_module__typing$as_nl" + if test "x$py_cv_module__typing" = xyes; then : + + + + +fi + + + case $py_stdlib_not_available in #( + *_xxsubinterpreters*) : + py_cv_module__xxsubinterpreters=n/a ;; #( + *) : + py_cv_module__xxsubinterpreters=yes + ;; +esac + if test "$py_cv_module__xxsubinterpreters" = yes; then MODULE__XXSUBINTERPRETERS_TRUE= MODULE__XXSUBINTERPRETERS_FALSE='#' else MODULE__XXSUBINTERPRETERS_TRUE='#' MODULE__XXSUBINTERPRETERS_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__XXSUBINTERPRETERS=yes$as_nl" - if true; then + as_fn_append MODULE_BLOCK "MODULE__XXSUBINTERPRETERS=$py_cv_module__xxsubinterpreters$as_nl" + if test "x$py_cv_module__xxsubinterpreters" = xyes; then : + + + + +fi + + + case $py_stdlib_not_available in #( + *_zoneinfo*) : + py_cv_module__zoneinfo=n/a ;; #( + *) : + py_cv_module__zoneinfo=yes + ;; +esac + if test "$py_cv_module__zoneinfo" = yes; then MODULE__ZONEINFO_TRUE= MODULE__ZONEINFO_FALSE='#' else MODULE__ZONEINFO_TRUE='#' MODULE__ZONEINFO_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__ZONEINFO=yes$as_nl" + + as_fn_append MODULE_BLOCK "MODULE__ZONEINFO=$py_cv_module__zoneinfo$as_nl" + if test "x$py_cv_module__zoneinfo" = xyes; then : + - if true; then + +fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _multiprocessing" >&5 +$as_echo_n "checking for stdlib extension module _multiprocessing... " >&6; } + case $py_stdlib_not_available in #( + *_multiprocessing*) : + py_cv_module__multiprocessing=n/a ;; #( + *) : + if true; then : + if test "$ac_cv_func_sem_unlink" = "yes"; then : + py_cv_module__multiprocessing=yes +else + py_cv_module__multiprocessing=missing +fi +else + py_cv_module__multiprocessing=disabled +fi + ;; +esac + as_fn_append MODULE_BLOCK "MODULE__MULTIPROCESSING=$py_cv_module__multiprocessing$as_nl" + if test "x$py_cv_module__multiprocessing" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE__MULTIPROCESSING_CFLAGS=-I\$(srcdir)/Modules/_multiprocessing$as_nl" + + +fi + if test "$py_cv_module__multiprocessing" = yes; then MODULE__MULTIPROCESSING_TRUE= MODULE__MULTIPROCESSING_FALSE='#' else MODULE__MULTIPROCESSING_TRUE='#' MODULE__MULTIPROCESSING_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__MULTIPROCESSING=yes$as_nl" - as_fn_append MODULE_BLOCK "MODULE__MULTIPROCESSING_CFLAGS=-I\$(srcdir)/Modules/_multiprocessing$as_nl" + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__multiprocessing" >&5 +$as_echo "$py_cv_module__multiprocessing" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _posixshmem" >&5 @@ -21320,61 +21641,126 @@ $as_echo "$py_cv_module__posixshmem" >&6; } - if true; then + case $py_stdlib_not_available in #( + *audioop*) : + py_cv_module_audioop=n/a ;; #( + *) : + py_cv_module_audioop=yes + ;; +esac + if test "$py_cv_module_audioop" = yes; then MODULE_AUDIOOP_TRUE= MODULE_AUDIOOP_FALSE='#' else MODULE_AUDIOOP_TRUE='#' MODULE_AUDIOOP_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE_AUDIOOP=yes$as_nl" + + as_fn_append MODULE_BLOCK "MODULE_AUDIOOP=$py_cv_module_audioop$as_nl" + if test "x$py_cv_module_audioop" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE_AUDIOOP_LDFLAGS=$LIBM$as_nl" +fi + - if true; then + case $py_stdlib_not_available in #( + *_statistics*) : + py_cv_module__statistics=n/a ;; #( + *) : + py_cv_module__statistics=yes + ;; +esac + if test "$py_cv_module__statistics" = yes; then MODULE__STATISTICS_TRUE= MODULE__STATISTICS_FALSE='#' else MODULE__STATISTICS_TRUE='#' MODULE__STATISTICS_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__STATISTICS=yes$as_nl" + + as_fn_append MODULE_BLOCK "MODULE__STATISTICS=$py_cv_module__statistics$as_nl" + if test "x$py_cv_module__statistics" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE__STATISTICS_LDFLAGS=$LIBM$as_nl" +fi + - if true; then + case $py_stdlib_not_available in #( + *cmath*) : + py_cv_module_cmath=n/a ;; #( + *) : + py_cv_module_cmath=yes + ;; +esac + if test "$py_cv_module_cmath" = yes; then MODULE_CMATH_TRUE= MODULE_CMATH_FALSE='#' else MODULE_CMATH_TRUE='#' MODULE_CMATH_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE_CMATH=yes$as_nl" + + as_fn_append MODULE_BLOCK "MODULE_CMATH=$py_cv_module_cmath$as_nl" + if test "x$py_cv_module_cmath" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE_CMATH_LDFLAGS=$LIBM$as_nl" +fi - if true; then + + case $py_stdlib_not_available in #( + *math*) : + py_cv_module_math=n/a ;; #( + *) : + py_cv_module_math=yes + ;; +esac + if test "$py_cv_module_math" = yes; then MODULE_MATH_TRUE= MODULE_MATH_FALSE='#' else MODULE_MATH_TRUE='#' MODULE_MATH_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE_MATH=yes$as_nl" + + as_fn_append MODULE_BLOCK "MODULE_MATH=$py_cv_module_math$as_nl" + if test "x$py_cv_module_math" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE_MATH_LDFLAGS=$LIBM$as_nl" +fi + - if true; then + case $py_stdlib_not_available in #( + *_datetime*) : + py_cv_module__datetime=n/a ;; #( + *) : + py_cv_module__datetime=yes + ;; +esac + if test "$py_cv_module__datetime" = yes; then MODULE__DATETIME_TRUE= MODULE__DATETIME_FALSE='#' else MODULE__DATETIME_TRUE='#' MODULE__DATETIME_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__DATETIME=yes$as_nl" + + as_fn_append MODULE_BLOCK "MODULE__DATETIME=$py_cv_module__datetime$as_nl" + if test "x$py_cv_module__datetime" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE__DATETIME_LDFLAGS=$TIMEMODULE_LIB $LIBM$as_nl" +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module fcntl" >&5 @@ -21811,77 +22197,197 @@ fi $as_echo "$py_cv_module__elementtree" >&6; } - if true; then + case $py_stdlib_not_available in #( + *_codecs_cn*) : + py_cv_module__codecs_cn=n/a ;; #( + *) : + py_cv_module__codecs_cn=yes + ;; +esac + if test "$py_cv_module__codecs_cn" = yes; then MODULE__CODECS_CN_TRUE= MODULE__CODECS_CN_FALSE='#' else MODULE__CODECS_CN_TRUE='#' MODULE__CODECS_CN_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__CODECS_CN=yes$as_nl" - if true; then + as_fn_append MODULE_BLOCK "MODULE__CODECS_CN=$py_cv_module__codecs_cn$as_nl" + if test "x$py_cv_module__codecs_cn" = xyes; then : + + + + +fi + + + case $py_stdlib_not_available in #( + *_codecs_hk*) : + py_cv_module__codecs_hk=n/a ;; #( + *) : + py_cv_module__codecs_hk=yes + ;; +esac + if test "$py_cv_module__codecs_hk" = yes; then MODULE__CODECS_HK_TRUE= MODULE__CODECS_HK_FALSE='#' else MODULE__CODECS_HK_TRUE='#' MODULE__CODECS_HK_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__CODECS_HK=yes$as_nl" - if true; then + as_fn_append MODULE_BLOCK "MODULE__CODECS_HK=$py_cv_module__codecs_hk$as_nl" + if test "x$py_cv_module__codecs_hk" = xyes; then : + + + + +fi + + + case $py_stdlib_not_available in #( + *_codecs_iso2022*) : + py_cv_module__codecs_iso2022=n/a ;; #( + *) : + py_cv_module__codecs_iso2022=yes + ;; +esac + if test "$py_cv_module__codecs_iso2022" = yes; then MODULE__CODECS_ISO2022_TRUE= MODULE__CODECS_ISO2022_FALSE='#' else MODULE__CODECS_ISO2022_TRUE='#' MODULE__CODECS_ISO2022_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__CODECS_ISO2022=yes$as_nl" - if true; then + as_fn_append MODULE_BLOCK "MODULE__CODECS_ISO2022=$py_cv_module__codecs_iso2022$as_nl" + if test "x$py_cv_module__codecs_iso2022" = xyes; then : + + + + +fi + + + case $py_stdlib_not_available in #( + *_codecs_jp*) : + py_cv_module__codecs_jp=n/a ;; #( + *) : + py_cv_module__codecs_jp=yes + ;; +esac + if test "$py_cv_module__codecs_jp" = yes; then MODULE__CODECS_JP_TRUE= MODULE__CODECS_JP_FALSE='#' else MODULE__CODECS_JP_TRUE='#' MODULE__CODECS_JP_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__CODECS_JP=yes$as_nl" - if true; then + as_fn_append MODULE_BLOCK "MODULE__CODECS_JP=$py_cv_module__codecs_jp$as_nl" + if test "x$py_cv_module__codecs_jp" = xyes; then : + + + + +fi + + + case $py_stdlib_not_available in #( + *_codecs_kr*) : + py_cv_module__codecs_kr=n/a ;; #( + *) : + py_cv_module__codecs_kr=yes + ;; +esac + if test "$py_cv_module__codecs_kr" = yes; then MODULE__CODECS_KR_TRUE= MODULE__CODECS_KR_FALSE='#' else MODULE__CODECS_KR_TRUE='#' MODULE__CODECS_KR_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__CODECS_KR=yes$as_nl" - if true; then + as_fn_append MODULE_BLOCK "MODULE__CODECS_KR=$py_cv_module__codecs_kr$as_nl" + if test "x$py_cv_module__codecs_kr" = xyes; then : + + + + +fi + + + case $py_stdlib_not_available in #( + *_codecs_tw*) : + py_cv_module__codecs_tw=n/a ;; #( + *) : + py_cv_module__codecs_tw=yes + ;; +esac + if test "$py_cv_module__codecs_tw" = yes; then MODULE__CODECS_TW_TRUE= MODULE__CODECS_TW_FALSE='#' else MODULE__CODECS_TW_TRUE='#' MODULE__CODECS_TW_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__CODECS_TW=yes$as_nl" - if true; then + as_fn_append MODULE_BLOCK "MODULE__CODECS_TW=$py_cv_module__codecs_tw$as_nl" + if test "x$py_cv_module__codecs_tw" = xyes; then : + + + + +fi + + + case $py_stdlib_not_available in #( + *_multibytecodec*) : + py_cv_module__multibytecodec=n/a ;; #( + *) : + py_cv_module__multibytecodec=yes + ;; +esac + if test "$py_cv_module__multibytecodec" = yes; then MODULE__MULTIBYTECODEC_TRUE= MODULE__MULTIBYTECODEC_FALSE='#' else MODULE__MULTIBYTECODEC_TRUE='#' MODULE__MULTIBYTECODEC_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__MULTIBYTECODEC=yes$as_nl" - if true; then + as_fn_append MODULE_BLOCK "MODULE__MULTIBYTECODEC=$py_cv_module__multibytecodec$as_nl" + if test "x$py_cv_module__multibytecodec" = xyes; then : + + + + +fi + + + case $py_stdlib_not_available in #( + *unicodedata*) : + py_cv_module_unicodedata=n/a ;; #( + *) : + py_cv_module_unicodedata=yes + ;; +esac + if test "$py_cv_module_unicodedata" = yes; then MODULE_UNICODEDATA_TRUE= MODULE_UNICODEDATA_FALSE='#' else MODULE_UNICODEDATA_TRUE='#' MODULE_UNICODEDATA_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE_UNICODEDATA=yes$as_nl" + + as_fn_append MODULE_BLOCK "MODULE_UNICODEDATA=$py_cv_module_unicodedata$as_nl" + if test "x$py_cv_module_unicodedata" = xyes; then : + + + + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _md5" >&5 @@ -22354,18 +22860,29 @@ fi $as_echo "$py_cv_module_zlib" >&6; } - if true; then + case $py_stdlib_not_available in #( + *binascii*) : + py_cv_module_binascii=n/a ;; #( + *) : + py_cv_module_binascii=yes + ;; +esac + if test "$py_cv_module_binascii" = yes; then MODULE_BINASCII_TRUE= MODULE_BINASCII_FALSE='#' else MODULE_BINASCII_TRUE='#' MODULE_BINASCII_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE_BINASCII=yes$as_nl" - as_fn_append MODULE_BLOCK "MODULE_BINASCII_CFLAGS=$BINASCII_CFLAGS$as_nl" + as_fn_append MODULE_BLOCK "MODULE_BINASCII=$py_cv_module_binascii$as_nl" + if test "x$py_cv_module_binascii" = xyes; then : + + as_fn_append MODULE_BLOCK "MODULE_BINASCII_CFLAGS=$BINASCII_CFLAGS$as_nl" as_fn_append MODULE_BLOCK "MODULE_BINASCII_LDFLAGS=$BINASCII_LIBS$as_nl" +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _bz2" >&5 $as_echo_n "checking for stdlib extension module _bz2... " >&6; } diff --git a/configure.ac b/configure.ac index 5c89b9c241d74..80f256073d68a 100644 --- a/configure.ac +++ b/configure.ac @@ -6205,6 +6205,7 @@ AS_CASE([$ac_sys_system], _posixsubprocess _scproxy _xxsubinterpreters + fcntl grp nis ossaudiodev @@ -6260,20 +6261,25 @@ AC_DEFUN([PY_STDLIB_MOD], [ m4_popdef([modstate])dnl ]) -dnl Define simple, always enabled stdlib extension module +dnl Define simple stdlib extension module +dnl Always enable unless the module is listed in py_stdlib_not_available dnl PY_STDLIB_MOD_SIMPLE([NAME], [CFLAGS], [LDFLAGS]) dnl cflags and ldflags are optional AC_DEFUN([PY_STDLIB_MOD_SIMPLE], [ m4_pushdef([modcond], [MODULE_]m4_toupper([$1]))dnl - AM_CONDITIONAL(modcond, [true])dnl - _MODULE_BLOCK_ADD(modcond, [yes])dnl - m4_ifval([$2], [ - _MODULE_BLOCK_ADD([MODULE_]m4_toupper([$1])[_CFLAGS], [$2]) - ])dnl - m4_ifval([$3], [ - _MODULE_BLOCK_ADD([MODULE_]m4_toupper([$1])[_LDFLAGS], [$3]) - ])dnl + m4_pushdef([modstate], [py_cv_module_$1])dnl + AS_CASE([$py_stdlib_not_available], + [*$1*], [modstate=n/a], + [modstate=yes] + ) + AM_CONDITIONAL(modcond, [test "$modstate" = yes]) + _MODULE_BLOCK_ADD(modcond, [$modstate]) + AS_VAR_IF([modstate], [yes], [ + m4_ifblank([$2], [], [_MODULE_BLOCK_ADD([MODULE_]m4_toupper([$1])[_CFLAGS], [$2])]) + m4_ifblank([$3], [], [_MODULE_BLOCK_ADD([MODULE_]m4_toupper([$1])[_LDFLAGS], [$3])]) + ]) m4_popdef([modcond])dnl + m4_popdef([modstate])dnl ]) dnl static modules in Modules/Setup.bootstrap @@ -6301,7 +6307,9 @@ PY_STDLIB_MOD_SIMPLE([_xxsubinterpreters]) PY_STDLIB_MOD_SIMPLE([_zoneinfo]) dnl multiprocessing modules -PY_STDLIB_MOD_SIMPLE([_multiprocessing], [-I\$(srcdir)/Modules/_multiprocessing]) +PY_STDLIB_MOD([_multiprocessing], + [], [test "$ac_cv_func_sem_unlink" = "yes"], + [-I\$(srcdir)/Modules/_multiprocessing]) PY_STDLIB_MOD([_posixshmem], [], [test "$have_posix_shmem" = "yes"], [$POSIXSHMEM_CFLAGS], [$POSIXSHMEM_LIBS]) From webhook-mailer at python.org Mon Nov 29 11:23:39 2021 From: webhook-mailer at python.org (tiran) Date: Mon, 29 Nov 2021 16:23:39 -0000 Subject: [Python-checkins] bpo-45881: configure --with-freeze-module --with-build-python (GH-29835) Message-ID: https://github.com/python/cpython/commit/992565f7f72fd8250b788795f76eedcff5636a64 commit: 992565f7f72fd8250b788795f76eedcff5636a64 branch: main author: Christian Heimes committer: tiran date: 2021-11-29T17:23:29+01:00 summary: bpo-45881: configure --with-freeze-module --with-build-python (GH-29835) Co-authored-by: Erlend Egeberg Aasland Co-authored-by: Ethan Smith files: A Misc/NEWS.d/next/Build/2021-11-29-16-32-55.bpo-45881.7597J6.rst M Doc/using/configure.rst M Makefile.pre.in M configure M configure.ac diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index c6aa4af73f4d3..5720f015eca06 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -513,6 +513,56 @@ See ``Mac/README.rst``. :option:`--enable-framework` is set (default: ``Python``). +Cross Compiling Options +----------------------- + +Cross compiling, also known as cross building, can be used to build Python +for another CPU architecture or platform. Cross compiling requires a Python +interpreter and the :program:`_freeze_module` binary from another build. The +version of the build Python and :program:`_freeze_module` command must be +the same as the cross compiled host Python. + +.. cmdoption:: --build=BUILD + + configure for building on BUILD, usually guessed by :program:`config.guess`. + +.. cmdoption:: --host=HOST + + cross-compile to build programs to run on HOST (target platform) + +.. cmdoption:: --with-freeze-module=Programs/_freeze_module + + path to ``_freeze_module`` binary for cross compiling. + + .. versionadded:: 3.11 + +.. cmdoption:: --with-build-python=python3.xx + + path to build ``python`` binary for cross compiling + + .. versionadded:: 3.11 + +.. cmdoption:: CONFIG_SITE=file + + An environment variable that points to a file with configure overrides. + + Example *config.site* file:: + + # config.site-aarch64 + ac_cv_buggy_getaddrinfo=no + ac_cv_file__dev_ptmx=yes + ac_cv_file__dev_ptc=no + + +Cross compiling example:: + + CONFIG_SITE=config.site-aarch64 ../configure \ + --build=x86_64-pc-linux-gnu \ + --host=aarch64-unknown-linux-gnu \ + --with-freeze-module=../x86_64/Programs/_freeze_module \ + --with-build-python=../x86_64/python + + Python Build System =================== diff --git a/Makefile.pre.in b/Makefile.pre.in index fc8ab99babcdb..d5be6edf784e2 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -282,6 +282,8 @@ PYTHON_FOR_BUILD=@PYTHON_FOR_BUILD@ _PYTHON_HOST_PLATFORM=@_PYTHON_HOST_PLATFORM@ BUILD_GNU_TYPE= @build@ HOST_GNU_TYPE= @host@ +# Allow developers to override freeze_module command for cross building (bpo-45886) +FREEZE_MODULE?=@FREEZE_MODULE@ # Tcl and Tk config info from --with-tcltk-includes and -libs options TCLTK_INCLUDES= @TCLTK_INCLUDES@ @@ -1011,9 +1013,6 @@ Python/deepfreeze/frozen_only.c: Python/frozen_modules/frozen_only.h $(DEEPFREEZ ############################################################################ # frozen modules (including importlib) -# Allow developers to override freeze_module command for cross building (bpo-45886) -FREEZE_MODULE?=Programs/_freeze_module - # FROZEN_FILES_* are auto-generated by Tools/scripts/freeze_modules.py. FROZEN_FILES_IN = \ Lib/importlib/_bootstrap.py \ diff --git a/Misc/NEWS.d/next/Build/2021-11-29-16-32-55.bpo-45881.7597J6.rst b/Misc/NEWS.d/next/Build/2021-11-29-16-32-55.bpo-45881.7597J6.rst new file mode 100644 index 0000000000000..7ee57d0db1a92 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-29-16-32-55.bpo-45881.7597J6.rst @@ -0,0 +1,2 @@ +The :program:`configure` script now accepts ``--with-build-python`` and +``--with-freeze-module`` options to make cross compiling easier. diff --git a/configure b/configure index 29c65a6bc94a4..382e030974727 100755 --- a/configure +++ b/configure @@ -931,8 +931,9 @@ PKG_CONFIG CONFIG_ARGS SOVERSION VERSION -PYTHON_FOR_BUILD PYTHON_FOR_REGEN +PYTHON_FOR_BUILD +FREEZE_MODULE host_os host_vendor host_cpu @@ -988,6 +989,8 @@ SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking +with_freeze_module +with_build_python with_pkg_config enable_universalsdk with_universal_archs @@ -1721,6 +1724,11 @@ Optional Features: Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-freeze-module=Programs/_freeze_module + path to _freeze_module binary for cross compiling + --with-build-python=python3.11 + path to build python binary for cross compiling + (default: python3.11) --with-pkg-config=[yes|no|check] use pkg-config to detect build options (default is check) @@ -3177,9 +3185,88 @@ case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac +if test "x$cross_compiling" = xmaybe; then : + as_fn_error $? "Cross compiling required --host=HOST-TUPLE and --build=ARCH" "$LINENO" 5 + +fi + # pybuilddir.txt will be created by --generate-posix-vars in the Makefile rm -f pybuilddir.txt + +# Check whether --with-freeze-module was given. +if test "${with_freeze_module+set}" = set; then : + withval=$with_freeze_module; + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-freeze-module" >&5 +$as_echo_n "checking for --with-freeze-module... " >&6; } + if test "x$cross_compiling" = xno; then : + as_fn_error $? "--with-freeze-module only applies to cross compiling" "$LINENO" 5 +fi + if test "$with_freeze_module" = yes -o "$with_freeze_module" = no; then + as_fn_error $? "invalid --with-freeze-module option: expected path, not \"$with_freeze_module\"" "$LINENO" 5 + fi + if ! $(command -v "$with_freeze_module" >/dev/null 2>&1); then + as_fn_error $? "invalid or missing freeze module binary \"$with_freeze_module\"" "$LINENO" 5 + fi + FREEZE_MODULE="$with_freeze_module" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FREEZE_MODULE" >&5 +$as_echo "$FREEZE_MODULE" >&6; } + +else + + if test "x$cross_compiling" = xyes; then : + as_fn_error $? "Cross compiling requires --with-freeze-module" "$LINENO" 5 + +fi + FREEZE_MODULE=Programs/_freeze_module + + +fi + + + + +# Check whether --with-build-python was given. +if test "${with_build_python+set}" = set; then : + withval=$with_build_python; + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-build-python" >&5 +$as_echo_n "checking for --with-build-python... " >&6; } + + if test "x$cross_compiling" = xno; then : + as_fn_error $? "--with-build-python only applies to cross compiling" "$LINENO" 5 +fi + if test "x$with_build_python" = xyes; then : + with_build_python=python$PACKAGE_VERSION +fi + if test "x$with_build_python" = xno; then : + as_fn_error $? "invalid --with-build-python option: expected path, not \"no\"" "$LINENO" 5 +fi + + if ! $(command -v "$with_build_python" >/dev/null 2>&1); then + as_fn_error $? "invalid or missing build python binary \"$with_build_python\"" "$LINENO" 5 + fi + build_python_ver=$($with_build_python -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')") + if test "$build_python_ver" != "$PACKAGE_VERSION"; then + as_fn_error $? "\"$with_build_python\" has incompatible version $build_python_ver (expected: $PACKAGE_VERSION)" "$LINENO" 5 + fi + ac_cv_prog_PYTHON_FOR_REGEN=$with_build_python + PYTHON_FOR_BUILD='_PYTHON_PROJECT_BASE=$(abs_builddir) _PYTHON_HOST_PLATFORM=$(_PYTHON_HOST_PLATFORM) PYTHONPATH=$(shell test -f pybuilddir.txt && echo $(abs_builddir)/`cat pybuilddir.txt`:)$(srcdir)/Lib _PYTHON_SYSCONFIGDATA_NAME=_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH) '$with_build_python + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_build_python" >&5 +$as_echo "$with_build_python" >&6; } + +else + + if test "x$cross_compiling" = xyes; then : + as_fn_error $? "Cross compiling requires --with-build-python" "$LINENO" 5 + +fi + PYTHON_FOR_BUILD='./$(BUILDPYTHON) -E' + + +fi + + + for ac_prog in python$PACKAGE_VERSION python3.10 python3.9 python3.8 python3.7 python3.6 python3 python do # Extract the first word of "$ac_prog", so it can be a program name with args. @@ -3235,31 +3322,6 @@ else $as_echo "missing" >&6; } fi -if test "$cross_compiling" = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for python interpreter for cross build" >&5 -$as_echo_n "checking for python interpreter for cross build... " >&6; } - if test -z "$PYTHON_FOR_BUILD"; then - for interp in python$PACKAGE_VERSION python3 python; do - which $interp >/dev/null 2>&1 || continue - if $interp -c "import sys;sys.exit(not '.'.join(str(n) for n in sys.version_info[:2]) == '$PACKAGE_VERSION')"; then - break - fi - interp= - done - if test x$interp = x; then - as_fn_error $? "python$PACKAGE_VERSION interpreter not found" "$LINENO" 5 - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $interp" >&5 -$as_echo "$interp" >&6; } - PYTHON_FOR_BUILD='_PYTHON_PROJECT_BASE=$(abs_builddir) _PYTHON_HOST_PLATFORM=$(_PYTHON_HOST_PLATFORM) PYTHONPATH=$(shell test -f pybuilddir.txt && echo $(abs_builddir)/`cat pybuilddir.txt`:)$(srcdir)/Lib _PYTHON_SYSCONFIGDATA_NAME=_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH) '$interp - fi -elif test "$cross_compiling" = maybe; then - as_fn_error $? "Cross compiling required --host=HOST-TUPLE and --build=ARCH" "$LINENO" 5 -else - PYTHON_FOR_BUILD='./$(BUILDPYTHON) -E' -fi - - if test "$prefix" != "/"; then prefix=`echo "$prefix" | sed -e 's/\/$//g'` diff --git a/configure.ac b/configure.ac index 80f256073d68a..1e5fef337ca5d 100644 --- a/configure.ac +++ b/configure.ac @@ -93,9 +93,69 @@ AC_CANONICAL_HOST AC_SUBST(build) AC_SUBST(host) +AS_VAR_IF([cross_compiling], [maybe], + [AC_MSG_ERROR([Cross compiling required --host=HOST-TUPLE and --build=ARCH])] +) + # pybuilddir.txt will be created by --generate-posix-vars in the Makefile rm -f pybuilddir.txt +dnl cross-compiling needs a freeze_module binary for build platform +AC_ARG_WITH( + [freeze-module], + [AS_HELP_STRING([--with-freeze-module=Programs/_freeze_module], + [path to _freeze_module binary for cross compiling])], + [ + AC_MSG_CHECKING([for --with-freeze-module]) + AS_VAR_IF([cross_compiling], [no], AC_MSG_ERROR([--with-freeze-module only applies to cross compiling])) + if test "$with_freeze_module" = yes -o "$with_freeze_module" = no; then + AC_MSG_ERROR([invalid --with-freeze-module option: expected path, not "$with_freeze_module"]) + fi + if ! $(command -v "$with_freeze_module" >/dev/null 2>&1); then + AC_MSG_ERROR([invalid or missing freeze module binary "$with_freeze_module"]) + fi + FREEZE_MODULE="$with_freeze_module" + AC_MSG_RESULT([$FREEZE_MODULE]) + ], [ + AS_VAR_IF([cross_compiling], [yes], + [AC_MSG_ERROR([Cross compiling requires --with-freeze-module])] + ) + FREEZE_MODULE=Programs/_freeze_module + ] +) +AC_SUBST([FREEZE_MODULE]) + +AC_ARG_WITH( + [build-python], + [AS_HELP_STRING([--with-build-python=python]PYTHON_VERSION, + [path to build python binary for cross compiling (default: python]PYTHON_VERSION[)])], + [ + AC_MSG_CHECKING([for --with-build-python]) + + AS_VAR_IF([cross_compiling], [no], AC_MSG_ERROR([--with-build-python only applies to cross compiling])) + AS_VAR_IF([with_build_python], [yes], [with_build_python=python$PACKAGE_VERSION]) + AS_VAR_IF([with_build_python], [no], [AC_MSG_ERROR([invalid --with-build-python option: expected path, not "no"])]) + + if ! $(command -v "$with_build_python" >/dev/null 2>&1); then + AC_MSG_ERROR([invalid or missing build python binary "$with_build_python"]) + fi + build_python_ver=$($with_build_python -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')") + if test "$build_python_ver" != "$PACKAGE_VERSION"; then + AC_MSG_ERROR(["$with_build_python" has incompatible version $build_python_ver (expected: $PACKAGE_VERSION)]) + fi + dnl use build Python for regeneration, too + ac_cv_prog_PYTHON_FOR_REGEN=$with_build_python + PYTHON_FOR_BUILD='_PYTHON_PROJECT_BASE=$(abs_builddir) _PYTHON_HOST_PLATFORM=$(_PYTHON_HOST_PLATFORM) PYTHONPATH=$(shell test -f pybuilddir.txt && echo $(abs_builddir)/`cat pybuilddir.txt`:)$(srcdir)/Lib _PYTHON_SYSCONFIGDATA_NAME=_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH) '$with_build_python + AC_MSG_RESULT([$with_build_python]) + ], [ + AS_VAR_IF([cross_compiling], [yes], + [AC_MSG_ERROR([Cross compiling requires --with-build-python])] + ) + PYTHON_FOR_BUILD='./$(BUILDPYTHON) -E' + ] +) +AC_SUBST([PYTHON_FOR_BUILD]) + AC_CHECK_PROGS([PYTHON_FOR_REGEN], [python$PACKAGE_VERSION python3.10 python3.9 python3.8 python3.7 python3.6 python3 python], [python3]) @@ -108,29 +168,6 @@ else AC_MSG_RESULT([missing]) fi -if test "$cross_compiling" = yes; then - AC_MSG_CHECKING([for python interpreter for cross build]) - if test -z "$PYTHON_FOR_BUILD"; then - for interp in python$PACKAGE_VERSION python3 python; do - which $interp >/dev/null 2>&1 || continue - if $interp -c "import sys;sys.exit(not '.'.join(str(n) for n in sys.version_info@<:@:2@:>@) == '$PACKAGE_VERSION')"; then - break - fi - interp= - done - if test x$interp = x; then - AC_MSG_ERROR([python$PACKAGE_VERSION interpreter not found]) - fi - AC_MSG_RESULT($interp) - PYTHON_FOR_BUILD='_PYTHON_PROJECT_BASE=$(abs_builddir) _PYTHON_HOST_PLATFORM=$(_PYTHON_HOST_PLATFORM) PYTHONPATH=$(shell test -f pybuilddir.txt && echo $(abs_builddir)/`cat pybuilddir.txt`:)$(srcdir)/Lib _PYTHON_SYSCONFIGDATA_NAME=_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH) '$interp - fi -elif test "$cross_compiling" = maybe; then - AC_MSG_ERROR([Cross compiling required --host=HOST-TUPLE and --build=ARCH]) -else - PYTHON_FOR_BUILD='./$(BUILDPYTHON) -E' -fi -AC_SUBST(PYTHON_FOR_BUILD) - dnl Ensure that if prefix is specified, it does not end in a slash. If dnl it does, we get path names containing '//' which is both ugly and dnl can cause trouble. From webhook-mailer at python.org Mon Nov 29 12:27:00 2021 From: webhook-mailer at python.org (vsajip) Date: Mon, 29 Nov 2021 17:27:00 -0000 Subject: [Python-checkins] bpo-44391: Remove unused argument from a varargs call. (GH-29843) Message-ID: https://github.com/python/cpython/commit/4141d94fa608cdf5c8cd3e62f7ea1c27fd41eb8d commit: 4141d94fa608cdf5c8cd3e62f7ea1c27fd41eb8d branch: main author: Vinay Sajip committer: vsajip date: 2021-11-29T17:26:50Z summary: bpo-44391: Remove unused argument from a varargs call. (GH-29843) files: M PC/launcher.c diff --git a/PC/launcher.c b/PC/launcher.c index f8b8a3db39775..d2e6462f13e31 100644 --- a/PC/launcher.c +++ b/PC/launcher.c @@ -344,7 +344,7 @@ _locate_pythons_for_key(HKEY root, LPCWSTR subkey, REGSAM flags, int bits, } else if (attrs & FILE_ATTRIBUTE_DIRECTORY) { debug(L"locate_pythons_for_key: '%ls' is a directory\n", - ip->executable, attrs); + ip->executable); } else if (find_existing_python(ip->executable)) { debug(L"locate_pythons_for_key: %ls: already found\n", From webhook-mailer at python.org Mon Nov 29 12:53:47 2021 From: webhook-mailer at python.org (vsajip) Date: Mon, 29 Nov 2021 17:53:47 -0000 Subject: [Python-checkins] [3.9] bpo-44391: Remove unused argument from a varargs call. (GH-29843) (GH-29850) Message-ID: https://github.com/python/cpython/commit/40a57532a5ad5dfd81ab6c72c5fb2e2dc4509199 commit: 40a57532a5ad5dfd81ab6c72c5fb2e2dc4509199 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: vsajip date: 2021-11-29T17:53:37Z summary: [3.9] bpo-44391: Remove unused argument from a varargs call. (GH-29843) (GH-29850) files: M PC/launcher.c diff --git a/PC/launcher.c b/PC/launcher.c index 106fc660755f7..11249d7ec78ae 100644 --- a/PC/launcher.c +++ b/PC/launcher.c @@ -344,7 +344,7 @@ _locate_pythons_for_key(HKEY root, LPCWSTR subkey, REGSAM flags, int bits, } else if (attrs & FILE_ATTRIBUTE_DIRECTORY) { debug(L"locate_pythons_for_key: '%ls' is a directory\n", - ip->executable, attrs); + ip->executable); } else if (find_existing_python(ip->executable)) { debug(L"locate_pythons_for_key: %ls: already found\n", From webhook-mailer at python.org Mon Nov 29 13:00:40 2021 From: webhook-mailer at python.org (vsajip) Date: Mon, 29 Nov 2021 18:00:40 -0000 Subject: [Python-checkins] [3.10] bpo-44391: Remove unused argument from a varargs call. (GH-29843) (GH-29849) Message-ID: https://github.com/python/cpython/commit/af39cfa6ca1e5dc4e5d28c1f09a875a14354e4ae commit: af39cfa6ca1e5dc4e5d28c1f09a875a14354e4ae branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: vsajip date: 2021-11-29T18:00:31Z summary: [3.10] bpo-44391: Remove unused argument from a varargs call. (GH-29843) (GH-29849) files: M PC/launcher.c diff --git a/PC/launcher.c b/PC/launcher.c index 84c8a1d14ea41..734e7533398b1 100644 --- a/PC/launcher.c +++ b/PC/launcher.c @@ -344,7 +344,7 @@ _locate_pythons_for_key(HKEY root, LPCWSTR subkey, REGSAM flags, int bits, } else if (attrs & FILE_ATTRIBUTE_DIRECTORY) { debug(L"locate_pythons_for_key: '%ls' is a directory\n", - ip->executable, attrs); + ip->executable); } else if (find_existing_python(ip->executable)) { debug(L"locate_pythons_for_key: %ls: already found\n", From webhook-mailer at python.org Mon Nov 29 13:10:41 2021 From: webhook-mailer at python.org (miss-islington) Date: Mon, 29 Nov 2021 18:10:41 -0000 Subject: [Python-checkins] bpo-43905: Expand dataclasses.astuple() and asdict() docs (GH-26154) Message-ID: https://github.com/python/cpython/commit/c1f93f0d378958dfae4f24aad0c0088e3e04e403 commit: c1f93f0d378958dfae4f24aad0c0088e3e04e403 branch: main author: andrei kulakov committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-29T10:10:32-08:00 summary: bpo-43905: Expand dataclasses.astuple() and asdict() docs (GH-26154) Expanded ``astuple()`` docs, warning about deepcopy being applied and providing a workaround. Automerge-Triggered-By: GH:ericvsmith files: A Misc/NEWS.d/next/Documentation/2021-05-24-05-00-12.bpo-43905.tBIndE.rst M Doc/library/dataclasses.rst diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst index a7144094c6849..b06547074378f 100644 --- a/Doc/library/dataclasses.rst +++ b/Doc/library/dataclasses.rst @@ -324,7 +324,10 @@ Module contents Converts the dataclass ``instance`` to a dict (by using the factory function ``dict_factory``). Each dataclass is converted to a dict of its fields, as ``name: value`` pairs. dataclasses, dicts, - lists, and tuples are recursed into. For example:: + lists, and tuples are recursed into. Other objects are copied with + :func:`copy.deepcopy`. + + Example of using :func:`asdict` on nested dataclasses:: @dataclass class Point: @@ -341,21 +344,32 @@ Module contents c = C([Point(0, 0), Point(10, 4)]) assert asdict(c) == {'mylist': [{'x': 0, 'y': 0}, {'x': 10, 'y': 4}]} - Raises :exc:`TypeError` if ``instance`` is not a dataclass instance. + To create a shallow copy, the following workaround may be used:: + + dict((field.name, getattr(instance, field.name)) for field in fields(instance)) + + :func:`asdict` raises :exc:`TypeError` if ``instance`` is not a dataclass + instance. .. function:: astuple(instance, *, tuple_factory=tuple) Converts the dataclass ``instance`` to a tuple (by using the factory function ``tuple_factory``). Each dataclass is converted to a tuple of its field values. dataclasses, dicts, lists, and - tuples are recursed into. + tuples are recursed into. Other objects are copied with + :func:`copy.deepcopy`. Continuing from the previous example:: assert astuple(p) == (10, 20) assert astuple(c) == ([(0, 0), (10, 4)],) - Raises :exc:`TypeError` if ``instance`` is not a dataclass instance. + To create a shallow copy, the following workaround may be used:: + + tuple(getattr(instance, field.name) for field in dataclasses.fields(instance)) + + :func:`astuple` raises :exc:`TypeError` if ``instance`` is not a dataclass + instance. .. function:: make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, match_args=True, kw_only=False, slots=False) diff --git a/Misc/NEWS.d/next/Documentation/2021-05-24-05-00-12.bpo-43905.tBIndE.rst b/Misc/NEWS.d/next/Documentation/2021-05-24-05-00-12.bpo-43905.tBIndE.rst new file mode 100644 index 0000000000000..760e1eea0deb7 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-05-24-05-00-12.bpo-43905.tBIndE.rst @@ -0,0 +1,2 @@ +Expanded :func:`~dataclasses.astuple` and :func:`~dataclasses.asdict` docs, +warning about deepcopy being applied and providing a workaround. From webhook-mailer at python.org Mon Nov 29 13:30:47 2021 From: webhook-mailer at python.org (miss-islington) Date: Mon, 29 Nov 2021 18:30:47 -0000 Subject: [Python-checkins] bpo-43905: Expand dataclasses.astuple() and asdict() docs (GH-26154) Message-ID: https://github.com/python/cpython/commit/376b24e4f69cba53bae9856e9d076af47bb2b6c6 commit: 376b24e4f69cba53bae9856e9d076af47bb2b6c6 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-29T10:30:38-08:00 summary: bpo-43905: Expand dataclasses.astuple() and asdict() docs (GH-26154) Expanded ``astuple()`` docs, warning about deepcopy being applied and providing a workaround. Automerge-Triggered-By: GH:ericvsmith (cherry picked from commit c1f93f0d378958dfae4f24aad0c0088e3e04e403) Co-authored-by: andrei kulakov files: A Misc/NEWS.d/next/Documentation/2021-05-24-05-00-12.bpo-43905.tBIndE.rst M Doc/library/dataclasses.rst diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst index b226cda46c72b..3a943e05309d9 100644 --- a/Doc/library/dataclasses.rst +++ b/Doc/library/dataclasses.rst @@ -292,7 +292,10 @@ Module-level decorators, classes, and functions Converts the dataclass ``instance`` to a dict (by using the factory function ``dict_factory``). Each dataclass is converted to a dict of its fields, as ``name: value`` pairs. dataclasses, dicts, - lists, and tuples are recursed into. For example:: + lists, and tuples are recursed into. Other objects are copied with + :func:`copy.deepcopy`. + + Example of using :func:`asdict` on nested dataclasses:: @dataclass class Point: @@ -309,21 +312,32 @@ Module-level decorators, classes, and functions c = C([Point(0, 0), Point(10, 4)]) assert asdict(c) == {'mylist': [{'x': 0, 'y': 0}, {'x': 10, 'y': 4}]} - Raises :exc:`TypeError` if ``instance`` is not a dataclass instance. + To create a shallow copy, the following workaround may be used:: + + dict((field.name, getattr(instance, field.name)) for field in fields(instance)) + + :func:`asdict` raises :exc:`TypeError` if ``instance`` is not a dataclass + instance. .. function:: astuple(instance, *, tuple_factory=tuple) Converts the dataclass ``instance`` to a tuple (by using the factory function ``tuple_factory``). Each dataclass is converted to a tuple of its field values. dataclasses, dicts, lists, and - tuples are recursed into. + tuples are recursed into. Other objects are copied with + :func:`copy.deepcopy`. Continuing from the previous example:: assert astuple(p) == (10, 20) assert astuple(c) == ([(0, 0), (10, 4)],) - Raises :exc:`TypeError` if ``instance`` is not a dataclass instance. + To create a shallow copy, the following workaround may be used:: + + tuple(getattr(instance, field.name) for field in dataclasses.fields(instance)) + + :func:`astuple` raises :exc:`TypeError` if ``instance`` is not a dataclass + instance. .. function:: make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False) diff --git a/Misc/NEWS.d/next/Documentation/2021-05-24-05-00-12.bpo-43905.tBIndE.rst b/Misc/NEWS.d/next/Documentation/2021-05-24-05-00-12.bpo-43905.tBIndE.rst new file mode 100644 index 0000000000000..760e1eea0deb7 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-05-24-05-00-12.bpo-43905.tBIndE.rst @@ -0,0 +1,2 @@ +Expanded :func:`~dataclasses.astuple` and :func:`~dataclasses.asdict` docs, +warning about deepcopy being applied and providing a workaround. From webhook-mailer at python.org Mon Nov 29 13:33:05 2021 From: webhook-mailer at python.org (miss-islington) Date: Mon, 29 Nov 2021 18:33:05 -0000 Subject: [Python-checkins] bpo-43905: Expand dataclasses.astuple() and asdict() docs (GH-26154) Message-ID: https://github.com/python/cpython/commit/32f1491a9770b7f2989507ecf8f13ef35dd95b0b commit: 32f1491a9770b7f2989507ecf8f13ef35dd95b0b branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-29T10:32:56-08:00 summary: bpo-43905: Expand dataclasses.astuple() and asdict() docs (GH-26154) Expanded ``astuple()`` docs, warning about deepcopy being applied and providing a workaround. Automerge-Triggered-By: GH:ericvsmith (cherry picked from commit c1f93f0d378958dfae4f24aad0c0088e3e04e403) Co-authored-by: andrei kulakov files: A Misc/NEWS.d/next/Documentation/2021-05-24-05-00-12.bpo-43905.tBIndE.rst M Doc/library/dataclasses.rst diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst index 5915bacbcdc4e..7f9ffcb6137b4 100644 --- a/Doc/library/dataclasses.rst +++ b/Doc/library/dataclasses.rst @@ -324,7 +324,10 @@ Module contents Converts the dataclass ``instance`` to a dict (by using the factory function ``dict_factory``). Each dataclass is converted to a dict of its fields, as ``name: value`` pairs. dataclasses, dicts, - lists, and tuples are recursed into. For example:: + lists, and tuples are recursed into. Other objects are copied with + :func:`copy.deepcopy`. + + Example of using :func:`asdict` on nested dataclasses:: @dataclass class Point: @@ -341,21 +344,32 @@ Module contents c = C([Point(0, 0), Point(10, 4)]) assert asdict(c) == {'mylist': [{'x': 0, 'y': 0}, {'x': 10, 'y': 4}]} - Raises :exc:`TypeError` if ``instance`` is not a dataclass instance. + To create a shallow copy, the following workaround may be used:: + + dict((field.name, getattr(instance, field.name)) for field in fields(instance)) + + :func:`asdict` raises :exc:`TypeError` if ``instance`` is not a dataclass + instance. .. function:: astuple(instance, *, tuple_factory=tuple) Converts the dataclass ``instance`` to a tuple (by using the factory function ``tuple_factory``). Each dataclass is converted to a tuple of its field values. dataclasses, dicts, lists, and - tuples are recursed into. + tuples are recursed into. Other objects are copied with + :func:`copy.deepcopy`. Continuing from the previous example:: assert astuple(p) == (10, 20) assert astuple(c) == ([(0, 0), (10, 4)],) - Raises :exc:`TypeError` if ``instance`` is not a dataclass instance. + To create a shallow copy, the following workaround may be used:: + + tuple(getattr(instance, field.name) for field in dataclasses.fields(instance)) + + :func:`astuple` raises :exc:`TypeError` if ``instance`` is not a dataclass + instance. .. function:: make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, match_args=True, kw_only=False, slots=False) diff --git a/Misc/NEWS.d/next/Documentation/2021-05-24-05-00-12.bpo-43905.tBIndE.rst b/Misc/NEWS.d/next/Documentation/2021-05-24-05-00-12.bpo-43905.tBIndE.rst new file mode 100644 index 0000000000000..760e1eea0deb7 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-05-24-05-00-12.bpo-43905.tBIndE.rst @@ -0,0 +1,2 @@ +Expanded :func:`~dataclasses.astuple` and :func:`~dataclasses.asdict` docs, +warning about deepcopy being applied and providing a workaround. From webhook-mailer at python.org Mon Nov 29 13:55:55 2021 From: webhook-mailer at python.org (mdickinson) Date: Mon, 29 Nov 2021 18:55:55 -0000 Subject: [Python-checkins] bpo-45917: Add math.exp2() method - return 2 raised to the power of x (GH-29829) Message-ID: https://github.com/python/cpython/commit/6266e4af873a27c9d352115f2f7a1ad0885fc031 commit: 6266e4af873a27c9d352115f2f7a1ad0885fc031 branch: main author: Gideon <41593269+Turreted at users.noreply.github.com> committer: mdickinson date: 2021-11-29T18:55:43Z summary: bpo-45917: Add math.exp2() method - return 2 raised to the power of x (GH-29829) Co-authored-by: Mark Dickinson files: A Misc/NEWS.d/next/Library/2021-11-28-17-24-11.bpo-45917.J5TIrd.rst M Doc/library/math.rst M Doc/whatsnew/3.11.rst M Lib/test/test_math.py M Misc/ACKS M Modules/mathmodule.c diff --git a/Doc/library/math.rst b/Doc/library/math.rst index 71186788a652a..1ad60459e8d37 100644 --- a/Doc/library/math.rst +++ b/Doc/library/math.rst @@ -356,6 +356,13 @@ Power and logarithmic functions or ``pow(math.e, x)``. +.. function:: exp2(x) + + Return *2* raised to the power *x*. + + .. versionadded:: 3.11 + + .. function:: expm1(x) Return *e* raised to the power *x*, minus 1. Here *e* is the base of natural diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 3b65921a92619..8db26cd0126b3 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -203,6 +203,8 @@ fractions math ---- +* Add :func:`math.exp2`: return 2 raised to the power of x. + (Contributed by Gideon Mitchell in :issue:`45917`.) * Add :func:`math.cbrt`: return the cube root of x. (Contributed by Ajith Ramachandran in :issue:`44357`.) diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py index a9f1b1e11bcb3..a7df00f0fb101 100644 --- a/Lib/test/test_math.py +++ b/Lib/test/test_math.py @@ -501,6 +501,17 @@ def testExp(self): self.assertTrue(math.isnan(math.exp(NAN))) self.assertRaises(OverflowError, math.exp, 1000000) + def testExp2(self): + self.assertRaises(TypeError, math.exp2) + self.ftest('exp2(-1)', math.exp2(-1), 0.5) + self.ftest('exp2(0)', math.exp2(0), 1) + self.ftest('exp2(1)', math.exp2(1), 2) + self.ftest('exp2(2.3)', math.exp2(2.3), 4.924577653379665) + self.assertEqual(math.exp2(INF), INF) + self.assertEqual(math.exp2(NINF), 0.) + self.assertTrue(math.isnan(math.exp2(NAN))) + self.assertRaises(OverflowError, math.exp2, 1000000) + def testFabs(self): self.assertRaises(TypeError, math.fabs) self.ftest('fabs(-1)', math.fabs(-1), 1) diff --git a/Misc/ACKS b/Misc/ACKS index 204293fa50d9c..94a82a0750622 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1191,6 +1191,7 @@ Julien Miotte Andrii V. Mishkovskyi Dom Mitchell Dustin J. Mitchell +Gideon Mitchell Tim Mitchell Zubin Mithra Florian Mladitsch diff --git a/Misc/NEWS.d/next/Library/2021-11-28-17-24-11.bpo-45917.J5TIrd.rst b/Misc/NEWS.d/next/Library/2021-11-28-17-24-11.bpo-45917.J5TIrd.rst new file mode 100644 index 0000000000000..effd8da29a0f2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-28-17-24-11.bpo-45917.J5TIrd.rst @@ -0,0 +1 @@ +Added :func:`math.exp2`:, which returns 2 raised to the power of x. diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 67669f19bc28c..64ce4e6a13fd5 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -1248,6 +1248,9 @@ FUNC1A(erfc, m_erfc, FUNC1(exp, exp, 1, "exp($module, x, /)\n--\n\n" "Return e raised to the power of x.") +FUNC1(exp2, exp2, 1, + "exp2($module, x, /)\n--\n\n" + "Return 2 raised to the power of x.") FUNC1(expm1, expm1, 1, "expm1($module, x, /)\n--\n\n" "Return exp(x)-1.\n\n" @@ -3564,6 +3567,7 @@ static PyMethodDef math_methods[] = { {"erf", math_erf, METH_O, math_erf_doc}, {"erfc", math_erfc, METH_O, math_erfc_doc}, {"exp", math_exp, METH_O, math_exp_doc}, + {"exp2", math_exp2, METH_O, math_exp2_doc}, {"expm1", math_expm1, METH_O, math_expm1_doc}, {"fabs", math_fabs, METH_O, math_fabs_doc}, MATH_FACTORIAL_METHODDEF From webhook-mailer at python.org Mon Nov 29 15:27:43 2021 From: webhook-mailer at python.org (gvanrossum) Date: Mon, 29 Nov 2021 20:27:43 -0000 Subject: [Python-checkins] bpo-45653: fix test_embed on windows (GH-29814) Message-ID: https://github.com/python/cpython/commit/02b5ac6091ada0c2df99c4e1eae37ddccbcd91f0 commit: 02b5ac6091ada0c2df99c4e1eae37ddccbcd91f0 branch: main author: Kumar Aditya committer: gvanrossum date: 2021-11-29T12:27:34-08:00 summary: bpo-45653: fix test_embed on windows (GH-29814) files: M Lib/test/test_embed.py diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index e1af15dd70ff9..94cdd98b2dbba 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -65,7 +65,7 @@ def setUp(self): ext = ("_d" if debug_build(sys.executable) else "") + ".exe" exename += ext exepath = builddir - expecteddir = support.REPO_ROOT + expecteddir = os.path.join(support.REPO_ROOT, builddir) else: exepath = os.path.join(builddir, 'Programs') expecteddir = os.path.join(support.REPO_ROOT, 'Programs') From webhook-mailer at python.org Mon Nov 29 17:40:42 2021 From: webhook-mailer at python.org (zooba) Date: Mon, 29 Nov 2021 22:40:42 -0000 Subject: [Python-checkins] bpo-45931: Prevent Directory.Build.props/targets from leaking from directories above the repo when building on Windows (GH-29854) Message-ID: https://github.com/python/cpython/commit/734ed3538314c9651ae64d5e2e0e98aae3aec17b commit: 734ed3538314c9651ae64d5e2e0e98aae3aec17b branch: main author: David Federman committer: zooba date: 2021-11-29T22:40:34Z summary: bpo-45931: Prevent Directory.Build.props/targets from leaking from directories above the repo when building on Windows (GH-29854) files: A PCbuild/Directory.Build.props A PCbuild/Directory.Build.targets M PCbuild/python.props diff --git a/PCbuild/Directory.Build.props b/PCbuild/Directory.Build.props new file mode 100644 index 0000000000000..3d2fe55078450 --- /dev/null +++ b/PCbuild/Directory.Build.props @@ -0,0 +1,4 @@ + + + + diff --git a/PCbuild/Directory.Build.targets b/PCbuild/Directory.Build.targets new file mode 100644 index 0000000000000..3d2fe55078450 --- /dev/null +++ b/PCbuild/Directory.Build.targets @@ -0,0 +1,4 @@ + + + + diff --git a/PCbuild/python.props b/PCbuild/python.props index b739e417fbaa5..c608fb9ee7187 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -11,8 +11,8 @@ We set BasePlatformToolset for ICC's benefit, it's otherwise ignored. --> - v142 - v142 + v142 + v142 v141 v140 v120 From webhook-mailer at python.org Mon Nov 29 18:08:42 2021 From: webhook-mailer at python.org (miss-islington) Date: Mon, 29 Nov 2021 23:08:42 -0000 Subject: [Python-checkins] bpo-45931: Prevent Directory.Build.props/targets from leaking from directories above the repo when building on Windows (GH-29854) Message-ID: https://github.com/python/cpython/commit/5a6d9ed700ecc6984387e0533b11d81692c40469 commit: 5a6d9ed700ecc6984387e0533b11d81692c40469 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-29T15:08:33-08:00 summary: bpo-45931: Prevent Directory.Build.props/targets from leaking from directories above the repo when building on Windows (GH-29854) (cherry picked from commit 734ed3538314c9651ae64d5e2e0e98aae3aec17b) Co-authored-by: David Federman files: A PCbuild/Directory.Build.props A PCbuild/Directory.Build.targets M PCbuild/python.props diff --git a/PCbuild/Directory.Build.props b/PCbuild/Directory.Build.props new file mode 100644 index 0000000000000..3d2fe55078450 --- /dev/null +++ b/PCbuild/Directory.Build.props @@ -0,0 +1,4 @@ + + + + diff --git a/PCbuild/Directory.Build.targets b/PCbuild/Directory.Build.targets new file mode 100644 index 0000000000000..3d2fe55078450 --- /dev/null +++ b/PCbuild/Directory.Build.targets @@ -0,0 +1,4 @@ + + + + diff --git a/PCbuild/python.props b/PCbuild/python.props index 42c67de4afa34..2ef290cca286a 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -11,8 +11,8 @@ We set BasePlatformToolset for ICC's benefit, it's otherwise ignored. --> - v142 - v142 + v142 + v142 v141 v140 v120 From webhook-mailer at python.org Mon Nov 29 18:08:57 2021 From: webhook-mailer at python.org (miss-islington) Date: Mon, 29 Nov 2021 23:08:57 -0000 Subject: [Python-checkins] bpo-45931: Prevent Directory.Build.props/targets from leaking from directories above the repo when building on Windows (GH-29854) Message-ID: https://github.com/python/cpython/commit/b91805ec0283f0642aa3311ec617c8596f65b7b4 commit: b91805ec0283f0642aa3311ec617c8596f65b7b4 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: miss-islington <31488909+miss-islington at users.noreply.github.com> date: 2021-11-29T15:08:53-08:00 summary: bpo-45931: Prevent Directory.Build.props/targets from leaking from directories above the repo when building on Windows (GH-29854) (cherry picked from commit 734ed3538314c9651ae64d5e2e0e98aae3aec17b) Co-authored-by: David Federman files: A PCbuild/Directory.Build.props A PCbuild/Directory.Build.targets M PCbuild/python.props diff --git a/PCbuild/Directory.Build.props b/PCbuild/Directory.Build.props new file mode 100644 index 0000000000000..3d2fe55078450 --- /dev/null +++ b/PCbuild/Directory.Build.props @@ -0,0 +1,4 @@ + + + + diff --git a/PCbuild/Directory.Build.targets b/PCbuild/Directory.Build.targets new file mode 100644 index 0000000000000..3d2fe55078450 --- /dev/null +++ b/PCbuild/Directory.Build.targets @@ -0,0 +1,4 @@ + + + + diff --git a/PCbuild/python.props b/PCbuild/python.props index 42c67de4afa34..2ef290cca286a 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -11,8 +11,8 @@ We set BasePlatformToolset for ICC's benefit, it's otherwise ignored. --> - v142 - v142 + v142 + v142 v141 v140 v120 From webhook-mailer at python.org Mon Nov 29 21:27:46 2021 From: webhook-mailer at python.org (corona10) Date: Tue, 30 Nov 2021 02:27:46 -0000 Subject: [Python-checkins] no-issue: remove unused import from test_graphlib.py (GH-29853) Message-ID: https://github.com/python/cpython/commit/bd9342dddead5993500e7978edad7b5e6a0c1f26 commit: bd9342dddead5993500e7978edad7b5e6a0c1f26 branch: main author: Adrian Garcia Badaracco <1755071+adriangb at users.noreply.github.com> committer: corona10 date: 2021-11-30T11:27:37+09:00 summary: no-issue: remove unused import from test_graphlib.py (GH-29853) files: M Lib/test/test_graphlib.py diff --git a/Lib/test/test_graphlib.py b/Lib/test/test_graphlib.py index 86246a62ed642..5f38af4024c5b 100644 --- a/Lib/test/test_graphlib.py +++ b/Lib/test/test_graphlib.py @@ -1,4 +1,3 @@ -from itertools import chain import graphlib import os import unittest @@ -34,7 +33,7 @@ def _assert_cycle(self, graph, cycle): try: ts.prepare() except graphlib.CycleError as e: - msg, seq = e.args + _, seq = e.args self.assertIn(" ".join(map(str, cycle)), " ".join(map(str, seq * 2))) else: raise From webhook-mailer at python.org Mon Nov 29 23:16:48 2021 From: webhook-mailer at python.org (methane) Date: Tue, 30 Nov 2021 04:16:48 -0000 Subject: [Python-checkins] Fix EncodingWarning in Tools/freeze/test/freeze.py (GH-29742) Message-ID: https://github.com/python/cpython/commit/9a5dec4e978f68ab956e979858ce3aa178436fa4 commit: 9a5dec4e978f68ab956e979858ce3aa178436fa4 branch: main author: Inada Naoki committer: methane date: 2021-11-30T13:16:40+09:00 summary: Fix EncodingWarning in Tools/freeze/test/freeze.py (GH-29742) files: M Tools/freeze/test/freeze.py diff --git a/Tools/freeze/test/freeze.py b/Tools/freeze/test/freeze.py index db2aa3101d879..abedac03f91b0 100644 --- a/Tools/freeze/test/freeze.py +++ b/Tools/freeze/test/freeze.py @@ -89,7 +89,7 @@ def get_makefile_var(builddir, name): regex = re.compile(rf'^{name} *=\s*(.*?)\s*$') filename = os.path.join(builddir, 'Makefile') try: - infile = open(filename) + infile = open(filename, encoding='utf-8') except FileNotFoundError: return None with infile: @@ -125,7 +125,7 @@ def prepare(script=None, outdir=None): if script: scriptfile = os.path.join(outdir, 'app.py') print(f'creating the script to be frozen at {scriptfile}') - with open(scriptfile, 'w') as outfile: + with open(scriptfile, 'w', encoding='utf-8') as outfile: outfile.write(script) # Make a copy of the repo to avoid affecting the current build From webhook-mailer at python.org Tue Nov 30 06:01:55 2021 From: webhook-mailer at python.org (iritkatriel) Date: Tue, 30 Nov 2021 11:01:55 -0000 Subject: [Python-checkins] bpo-33381: [doc] strftime's %f option may pad zeros on the left or the right (GH-29801) Message-ID: https://github.com/python/cpython/commit/f97ec09baf8431494fd2ef5133090c7b0afd0551 commit: f97ec09baf8431494fd2ef5133090c7b0afd0551 branch: main author: Vishal Pandey committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-11-30T11:01:44Z summary: bpo-33381: [doc] strftime's %f option may pad zeros on the left or the right (GH-29801) files: M Doc/library/datetime.rst diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index 0f8b70cdedb45..217cdf222b89b 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -2359,8 +2359,8 @@ requires, and these work on all platforms with a standard C implementation. | | decimal number. | | \(9) | +-----------+--------------------------------+------------------------+-------+ | ``%f`` | Microsecond as a decimal | 000000, 000001, ..., | \(5) | -| | number, zero-padded on the | 999999 | | -| | left. | | | +| | number, zero-padded to 6 | 999999 | | +| | digits. | | | +-----------+--------------------------------+------------------------+-------+ | ``%z`` | UTC offset in the form | (empty), +0000, | \(6) | | | ``?HHMM[SS[.ffffff]]`` (empty | -0400, +1030, | | From webhook-mailer at python.org Tue Nov 30 06:14:50 2021 From: webhook-mailer at python.org (vstinner) Date: Tue, 30 Nov 2021 11:14:50 -0000 Subject: [Python-checkins] bpo-45476: Add _Py_RVALUE() macro (GH-29860) Message-ID: https://github.com/python/cpython/commit/c19c3a09618ac400538ee412f84be4c1196c7bab commit: c19c3a09618ac400538ee412f84be4c1196c7bab branch: main author: Victor Stinner committer: vstinner date: 2021-11-30T12:14:45+01:00 summary: bpo-45476: Add _Py_RVALUE() macro (GH-29860) Add a new _Py_RVALUE() macro to prevent using an expression as an l-value. Replace a "(void)" cast with the _Py_RVALUE() macro in the following macros: * PyCell_SET() * PyList_SET_ITEM() * PyTuple_SET_ITEM() * _PyGCHead_SET_FINALIZED() * _PyGCHead_SET_NEXT() * asdl_seq_SET() * asdl_seq_SET_UNTYPED() Add also parentheses around macro arguments in PyCell_SET() and PyTuple_SET_ITEM() macros. files: M Include/cpython/cellobject.h M Include/cpython/listobject.h M Include/cpython/tupleobject.h M Include/internal/pycore_asdl.h M Include/internal/pycore_gc.h M Include/pymacro.h diff --git a/Include/cpython/cellobject.h b/Include/cpython/cellobject.h index 8dc7b8f4cf6f8..e07f9d1de7942 100644 --- a/Include/cpython/cellobject.h +++ b/Include/cpython/cellobject.h @@ -22,7 +22,7 @@ PyAPI_FUNC(PyObject *) PyCell_Get(PyObject *); PyAPI_FUNC(int) PyCell_Set(PyObject *, PyObject *); #define PyCell_GET(op) (((PyCellObject *)(op))->ob_ref) -#define PyCell_SET(op, v) ((void)(((PyCellObject *)(op))->ob_ref = v)) +#define PyCell_SET(op, v) _Py_RVALUE(((PyCellObject *)(op))->ob_ref = (v)) #ifdef __cplusplus } diff --git a/Include/cpython/listobject.h b/Include/cpython/listobject.h index e3239152c497c..51687d866ce97 100644 --- a/Include/cpython/listobject.h +++ b/Include/cpython/listobject.h @@ -30,5 +30,5 @@ PyAPI_FUNC(void) _PyList_DebugMallocStats(FILE *out); #define _PyList_CAST(op) (assert(PyList_Check(op)), (PyListObject *)(op)) #define PyList_GET_ITEM(op, i) (_PyList_CAST(op)->ob_item[i]) -#define PyList_SET_ITEM(op, i, v) ((void)(_PyList_CAST(op)->ob_item[i] = (v))) +#define PyList_SET_ITEM(op, i, v) _Py_RVALUE(_PyList_CAST(op)->ob_item[i] = (v)) #define PyList_GET_SIZE(op) Py_SIZE(_PyList_CAST(op)) diff --git a/Include/cpython/tupleobject.h b/Include/cpython/tupleobject.h index 7cada8848c49f..fc37c4e6de1ca 100644 --- a/Include/cpython/tupleobject.h +++ b/Include/cpython/tupleobject.h @@ -23,6 +23,6 @@ PyAPI_FUNC(void) _PyTuple_MaybeUntrack(PyObject *); #define PyTuple_GET_ITEM(op, i) (_PyTuple_CAST(op)->ob_item[i]) /* Macro, *only* to be used to fill in brand new tuples */ -#define PyTuple_SET_ITEM(op, i, v) ((void)(_PyTuple_CAST(op)->ob_item[i] = v)) +#define PyTuple_SET_ITEM(op, i, v) _Py_RVALUE(_PyTuple_CAST(op)->ob_item[i] = (v)) PyAPI_FUNC(void) _PyTuple_DebugMallocStats(FILE *out); diff --git a/Include/internal/pycore_asdl.h b/Include/internal/pycore_asdl.h index 2929e030872d9..d00a7f04e6d00 100644 --- a/Include/internal/pycore_asdl.h +++ b/Include/internal/pycore_asdl.h @@ -91,7 +91,7 @@ asdl_ ## NAME ## _seq *_Py_asdl_ ## NAME ## _seq_new(Py_ssize_t size, PyArena *a (S)->typed_elements[_asdl_i] = (V); \ } while (0) #else -# define asdl_seq_SET(S, I, V) ((void)((S)->typed_elements[I] = (V))) +# define asdl_seq_SET(S, I, V) _Py_RVALUE((S)->typed_elements[I] = (V)) #endif #ifdef Py_DEBUG @@ -103,7 +103,7 @@ asdl_ ## NAME ## _seq *_Py_asdl_ ## NAME ## _seq_new(Py_ssize_t size, PyArena *a (S)->elements[_asdl_i] = (V); \ } while (0) #else -# define asdl_seq_SET_UNTYPED(S, I, V) ((void)((S)->elements[I] = (V))) +# define asdl_seq_SET_UNTYPED(S, I, V) _Py_RVALUE((S)->elements[I] = (V)) #endif #ifdef __cplusplus diff --git a/Include/internal/pycore_gc.h b/Include/internal/pycore_gc.h index 129d53921dc49..a23dca805491d 100644 --- a/Include/internal/pycore_gc.h +++ b/Include/internal/pycore_gc.h @@ -43,7 +43,7 @@ typedef struct { // Lowest bit of _gc_next is used for flags only in GC. // But it is always 0 for normal code. #define _PyGCHead_NEXT(g) ((PyGC_Head*)(g)->_gc_next) -#define _PyGCHead_SET_NEXT(g, p) ((void)((g)->_gc_next = (uintptr_t)(p))) +#define _PyGCHead_SET_NEXT(g, p) _Py_RVALUE((g)->_gc_next = (uintptr_t)(p)) // Lowest two bits of _gc_prev is used for _PyGC_PREV_MASK_* flags. #define _PyGCHead_PREV(g) ((PyGC_Head*)((g)->_gc_prev & _PyGC_PREV_MASK)) @@ -56,7 +56,7 @@ typedef struct { #define _PyGCHead_FINALIZED(g) \ (((g)->_gc_prev & _PyGC_PREV_MASK_FINALIZED) != 0) #define _PyGCHead_SET_FINALIZED(g) \ - ((void)((g)->_gc_prev |= _PyGC_PREV_MASK_FINALIZED)) + _Py_RVALUE((g)->_gc_prev |= _PyGC_PREV_MASK_FINALIZED) #define _PyGC_FINALIZED(o) \ _PyGCHead_FINALIZED(_Py_AS_GC(o)) diff --git a/Include/pymacro.h b/Include/pymacro.h index 202b936d964f0..2728496976de7 100644 --- a/Include/pymacro.h +++ b/Include/pymacro.h @@ -129,4 +129,8 @@ Py_FatalError("Unreachable C code path reached") #endif +// Prevent using an expression as a l-value. +// For example, "int x; _Py_RVALUE(x) = 1;" fails with a compiler error. +#define _Py_RVALUE(EXPR) ((void)0, (EXPR)) + #endif /* Py_PYMACRO_H */ From webhook-mailer at python.org Tue Nov 30 06:50:04 2021 From: webhook-mailer at python.org (iritkatriel) Date: Tue, 30 Nov 2021 11:50:04 -0000 Subject: [Python-checkins] bpo-33381: [doc] strftime's %f option may pad zeros on the left or the right (GH-29801) (GH-29862) Message-ID: https://github.com/python/cpython/commit/39751420b363530ef46506f10691d7b91ffe9b44 commit: 39751420b363530ef46506f10691d7b91ffe9b44 branch: 3.10 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-11-30T11:49:59Z summary: bpo-33381: [doc] strftime's %f option may pad zeros on the left or the right (GH-29801) (GH-29862) (cherry picked from commit f97ec09baf8431494fd2ef5133090c7b0afd0551) Co-authored-by: Vishal Pandey files: M Doc/library/datetime.rst diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index 0f8b70cdedb45..217cdf222b89b 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -2359,8 +2359,8 @@ requires, and these work on all platforms with a standard C implementation. | | decimal number. | | \(9) | +-----------+--------------------------------+------------------------+-------+ | ``%f`` | Microsecond as a decimal | 000000, 000001, ..., | \(5) | -| | number, zero-padded on the | 999999 | | -| | left. | | | +| | number, zero-padded to 6 | 999999 | | +| | digits. | | | +-----------+--------------------------------+------------------------+-------+ | ``%z`` | UTC offset in the form | (empty), +0000, | \(6) | | | ``?HHMM[SS[.ffffff]]`` (empty | -0400, +1030, | | From webhook-mailer at python.org Tue Nov 30 06:50:33 2021 From: webhook-mailer at python.org (iritkatriel) Date: Tue, 30 Nov 2021 11:50:33 -0000 Subject: [Python-checkins] bpo-33381: [doc] strftime's %f option may pad zeros on the left or the right (GH-29801) (GH-29863) Message-ID: https://github.com/python/cpython/commit/031e2bb3326be542b224bbe35e7829846ea422cd commit: 031e2bb3326be542b224bbe35e7829846ea422cd branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-11-30T11:50:28Z summary: bpo-33381: [doc] strftime's %f option may pad zeros on the left or the right (GH-29801) (GH-29863) (cherry picked from commit f97ec09baf8431494fd2ef5133090c7b0afd0551) Co-authored-by: Vishal Pandey files: M Doc/library/datetime.rst diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index 0f8b70cdedb45..217cdf222b89b 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -2359,8 +2359,8 @@ requires, and these work on all platforms with a standard C implementation. | | decimal number. | | \(9) | +-----------+--------------------------------+------------------------+-------+ | ``%f`` | Microsecond as a decimal | 000000, 000001, ..., | \(5) | -| | number, zero-padded on the | 999999 | | -| | left. | | | +| | number, zero-padded to 6 | 999999 | | +| | digits. | | | +-----------+--------------------------------+------------------------+-------+ | ``%z`` | UTC offset in the form | (empty), +0000, | \(6) | | | ``?HHMM[SS[.ffffff]]`` (empty | -0400, +1030, | | From webhook-mailer at python.org Tue Nov 30 08:39:32 2021 From: webhook-mailer at python.org (asvetlov) Date: Tue, 30 Nov 2021 13:39:32 -0000 Subject: [Python-checkins] bpo-37658: Actually return result in race condition (GH-29202) (GH-29832) Message-ID: https://github.com/python/cpython/commit/99a9b343316172f049a52b39a406f0c0c42c106f commit: 99a9b343316172f049a52b39a406f0c0c42c106f branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: asvetlov date: 2021-11-30T15:39:13+02:00 summary: bpo-37658: Actually return result in race condition (GH-29202) (GH-29832) (cherry picked from commit 934a82623793e9d52b85f74d5395d65927a52205) Co-authored-by: Sam Bull Co-authored-by: Sam Bull files: A Misc/NEWS.d/next/Library/2021-11-28-15-30-34.bpo-37658.8Hno7d.rst M Lib/asyncio/tasks.py M Lib/test/test_asyncio/test_tasks.py diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 22ed3289edf3c..27a3c8c5a88df 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -449,11 +449,9 @@ async def wait_for(fut, timeout, *, loop=None): await _cancel_and_wait(fut, loop=loop) try: - fut.result() + return fut.result() except exceptions.CancelledError as exc: raise exceptions.TimeoutError() from exc - else: - raise exceptions.TimeoutError() waiter = loop.create_future() timeout_handle = loop.call_later(timeout, _release_waiter, waiter) @@ -489,11 +487,9 @@ async def wait_for(fut, timeout, *, loop=None): # exception, we should re-raise it # See https://bugs.python.org/issue40607 try: - fut.result() + return fut.result() except exceptions.CancelledError as exc: raise exceptions.TimeoutError() from exc - else: - raise exceptions.TimeoutError() finally: timeout_handle.cancel() diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 402edaec0d8f9..a6afce0766493 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -1121,20 +1121,16 @@ def gen(): self.assertEqual(res, "ok") def test_wait_for_cancellation_race_condition(self): - def gen(): - yield 0.1 - yield 0.1 - yield 0.1 - yield 0.1 + async def inner(): + with contextlib.suppress(asyncio.CancelledError): + await asyncio.sleep(1) + return 1 - loop = self.new_test_loop(gen) + async def main(): + result = await asyncio.wait_for(inner(), timeout=.01) + assert result == 1 - fut = self.new_future(loop) - loop.call_later(0.1, fut.set_result, "ok") - task = loop.create_task(asyncio.wait_for(fut, timeout=1)) - loop.call_later(0.1, task.cancel) - res = loop.run_until_complete(task) - self.assertEqual(res, "ok") + asyncio.run(main()) def test_wait_for_waits_for_task_cancellation(self): loop = asyncio.new_event_loop() @@ -1213,24 +1209,6 @@ async def inner(): with self.assertRaises(FooException): loop.run_until_complete(foo()) - def test_wait_for_raises_timeout_error_if_returned_during_cancellation(self): - loop = asyncio.new_event_loop() - self.addCleanup(loop.close) - - async def foo(): - async def inner(): - try: - await asyncio.sleep(0.2) - except asyncio.CancelledError: - return 42 - - inner_task = self.new_task(loop, inner()) - - await asyncio.wait_for(inner_task, timeout=_EPSILON) - - with self.assertRaises(asyncio.TimeoutError): - loop.run_until_complete(foo()) - def test_wait_for_self_cancellation(self): loop = asyncio.new_event_loop() self.addCleanup(loop.close) diff --git a/Misc/NEWS.d/next/Library/2021-11-28-15-30-34.bpo-37658.8Hno7d.rst b/Misc/NEWS.d/next/Library/2021-11-28-15-30-34.bpo-37658.8Hno7d.rst new file mode 100644 index 0000000000000..97d1e961ac2be --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-28-15-30-34.bpo-37658.8Hno7d.rst @@ -0,0 +1,3 @@ +Fix issue when on certain conditions ``asyncio.wait_for()`` may allow a +coroutine to complete successfully, but fail to return the result, +potentially causing memory leaks or other issues. From webhook-mailer at python.org Tue Nov 30 09:14:03 2021 From: webhook-mailer at python.org (vstinner) Date: Tue, 30 Nov 2021 14:14:03 -0000 Subject: [Python-checkins] bpo-45476: Disallow using asdl_seq_GET() as l-value (GH-29866) Message-ID: https://github.com/python/cpython/commit/4b97d974ecca9cce532be55410fe851eb9fdcf21 commit: 4b97d974ecca9cce532be55410fe851eb9fdcf21 branch: main author: Victor Stinner committer: vstinner date: 2021-11-30T15:13:55+01:00 summary: bpo-45476: Disallow using asdl_seq_GET() as l-value (GH-29866) The following internal macros can not longer be used as l-value: * asdl_seq_GET() * asdl_seq_GET_UNTYPED() * asdl_seq_LEN() They are modified to use the _Py_RVALUE() macro. files: M Include/internal/pycore_asdl.h diff --git a/Include/internal/pycore_asdl.h b/Include/internal/pycore_asdl.h index d00a7f04e6d00..5b01c7a66599e 100644 --- a/Include/internal/pycore_asdl.h +++ b/Include/internal/pycore_asdl.h @@ -78,9 +78,9 @@ asdl_ ## NAME ## _seq *_Py_asdl_ ## NAME ## _seq_new(Py_ssize_t size, PyArena *a return seq; \ } -#define asdl_seq_GET_UNTYPED(S, I) (S)->elements[(I)] -#define asdl_seq_GET(S, I) (S)->typed_elements[(I)] -#define asdl_seq_LEN(S) ((S) == NULL ? 0 : (S)->size) +#define asdl_seq_GET_UNTYPED(S, I) _Py_RVALUE((S)->elements[(I)]) +#define asdl_seq_GET(S, I) _Py_RVALUE((S)->typed_elements[(I)]) +#define asdl_seq_LEN(S) _Py_RVALUE(((S) == NULL ? 0 : (S)->size)) #ifdef Py_DEBUG # define asdl_seq_SET(S, I, V) \ From webhook-mailer at python.org Tue Nov 30 13:23:23 2021 From: webhook-mailer at python.org (DinoV) Date: Tue, 30 Nov 2021 18:23:23 -0000 Subject: [Python-checkins] bpo-30533:Add function inspect.getmembers_static that does not call properties or dynamic properties. (#20911) Message-ID: https://github.com/python/cpython/commit/af8c8caaf5e07c02202d736a31f6a2f7e27819b8 commit: af8c8caaf5e07c02202d736a31f6a2f7e27819b8 branch: main author: Weipeng Hong committer: DinoV date: 2021-11-30T10:23:13-08:00 summary: bpo-30533:Add function inspect.getmembers_static that does not call properties or dynamic properties. (#20911) * Add function inspect.getmembers_static that does not call properties or dynamic properties. * update _getmembers args * Update Misc/NEWS.d/next/Library/2020-06-16-18-00-56.bpo-30533.StL57t.rst Co-authored-by: Itamar Ostricher * Update Lib/inspect.py Co-authored-by: Itamar Ostricher * Removes the copy pasted doc string Co-authored-by: Itamar Ostricher Co-authored-by: Dino Viehland files: A Misc/NEWS.d/next/Library/2020-06-16-18-00-56.bpo-30533.StL57t.rst M Lib/inspect.py M Lib/test/test_inspect.py diff --git a/Lib/inspect.py b/Lib/inspect.py index dd891112570c6..1eb2f2b575ef4 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -440,9 +440,7 @@ def isabstract(object): return True return False -def getmembers(object, predicate=None): - """Return all members of an object as (name, value) pairs sorted by name. - Optionally, only return members that satisfy a given predicate.""" +def _getmembers(object, predicate, getter): if isclass(object): mro = (object,) + getmro(object) else: @@ -465,7 +463,7 @@ def getmembers(object, predicate=None): # like calling their __get__ (see bug #1785), so fall back to # looking in the __dict__. try: - value = getattr(object, key) + value = getter(object, key) # handle the duplicate key if key in processed: raise AttributeError @@ -484,6 +482,25 @@ def getmembers(object, predicate=None): results.sort(key=lambda pair: pair[0]) return results +def getmembers(object, predicate=None): + """Return all members of an object as (name, value) pairs sorted by name. + Optionally, only return members that satisfy a given predicate.""" + return _getmembers(object, predicate, getattr) + +def getmembers_static(object, predicate=None): + """Return all members of an object as (name, value) pairs sorted by name + without triggering dynamic lookup via the descriptor protocol, + __getattr__ or __getattribute__. Optionally, only return members that + satisfy a given predicate. + + Note: this function may not be able to retrieve all members + that getmembers can fetch (like dynamically created attributes) + and may find members that getmembers can't (like descriptors + that raise AttributeError). It can also return descriptor objects + instead of instance members in some cases. + """ + return _getmembers(object, predicate, getattr_static) + Attribute = namedtuple('Attribute', 'name kind defining_class object') def classify_class_attrs(cls): diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index d43486a219158..33665cf3c79eb 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -1215,6 +1215,23 @@ def eggs(self): self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A)) self.assertIn(('eggs', 'spam'), inspect.getmembers(A())) + def test_getmembers_static(self): + class A: + @property + def name(self): + raise NotImplementedError + @types.DynamicClassAttribute + def eggs(self): + raise NotImplementedError + + a = A() + instance_members = inspect.getmembers_static(a) + class_members = inspect.getmembers_static(A) + self.assertIn(('name', inspect.getattr_static(a, 'name')), instance_members) + self.assertIn(('eggs', inspect.getattr_static(a, 'eggs')), instance_members) + self.assertIn(('name', inspect.getattr_static(A, 'name')), class_members) + self.assertIn(('eggs', inspect.getattr_static(A, 'eggs')), class_members) + def test_getmembers_with_buggy_dir(self): class M(type): def __dir__(cls): diff --git a/Misc/NEWS.d/next/Library/2020-06-16-18-00-56.bpo-30533.StL57t.rst b/Misc/NEWS.d/next/Library/2020-06-16-18-00-56.bpo-30533.StL57t.rst new file mode 100644 index 0000000000000..bc4523f626666 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-06-16-18-00-56.bpo-30533.StL57t.rst @@ -0,0 +1,2 @@ +Add :func:`inspect.getmembers_static` , it return all members without +triggering dynamic lookup via the descriptor protocol. Patch by Weipeng Hong. From webhook-mailer at python.org Tue Nov 30 17:37:29 2021 From: webhook-mailer at python.org (iritkatriel) Date: Tue, 30 Nov 2021 22:37:29 -0000 Subject: [Python-checkins] bpo-45711: Change exc_info related APIs to derive type and traceback from the exception instance (GH-29780) Message-ID: https://github.com/python/cpython/commit/8a45ca542a65ea27e7acaa44a4c833a27830e796 commit: 8a45ca542a65ea27e7acaa44a4c833a27830e796 branch: main author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com> committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com> date: 2021-11-30T22:37:04Z summary: bpo-45711: Change exc_info related APIs to derive type and traceback from the exception instance (GH-29780) files: A Misc/NEWS.d/next/Core and Builtins/2021-11-25-17-51-29.bpo-45711.D2igmz.rst M Doc/c-api/exceptions.rst M Doc/library/sys.rst M Doc/reference/simple_stmts.rst M Doc/whatsnew/3.11.rst M Python/ceval.c M Python/errors.c diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst index 5d90248f85a5d..27feab92dede6 100644 --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -482,7 +482,6 @@ Querying the error indicator to an exception that was *already caught*, not to an exception that was freshly raised. This function steals the references of the arguments. To clear the exception state, pass ``NULL`` for all three arguments. - For general rules about the three arguments, see :c:func:`PyErr_Restore`. .. note:: @@ -493,6 +492,12 @@ Querying the error indicator .. versionadded:: 3.3 + .. versionchanged:: 3.11 + The ``type`` and ``traceback`` arguments are no longer used and + can be NULL. The interpreter now derives them from the exception + instance (the ``value`` argument). The function still steals + references of all three arguments. + Signal Handling =============== diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index 175fc09165206..7d1b21f05edb1 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -396,9 +396,14 @@ always available. ``(type, value, traceback)``. Their meaning is: *type* gets the type of the exception being handled (a subclass of :exc:`BaseException`); *value* gets the exception instance (an instance of the exception type); *traceback* gets - a :ref:`traceback object ` which encapsulates the call - stack at the point where the exception originally occurred. - + a :ref:`traceback object ` which typically encapsulates + the call stack at the point where the exception last occurred. + + .. versionchanged:: 3.11 + The ``type`` and ``traceback`` fields are now derived from the ``value`` + (the exception instance), so when an exception is modified while it is + being handled, the changes are reflected in the results of subsequent + calls to :func:`exc_info`. .. data:: exec_prefix diff --git a/Doc/reference/simple_stmts.rst b/Doc/reference/simple_stmts.rst index bb1209dfc33be..3d02074960ff3 100644 --- a/Doc/reference/simple_stmts.rst +++ b/Doc/reference/simple_stmts.rst @@ -655,6 +655,12 @@ and information about handling exceptions is in section :ref:`try`. The ``__suppress_context__`` attribute to suppress automatic display of the exception context. +.. versionchanged:: 3.11 + If the traceback of the active exception is modified in an :keyword:`except` + clause, a subsequent ``raise`` statement re-raises the exception with the + modified traceback. Previously, the exception was re-raised with the + traceback it had when it was caught. + .. _break: The :keyword:`!break` statement diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 8db26cd0126b3..6853c04143512 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -181,6 +181,12 @@ Other CPython Implementation Changes hash-based pyc files now use ``siphash13``, too. (Contributed by Inada Naoki in :issue:`29410`.) +* When an active exception is re-raised by a :keyword:`raise` statement with no parameters, + the traceback attached to this exception is now always ``sys.exc_info()[1].__traceback__``. + This means that changes made to the traceback in the current :keyword:`except` clause are + reflected in the re-raised exception. + (Contributed by Irit Katriel in :issue:`45711`.) + New Modules =========== @@ -266,6 +272,16 @@ sqlite3 (Contributed by Erlend E. Aasland in :issue:`45828`.) +sys +--- + +* :func:`sys.exc_info` now derives the ``type`` and ``traceback`` fields + from the ``value`` (the exception instance), so when an exception is + modified while it is being handled, the changes are reflected in + the results of subsequent calls to :func:`exc_info`. + (Contributed by Irit Katriel in :issue:`45711`.) + + threading --------- @@ -579,6 +595,17 @@ New Features suspend and resume tracing and profiling. (Contributed by Victor Stinner in :issue:`43760`.) +* :c:func:`PyErr_SetExcInfo()` no longer uses the ``type`` and ``traceback`` + arguments, the interpreter now derives those values from the exception + instance (the ``value`` argument). The function still steals references + of all three arguments. + (Contributed by Irit Katriel in :issue:`45711`.) + +* :c:func:`PyErr_GetExcInfo()` now derives the ``type`` and ``traceback`` + fields of the result from the exception instance (the ``value`` field). + (Contributed by Irit Katriel in :issue:`45711`.) + + Porting to Python 3.11 ---------------------- diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-25-17-51-29.bpo-45711.D2igmz.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-25-17-51-29.bpo-45711.D2igmz.rst new file mode 100644 index 0000000000000..c499f185d2038 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-25-17-51-29.bpo-45711.D2igmz.rst @@ -0,0 +1,6 @@ +The three values of ``exc_info`` are now always consistent with each other. +In particular, the ``type`` and ``traceback`` fields are now derived from +the exception instance. This impacts the return values of :func:`sys.exc_info` +and :c:func:`PyErr_GetExcInfo()` if the exception instance is modified while +the exception is handled, as well as :c:func:`PyErr_SetExcInfo()`, which now +ignores the ``type`` and ``traceback`` arguments provided to it. diff --git a/Python/ceval.c b/Python/ceval.c index 0427361a03a8b..c5477b30f7e56 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -5918,20 +5918,17 @@ do_raise(PyThreadState *tstate, PyObject *exc, PyObject *cause) if (exc == NULL) { /* Reraise */ _PyErr_StackItem *exc_info = _PyErr_GetTopmostException(tstate); - PyObject *tb; - type = exc_info->exc_type; value = exc_info->exc_value; - tb = exc_info->exc_traceback; - assert(((Py_IsNone(value) || value == NULL)) == - ((Py_IsNone(type) || type == NULL))); if (Py_IsNone(value) || value == NULL) { _PyErr_SetString(tstate, PyExc_RuntimeError, "No active exception to reraise"); return 0; } + assert(PyExceptionInstance_Check(value)); + type = PyExceptionInstance_Class(value); Py_XINCREF(type); Py_XINCREF(value); - Py_XINCREF(tb); + PyObject *tb = PyException_GetTraceback(value); /* new ref */ _PyErr_Restore(tstate, type, value, tb); return 1; } diff --git a/Python/errors.c b/Python/errors.c index 6e74d19b78ef3..0a8b5a257fb2c 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -470,6 +470,33 @@ PyErr_Clear(void) _PyErr_Clear(tstate); } +static PyObject* +get_exc_type(PyObject *exc_value) /* returns a borrowed ref */ +{ + if (exc_value == NULL || exc_value == Py_None) { + return Py_None; + } + else { + assert(PyExceptionInstance_Check(exc_value)); + PyObject *type = PyExceptionInstance_Class(exc_value); + assert(type != NULL); + return type; + } +} + +static PyObject* +get_exc_traceback(PyObject *exc_value) /* returns a borrowed ref */ +{ + if (exc_value == NULL || exc_value == Py_None) { + return Py_None; + } + else { + assert(PyExceptionInstance_Check(exc_value)); + PyObject *tb = PyException_GetTraceback(exc_value); + Py_XDECREF(tb); + return tb ? tb : Py_None; + } +} void _PyErr_GetExcInfo(PyThreadState *tstate, @@ -477,18 +504,9 @@ _PyErr_GetExcInfo(PyThreadState *tstate, { _PyErr_StackItem *exc_info = _PyErr_GetTopmostException(tstate); + *p_type = get_exc_type(exc_info->exc_value); *p_value = exc_info->exc_value; - *p_traceback = exc_info->exc_traceback; - - if (*p_value == NULL || *p_value == Py_None) { - assert(exc_info->exc_type == NULL || exc_info->exc_type == Py_None); - *p_type = Py_None; - } - else { - assert(PyExceptionInstance_Check(*p_value)); - assert(exc_info->exc_type == PyExceptionInstance_Class(*p_value)); - *p_type = PyExceptionInstance_Class(*p_value); - } + *p_traceback = get_exc_traceback(exc_info->exc_value); Py_XINCREF(*p_type); Py_XINCREF(*p_value); @@ -504,7 +522,7 @@ PyErr_GetExcInfo(PyObject **p_type, PyObject **p_value, PyObject **p_traceback) } void -PyErr_SetExcInfo(PyObject *p_type, PyObject *p_value, PyObject *p_traceback) +PyErr_SetExcInfo(PyObject *type, PyObject *value, PyObject *traceback) { PyObject *oldtype, *oldvalue, *oldtraceback; PyThreadState *tstate = _PyThreadState_GET(); @@ -513,9 +531,16 @@ PyErr_SetExcInfo(PyObject *p_type, PyObject *p_value, PyObject *p_traceback) oldvalue = tstate->exc_info->exc_value; oldtraceback = tstate->exc_info->exc_traceback; - tstate->exc_info->exc_type = p_type; - tstate->exc_info->exc_value = p_value; - tstate->exc_info->exc_traceback = p_traceback; + + tstate->exc_info->exc_type = get_exc_type(value); + Py_XINCREF(tstate->exc_info->exc_type); + tstate->exc_info->exc_value = value; + tstate->exc_info->exc_traceback = get_exc_traceback(value); + Py_XINCREF(tstate->exc_info->exc_traceback); + + /* These args are no longer used, but we still need to steal a ref */ + Py_XDECREF(type); + Py_XDECREF(traceback); Py_XDECREF(oldtype); Py_XDECREF(oldvalue); @@ -527,22 +552,19 @@ PyObject* _PyErr_StackItemToExcInfoTuple(_PyErr_StackItem *err_info) { PyObject *exc_value = err_info->exc_value; - if (exc_value == NULL) { - exc_value = Py_None; - } - assert(exc_value == Py_None || PyExceptionInstance_Check(exc_value)); + assert(exc_value == NULL || + exc_value == Py_None || + PyExceptionInstance_Check(exc_value)); - PyObject *exc_type = PyExceptionInstance_Check(exc_value) ? - PyExceptionInstance_Class(exc_value) : - Py_None; + PyObject *exc_type = get_exc_type(exc_value); + PyObject *exc_traceback = get_exc_traceback(exc_value); return Py_BuildValue( "(OOO)", - exc_type, - exc_value, - err_info->exc_traceback != NULL ? - err_info->exc_traceback : Py_None); + exc_type ? exc_type : Py_None, + exc_value ? exc_value : Py_None, + exc_traceback ? exc_traceback : Py_None); } From webhook-mailer at python.org Tue Nov 30 19:20:17 2021 From: webhook-mailer at python.org (rhettinger) Date: Wed, 01 Dec 2021 00:20:17 -0000 Subject: [Python-checkins] bpo-45876: Correctly rounded stdev() and pstdev() for the Decimal case (GH-29828) Message-ID: https://github.com/python/cpython/commit/a39f46afdead515e7ac3722464b5ee8d7b0b2c9b commit: a39f46afdead515e7ac3722464b5ee8d7b0b2c9b branch: main author: Raymond Hettinger committer: rhettinger date: 2021-11-30T18:20:08-06:00 summary: bpo-45876: Correctly rounded stdev() and pstdev() for the Decimal case (GH-29828) files: M Lib/statistics.py M Lib/test/test_statistics.py diff --git a/Lib/statistics.py b/Lib/statistics.py index cf8eaa0a61e62..9f1efa21b15e3 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -137,7 +137,7 @@ from itertools import groupby, repeat from bisect import bisect_left, bisect_right from math import hypot, sqrt, fabs, exp, erf, tau, log, fsum -from operator import itemgetter, mul +from operator import mul from collections import Counter, namedtuple _SQRT2 = sqrt(2.0) @@ -248,6 +248,28 @@ def _exact_ratio(x): x is expected to be an int, Fraction, Decimal or float. """ + + # XXX We should revisit whether using fractions to accumulate exact + # ratios is the right way to go. + + # The integer ratios for binary floats can have numerators or + # denominators with over 300 decimal digits. The problem is more + # acute with decimal floats where the the default decimal context + # supports a huge range of exponents from Emin=-999999 to + # Emax=999999. When expanded with as_integer_ratio(), numbers like + # Decimal('3.14E+5000') and Decimal('3.14E-5000') have large + # numerators or denominators that will slow computation. + + # When the integer ratios are accumulated as fractions, the size + # grows to cover the full range from the smallest magnitude to the + # largest. For example, Fraction(3.14E+300) + Fraction(3.14E-300), + # has a 616 digit numerator. Likewise, + # Fraction(Decimal('3.14E+5000')) + Fraction(Decimal('3.14E-5000')) + # has 10,003 digit numerator. + + # This doesn't seem to have been problem in practice, but it is a + # potential pitfall. + try: return x.as_integer_ratio() except AttributeError: @@ -305,28 +327,60 @@ def _fail_neg(values, errmsg='negative value'): raise StatisticsError(errmsg) yield x -def _isqrt_frac_rto(n: int, m: int) -> float: + +def _integer_sqrt_of_frac_rto(n: int, m: int) -> int: """Square root of n/m, rounded to the nearest integer using round-to-odd.""" # Reference: https://www.lri.fr/~melquion/doc/05-imacs17_1-expose.pdf a = math.isqrt(n // m) return a | (a*a*m != n) -# For 53 bit precision floats, the _sqrt_frac() shift is 109. -_sqrt_shift: int = 2 * sys.float_info.mant_dig + 3 -def _sqrt_frac(n: int, m: int) -> float: +# For 53 bit precision floats, the bit width used in +# _float_sqrt_of_frac() is 109. +_sqrt_bit_width: int = 2 * sys.float_info.mant_dig + 3 + + +def _float_sqrt_of_frac(n: int, m: int) -> float: """Square root of n/m as a float, correctly rounded.""" # See principle and proof sketch at: https://bugs.python.org/msg407078 - q = (n.bit_length() - m.bit_length() - _sqrt_shift) // 2 + q = (n.bit_length() - m.bit_length() - _sqrt_bit_width) // 2 if q >= 0: - numerator = _isqrt_frac_rto(n, m << 2 * q) << q + numerator = _integer_sqrt_of_frac_rto(n, m << 2 * q) << q denominator = 1 else: - numerator = _isqrt_frac_rto(n << -2 * q, m) + numerator = _integer_sqrt_of_frac_rto(n << -2 * q, m) denominator = 1 << -q return numerator / denominator # Convert to float +def _decimal_sqrt_of_frac(n: int, m: int) -> Decimal: + """Square root of n/m as a Decimal, correctly rounded.""" + # Premise: For decimal, computing (n/m).sqrt() can be off + # by 1 ulp from the correctly rounded result. + # Method: Check the result, moving up or down a step if needed. + if n <= 0: + if not n: + return Decimal('0.0') + n, m = -n, -m + + root = (Decimal(n) / Decimal(m)).sqrt() + nr, dr = root.as_integer_ratio() + + plus = root.next_plus() + np, dp = plus.as_integer_ratio() + # test: n / m > ((root + plus) / 2) ** 2 + if 4 * n * (dr*dp)**2 > m * (dr*np + dp*nr)**2: + return plus + + minus = root.next_minus() + nm, dm = minus.as_integer_ratio() + # test: n / m < ((root + minus) / 2) ** 2 + if 4 * n * (dr*dm)**2 < m * (dr*nm + dm*nr)**2: + return minus + + return root + + # === Measures of central tendency (averages) === def mean(data): @@ -869,7 +923,7 @@ def stdev(data, xbar=None): if hasattr(T, 'sqrt'): var = _convert(mss, T) return var.sqrt() - return _sqrt_frac(mss.numerator, mss.denominator) + return _float_sqrt_of_frac(mss.numerator, mss.denominator) def pstdev(data, mu=None): @@ -888,10 +942,9 @@ def pstdev(data, mu=None): raise StatisticsError('pstdev requires at least one data point') T, ss = _ss(data, mu) mss = ss / n - if hasattr(T, 'sqrt'): - var = _convert(mss, T) - return var.sqrt() - return _sqrt_frac(mss.numerator, mss.denominator) + if issubclass(T, Decimal): + return _decimal_sqrt_of_frac(mss.numerator, mss.denominator) + return _float_sqrt_of_frac(mss.numerator, mss.denominator) # === Statistics for relations between two inputs === diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py index 771a03e707ee0..bacb76a9b036b 100644 --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -2164,9 +2164,9 @@ def test_center_not_at_mean(self): class TestSqrtHelpers(unittest.TestCase): - def test_isqrt_frac_rto(self): + def test_integer_sqrt_of_frac_rto(self): for n, m in itertools.product(range(100), range(1, 1000)): - r = statistics._isqrt_frac_rto(n, m) + r = statistics._integer_sqrt_of_frac_rto(n, m) self.assertIsInstance(r, int) if r*r*m == n: # Root is exact @@ -2177,7 +2177,7 @@ def test_isqrt_frac_rto(self): self.assertTrue(m * (r - 1)**2 < n < m * (r + 1)**2) @requires_IEEE_754 - def test_sqrt_frac(self): + def test_float_sqrt_of_frac(self): def is_root_correctly_rounded(x: Fraction, root: float) -> bool: if not x: @@ -2204,22 +2204,59 @@ def is_root_correctly_rounded(x: Fraction, root: float) -> bool: denonimator: int = randrange(10 ** randrange(50)) + 1 with self.subTest(numerator=numerator, denonimator=denonimator): x: Fraction = Fraction(numerator, denonimator) - root: float = statistics._sqrt_frac(numerator, denonimator) + root: float = statistics._float_sqrt_of_frac(numerator, denonimator) self.assertTrue(is_root_correctly_rounded(x, root)) # Verify that corner cases and error handling match math.sqrt() - self.assertEqual(statistics._sqrt_frac(0, 1), 0.0) + self.assertEqual(statistics._float_sqrt_of_frac(0, 1), 0.0) with self.assertRaises(ValueError): - statistics._sqrt_frac(-1, 1) + statistics._float_sqrt_of_frac(-1, 1) with self.assertRaises(ValueError): - statistics._sqrt_frac(1, -1) + statistics._float_sqrt_of_frac(1, -1) # Error handling for zero denominator matches that for Fraction(1, 0) with self.assertRaises(ZeroDivisionError): - statistics._sqrt_frac(1, 0) + statistics._float_sqrt_of_frac(1, 0) # The result is well defined if both inputs are negative - self.assertAlmostEqual(statistics._sqrt_frac(-2, -1), math.sqrt(2.0)) + self.assertEqual(statistics._float_sqrt_of_frac(-2, -1), statistics._float_sqrt_of_frac(2, 1)) + + def test_decimal_sqrt_of_frac(self): + root: Decimal + numerator: int + denominator: int + + for root, numerator, denominator in [ + (Decimal('0.4481904599041192673635338663'), 200874688349065940678243576378, 1000000000000000000000000000000), # No adj + (Decimal('0.7924949131383786609961759598'), 628048187350206338833590574929, 1000000000000000000000000000000), # Adj up + (Decimal('0.8500554152289934068192208727'), 722594208960136395984391238251, 1000000000000000000000000000000), # Adj down + ]: + with decimal.localcontext(decimal.DefaultContext): + self.assertEqual(statistics._decimal_sqrt_of_frac(numerator, denominator), root) + + # Confirm expected root with a quad precision decimal computation + with decimal.localcontext(decimal.DefaultContext) as ctx: + ctx.prec *= 4 + high_prec_ratio = Decimal(numerator) / Decimal(denominator) + ctx.rounding = decimal.ROUND_05UP + high_prec_root = high_prec_ratio.sqrt() + with decimal.localcontext(decimal.DefaultContext): + target_root = +high_prec_root + self.assertEqual(root, target_root) + + # Verify that corner cases and error handling match Decimal.sqrt() + self.assertEqual(statistics._decimal_sqrt_of_frac(0, 1), 0.0) + with self.assertRaises(decimal.InvalidOperation): + statistics._decimal_sqrt_of_frac(-1, 1) + with self.assertRaises(decimal.InvalidOperation): + statistics._decimal_sqrt_of_frac(1, -1) + + # Error handling for zero denominator matches that for Fraction(1, 0) + with self.assertRaises(ZeroDivisionError): + statistics._decimal_sqrt_of_frac(1, 0) + + # The result is well defined if both inputs are negative + self.assertEqual(statistics._decimal_sqrt_of_frac(-2, -1), statistics._decimal_sqrt_of_frac(2, 1)) class TestStdev(VarianceStdevMixin, NumericTestCase): From webhook-mailer at python.org Tue Nov 30 20:26:07 2021 From: webhook-mailer at python.org (rhettinger) Date: Wed, 01 Dec 2021 01:26:07 -0000 Subject: [Python-checkins] bpo-45876: Have stdev() also use decimal specific square root. (GH-29869) Message-ID: https://github.com/python/cpython/commit/0aa0bd056349f73de9577ccc38560c1d01864d51 commit: 0aa0bd056349f73de9577ccc38560c1d01864d51 branch: main author: Raymond Hettinger committer: rhettinger date: 2021-11-30T19:25:57-06:00 summary: bpo-45876: Have stdev() also use decimal specific square root. (GH-29869) files: M Lib/statistics.py diff --git a/Lib/statistics.py b/Lib/statistics.py index 9f1efa21b15e3..ff19ce9672d33 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -920,9 +920,8 @@ def stdev(data, xbar=None): raise StatisticsError('stdev requires at least two data points') T, ss = _ss(data, xbar) mss = ss / (n - 1) - if hasattr(T, 'sqrt'): - var = _convert(mss, T) - return var.sqrt() + if issubclass(T, Decimal): + return _decimal_sqrt_of_frac(mss.numerator, mss.denominator) return _float_sqrt_of_frac(mss.numerator, mss.denominator)