[Python-checkins] gh-112640: Add `kwdefaults` parameter to `types.FunctionType.__new__` (#112641)

2024-01-11 Thread hauntsaninja
https://github.com/python/cpython/commit/2ac4cf4743a65ac54c7ac6a762bed636800598fe
commit: 2ac4cf4743a65ac54c7ac6a762bed636800598fe
branch: main
author: Nikita Sobolev 
committer: hauntsaninja <[email protected]>
date: 2024-01-11T00:42:30-08:00
summary:

gh-112640: Add `kwdefaults` parameter to `types.FunctionType.__new__` (#112641)

files:
A Misc/NEWS.d/next/Library/2023-12-03-11-15-53.gh-issue-112640.-FVwP7.rst
M Include/internal/pycore_global_objects_fini_generated.h
M Include/internal/pycore_global_strings.h
M Include/internal/pycore_runtime_init_generated.h
M Include/internal/pycore_unicodeobject_generated.h
M Lib/test/test_types.py
M Objects/clinic/funcobject.c.h
M Objects/funcobject.c

diff --git a/Include/internal/pycore_global_objects_fini_generated.h 
b/Include/internal/pycore_global_objects_fini_generated.h
index 8dbdc399d77f57..1fd67ceb3c05fb 100644
--- a/Include/internal/pycore_global_objects_fini_generated.h
+++ b/Include/internal/pycore_global_objects_fini_generated.h
@@ -1015,6 +1015,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
 _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(kw));
 _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(kw1));
 _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(kw2));
+_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(kwdefaults));
 _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(lambda));
 _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(last));
 _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(last_exc));
diff --git a/Include/internal/pycore_global_strings.h 
b/Include/internal/pycore_global_strings.h
index 1fa2d1d49cbb49..da1f9b67bdfb6a 100644
--- a/Include/internal/pycore_global_strings.h
+++ b/Include/internal/pycore_global_strings.h
@@ -504,6 +504,7 @@ struct _Py_global_strings {
 STRUCT_FOR_ID(kw)
 STRUCT_FOR_ID(kw1)
 STRUCT_FOR_ID(kw2)
+STRUCT_FOR_ID(kwdefaults)
 STRUCT_FOR_ID(lambda)
 STRUCT_FOR_ID(last)
 STRUCT_FOR_ID(last_exc)
diff --git a/Include/internal/pycore_runtime_init_generated.h 
b/Include/internal/pycore_runtime_init_generated.h
index 8fd922af2654e0..e285d02b48a9f4 100644
--- a/Include/internal/pycore_runtime_init_generated.h
+++ b/Include/internal/pycore_runtime_init_generated.h
@@ -1013,6 +1013,7 @@ extern "C" {
 INIT_ID(kw), \
 INIT_ID(kw1), \
 INIT_ID(kw2), \
+INIT_ID(kwdefaults), \
 INIT_ID(lambda), \
 INIT_ID(last), \
 INIT_ID(last_exc), \
diff --git a/Include/internal/pycore_unicodeobject_generated.h 
b/Include/internal/pycore_unicodeobject_generated.h
index 0b5fb7363b4f4e..2f9874029fb8f1 100644
--- a/Include/internal/pycore_unicodeobject_generated.h
+++ b/Include/internal/pycore_unicodeobject_generated.h
@@ -1353,6 +1353,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
 string = &_Py_ID(kw2);
 assert(_PyUnicode_CheckConsistency(string, 1));
 _PyUnicode_InternInPlace(interp, &string);
+string = &_Py_ID(kwdefaults);
+assert(_PyUnicode_CheckConsistency(string, 1));
+_PyUnicode_InternInPlace(interp, &string);
 string = &_Py_ID(lambda);
 assert(_PyUnicode_CheckConsistency(string, 1));
 _PyUnicode_InternInPlace(interp, &string);
diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py
index bfecd8eb71220c..1acb2a4d81adf3 100644
--- a/Lib/test/test_types.py
+++ b/Lib/test/test_types.py
@@ -2263,5 +2263,38 @@ def coro():
 'close', 'throw'}))
 
 
+class FunctionTests(unittest.TestCase):
+def test_function_type_defaults(self):
+def ex(a, /, b, *, c):
+return a + b + c
+
+func = types.FunctionType(
+ex.__code__, {}, "func", (1, 2), None, {'c': 3},
+)
+
+self.assertEqual(func(), 6)
+self.assertEqual(func.__defaults__, (1, 2))
+self.assertEqual(func.__kwdefaults__, {'c': 3})
+
+func = types.FunctionType(
+ex.__code__, {}, "func", None, None, None,
+)
+self.assertEqual(func.__defaults__, None)
+self.assertEqual(func.__kwdefaults__, None)
+
+def test_function_type_wrong_defaults(self):
+def ex(a, /, b, *, c):
+return a + b + c
+
+with self.assertRaisesRegex(TypeError, 'arg 4'):
+types.FunctionType(
+ex.__code__, {}, "func", 1, None, {'c': 3},
+)
+with self.assertRaisesRegex(TypeError, 'arg 6'):
+types.FunctionType(
+ex.__code__, {}, "func", None, None, 3,
+)
+
+
 if __name__ == '__main__':
 unittest.main()
diff --git 
a/Misc/NEWS.d/next/Library/2023-12-03-11-15-53.gh-issue-112640.-FVwP7.rst 
b/Misc/NEWS.d/next/Library/2023-12-03-11-15-53.gh-issue-112640.-FVwP7.rst
new file mode 100644
index 00..901d4368173a8c
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-12-03-11-15-53.gh-issue-112640.-FVwP7.rst
@@ -0,0 +1,2 @@
+Add ``kwdefaults`` parameter to :data:`types.FunctionType` to set
+de

[Python-checkins] [3.12] gh-109858: Protect zipfile from "quoted-overlap" zipbomb (GH-110016) (GH-113912)

2024-01-11 Thread serhiy-storchaka
https://github.com/python/cpython/commit/fa181fcf2156f703347b03a3b1966ce47be8ab3b
commit: fa181fcf2156f703347b03a3b1966ce47be8ab3b
branch: 3.12
author: Miss Islington (bot) <[email protected]>
committer: serhiy-storchaka 
date: 2024-01-11T11:24:29+02:00
summary:

[3.12] gh-109858: Protect zipfile from "quoted-overlap" zipbomb (GH-110016) 
(GH-113912)

Raise BadZipFile when try to read an entry that overlaps with other entry or
central directory.
(cherry picked from commit 66363b9a7b9fe7c99eba3a185b74c5fdbf842eba)

Co-authored-by: Serhiy Storchaka 

files:
A Misc/NEWS.d/next/Library/2023-09-28-13-15-51.gh-issue-109858.43e2dg.rst
M Lib/test/test_zipfile/test_core.py
M Lib/zipfile/__init__.py

diff --git a/Lib/test/test_zipfile/test_core.py 
b/Lib/test/test_zipfile/test_core.py
index d8a83d4dbba4d0..00fba11d23c85c 100644
--- a/Lib/test/test_zipfile/test_core.py
+++ b/Lib/test/test_zipfile/test_core.py
@@ -2272,6 +2272,66 @@ def test_decompress_without_3rd_party_library(self):
 with zipfile.ZipFile(zip_file) as zf:
 self.assertRaises(RuntimeError, zf.extract, 'a.txt')
 
+@requires_zlib()
+def test_full_overlap(self):
+data = (
+b'PK\x03\x04\x14\x00\x00\x00\x08\x00\xa0lH\x05\xe2\x1e'
+b'8\xbb\x10\x00\x00\x00\t\x04\x00\x00\x01\x00\x00\x00a\xed'
+b'\xc0\x81\x08\x00\x00\x00\xc00\xd6\xfbK\\d\x0b`P'
+b'K\x01\x02\x14\x00\x14\x00\x00\x00\x08\x00\xa0lH\x05\xe2'
+b'\x1e8\xbb\x10\x00\x00\x00\t\x04\x00\x00\x01\x00\x00\x00\x00'
+b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00aPK'
+b'\x01\x02\x14\x00\x14\x00\x00\x00\x08\x00\xa0lH\x05\xe2\x1e'
+b'8\xbb\x10\x00\x00\x00\t\x04\x00\x00\x01\x00\x00\x00\x00\x00'
+b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00bPK\x05'
+b'\x06\x00\x00\x00\x00\x02\x00\x02\x00^\x00\x00\x00/\x00\x00'
+b'\x00\x00\x00'
+)
+with zipfile.ZipFile(io.BytesIO(data), 'r') as zipf:
+self.assertEqual(zipf.namelist(), ['a', 'b'])
+zi = zipf.getinfo('a')
+self.assertEqual(zi.header_offset, 0)
+self.assertEqual(zi.compress_size, 16)
+self.assertEqual(zi.file_size, 1033)
+zi = zipf.getinfo('b')
+self.assertEqual(zi.header_offset, 0)
+self.assertEqual(zi.compress_size, 16)
+self.assertEqual(zi.file_size, 1033)
+self.assertEqual(len(zipf.read('a')), 1033)
+with self.assertRaisesRegex(zipfile.BadZipFile, 'File 
name.*differ'):
+zipf.read('b')
+
+@requires_zlib()
+def test_quoted_overlap(self):
+data = (
+b'PK\x03\x04\x14\x00\x00\x00\x08\x00\xa0lH\x05Y\xfc'
+b'8\x044\x00\x00\x00(\x04\x00\x00\x01\x00\x00\x00a\x00'
+b'\x1f\x00\xe0\xffPK\x03\x04\x14\x00\x00\x00\x08\x00\xa0l'
+b'H\x05\xe2\x1e8\xbb\x10\x00\x00\x00\t\x04\x00\x00\x01\x00'
+b'\x00\x00b\xed\xc0\x81\x08\x00\x00\x00\xc00\xd6\xfbK\\'
+b'd\x0b`PK\x01\x02\x14\x00\x14\x00\x00\x00\x08\x00\xa0'
+b'lH\x05Y\xfc8\x044\x00\x00\x00(\x04\x00\x00\x01'
+b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+b'\x00aPK\x01\x02\x14\x00\x14\x00\x00\x00\x08\x00\xa0l'
+b'H\x05\xe2\x1e8\xbb\x10\x00\x00\x00\t\x04\x00\x00\x01\x00'
+b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$\x00\x00\x00'
+b'bPK\x05\x06\x00\x00\x00\x00\x02\x00\x02\x00^\x00\x00'
+b'\x00S\x00\x00\x00\x00\x00'
+)
+with zipfile.ZipFile(io.BytesIO(data), 'r') as zipf:
+self.assertEqual(zipf.namelist(), ['a', 'b'])
+zi = zipf.getinfo('a')
+self.assertEqual(zi.header_offset, 0)
+self.assertEqual(zi.compress_size, 52)
+self.assertEqual(zi.file_size, 1064)
+zi = zipf.getinfo('b')
+self.assertEqual(zi.header_offset, 36)
+self.assertEqual(zi.compress_size, 16)
+self.assertEqual(zi.file_size, 1033)
+with self.assertRaisesRegex(zipfile.BadZipFile, 'Overlapped 
entries'):
+zipf.read('a')
+self.assertEqual(len(zipf.read('b')), 1033)
+
 def tearDown(self):
 unlink(TESTFN)
 unlink(TESTFN2)
diff --git a/Lib/zipfile/__init__.py b/Lib/zipfile/__init__.py
index e289c6c30e8cbd..8918484207a326 100644
--- a/Lib/zipfile/__init__.py
+++ b/Lib/zipfile/__init__.py
@@ -381,6 +381,7 @@ class ZipInfo (object):
 'compress_size',
 'file_size',
 '_raw_time',
+'_end_offset',
 )
 
 def __init__(self, filename="NoName", date_time=(1980,1,1,0,0,0)):
@@ -415,6 +416,7 @@ def __init__(self, filename="NoName", 
date_time=(1980,1,1,0,0,0)):
 self.external_attr = 0  # External file attributes
 self.compress_size = 0  # Size of the compressed file
 

[Python-checkins] [3.11] gh-109858: Protect zipfile from "quoted-overlap" zipbomb (GH-110016) (GH-113913)

2024-01-11 Thread serhiy-storchaka
https://github.com/python/cpython/commit/a956e510f6336d5ae111ba429a61c3ade30a7549
commit: a956e510f6336d5ae111ba429a61c3ade30a7549
branch: 3.11
author: Miss Islington (bot) <[email protected]>
committer: serhiy-storchaka 
date: 2024-01-11T11:24:47+02:00
summary:

[3.11] gh-109858: Protect zipfile from "quoted-overlap" zipbomb (GH-110016) 
(GH-113913)

Raise BadZipFile when try to read an entry that overlaps with other entry or
central directory.
(cherry picked from commit 66363b9a7b9fe7c99eba3a185b74c5fdbf842eba)

Co-authored-by: Serhiy Storchaka 

files:
A Misc/NEWS.d/next/Library/2023-09-28-13-15-51.gh-issue-109858.43e2dg.rst
M Lib/test/test_zipfile.py
M Lib/zipfile.py

diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py
index c8e0159765ec2c..9354ab74faa94a 100644
--- a/Lib/test/test_zipfile.py
+++ b/Lib/test/test_zipfile.py
@@ -2216,6 +2216,66 @@ def test_decompress_without_3rd_party_library(self):
 with zipfile.ZipFile(zip_file) as zf:
 self.assertRaises(RuntimeError, zf.extract, 'a.txt')
 
+@requires_zlib()
+def test_full_overlap(self):
+data = (
+b'PK\x03\x04\x14\x00\x00\x00\x08\x00\xa0lH\x05\xe2\x1e'
+b'8\xbb\x10\x00\x00\x00\t\x04\x00\x00\x01\x00\x00\x00a\xed'
+b'\xc0\x81\x08\x00\x00\x00\xc00\xd6\xfbK\\d\x0b`P'
+b'K\x01\x02\x14\x00\x14\x00\x00\x00\x08\x00\xa0lH\x05\xe2'
+b'\x1e8\xbb\x10\x00\x00\x00\t\x04\x00\x00\x01\x00\x00\x00\x00'
+b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00aPK'
+b'\x01\x02\x14\x00\x14\x00\x00\x00\x08\x00\xa0lH\x05\xe2\x1e'
+b'8\xbb\x10\x00\x00\x00\t\x04\x00\x00\x01\x00\x00\x00\x00\x00'
+b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00bPK\x05'
+b'\x06\x00\x00\x00\x00\x02\x00\x02\x00^\x00\x00\x00/\x00\x00'
+b'\x00\x00\x00'
+)
+with zipfile.ZipFile(io.BytesIO(data), 'r') as zipf:
+self.assertEqual(zipf.namelist(), ['a', 'b'])
+zi = zipf.getinfo('a')
+self.assertEqual(zi.header_offset, 0)
+self.assertEqual(zi.compress_size, 16)
+self.assertEqual(zi.file_size, 1033)
+zi = zipf.getinfo('b')
+self.assertEqual(zi.header_offset, 0)
+self.assertEqual(zi.compress_size, 16)
+self.assertEqual(zi.file_size, 1033)
+self.assertEqual(len(zipf.read('a')), 1033)
+with self.assertRaisesRegex(zipfile.BadZipFile, 'File 
name.*differ'):
+zipf.read('b')
+
+@requires_zlib()
+def test_quoted_overlap(self):
+data = (
+b'PK\x03\x04\x14\x00\x00\x00\x08\x00\xa0lH\x05Y\xfc'
+b'8\x044\x00\x00\x00(\x04\x00\x00\x01\x00\x00\x00a\x00'
+b'\x1f\x00\xe0\xffPK\x03\x04\x14\x00\x00\x00\x08\x00\xa0l'
+b'H\x05\xe2\x1e8\xbb\x10\x00\x00\x00\t\x04\x00\x00\x01\x00'
+b'\x00\x00b\xed\xc0\x81\x08\x00\x00\x00\xc00\xd6\xfbK\\'
+b'd\x0b`PK\x01\x02\x14\x00\x14\x00\x00\x00\x08\x00\xa0'
+b'lH\x05Y\xfc8\x044\x00\x00\x00(\x04\x00\x00\x01'
+b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+b'\x00aPK\x01\x02\x14\x00\x14\x00\x00\x00\x08\x00\xa0l'
+b'H\x05\xe2\x1e8\xbb\x10\x00\x00\x00\t\x04\x00\x00\x01\x00'
+b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$\x00\x00\x00'
+b'bPK\x05\x06\x00\x00\x00\x00\x02\x00\x02\x00^\x00\x00'
+b'\x00S\x00\x00\x00\x00\x00'
+)
+with zipfile.ZipFile(io.BytesIO(data), 'r') as zipf:
+self.assertEqual(zipf.namelist(), ['a', 'b'])
+zi = zipf.getinfo('a')
+self.assertEqual(zi.header_offset, 0)
+self.assertEqual(zi.compress_size, 52)
+self.assertEqual(zi.file_size, 1064)
+zi = zipf.getinfo('b')
+self.assertEqual(zi.header_offset, 36)
+self.assertEqual(zi.compress_size, 16)
+self.assertEqual(zi.file_size, 1033)
+with self.assertRaisesRegex(zipfile.BadZipFile, 'Overlapped 
entries'):
+zipf.read('a')
+self.assertEqual(len(zipf.read('b')), 1033)
+
 def tearDown(self):
 unlink(TESTFN)
 unlink(TESTFN2)
diff --git a/Lib/zipfile.py b/Lib/zipfile.py
index 6189db5e3e420d..058d7163ea17ac 100644
--- a/Lib/zipfile.py
+++ b/Lib/zipfile.py
@@ -367,6 +367,7 @@ class ZipInfo (object):
 'compress_size',
 'file_size',
 '_raw_time',
+'_end_offset',
 )
 
 def __init__(self, filename="NoName", date_time=(1980,1,1,0,0,0)):
@@ -408,6 +409,7 @@ def __init__(self, filename="NoName", 
date_time=(1980,1,1,0,0,0)):
 self.external_attr = 0  # External file attributes
 self.compress_size = 0  # Size of the compressed file
 self.file_size = 0  # Size of the uncompressed file
+self._end_offse

[Python-checkins] gh-112419: Document removal of sys.meta_path's 'find_module' fallback (#112421)

2024-01-11 Thread erlend-aasland
https://github.com/python/cpython/commit/ec23e90082ffdedc7f0bdd2dfadfc4983ddc0712
commit: ec23e90082ffdedc7f0bdd2dfadfc4983ddc0712
branch: main
author: AN Long 
committer: erlend-aasland 
date: 2024-01-11T09:43:35Z
summary:

gh-112419: Document removal of sys.meta_path's 'find_module' fallback (#112421)

Co-authored-by: Erlend E. Aasland 

files:
M Doc/library/sys.rst

diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst
index 2426c37ccb1e0f..c371663934314a 100644
--- a/Doc/library/sys.rst
+++ b/Doc/library/sys.rst
@@ -1268,10 +1268,13 @@ always available.
 .. versionchanged:: 3.4
 
 :term:`Module specs ` were introduced in Python 3.4, by
-:pep:`451`. Earlier versions of Python looked for a method called
-:meth:`!find_module`.
-This is still called as a fallback if a :data:`meta_path` entry doesn't
-have a :meth:`~importlib.abc.MetaPathFinder.find_spec` method.
+:pep:`451`.
+
+.. versionchanged:: 3.12
+
+Removed the fallback that looked for a :meth:`!find_module` method
+if a :data:`meta_path` entry didn't have a
+:meth:`~importlib.abc.MetaPathFinder.find_spec` method.
 
 .. data:: modules
 

___
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]


[Python-checkins] [3.12] gh-112419: Document removal of sys.meta_path's 'find_module' fallback (GH-112421) (#113934)

2024-01-11 Thread erlend-aasland
https://github.com/python/cpython/commit/5c238225f60c33cf1931b1a8c9a3310192c716ae
commit: 5c238225f60c33cf1931b1a8c9a3310192c716ae
branch: 3.12
author: Miss Islington (bot) <[email protected]>
committer: erlend-aasland 
date: 2024-01-11T09:49:21Z
summary:

[3.12] gh-112419: Document removal of sys.meta_path's 'find_module' fallback 
(GH-112421) (#113934)

(cherry picked from commit ec23e90082ffdedc7f0bdd2dfadfc4983ddc0712)

Co-authored-by: AN Long 
Co-authored-by: Erlend E. Aasland 

files:
M Doc/library/sys.rst

diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst
index f0b1d940ec5ec6..af0eae668e10d6 100644
--- a/Doc/library/sys.rst
+++ b/Doc/library/sys.rst
@@ -1254,10 +1254,13 @@ always available.
 .. versionchanged:: 3.4
 
 :term:`Module specs ` were introduced in Python 3.4, by
-:pep:`451`. Earlier versions of Python looked for a method called
-:meth:`!find_module`.
-This is still called as a fallback if a :data:`meta_path` entry doesn't
-have a :meth:`~importlib.abc.MetaPathFinder.find_spec` method.
+:pep:`451`.
+
+.. versionchanged:: 3.12
+
+Removed the fallback that looked for a :meth:`!find_module` method
+if a :data:`meta_path` entry didn't have a
+:meth:`~importlib.abc.MetaPathFinder.find_spec` method.
 
 .. data:: modules
 

___
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]


[Python-checkins] gh-113932: assert ``SyntaxWarning`` in test_compile.TestSpecifics.test_… (#113933)

2024-01-11 Thread iritkatriel
https://github.com/python/cpython/commit/9f088336b268dfe9011a7cb550f4e488ccd7e8f5
commit: 9f088336b268dfe9011a7cb550f4e488ccd7e8f5
branch: main
author: Kirill Podoprigora 
committer: iritkatriel <[email protected]>
date: 2024-01-11T11:25:07Z
summary:

gh-113932: assert ``SyntaxWarning`` in test_compile.TestSpecifics.test_… 
(#113933)

files:
M Lib/test/test_compile.py

diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py
index 7850977428985f..45fd30987760cb 100644
--- a/Lib/test/test_compile.py
+++ b/Lib/test/test_compile.py
@@ -450,7 +450,8 @@ def 
test_condition_expression_with_dead_blocks_compiles(self):
 
 def test_condition_expression_with_redundant_comparisons_compiles(self):
 # See gh-113054
-compile('if 9<9<9and 9or 9:9', '', 'exec')
+with self.assertWarns(SyntaxWarning):
+compile('if 9<9<9and 9or 9:9', '', 'exec')
 
 def test_dead_code_with_except_handler_compiles(self):
 compile(textwrap.dedent("""

___
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]


[Python-checkins] gh-91960: Remove Cirrus CI configuration (#113938)

2024-01-11 Thread vstinner
https://github.com/python/cpython/commit/7ed76fc368c340307290cde9f183dc0ba6dd920c
commit: 7ed76fc368c340307290cde9f183dc0ba6dd920c
branch: main
author: Victor Stinner 
committer: vstinner 
date: 2024-01-11T14:33:24+01:00
summary:

gh-91960: Remove Cirrus CI configuration (#113938)

Remove .cirrus.yml which was already disabled by being renamed to
.cirrus-DISABLED.yml. In total, Cirrus CI only run for less than one
month.

files:
D .cirrus-DISABLED.yml

diff --git a/.cirrus-DISABLED.yml b/.cirrus-DISABLED.yml
deleted file mode 100644
index f20835cb6cac2a..00
--- a/.cirrus-DISABLED.yml
+++ /dev/null
@@ -1,29 +0,0 @@
-# gh-91960: Job disabled since Python is out of free credit (September 2023):
-# 
https://discuss.python.org/t/freebsd-gets-a-new-cirrus-ci-github-action-job-and-a-new-buildbot/33122/26
-
-freebsd_task:
-  freebsd_instance:
-matrix:
-- image: freebsd-13-2-release-amd64
-  # Turn off TCP and UDP blackhole.  It is not enabled by default in FreeBSD,
-  # but it is in the FreeBSD GCE images as used by Cirrus-CI.  It causes even
-  # local local connections to fail with ETIMEDOUT instead of ECONNREFUSED.
-  # For more information see https://reviews.freebsd.org/D41751 and
-  # https://github.com/cirruslabs/cirrus-ci-docs/issues/483.
-  sysctl_script:
-- sysctl net.inet.tcp.blackhole=0
-- sysctl net.inet.udp.blackhole=0
-  configure_script:
-- mkdir build
-- cd build
-- ../configure --with-pydebug
-  build_script:
-- cd build
-- make -j$(sysctl -n hw.ncpu)
-  pythoninfo_script:
-- cd build
-- make pythoninfo
-  test_script:
-- cd build
-# dtrace fails to build on FreeBSD - see gh-73263
-- make buildbottest TESTOPTS="-j0 -x test_dtrace --timeout=600"

___
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]


[Python-checkins] gh-107901: jump leaving an exception handler doesn't need an eval break check (#113943)

2024-01-11 Thread iritkatriel
https://github.com/python/cpython/commit/0d8fec79ca30e67870752c6ad4e299f591271e69
commit: 0d8fec79ca30e67870752c6ad4e299f591271e69
branch: main
author: Irit Katriel <[email protected]>
committer: iritkatriel <[email protected]>
date: 2024-01-11T14:27:41Z
summary:

gh-107901: jump leaving an exception handler doesn't need an eval break check 
(#113943)

files:
A Misc/NEWS.d/next/Core and 
Builtins/2024-01-11-14-03-31.gh-issue-107901.U65IyC.rst
M Lib/test/test_dis.py
M Python/flowgraph.c

diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py
index e46ff3d43d16ec..097f05afdf1517 100644
--- a/Lib/test/test_dis.py
+++ b/Lib/test/test_dis.py
@@ -578,11 +578,11 @@ async def _asyncwith(c):
 
 %4d   L12: CLEANUP_THROW
 
-  --   L13: JUMP_BACKWARD   26 (to L5)
+  --   L13: JUMP_BACKWARD_NO_INTERRUPT 25 (to L5)
 
 %4d   L14: CLEANUP_THROW
 
-  --   L15: JUMP_BACKWARD   11 (to L11)
+  --   L15: JUMP_BACKWARD_NO_INTERRUPT 9 (to L11)
 
 %4d   L16: PUSH_EXC_INFO
 WITH_EXCEPT_START
diff --git a/Misc/NEWS.d/next/Core and 
Builtins/2024-01-11-14-03-31.gh-issue-107901.U65IyC.rst b/Misc/NEWS.d/next/Core 
and Builtins/2024-01-11-14-03-31.gh-issue-107901.U65IyC.rst
new file mode 100644
index 00..5c81b665216f82
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and 
Builtins/2024-01-11-14-03-31.gh-issue-107901.U65IyC.rst 
@@ -0,0 +1 @@
+A jump leaving an exception handler back to normal code no longer checks the 
eval breaker.
diff --git a/Python/flowgraph.c b/Python/flowgraph.c
index 1fcacbce9177ca..dad945761a4a58 100644
--- a/Python/flowgraph.c
+++ b/Python/flowgraph.c
@@ -2164,7 +2164,7 @@ push_cold_blocks_to_end(cfg_builder *g) {
 if (!IS_LABEL(b->b_next->b_label)) {
 b->b_next->b_label.id = next_lbl++;
 }
-basicblock_addop(explicit_jump, JUMP, b->b_next->b_label.id, 
NO_LOCATION);
+basicblock_addop(explicit_jump, JUMP_NO_INTERRUPT, 
b->b_next->b_label.id, NO_LOCATION);
 explicit_jump->b_cold = 1;
 explicit_jump->b_next = b->b_next;
 b->b_next = explicit_jump;

___
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]


[Python-checkins] GH-113853: Guarantee forward progress in executors (GH-113854)

2024-01-11 Thread markshannon
https://github.com/python/cpython/commit/55824d01f866d1fa0f21996d897fba0e07d09ac8
commit: 55824d01f866d1fa0f21996d897fba0e07d09ac8
branch: main
author: Mark Shannon 
committer: markshannon 
date: 2024-01-11T18:20:42Z
summary:

GH-113853: Guarantee forward progress in executors (GH-113854)

files:
A Misc/NEWS.d/next/Core and 
Builtins/2024-01-08-05-36-59.gh-issue-113853.lm-6_a.rst
M Include/cpython/optimizer.h
M Python/bytecodes.c
M Python/generated_cases.c.h
M Python/optimizer.c

diff --git a/Include/cpython/optimizer.h b/Include/cpython/optimizer.h
index f077da7ee88456..0e7bc9fdd7a07d 100644
--- a/Include/cpython/optimizer.h
+++ b/Include/cpython/optimizer.h
@@ -65,7 +65,7 @@ PyAPI_FUNC(_PyOptimizerObject *) 
PyUnstable_GetOptimizer(void);
 PyAPI_FUNC(_PyExecutorObject *) PyUnstable_GetExecutor(PyCodeObject *code, int 
offset);
 
 int
-_PyOptimizer_BackEdge(struct _PyInterpreterFrame *frame, _Py_CODEUNIT *src, 
_Py_CODEUNIT *dest, PyObject **stack_pointer);
+_PyOptimizer_Optimize(struct _PyInterpreterFrame *frame, _Py_CODEUNIT *start, 
PyObject **stack_pointer);
 
 extern _PyOptimizerObject _PyOptimizer_Default;
 
diff --git a/Misc/NEWS.d/next/Core and 
Builtins/2024-01-08-05-36-59.gh-issue-113853.lm-6_a.rst b/Misc/NEWS.d/next/Core 
and Builtins/2024-01-08-05-36-59.gh-issue-113853.lm-6_a.rst
new file mode 100644
index 00..d4f0a764153579
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and 
Builtins/2024-01-08-05-36-59.gh-issue-113853.lm-6_a.rst 
@@ -0,0 +1,2 @@
+Guarantee that all executors make progress. This then guarantees that tier 2
+execution always makes progress.
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index f53ddae8df985a..2011d963e3687c 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -2325,12 +2325,18 @@ dummy_func(
 // Double-check that the opcode isn't instrumented or something:
 if (ucounter > threshold && this_instr->op.code == JUMP_BACKWARD) {
 OPT_STAT_INC(attempts);
-int optimized = _PyOptimizer_BackEdge(frame, this_instr, 
next_instr, stack_pointer);
+_Py_CODEUNIT *start = this_instr;
+/* Back up over EXTENDED_ARGs so optimizer sees the whole 
instruction */
+while (oparg > 255) {
+oparg >>= 8;
+start--;
+}
+int optimized = _PyOptimizer_Optimize(frame, start, 
stack_pointer);
 ERROR_IF(optimized < 0, error);
 if (optimized) {
 // Rewind and enter the executor:
-assert(this_instr->op.code == ENTER_EXECUTOR);
-next_instr = this_instr;
+assert(start->op.code == ENTER_EXECUTOR);
+next_instr = start;
 this_instr[1].cache &= ((1 << OPTIMIZER_BITS_IN_COUNTER) - 
1);
 }
 else {
@@ -2370,10 +2376,12 @@ dummy_func(
 GOTO_TIER_TWO();
 }
 else {
-code->co_executors->executors[oparg & 255] = NULL;
+/* ENTER_EXECUTOR will be the first code unit of the 
instruction */
+assert(oparg < 256);
+code->co_executors->executors[oparg] = NULL;
 opcode = this_instr->op.code = executor->vm_data.opcode;
 this_instr->op.arg = executor->vm_data.oparg;
-oparg = (oparg & (~255)) | executor->vm_data.oparg;
+oparg = executor->vm_data.oparg;
 Py_DECREF(executor);
 next_instr = this_instr;
 DISPATCH_GOTO();
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index e693e3e2560e7b..1e995b62a72fcf 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -2384,10 +2384,12 @@
 GOTO_TIER_TWO();
 }
 else {
-code->co_executors->executors[oparg & 255] = NULL;
+/* ENTER_EXECUTOR will be the first code unit of the 
instruction */
+assert(oparg < 256);
+code->co_executors->executors[oparg] = NULL;
 opcode = this_instr->op.code = executor->vm_data.opcode;
 this_instr->op.arg = executor->vm_data.oparg;
-oparg = (oparg & (~255)) | executor->vm_data.oparg;
+oparg = executor->vm_data.oparg;
 Py_DECREF(executor);
 next_instr = this_instr;
 DISPATCH_GOTO();
@@ -3289,12 +3291,18 @@
 // Double-check that the opcode isn't instrumented or something:
 if (ucounter > threshold && this_instr->op.code == JUMP_BACKWARD) {
 OPT_STAT_INC(attempts);
-int optimized = _PyOptimizer_BackEdge(frame, this_instr, 
next_instr, stack_pointer);
+_Py_CODEUNIT *start = this_instr;
+/* Back up over EXTENDED_ARGs so optimizer sees the who

[Python-checkins] gh-113845: Fix a compiler warning in Python/suggestions.c (GH-113949)

2024-01-11 Thread serhiy-storchaka
https://github.com/python/cpython/commit/8717f7b495c8c33fd37017f4e7684609c304c556
commit: 8717f7b495c8c33fd37017f4e7684609c304c556
branch: main
author: Serhiy Storchaka 
committer: serhiy-storchaka 
date: 2024-01-11T20:31:24+02:00
summary:

gh-113845: Fix a compiler warning in Python/suggestions.c (GH-113949)

files:
M Python/suggestions.c

diff --git a/Python/suggestions.c b/Python/suggestions.c
index 69c3e4fe4d2146..a09b3ce6d9dab2 100644
--- a/Python/suggestions.c
+++ b/Python/suggestions.c
@@ -4,8 +4,6 @@
 #include "pycore_pyerrors.h"  // export _Py_UTF8_Edit_Cost()
 #include "pycore_runtime.h"   // _Py_ID()
 
-#include "stdlib_module_names.h"  // _Py_stdlib_module_names
-
 #define MAX_CANDIDATE_ITEMS 750
 #define MAX_STRING_SIZE 40
 

___
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]


[Python-checkins] gh-111968: Use per-thread freelists for tuple in free-threading (gh-113921)

2024-01-11 Thread corona10
https://github.com/python/cpython/commit/2e7577b622616ef5ff2d1460fb5bebf845f0edf3
commit: 2e7577b622616ef5ff2d1460fb5bebf845f0edf3
branch: main
author: Donghee Na 
committer: corona10 
date: 2024-01-12T03:46:28+09:00
summary:

gh-111968: Use per-thread freelists for tuple in free-threading (gh-113921)

files:
M Include/internal/pycore_freelist.h
M Include/internal/pycore_gc.h
M Include/internal/pycore_tuple.h
M Objects/tupleobject.c
M Python/gc_free_threading.c
M Python/gc_gil.c
M Python/pylifecycle.c
M Python/pystate.c

diff --git a/Include/internal/pycore_freelist.h 
b/Include/internal/pycore_freelist.h
index d41153d26a2546..34009435910d99 100644
--- a/Include/internal/pycore_freelist.h
+++ b/Include/internal/pycore_freelist.h
@@ -8,11 +8,19 @@ extern "C" {
 #  error "this header requires Py_BUILD_CORE define"
 #endif
 
+// PyTuple_MAXSAVESIZE - largest tuple to save on free list
+// PyTuple_MAXFREELIST - maximum number of tuples of each size to save
+
 #ifdef WITH_FREELISTS
 // with freelists
+#  define PyTuple_MAXSAVESIZE 20
+#  define PyTuple_NFREELISTS PyTuple_MAXSAVESIZE
+#  define PyTuple_MAXFREELIST 2000
 #  define PyList_MAXFREELIST 80
 #  define PyFloat_MAXFREELIST 100
 #else
+#  define PyTuple_NFREELISTS 0
+#  define PyTuple_MAXFREELIST 0
 #  define PyList_MAXFREELIST 0
 #  define PyFloat_MAXFREELIST 0
 #endif
@@ -24,6 +32,23 @@ struct _Py_list_state {
 #endif
 };
 
+struct _Py_tuple_state {
+#if WITH_FREELISTS
+/* There is one freelist for each size from 1 to PyTuple_MAXSAVESIZE.
+   The empty tuple is handled separately.
+
+   Each tuple stored in the array is the head of the linked list
+   (and the next available tuple) for that size.  The actual tuple
+   object is used as the linked list node, with its first item
+   (ob_item[0]) pointing to the next node (i.e. the previous head).
+   Each linked list is initially NULL. */
+PyTupleObject *free_list[PyTuple_NFREELISTS];
+int numfree[PyTuple_NFREELISTS];
+#else
+char _unused;  // Empty structs are not allowed.
+#endif
+};
+
 struct _Py_float_state {
 #ifdef WITH_FREELISTS
 /* Special free list
@@ -36,6 +61,7 @@ struct _Py_float_state {
 
 typedef struct _Py_freelist_state {
 struct _Py_float_state float_state;
+struct _Py_tuple_state tuple_state;
 struct _Py_list_state list_state;
 } _PyFreeListState;
 
diff --git a/Include/internal/pycore_gc.h b/Include/internal/pycore_gc.h
index 753763a5a50220..c029b239306648 100644
--- a/Include/internal/pycore_gc.h
+++ b/Include/internal/pycore_gc.h
@@ -246,7 +246,7 @@ extern PyObject *_PyGC_GetReferrers(PyInterpreterState 
*interp, PyObject *objs);
 // Functions to clear types free lists
 extern void _PyGC_ClearAllFreeLists(PyInterpreterState *interp);
 extern void _Py_ClearFreeLists(_PyFreeListState *state, int is_finalization);
-extern void _PyTuple_ClearFreeList(PyInterpreterState *interp);
+extern void _PyTuple_ClearFreeList(_PyFreeListState *state, int 
is_finalization);
 extern void _PyFloat_ClearFreeList(_PyFreeListState *state, int 
is_finalization);
 extern void _PyList_ClearFreeList(_PyFreeListState *state, int 
is_finalization);
 extern void _PyDict_ClearFreeList(PyInterpreterState *interp);
diff --git a/Include/internal/pycore_tuple.h b/Include/internal/pycore_tuple.h
index 4fa7a12206bcb2..b348339a505b0f 100644
--- a/Include/internal/pycore_tuple.h
+++ b/Include/internal/pycore_tuple.h
@@ -14,59 +14,16 @@ extern void _PyTuple_DebugMallocStats(FILE *out);
 /* runtime lifecycle */
 
 extern PyStatus _PyTuple_InitGlobalObjects(PyInterpreterState *);
-extern void _PyTuple_Fini(PyInterpreterState *);
+extern void _PyTuple_Fini(_PyFreeListState *);
 
 
 /* other API */
 
-// PyTuple_MAXSAVESIZE - largest tuple to save on free list
-// PyTuple_MAXFREELIST - maximum number of tuples of each size to save
-
-#if defined(PyTuple_MAXSAVESIZE) && PyTuple_MAXSAVESIZE <= 0
-   // A build indicated that tuple freelists should not be used.
-#  define PyTuple_NFREELISTS 0
-#  undef PyTuple_MAXSAVESIZE
-#  undef PyTuple_MAXFREELIST
-
-#elif !defined(WITH_FREELISTS)
-#  define PyTuple_NFREELISTS 0
-#  undef PyTuple_MAXSAVESIZE
-#  undef PyTuple_MAXFREELIST
-
-#else
-   // We are using a freelist for tuples.
-#  ifndef PyTuple_MAXSAVESIZE
-#define PyTuple_MAXSAVESIZE 20
-#  endif
-#  define PyTuple_NFREELISTS PyTuple_MAXSAVESIZE
-#  ifndef PyTuple_MAXFREELIST
-#define PyTuple_MAXFREELIST 2000
-#  endif
-#endif
-
-struct _Py_tuple_state {
-#if PyTuple_NFREELISTS > 0
-/* There is one freelist for each size from 1 to PyTuple_MAXSAVESIZE.
-   The empty tuple is handled separately.
-
-   Each tuple stored in the array is the head of the linked list
-   (and the next available tuple) for that size.  The actual tuple
-   object is used as the linked list node, with its first item
-   (ob_item[0]) pointing to the next node (i.e. the previous head).
-   Each linked list is initially NULL. */
-PyTupleObject *free_list[PyTuple_

[Python-checkins] Update KDE recipe to match the standard use of the h parameter (gh-#113958)

2024-01-11 Thread rhettinger
https://github.com/python/cpython/commit/2f126a70f36e36dd90db53ebdcdff9b990cf3452
commit: 2f126a70f36e36dd90db53ebdcdff9b990cf3452
branch: main
author: Raymond Hettinger 
committer: rhettinger 
date: 2024-01-11T16:21:21-06:00
summary:

Update KDE recipe to match the standard use of the h parameter (gh-#113958)

files:
M Doc/library/statistics.rst

diff --git a/Doc/library/statistics.rst b/Doc/library/statistics.rst
index 588c9c0be4ea02..0417b3f38a9807 100644
--- a/Doc/library/statistics.rst
+++ b/Doc/library/statistics.rst
@@ -1104,17 +1104,15 @@ from a fixed number of discrete samples.
 The basic idea is to smooth the data using `a kernel function such as a
 normal distribution, triangular distribution, or uniform distribution
 
`_.
-The degree of smoothing is controlled by a single
-parameter, ``h``, representing the variance of the kernel function.
+The degree of smoothing is controlled by a scaling parameter, ``h``,
+which is called the *bandwidth*.
 
 .. testcode::
 
-   import math
-
def kde_normal(sample, h):
"Create a continuous probability density function from a sample."
-   # Smooth the sample with a normal distribution of variance h.
-   kernel_h = NormalDist(0.0, math.sqrt(h)).pdf
+   # Smooth the sample with a normal distribution kernel scaled by h.
+   kernel_h = NormalDist(0.0, h).pdf
n = len(sample)
def pdf(x):
return sum(kernel_h(x - x_i) for x_i in sample) / n
@@ -1128,7 +1126,7 @@ a probability density function estimated from a small 
sample:
 .. doctest::
 
>>> sample = [-2.1, -1.3, -0.4, 1.9, 5.1, 6.2]
-   >>> f_hat = kde_normal(sample, h=2.25)
+   >>> f_hat = kde_normal(sample, h=1.5)
>>> xarr = [i/100 for i in range(-750, 1100)]
>>> yarr = [f_hat(x) for x in xarr]
 

___
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]


[Python-checkins] gh-87868: Sort and remove duplicates in getenvironment() (GH-102731)

2024-01-11 Thread zooba
https://github.com/python/cpython/commit/d15e1ac828716623253ef1a0db404bc42434e3f5
commit: d15e1ac828716623253ef1a0db404bc42434e3f5
branch: 3.11
author: Miss Islington (bot) <[email protected]>
committer: zooba 
date: 2024-01-11T22:27:12Z
summary:

gh-87868: Sort and remove duplicates in getenvironment() (GH-102731)

(cherry picked from commit c31be58da8577ef140e83d4e46502c7bb1eb9abf)

Co-authored-by: AN Long 
Co-authored-by: Alex Waygood 
Co-authored-by: Pieter Eendebak 
Co-authored-by: Erlend E. Aasland 

files:
A Misc/NEWS.d/next/Windows/2023-03-15-23-53-45.gh-issue-87868.4C36oQ.rst
M Lib/test/test_subprocess.py
M Modules/_winapi.c

diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py
index b7b16e22fa6419..f71f953fbd1797 100644
--- a/Lib/test/test_subprocess.py
+++ b/Lib/test/test_subprocess.py
@@ -789,6 +789,19 @@ def test_env(self):
 stdout, stderr = p.communicate()
 self.assertEqual(stdout, b"orange")
 
[email protected](sys.platform == "win32", "Windows only issue")
+def test_win32_duplicate_envs(self):
+newenv = os.environ.copy()
+newenv["fRUit"] = "cherry"
+newenv["fruit"] = "lemon"
+newenv["FRUIT"] = "orange"
+newenv["frUit"] = "banana"
+with subprocess.Popen(["CMD", "/c", "SET", "fruit"],
+  stdout=subprocess.PIPE,
+  env=newenv) as p:
+stdout, _ = p.communicate()
+self.assertEqual(stdout.strip(), b"frUit=banana")
+
 # Windows requires at least the SYSTEMROOT environment variable to start
 # Python
 @unittest.skipIf(sys.platform == 'win32',
@@ -820,6 +833,26 @@ def is_env_var_to_ignore(n):
if not is_env_var_to_ignore(k)]
 self.assertEqual(child_env_names, [])
 
[email protected](sysconfig.get_config_var('Py_ENABLE_SHARED') == 1,
+ 'The Python shared library cannot be loaded '
+ 'without some system environments.')
[email protected](check_sanitizer(address=True),
+ 'AddressSanitizer adds to the environment.')
+def test_one_environment_variable(self):
+newenv = {'fruit': 'orange'}
+cmd = [sys.executable, '-c',
+   'import sys,os;'
+   'sys.stdout.write("fruit="+os.getenv("fruit"))']
+if sys.platform == "win32":
+cmd = ["CMD", "/c", "SET", "fruit"]
+with subprocess.Popen(cmd, stdout=subprocess.PIPE, 
stderr=subprocess.PIPE, env=newenv) as p:
+stdout, stderr = p.communicate()
+if p.returncode and support.verbose:
+print("STDOUT:", stdout.decode("ascii", "replace"))
+print("STDERR:", stderr.decode("ascii", "replace"))
+self.assertEqual(p.returncode, 0)
+self.assertEqual(stdout.strip(), b"fruit=orange")
+
 def test_invalid_cmd(self):
 # null character in the command name
 cmd = sys.executable + '\0'
@@ -860,6 +893,19 @@ def test_invalid_env(self):
 stdout, stderr = p.communicate()
 self.assertEqual(stdout, b"orange=lemon")
 
[email protected](sys.platform == "win32", "Windows only issue")
+def test_win32_invalid_env(self):
+# '=' in the environment variable name
+newenv = os.environ.copy()
+newenv["FRUIT=VEGETABLE"] = "cabbage"
+with self.assertRaises(ValueError):
+subprocess.Popen(ZERO_RETURN_CMD, env=newenv)
+
+newenv = os.environ.copy()
+newenv["==FRUIT"] = "cabbage"
+with self.assertRaises(ValueError):
+subprocess.Popen(ZERO_RETURN_CMD, env=newenv)
+
 def test_communicate_stdin(self):
 p = subprocess.Popen([sys.executable, "-c",
   'import sys;'
diff --git 
a/Misc/NEWS.d/next/Windows/2023-03-15-23-53-45.gh-issue-87868.4C36oQ.rst 
b/Misc/NEWS.d/next/Windows/2023-03-15-23-53-45.gh-issue-87868.4C36oQ.rst
new file mode 100644
index 00..37e8103c9ec34b
--- /dev/null
+++ b/Misc/NEWS.d/next/Windows/2023-03-15-23-53-45.gh-issue-87868.4C36oQ.rst
@@ -0,0 +1,2 @@
+Correctly sort and remove duplicate environment variables in
+:py:func:`!_winapi.CreateProcess`.
diff --git a/Modules/_winapi.c b/Modules/_winapi.c
index 7fb1f2f561b0f9..55b37188d24e45 100644
--- a/Modules/_winapi.c
+++ b/Modules/_winapi.c
@@ -39,11 +39,12 @@
 #include "structmember.h" // PyMemberDef
 
 
-#define WINDOWS_LEAN_AND_MEAN
 #include "windows.h"
 #include 
 #include "winreparse.h"
 
+#include "pycore_runtime.h"   // _Py_ID
+
 #if defined(MS_WIN32) && !defined(MS_WIN64)
 #define HANDLE_TO_PYNUM(handle) \
 PyLong_FromUnsignedLong((unsigned long) handle)
@@ -781,12 +782,162 @@ gethandle(PyObject* obj, const char* name)
 return ret;
 }
 
+static PyObject *
+sortenvironmentkey(PyObject *module, PyObject *item)
+{
+PyObject *r

[Python-checkins] gh-81489: Use Unicode APIs for mmap tagname on Windows (GH-14133)

2024-01-11 Thread zooba
https://github.com/python/cpython/commit/b4d4aa9e8d61476267951c72321fadffc2d82227
commit: b4d4aa9e8d61476267951c72321fadffc2d82227
branch: main
author: Zackery Spytz 
committer: zooba 
date: 2024-01-11T22:39:47Z
summary:

gh-81489: Use Unicode APIs for mmap tagname on Windows (GH-14133)

Co-authored-by: Erlend E. Aasland 

files:
A Misc/NEWS.d/next/Windows/2019-06-16-11-27-05.bpo-37308.Iz_NU_.rst
M Doc/library/mmap.rst
M Lib/test/test_mmap.py
M Modules/mmapmodule.c
M PC/config.c

diff --git a/Doc/library/mmap.rst b/Doc/library/mmap.rst
index 3fa69e717329e4..1e8bfdf251e7da 100644
--- a/Doc/library/mmap.rst
+++ b/Doc/library/mmap.rst
@@ -62,8 +62,8 @@ To map anonymous memory, -1 should be passed as the fileno 
along with the length
the same file.  If you specify the name of an existing tag, that tag is
opened, otherwise a new tag of this name is created.  If this parameter is
omitted or ``None``, the mapping is created without a name.  Avoiding the
-   use of the tag parameter will assist in keeping your code portable between
-   Unix and Windows.
+   use of the *tagname* parameter will assist in keeping your code portable
+   between Unix and Windows.
 
*offset* may be specified as a non-negative integer offset. mmap references
will be relative to the offset from the beginning of the file. *offset*
diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py
index 866ede5b83dff0..f1e4b1efe2d0aa 100644
--- a/Lib/test/test_mmap.py
+++ b/Lib/test/test_mmap.py
@@ -672,14 +672,16 @@ def test_tagname(self):
 m2.close()
 m1.close()
 
+with self.assertRaisesRegex(TypeError, 'tagname'):
+mmap.mmap(-1, 8, tagname=1)
+
 @cpython_only
 @unittest.skipUnless(os.name == 'nt', 'requires Windows')
 def test_sizeof(self):
 m1 = mmap.mmap(-1, 100)
 tagname = random_tagname()
 m2 = mmap.mmap(-1, 100, tagname=tagname)
-self.assertEqual(sys.getsizeof(m2),
- sys.getsizeof(m1) + len(tagname) + 1)
+self.assertGreater(sys.getsizeof(m2), sys.getsizeof(m1))
 
 @unittest.skipUnless(os.name == 'nt', 'requires Windows')
 def test_crasher_on_windows(self):
diff --git a/Misc/NEWS.d/next/Windows/2019-06-16-11-27-05.bpo-37308.Iz_NU_.rst 
b/Misc/NEWS.d/next/Windows/2019-06-16-11-27-05.bpo-37308.Iz_NU_.rst
new file mode 100644
index 00..3ba29d60a23e98
--- /dev/null
+++ b/Misc/NEWS.d/next/Windows/2019-06-16-11-27-05.bpo-37308.Iz_NU_.rst
@@ -0,0 +1,2 @@
+Fix mojibake in :class:`mmap.mmap` when using a non-ASCII *tagname* argument
+on Windows.
diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c
index 66ed0b8efb775c..d0014e3a0429e4 100644
--- a/Modules/mmapmodule.c
+++ b/Modules/mmapmodule.c
@@ -32,10 +32,6 @@
 #  include  // close()
 #endif
 
-// to support MS_WINDOWS_SYSTEM OpenFileMappingA / CreateFileMappingA
-// need to be replaced with OpenFileMappingW / CreateFileMappingW
-#if !defined(MS_WINDOWS) || defined(MS_WINDOWS_DESKTOP) || 
defined(MS_WINDOWS_GAMES)
-
 #ifndef MS_WINDOWS
 #define UNIX
 # ifdef HAVE_FCNTL_H
@@ -116,7 +112,7 @@ typedef struct {
 #ifdef MS_WINDOWS
 HANDLE  map_handle;
 HANDLE  file_handle;
-char *  tagname;
+wchar_t *   tagname;
 #endif
 
 #ifdef UNIX
@@ -534,7 +530,7 @@ mmap_resize_method(mmap_object *self,
 CloseHandle(self->map_handle);
 /* if the file mapping still exists, it cannot be resized. */
 if (self->tagname) {
-self->map_handle = OpenFileMappingA(FILE_MAP_WRITE, FALSE,
+self->map_handle = OpenFileMappingW(FILE_MAP_WRITE, FALSE,
 self->tagname);
 if (self->map_handle) {
 PyErr_SetFromWindowsErr(ERROR_USER_MAPPED_FILE);
@@ -563,7 +559,7 @@ mmap_resize_method(mmap_object *self,
 
 /* create a new file mapping and map a new view */
 /* FIXME: call CreateFileMappingW with wchar_t tagname */
-self->map_handle = CreateFileMappingA(
+self->map_handle = CreateFileMappingW(
 self->file_handle,
 NULL,
 PAGE_READWRITE,
@@ -845,7 +841,7 @@ mmap__sizeof__method(mmap_object *self, void 
*Py_UNUSED(ignored))
 {
 size_t res = _PyObject_SIZE(Py_TYPE(self));
 if (self->tagname) {
-res += strlen(self->tagname) + 1;
+res += (wcslen(self->tagname) + 1) * sizeof(self->tagname[0]);
 }
 return PyLong_FromSize_t(res);
 }
@@ -1400,7 +1396,7 @@ new_mmap_object(PyTypeObject *type, PyObject *args, 
PyObject *kwdict)
 DWORD off_lo;   /* lower 32 bits of offset */
 DWORD size_hi;  /* upper 32 bits of size */
 DWORD size_lo;  /* lower 32 bits of size */
-const char *tagname = "";
+PyObject *tagname = Py_None;
 DWORD dwErr = 0;
 int fileno;
 HANDLE fh = 0;
@@ -1410,7 +1406,7 @@ new_mmap_object(PyTypeObject *type, PyObject *args, 
PyObject *kwdict)
 "tagname",
  

[Python-checkins] gh-81489: Use Unicode APIs for mmap tagname on Windows (GH-14133)

2024-01-11 Thread zooba
https://github.com/python/cpython/commit/186c0216882b5ebde4c00b6c9a3da14fa9375f51
commit: 186c0216882b5ebde4c00b6c9a3da14fa9375f51
branch: 3.11
author: Steve Dower 
committer: zooba 
date: 2024-01-11T23:04:36Z
summary:

gh-81489: Use Unicode APIs for mmap tagname on Windows (GH-14133)

Co-authored-by: Zackery Spytz 
Co-authored-by: Erlend E. Aasland 

files:
A Misc/NEWS.d/next/Windows/2019-06-16-11-27-05.bpo-37308.Iz_NU_.rst
M Doc/library/mmap.rst
M Lib/test/test_mmap.py
M Modules/mmapmodule.c

diff --git a/Doc/library/mmap.rst b/Doc/library/mmap.rst
index 21fa97a2a3cef8..0495bce7add77d 100644
--- a/Doc/library/mmap.rst
+++ b/Doc/library/mmap.rst
@@ -62,8 +62,8 @@ To map anonymous memory, -1 should be passed as the fileno 
along with the length
the same file.  If you specify the name of an existing tag, that tag is
opened, otherwise a new tag of this name is created.  If this parameter is
omitted or ``None``, the mapping is created without a name.  Avoiding the
-   use of the tag parameter will assist in keeping your code portable between
-   Unix and Windows.
+   use of the *tagname* parameter will assist in keeping your code portable
+   between Unix and Windows.
 
*offset* may be specified as a non-negative integer offset. mmap references
will be relative to the offset from the beginning of the file. *offset*
diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py
index dfcf3039422af5..1867e8c957f58c 100644
--- a/Lib/test/test_mmap.py
+++ b/Lib/test/test_mmap.py
@@ -671,14 +671,16 @@ def test_tagname(self):
 m2.close()
 m1.close()
 
+with self.assertRaisesRegex(TypeError, 'tagname'):
+mmap.mmap(-1, 8, tagname=1)
+
 @cpython_only
 @unittest.skipUnless(os.name == 'nt', 'requires Windows')
 def test_sizeof(self):
 m1 = mmap.mmap(-1, 100)
 tagname = random_tagname()
 m2 = mmap.mmap(-1, 100, tagname=tagname)
-self.assertEqual(sys.getsizeof(m2),
- sys.getsizeof(m1) + len(tagname) + 1)
+self.assertGreater(sys.getsizeof(m2), sys.getsizeof(m1))
 
 @unittest.skipUnless(os.name == 'nt', 'requires Windows')
 def test_crasher_on_windows(self):
diff --git a/Misc/NEWS.d/next/Windows/2019-06-16-11-27-05.bpo-37308.Iz_NU_.rst 
b/Misc/NEWS.d/next/Windows/2019-06-16-11-27-05.bpo-37308.Iz_NU_.rst
new file mode 100644
index 00..3ba29d60a23e98
--- /dev/null
+++ b/Misc/NEWS.d/next/Windows/2019-06-16-11-27-05.bpo-37308.Iz_NU_.rst
@@ -0,0 +1,2 @@
+Fix mojibake in :class:`mmap.mmap` when using a non-ASCII *tagname* argument
+on Windows.
diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c
index a8d48ec6f30989..b315becc48ca7a 100644
--- a/Modules/mmapmodule.c
+++ b/Modules/mmapmodule.c
@@ -109,7 +109,7 @@ typedef struct {
 #ifdef MS_WINDOWS
 HANDLE  map_handle;
 HANDLE  file_handle;
-char *  tagname;
+wchar_t *   tagname;
 #endif
 
 #ifdef UNIX
@@ -539,7 +539,7 @@ mmap_resize_method(mmap_object *self,
 CloseHandle(self->map_handle);
 /* if the file mapping still exists, it cannot be resized. */
 if (self->tagname) {
-self->map_handle = OpenFileMapping(FILE_MAP_WRITE, FALSE,
+self->map_handle = OpenFileMappingW(FILE_MAP_WRITE, FALSE,
 self->tagname);
 if (self->map_handle) {
 PyErr_SetFromWindowsErr(ERROR_USER_MAPPED_FILE);
@@ -568,7 +568,7 @@ mmap_resize_method(mmap_object *self,
 
 /* create a new file mapping and map a new view */
 /* FIXME: call CreateFileMappingW with wchar_t tagname */
-self->map_handle = CreateFileMapping(
+self->map_handle = CreateFileMappingW(
 self->file_handle,
 NULL,
 PAGE_READWRITE,
@@ -843,12 +843,11 @@ mmap__repr__method(PyObject *self)
 static PyObject *
 mmap__sizeof__method(mmap_object *self, void *unused)
 {
-Py_ssize_t res;
-
-res = _PyObject_SIZE(Py_TYPE(self));
-if (self->tagname)
-res += strlen(self->tagname) + 1;
-return PyLong_FromSsize_t(res);
+size_t res = _PyObject_SIZE(Py_TYPE(self));
+if (self->tagname) {
+res += (wcslen(self->tagname) + 1) * sizeof(self->tagname[0]);
+}
+return PyLong_FromSize_t(res);
 }
 #endif
 
@@ -1400,7 +1399,7 @@ new_mmap_object(PyTypeObject *type, PyObject *args, 
PyObject *kwdict)
 DWORD off_lo;   /* lower 32 bits of offset */
 DWORD size_hi;  /* upper 32 bits of size */
 DWORD size_lo;  /* lower 32 bits of size */
-const char *tagname = "";
+PyObject *tagname = Py_None;
 DWORD dwErr = 0;
 int fileno;
 HANDLE fh = 0;
@@ -1410,7 +1409,7 @@ new_mmap_object(PyTypeObject *type, PyObject *args, 
PyObject *kwdict)
 "tagname",
 "access", "offset", NULL };
 
-if (!PyArg_ParseTupleAndKeywords(args, kwdict, "in|ziL", keywords,
+if (!PyArg_ParseTuple

[Python-checkins] gh-81489: Use Unicode APIs for mmap tagname on Windows (GH-14133)

2024-01-11 Thread zooba
https://github.com/python/cpython/commit/b902671d36da219efee16c8b183882dc93132898
commit: b902671d36da219efee16c8b183882dc93132898
branch: 3.12
author: Miss Islington (bot) <[email protected]>
committer: zooba 
date: 2024-01-11T23:13:02Z
summary:

gh-81489: Use Unicode APIs for mmap tagname on Windows (GH-14133)

(cherry picked from commit b4d4aa9e8d61476267951c72321fadffc2d82227)

Co-authored-by: Zackery Spytz 
Co-authored-by: Erlend E. Aasland 

files:
A Misc/NEWS.d/next/Windows/2019-06-16-11-27-05.bpo-37308.Iz_NU_.rst
M Doc/library/mmap.rst
M Lib/test/test_mmap.py
M Modules/mmapmodule.c
M PC/config.c

diff --git a/Doc/library/mmap.rst b/Doc/library/mmap.rst
index 4ca7a64451d4c7..9572468ddf804c 100644
--- a/Doc/library/mmap.rst
+++ b/Doc/library/mmap.rst
@@ -62,8 +62,8 @@ To map anonymous memory, -1 should be passed as the fileno 
along with the length
the same file.  If you specify the name of an existing tag, that tag is
opened, otherwise a new tag of this name is created.  If this parameter is
omitted or ``None``, the mapping is created without a name.  Avoiding the
-   use of the tag parameter will assist in keeping your code portable between
-   Unix and Windows.
+   use of the *tagname* parameter will assist in keeping your code portable
+   between Unix and Windows.
 
*offset* may be specified as a non-negative integer offset. mmap references
will be relative to the offset from the beginning of the file. *offset*
diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py
index dfcf3039422af5..1867e8c957f58c 100644
--- a/Lib/test/test_mmap.py
+++ b/Lib/test/test_mmap.py
@@ -671,14 +671,16 @@ def test_tagname(self):
 m2.close()
 m1.close()
 
+with self.assertRaisesRegex(TypeError, 'tagname'):
+mmap.mmap(-1, 8, tagname=1)
+
 @cpython_only
 @unittest.skipUnless(os.name == 'nt', 'requires Windows')
 def test_sizeof(self):
 m1 = mmap.mmap(-1, 100)
 tagname = random_tagname()
 m2 = mmap.mmap(-1, 100, tagname=tagname)
-self.assertEqual(sys.getsizeof(m2),
- sys.getsizeof(m1) + len(tagname) + 1)
+self.assertGreater(sys.getsizeof(m2), sys.getsizeof(m1))
 
 @unittest.skipUnless(os.name == 'nt', 'requires Windows')
 def test_crasher_on_windows(self):
diff --git a/Misc/NEWS.d/next/Windows/2019-06-16-11-27-05.bpo-37308.Iz_NU_.rst 
b/Misc/NEWS.d/next/Windows/2019-06-16-11-27-05.bpo-37308.Iz_NU_.rst
new file mode 100644
index 00..3ba29d60a23e98
--- /dev/null
+++ b/Misc/NEWS.d/next/Windows/2019-06-16-11-27-05.bpo-37308.Iz_NU_.rst
@@ -0,0 +1,2 @@
+Fix mojibake in :class:`mmap.mmap` when using a non-ASCII *tagname* argument
+on Windows.
diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c
index c5e6c27f73b855..827f619e6eb8b6 100644
--- a/Modules/mmapmodule.c
+++ b/Modules/mmapmodule.c
@@ -29,10 +29,6 @@
 #include "structmember.h" // PyMemberDef
 #include// offsetof()
 
-// to support MS_WINDOWS_SYSTEM OpenFileMappingA / CreateFileMappingA
-// need to be replaced with OpenFileMappingW / CreateFileMappingW
-#if !defined(MS_WINDOWS) || defined(MS_WINDOWS_DESKTOP) || 
defined(MS_WINDOWS_GAMES)
-
 #ifndef MS_WINDOWS
 #define UNIX
 # ifdef HAVE_FCNTL_H
@@ -113,7 +109,7 @@ typedef struct {
 #ifdef MS_WINDOWS
 HANDLE  map_handle;
 HANDLE  file_handle;
-char *  tagname;
+wchar_t *   tagname;
 #endif
 
 #ifdef UNIX
@@ -531,7 +527,7 @@ mmap_resize_method(mmap_object *self,
 CloseHandle(self->map_handle);
 /* if the file mapping still exists, it cannot be resized. */
 if (self->tagname) {
-self->map_handle = OpenFileMappingA(FILE_MAP_WRITE, FALSE,
+self->map_handle = OpenFileMappingW(FILE_MAP_WRITE, FALSE,
 self->tagname);
 if (self->map_handle) {
 PyErr_SetFromWindowsErr(ERROR_USER_MAPPED_FILE);
@@ -560,7 +556,7 @@ mmap_resize_method(mmap_object *self,
 
 /* create a new file mapping and map a new view */
 /* FIXME: call CreateFileMappingW with wchar_t tagname */
-self->map_handle = CreateFileMappingA(
+self->map_handle = CreateFileMappingW(
 self->file_handle,
 NULL,
 PAGE_READWRITE,
@@ -836,7 +832,7 @@ mmap__sizeof__method(mmap_object *self, void *unused)
 {
 size_t res = _PyObject_SIZE(Py_TYPE(self));
 if (self->tagname) {
-res += strlen(self->tagname) + 1;
+res += (wcslen(self->tagname) + 1) * sizeof(self->tagname[0]);
 }
 return PyLong_FromSize_t(res);
 }
@@ -1390,7 +1386,7 @@ new_mmap_object(PyTypeObject *type, PyObject *args, 
PyObject *kwdict)
 DWORD off_lo;   /* lower 32 bits of offset */
 DWORD size_hi;  /* upper 32 bits of size */
 DWORD size_lo;  /* lower 32 bits of size */
-const char *tagname = "";
+PyObject *tagname = Py_None;
 DWORD d

[Python-checkins] [3.11] GH-92584: Move installation schemes overview to sysconfig docs (GH-108018) (#110214)

2024-01-11 Thread AA-Turner
https://github.com/python/cpython/commit/71288ed8b0765a67b4cd15f96319f06c10784535
commit: 71288ed8b0765a67b4cd15f96319f06c10784535
branch: 3.11
author: Adam Turner <[email protected]>
committer: AA-Turner <[email protected]>
date: 2024-01-11T23:48:10Z
summary:

[3.11] GH-92584: Move installation schemes overview to sysconfig docs 
(GH-108018) (#110214)

* Add new installation path functions subsection

* Add content from install/index to sysconfig

* Fix table

* Update note about installers

* Clean up the list of schemes, remove references to Distutils.
(cherry picked from commit f16e81f368d08891e28dc1f038c1826ea80d7801)

files:
M Doc/library/site.rst
M Doc/library/sysconfig.rst
M Doc/using/cmdline.rst

diff --git a/Doc/library/site.rst b/Doc/library/site.rst
index ab4fa765bf63d5..dee63511164f12 100644
--- a/Doc/library/site.rst
+++ b/Doc/library/site.rst
@@ -199,7 +199,7 @@ Module contents
:file:`~/Library/Python/{X.Y}` for macOS framework builds, and
:file:`{%APPDATA%}\\Python` for Windows.  This value is used by Distutils to
compute the installation directories for scripts, data files, Python 
modules,
-   etc. for the :ref:`user installation scheme `.
+   etc. for the :ref:`user installation scheme `.
See also :envvar:`PYTHONUSERBASE`.
 
 
diff --git a/Doc/library/sysconfig.rst b/Doc/library/sysconfig.rst
index 2de47cfd36a0f7..7ffacc113148d6 100644
--- a/Doc/library/sysconfig.rst
+++ b/Doc/library/sysconfig.rst
@@ -20,6 +20,7 @@ The :mod:`sysconfig` module provides access to Python's 
configuration
 information like the list of installation paths and the configuration variables
 relevant for the current platform.
 
+
 Configuration variables
 ---
 
@@ -60,6 +61,7 @@ Example of usage::
>>> sysconfig.get_config_vars('AR', 'CXX')
['ar', 'g++']
 
+
 .. _installation_paths:
 
 Installation paths
@@ -68,27 +70,24 @@ Installation paths
 Python uses an installation scheme that differs depending on the platform and 
on
 the installation options.  These schemes are stored in :mod:`sysconfig` under
 unique identifiers based on the value returned by :const:`os.name`.
-
-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.
+The schemes are used by package installers to determine where to copy files to.
 
 Python currently supports nine schemes:
 
 - *posix_prefix*: scheme for POSIX platforms like Linux or macOS.  This is
   the default scheme used when Python or a component is installed.
-- *posix_home*: scheme for POSIX platforms used when a *home* option is used
-  upon installation.  This scheme is used when a component is installed through
-  Distutils with a specific home prefix.
-- *posix_user*: scheme for POSIX platforms used when a component is installed
-  through Distutils and the *user* option is used.  This scheme defines paths
-  located under the user home directory.
+- *posix_home*: scheme for POSIX platforms, when the *home* option is used.
+  This scheme defines paths located under a specific home prefix.
+- *posix_user*: scheme for POSIX platforms, when the *user* option is used.
+  This scheme defines paths located under the user's home directory
+  (:const:`site.USER_BASE`).
 - *posix_venv*: scheme for :mod:`Python virtual environments ` on POSIX
   platforms; by default it is the same as *posix_prefix*.
-- *nt*: scheme for NT platforms like Windows.
-- *nt_user*: scheme for NT platforms, when the *user* option is used.
-- *nt_venv*: scheme for :mod:`Python virtual environments ` on NT
-  platforms; by default it is the same as *nt*.
+- *nt*: scheme for Windows.
+  This is the default scheme used when Python or a component is installed.
+- *nt_user*: scheme for Windows, when the *user* option is used.
+- *nt_venv*: scheme for :mod:`Python virtual environments ` on Windows;
+  by default it is the same as *nt*.
 - *venv*: a scheme with values from either *posix_venv* or *nt_venv* depending
   on the platform Python runs on.
 - *osx_framework_user*: scheme for macOS, when the *user* option is used.
@@ -101,7 +100,7 @@ identifier.  Python currently uses eight paths:
 - *platstdlib*: directory containing the standard Python library files that are
   platform-specific.
 - *platlib*: directory for site-specific, platform-specific files.
-- *purelib*: directory for site-specific, non-platform-specific files.
+- *purelib*: directory for site-specific, non-platform-specific files ('pure' 
Python).
 - *include*: directory for non-platform-specific header files for
   the Python C-API.
 - *platinclude*: directory for platform-specific header files for
@@ -109,7 +108,157 @@ identifier.  Python currently uses eight paths:
 - *scripts*: directory for script files.
 - *data*: directory for data files.
 
-:mod:`sysconfig` provides some functions to determine these paths.
+
+.. _sysconfig-user-scheme:
+
+User sche

[Python-checkins] GH-107678: Improve Unicode handling clarity in ``library/re.rst`` (#107679)

2024-01-11 Thread AA-Turner
https://github.com/python/cpython/commit/c9b8a22f3404d59e2c4950715f8c29413a349b8e
commit: c9b8a22f3404d59e2c4950715f8c29413a349b8e
branch: main
author: Adam Turner <[email protected]>
committer: AA-Turner <[email protected]>
date: 2024-01-11T23:56:10Z
summary:

GH-107678: Improve Unicode handling clarity in ``library/re.rst`` (#107679)

files:
M Doc/library/re.rst

diff --git a/Doc/library/re.rst b/Doc/library/re.rst
index 302f7224de4a7a..5bb93390aa5f79 100644
--- a/Doc/library/re.rst
+++ b/Doc/library/re.rst
@@ -17,7 +17,7 @@ those found in Perl.
 Both patterns and strings to be searched can be Unicode strings (:class:`str`)
 as well as 8-bit strings (:class:`bytes`).
 However, Unicode strings and 8-bit strings cannot be mixed:
-that is, you cannot match a Unicode string with a byte pattern or
+that is, you cannot match a Unicode string with a bytes pattern or
 vice-versa; similarly, when asking for a substitution, the replacement
 string must be of the same type as both the pattern and the search string.
 
@@ -257,8 +257,7 @@ The special characters are:
.. index:: single: \ (backslash); in regular expressions
 
* Character classes such as ``\w`` or ``\S`` (defined below) are also 
accepted
- inside a set, although the characters they match depends on whether
- :const:`ASCII` or :const:`LOCALE` mode is in force.
+ inside a set, although the characters they match depend on the flags_ 
used.
 
.. index:: single: ^ (caret); in regular expressions
 
@@ -326,18 +325,24 @@ The special characters are:
currently supported extensions.
 
 ``(?aiLmsux)``
-   (One or more letters from the set ``'a'``, ``'i'``, ``'L'``, ``'m'``,
-   ``'s'``, ``'u'``, ``'x'``.)  The group matches the empty string; the
-   letters set the corresponding flags: :const:`re.A` (ASCII-only matching),
-   :const:`re.I` (ignore case), :const:`re.L` (locale dependent),
-   :const:`re.M` (multi-line), :const:`re.S` (dot matches all),
-   :const:`re.U` (Unicode matching), and :const:`re.X` (verbose),
-   for the entire regular expression.
+   (One or more letters from the set
+   ``'a'``, ``'i'``, ``'L'``, ``'m'``, ``'s'``, ``'u'``, ``'x'``.)
+   The group matches the empty string;
+   the letters set the corresponding flags for the entire regular expression:
+
+   * :const:`re.A` (ASCII-only matching)
+   * :const:`re.I` (ignore case)
+   * :const:`re.L` (locale dependent)
+   * :const:`re.M` (multi-line)
+   * :const:`re.S` (dot matches all)
+   * :const:`re.U` (Unicode matching)
+   * :const:`re.X` (verbose)
+
(The flags are described in :ref:`contents-of-module-re`.)
This is useful if you wish to include the flags as part of the
regular expression, instead of passing a *flag* argument to the
-   :func:`re.compile` function.  Flags should be used first in the
-   expression string.
+   :func:`re.compile` function.
+   Flags should be used first in the expression string.
 
.. versionchanged:: 3.11
   This construction can only be used at the start of the expression.
@@ -351,14 +356,20 @@ The special characters are:
pattern.
 
 ``(?aiLmsux-imsx:...)``
-   (Zero or more letters from the set ``'a'``, ``'i'``, ``'L'``, ``'m'``,
-   ``'s'``, ``'u'``, ``'x'``, optionally followed by ``'-'`` followed by
+   (Zero or more letters from the set
+   ``'a'``, ``'i'``, ``'L'``, ``'m'``, ``'s'``, ``'u'``, ``'x'``,
+   optionally followed by ``'-'`` followed by
one or more letters from the ``'i'``, ``'m'``, ``'s'``, ``'x'``.)
-   The letters set or remove the corresponding flags:
-   :const:`re.A` (ASCII-only matching), :const:`re.I` (ignore case),
-   :const:`re.L` (locale dependent), :const:`re.M` (multi-line),
-   :const:`re.S` (dot matches all), :const:`re.U` (Unicode matching),
-   and :const:`re.X` (verbose), for the part of the expression.
+   The letters set or remove the corresponding flags for the part of the 
expression:
+
+   * :const:`re.A` (ASCII-only matching)
+   * :const:`re.I` (ignore case)
+   * :const:`re.L` (locale dependent)
+   * :const:`re.M` (multi-line)
+   * :const:`re.S` (dot matches all)
+   * :const:`re.U` (Unicode matching)
+   * :const:`re.X` (verbose)
+
(The flags are described in :ref:`contents-of-module-re`.)
 
The letters ``'a'``, ``'L'`` and ``'u'`` are mutually exclusive when used
@@ -366,7 +377,7 @@ The special characters are:
when one of them appears in an inline group, it overrides the matching mode
in the enclosing group.  In Unicode patterns ``(?a:...)`` switches to
ASCII-only matching, and ``(?u:...)`` switches to Unicode matching
-   (default).  In byte pattern ``(?L:...)`` switches to locale depending
+   (default).  In bytes patterns ``(?L:...)`` switches to locale dependent
matching, and ``(?a:...)`` switches to ASCII-only matching (default).
This override is only in effect for the narrow inline group, and the
original matching mode is restored outside of the group.
@@ -529,47

[Python-checkins] [3.12] GH-107678: Improve Unicode handling clarity in ``library/re.rst`` (GH-107679) (#113965)

2024-01-11 Thread AA-Turner
https://github.com/python/cpython/commit/bd9ea91e5f7ace12fe26584f4b130141c62d5ba3
commit: bd9ea91e5f7ace12fe26584f4b130141c62d5ba3
branch: 3.12
author: Miss Islington (bot) <[email protected]>
committer: AA-Turner <[email protected]>
date: 2024-01-12T00:02:28Z
summary:

[3.12] GH-107678: Improve Unicode handling clarity in ``library/re.rst`` 
(GH-107679) (#113965)

GH-107678: Improve Unicode handling clarity in ``library/re.rst`` (GH-107679)
(cherry picked from commit c9b8a22f3404d59e2c4950715f8c29413a349b8e)

Co-authored-by: Adam Turner <[email protected]>

files:
M Doc/library/re.rst

diff --git a/Doc/library/re.rst b/Doc/library/re.rst
index bb1c3132ba8230..07e57f1582d5e8 100644
--- a/Doc/library/re.rst
+++ b/Doc/library/re.rst
@@ -17,7 +17,7 @@ those found in Perl.
 Both patterns and strings to be searched can be Unicode strings (:class:`str`)
 as well as 8-bit strings (:class:`bytes`).
 However, Unicode strings and 8-bit strings cannot be mixed:
-that is, you cannot match a Unicode string with a byte pattern or
+that is, you cannot match a Unicode string with a bytes pattern or
 vice-versa; similarly, when asking for a substitution, the replacement
 string must be of the same type as both the pattern and the search string.
 
@@ -257,8 +257,7 @@ The special characters are:
.. index:: single: \ (backslash); in regular expressions
 
* Character classes such as ``\w`` or ``\S`` (defined below) are also 
accepted
- inside a set, although the characters they match depends on whether
- :const:`ASCII` or :const:`LOCALE` mode is in force.
+ inside a set, although the characters they match depend on the flags_ 
used.
 
.. index:: single: ^ (caret); in regular expressions
 
@@ -326,18 +325,24 @@ The special characters are:
currently supported extensions.
 
 ``(?aiLmsux)``
-   (One or more letters from the set ``'a'``, ``'i'``, ``'L'``, ``'m'``,
-   ``'s'``, ``'u'``, ``'x'``.)  The group matches the empty string; the
-   letters set the corresponding flags: :const:`re.A` (ASCII-only matching),
-   :const:`re.I` (ignore case), :const:`re.L` (locale dependent),
-   :const:`re.M` (multi-line), :const:`re.S` (dot matches all),
-   :const:`re.U` (Unicode matching), and :const:`re.X` (verbose),
-   for the entire regular expression.
+   (One or more letters from the set
+   ``'a'``, ``'i'``, ``'L'``, ``'m'``, ``'s'``, ``'u'``, ``'x'``.)
+   The group matches the empty string;
+   the letters set the corresponding flags for the entire regular expression:
+
+   * :const:`re.A` (ASCII-only matching)
+   * :const:`re.I` (ignore case)
+   * :const:`re.L` (locale dependent)
+   * :const:`re.M` (multi-line)
+   * :const:`re.S` (dot matches all)
+   * :const:`re.U` (Unicode matching)
+   * :const:`re.X` (verbose)
+
(The flags are described in :ref:`contents-of-module-re`.)
This is useful if you wish to include the flags as part of the
regular expression, instead of passing a *flag* argument to the
-   :func:`re.compile` function.  Flags should be used first in the
-   expression string.
+   :func:`re.compile` function.
+   Flags should be used first in the expression string.
 
.. versionchanged:: 3.11
   This construction can only be used at the start of the expression.
@@ -351,14 +356,20 @@ The special characters are:
pattern.
 
 ``(?aiLmsux-imsx:...)``
-   (Zero or more letters from the set ``'a'``, ``'i'``, ``'L'``, ``'m'``,
-   ``'s'``, ``'u'``, ``'x'``, optionally followed by ``'-'`` followed by
+   (Zero or more letters from the set
+   ``'a'``, ``'i'``, ``'L'``, ``'m'``, ``'s'``, ``'u'``, ``'x'``,
+   optionally followed by ``'-'`` followed by
one or more letters from the ``'i'``, ``'m'``, ``'s'``, ``'x'``.)
-   The letters set or remove the corresponding flags:
-   :const:`re.A` (ASCII-only matching), :const:`re.I` (ignore case),
-   :const:`re.L` (locale dependent), :const:`re.M` (multi-line),
-   :const:`re.S` (dot matches all), :const:`re.U` (Unicode matching),
-   and :const:`re.X` (verbose), for the part of the expression.
+   The letters set or remove the corresponding flags for the part of the 
expression:
+
+   * :const:`re.A` (ASCII-only matching)
+   * :const:`re.I` (ignore case)
+   * :const:`re.L` (locale dependent)
+   * :const:`re.M` (multi-line)
+   * :const:`re.S` (dot matches all)
+   * :const:`re.U` (Unicode matching)
+   * :const:`re.X` (verbose)
+
(The flags are described in :ref:`contents-of-module-re`.)
 
The letters ``'a'``, ``'L'`` and ``'u'`` are mutually exclusive when used
@@ -366,7 +377,7 @@ The special characters are:
when one of them appears in an inline group, it overrides the matching mode
in the enclosing group.  In Unicode patterns ``(?a:...)`` switches to
ASCII-only matching, and ``(?u:...)`` switches to Unicode matching
-   (default).  In byte pattern ``(?L:...)`` switches to locale depending
+   (default).  In bytes patterns ``(

[Python-checkins] [3.11] GH-107678: Improve Unicode handling clarity in ``library/re.rst`` (GH-107679) (#113966)

2024-01-11 Thread AA-Turner
https://github.com/python/cpython/commit/535b1dedb3fd374fc22ade339f860ca66a7292b7
commit: 535b1dedb3fd374fc22ade339f860ca66a7292b7
branch: 3.11
author: Miss Islington (bot) <[email protected]>
committer: AA-Turner <[email protected]>
date: 2024-01-12T00:02:35Z
summary:

[3.11] GH-107678: Improve Unicode handling clarity in ``library/re.rst`` 
(GH-107679) (#113966)

GH-107678: Improve Unicode handling clarity in ``library/re.rst`` (GH-107679)
(cherry picked from commit c9b8a22f3404d59e2c4950715f8c29413a349b8e)

Co-authored-by: Adam Turner <[email protected]>

files:
M Doc/library/re.rst

diff --git a/Doc/library/re.rst b/Doc/library/re.rst
index 83fff79d2884e5..8ddfce79a1b022 100644
--- a/Doc/library/re.rst
+++ b/Doc/library/re.rst
@@ -17,7 +17,7 @@ those found in Perl.
 Both patterns and strings to be searched can be Unicode strings (:class:`str`)
 as well as 8-bit strings (:class:`bytes`).
 However, Unicode strings and 8-bit strings cannot be mixed:
-that is, you cannot match a Unicode string with a byte pattern or
+that is, you cannot match a Unicode string with a bytes pattern or
 vice-versa; similarly, when asking for a substitution, the replacement
 string must be of the same type as both the pattern and the search string.
 
@@ -257,8 +257,7 @@ The special characters are:
.. index:: single: \ (backslash); in regular expressions
 
* Character classes such as ``\w`` or ``\S`` (defined below) are also 
accepted
- inside a set, although the characters they match depends on whether
- :const:`ASCII` or :const:`LOCALE` mode is in force.
+ inside a set, although the characters they match depend on the flags_ 
used.
 
.. index:: single: ^ (caret); in regular expressions
 
@@ -326,18 +325,24 @@ The special characters are:
currently supported extensions.
 
 ``(?aiLmsux)``
-   (One or more letters from the set ``'a'``, ``'i'``, ``'L'``, ``'m'``,
-   ``'s'``, ``'u'``, ``'x'``.)  The group matches the empty string; the
-   letters set the corresponding flags: :const:`re.A` (ASCII-only matching),
-   :const:`re.I` (ignore case), :const:`re.L` (locale dependent),
-   :const:`re.M` (multi-line), :const:`re.S` (dot matches all),
-   :const:`re.U` (Unicode matching), and :const:`re.X` (verbose),
-   for the entire regular expression.
+   (One or more letters from the set
+   ``'a'``, ``'i'``, ``'L'``, ``'m'``, ``'s'``, ``'u'``, ``'x'``.)
+   The group matches the empty string;
+   the letters set the corresponding flags for the entire regular expression:
+
+   * :const:`re.A` (ASCII-only matching)
+   * :const:`re.I` (ignore case)
+   * :const:`re.L` (locale dependent)
+   * :const:`re.M` (multi-line)
+   * :const:`re.S` (dot matches all)
+   * :const:`re.U` (Unicode matching)
+   * :const:`re.X` (verbose)
+
(The flags are described in :ref:`contents-of-module-re`.)
This is useful if you wish to include the flags as part of the
regular expression, instead of passing a *flag* argument to the
-   :func:`re.compile` function.  Flags should be used first in the
-   expression string.
+   :func:`re.compile` function.
+   Flags should be used first in the expression string.
 
.. versionchanged:: 3.11
   This construction can only be used at the start of the expression.
@@ -351,14 +356,20 @@ The special characters are:
pattern.
 
 ``(?aiLmsux-imsx:...)``
-   (Zero or more letters from the set ``'a'``, ``'i'``, ``'L'``, ``'m'``,
-   ``'s'``, ``'u'``, ``'x'``, optionally followed by ``'-'`` followed by
+   (Zero or more letters from the set
+   ``'a'``, ``'i'``, ``'L'``, ``'m'``, ``'s'``, ``'u'``, ``'x'``,
+   optionally followed by ``'-'`` followed by
one or more letters from the ``'i'``, ``'m'``, ``'s'``, ``'x'``.)
-   The letters set or remove the corresponding flags:
-   :const:`re.A` (ASCII-only matching), :const:`re.I` (ignore case),
-   :const:`re.L` (locale dependent), :const:`re.M` (multi-line),
-   :const:`re.S` (dot matches all), :const:`re.U` (Unicode matching),
-   and :const:`re.X` (verbose), for the part of the expression.
+   The letters set or remove the corresponding flags for the part of the 
expression:
+
+   * :const:`re.A` (ASCII-only matching)
+   * :const:`re.I` (ignore case)
+   * :const:`re.L` (locale dependent)
+   * :const:`re.M` (multi-line)
+   * :const:`re.S` (dot matches all)
+   * :const:`re.U` (Unicode matching)
+   * :const:`re.X` (verbose)
+
(The flags are described in :ref:`contents-of-module-re`.)
 
The letters ``'a'``, ``'L'`` and ``'u'`` are mutually exclusive when used
@@ -366,7 +377,7 @@ The special characters are:
when one of them appears in an inline group, it overrides the matching mode
in the enclosing group.  In Unicode patterns ``(?a:...)`` switches to
ASCII-only matching, and ``(?u:...)`` switches to Unicode matching
-   (default).  In byte pattern ``(?L:...)`` switches to locale depending
+   (default).  In bytes patterns ``(

[Python-checkins] Improve kde graph with better caption and number formatting (gh-113967)

2024-01-11 Thread rhettinger
https://github.com/python/cpython/commit/53d2e1f26c3fca88a9217f1935cb288f4ba78464
commit: 53d2e1f26c3fca88a9217f1935cb288f4ba78464
branch: main
author: Raymond Hettinger 
committer: rhettinger 
date: 2024-01-11T18:25:18-06:00
summary:

Improve kde graph with better caption and number formatting (gh-113967)

files:
M Doc/library/kde_example.png

diff --git a/Doc/library/kde_example.png b/Doc/library/kde_example.png
index f4504895699974..4c26f26292faa5 100644
Binary files a/Doc/library/kde_example.png and b/Doc/library/kde_example.png 
differ

___
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]


[Python-checkins] gh-111968: Explicit handling for finalized freelist (gh-113929)

2024-01-11 Thread corona10
https://github.com/python/cpython/commit/efa738e862da26f870ca659b01ff732649f400a7
commit: efa738e862da26f870ca659b01ff732649f400a7
branch: main
author: Donghee Na 
committer: corona10 
date: 2024-01-12T00:31:28Z
summary:

gh-111968: Explicit handling for finalized freelist (gh-113929)

files:
M Objects/floatobject.c
M Objects/listobject.c

diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index f1a09c0a94f4a6..912c450a5e1055 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -132,10 +132,6 @@ PyFloat_FromDouble(double fval)
 struct _Py_float_state *state = get_float_state();
 op = state->free_list;
 if (op != NULL) {
-#ifdef Py_DEBUG
-// PyFloat_FromDouble() must not be called after _PyFloat_Fini()
-assert(state->numfree != -1);
-#endif
 state->free_list = (PyFloatObject *) Py_TYPE(op);
 state->numfree--;
 OBJECT_STAT_INC(from_freelist);
diff --git a/Objects/listobject.c b/Objects/listobject.c
index c05c4fdff83883..288c704be9842a 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -20,7 +20,7 @@ class list "PyListObject *" "&PyList_Type"
 
 _Py_DECLARE_STR(list_err, "list index out of range");
 
-#if PyList_MAXFREELIST > 0
+#ifdef WITH_FREELISTS
 static struct _Py_list_state *
 get_list_state(void)
 {
@@ -123,7 +123,7 @@ list_preallocate_exact(PyListObject *self, Py_ssize_t size)
 void
 _PyList_ClearFreeList(_PyFreeListState *freelist_state, int is_finalization)
 {
-#if PyList_MAXFREELIST > 0
+#ifdef WITH_FREELISTS
 struct _Py_list_state *state = &freelist_state->list_state;
 while (state->numfree > 0) {
 PyListObject *op = state->free_list[--state->numfree];
@@ -146,7 +146,7 @@ _PyList_Fini(_PyFreeListState *state)
 void
 _PyList_DebugMallocStats(FILE *out)
 {
-#if PyList_MAXFREELIST > 0
+#ifdef WITH_FREELISTS
 struct _Py_list_state *state = get_list_state();
 _PyDebugAllocatorStats(out,
"free PyListObject",
@@ -164,13 +164,9 @@ PyList_New(Py_ssize_t size)
 return NULL;
 }
 
-#if PyList_MAXFREELIST > 0
+#ifdef WITH_FREELISTS
 struct _Py_list_state *state = get_list_state();
-#ifdef Py_DEBUG
-// PyList_New() must not be called after _PyList_Fini()
-assert(state->numfree != -1);
-#endif
-if (PyList_MAXFREELIST && state->numfree) {
+if (PyList_MAXFREELIST && state->numfree > 0) {
 state->numfree--;
 op = state->free_list[state->numfree];
 OBJECT_STAT_INC(from_freelist);
@@ -360,13 +356,9 @@ list_dealloc(PyObject *self)
 }
 PyMem_Free(op->ob_item);
 }
-#if PyList_MAXFREELIST > 0
+#ifdef WITH_FREELISTS
 struct _Py_list_state *state = get_list_state();
-#ifdef Py_DEBUG
-// list_dealloc() must not be called after _PyList_Fini()
-assert(state->numfree != -1);
-#endif
-if (state->numfree < PyList_MAXFREELIST && PyList_CheckExact(op)) {
+if (state->numfree < PyList_MAXFREELIST && state->numfree >= 0 && 
PyList_CheckExact(op)) {
 state->free_list[state->numfree++] = op;
 OBJECT_STAT_INC(to_freelist);
 }

___
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]


[Python-checkins] [3.12] Improve kde graph with better caption and number formatting (gh-113967) (gh-113968)

2024-01-11 Thread rhettinger
https://github.com/python/cpython/commit/d50d074cd981b2ca6d3266865957de092e913a88
commit: d50d074cd981b2ca6d3266865957de092e913a88
branch: 3.12
author: Miss Islington (bot) <[email protected]>
committer: rhettinger 
date: 2024-01-11T18:49:10-06:00
summary:

[3.12] Improve kde graph with better caption and number formatting (gh-113967) 
(gh-113968)

files:
M Doc/library/kde_example.png

diff --git a/Doc/library/kde_example.png b/Doc/library/kde_example.png
index f4504895699974..4c26f26292faa5 100644
Binary files a/Doc/library/kde_example.png and b/Doc/library/kde_example.png 
differ

___
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]


[Python-checkins] gh-113903: Fix an IDLE configdialog test (#113973)

2024-01-11 Thread terryjreedy
https://github.com/python/cpython/commit/c4992f4106aa509375f5beca8dc044a7f6c36a72
commit: c4992f4106aa509375f5beca8dc044a7f6c36a72
branch: main
author: Terry Jan Reedy 
committer: terryjreedy 
date: 2024-01-11T22:10:00-05:00
summary:

gh-113903: Fix an IDLE configdialog test (#113973)

test_configdialog.HighPageTest.test_highlight_target_text_mouse fails
if a line of the Highlight tab text sample is not visible. If so, bbox()
in click_char() returns None and the unpacking iteration fails.

This occurred on a Devuan Linux system. Fix by moving the
'see character' call inside click_char, just before the bbox call.

Also, reduce the click_char calls to just one per tag name and
replace the other nested function with a dict comprehension.

files:
A Misc/NEWS.d/next/IDLE/2024-01-11-21-26-58.gh-issue-113903.__GLlQ.rst
M Lib/idlelib/News3.txt
M Lib/idlelib/idle_test/test_configdialog.py

diff --git a/Lib/idlelib/News3.txt b/Lib/idlelib/News3.txt
index 84484571a49cf7..f6ddbca0e64b06 100644
--- a/Lib/idlelib/News3.txt
+++ b/Lib/idlelib/News3.txt
@@ -4,6 +4,8 @@ Released on 2024-10-xx
 =
 
 
+gh-113903: Fix rare failure of test.test_idle, in test_configdialog.
+
 gh-113729: Fix the "Help -> IDLE Doc" menu bug in 3.11.7 and 3.12.1.
 
 gh-57795: Enter selected text into the Find box when opening
diff --git a/Lib/idlelib/idle_test/test_configdialog.py 
b/Lib/idlelib/idle_test/test_configdialog.py
index 6f8518a9bb19d0..5099d093382445 100644
--- a/Lib/idlelib/idle_test/test_configdialog.py
+++ b/Lib/idlelib/idle_test/test_configdialog.py
@@ -420,20 +420,14 @@ def test_highlight_target_text_mouse(self):
 # Set highlight_target through clicking highlight_sample.
 eq = self.assertEqual
 d = self.page
-
-elem = {}
-count = 0
 hs = d.highlight_sample
 hs.focus_force()
-hs.see(1.0)
-hs.update_idletasks()
 
-def tag_to_element(elem):
-for element, tag in d.theme_elements.items():
-elem[tag] = element
-
-def click_it(start):
-x, y, dx, dy = hs.bbox(start)
+def click_char(index):
+"Simulate click on character at *index*."
+hs.see(index)
+hs.update_idletasks()
+x, y, dx, dy = hs.bbox(index)
 x += dx // 2
 y += dy // 2
 hs.event_generate('', x=0, y=0)
@@ -441,17 +435,20 @@ def click_it(start):
 hs.event_generate('', x=x, y=y)
 hs.event_generate('', x=x, y=y)
 
-# Flip theme_elements to make the tag the key.
-tag_to_element(elem)
+# Reverse theme_elements to make the tag the key.
+elem = {tag: element for element, tag in d.theme_elements.items()}
 
 # If highlight_sample has a tag that isn't in theme_elements, there
 # will be a KeyError in the test run.
+count = 0
 for tag in hs.tag_names():
-for start_index in hs.tag_ranges(tag)[0::2]:
-count += 1
-click_it(start_index)
+try:
+click_char(hs.tag_nextrange(tag, "1.0")[0])
 eq(d.highlight_target.get(), elem[tag])
+count += 1
 eq(d.set_highlight_target.called, count)
+except IndexError:
+pass  # Skip unused theme_elements tag, like 'sel'.
 
 def test_highlight_sample_double_click(self):
 # Test double click on highlight_sample.
diff --git 
a/Misc/NEWS.d/next/IDLE/2024-01-11-21-26-58.gh-issue-113903.__GLlQ.rst 
b/Misc/NEWS.d/next/IDLE/2024-01-11-21-26-58.gh-issue-113903.__GLlQ.rst
new file mode 100644
index 00..b60c5ac1dd4cd0
--- /dev/null
+++ b/Misc/NEWS.d/next/IDLE/2024-01-11-21-26-58.gh-issue-113903.__GLlQ.rst
@@ -0,0 +1 @@
+Fix rare failure of test.test_idle, in test_configdialog.

___
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]


[Python-checkins] [3.11] gh-113903: Fix an IDLE configdialog test (GH-113973) (#113975)

2024-01-11 Thread terryjreedy
https://github.com/python/cpython/commit/96eff8c1502298194802029f8d129ba0db1eec63
commit: 96eff8c1502298194802029f8d129ba0db1eec63
branch: 3.11
author: Miss Islington (bot) <[email protected]>
committer: terryjreedy 
date: 2024-01-12T03:23:52Z
summary:

[3.11] gh-113903: Fix an IDLE configdialog test (GH-113973) (#113975)

test_configdialog.HighPageTest.test_highlight_target_text_mouse fails
if a line of the Highlight tab text sample is not visible. If so, bbox()
in click_char() returns None and the unpacking iteration fails.

This occurred on a Devuan Linux system. Fix by moving the
'see character' call inside click_char, just before the bbox call.

Also, reduce the click_char calls to just one per tag name and
replace the other nested function with a dict comprehension.
(cherry picked from commit c4992f4106aa509375f5beca8dc044a7f6c36a72)

Co-authored-by: Terry Jan Reedy 

files:
A Misc/NEWS.d/next/IDLE/2024-01-11-21-26-58.gh-issue-113903.__GLlQ.rst
M Lib/idlelib/News3.txt
M Lib/idlelib/idle_test/test_configdialog.py

diff --git a/Lib/idlelib/News3.txt b/Lib/idlelib/News3.txt
index d79be372004e3a..04135e315098b1 100644
--- a/Lib/idlelib/News3.txt
+++ b/Lib/idlelib/News3.txt
@@ -4,6 +4,8 @@ Released after 2022-10-24
 =
 
 
+gh-113903: Fix rare failure of test.test_idle, in test_configdialog.
+
 gh-113729: Fix the "Help -> IDLE Doc" menu bug in 3.11.7 and 3.12.1.
 
 gh-57795: Enter selected text into the Find box when opening
diff --git a/Lib/idlelib/idle_test/test_configdialog.py 
b/Lib/idlelib/idle_test/test_configdialog.py
index 6f8518a9bb19d0..5099d093382445 100644
--- a/Lib/idlelib/idle_test/test_configdialog.py
+++ b/Lib/idlelib/idle_test/test_configdialog.py
@@ -420,20 +420,14 @@ def test_highlight_target_text_mouse(self):
 # Set highlight_target through clicking highlight_sample.
 eq = self.assertEqual
 d = self.page
-
-elem = {}
-count = 0
 hs = d.highlight_sample
 hs.focus_force()
-hs.see(1.0)
-hs.update_idletasks()
 
-def tag_to_element(elem):
-for element, tag in d.theme_elements.items():
-elem[tag] = element
-
-def click_it(start):
-x, y, dx, dy = hs.bbox(start)
+def click_char(index):
+"Simulate click on character at *index*."
+hs.see(index)
+hs.update_idletasks()
+x, y, dx, dy = hs.bbox(index)
 x += dx // 2
 y += dy // 2
 hs.event_generate('', x=0, y=0)
@@ -441,17 +435,20 @@ def click_it(start):
 hs.event_generate('', x=x, y=y)
 hs.event_generate('', x=x, y=y)
 
-# Flip theme_elements to make the tag the key.
-tag_to_element(elem)
+# Reverse theme_elements to make the tag the key.
+elem = {tag: element for element, tag in d.theme_elements.items()}
 
 # If highlight_sample has a tag that isn't in theme_elements, there
 # will be a KeyError in the test run.
+count = 0
 for tag in hs.tag_names():
-for start_index in hs.tag_ranges(tag)[0::2]:
-count += 1
-click_it(start_index)
+try:
+click_char(hs.tag_nextrange(tag, "1.0")[0])
 eq(d.highlight_target.get(), elem[tag])
+count += 1
 eq(d.set_highlight_target.called, count)
+except IndexError:
+pass  # Skip unused theme_elements tag, like 'sel'.
 
 def test_highlight_sample_double_click(self):
 # Test double click on highlight_sample.
diff --git 
a/Misc/NEWS.d/next/IDLE/2024-01-11-21-26-58.gh-issue-113903.__GLlQ.rst 
b/Misc/NEWS.d/next/IDLE/2024-01-11-21-26-58.gh-issue-113903.__GLlQ.rst
new file mode 100644
index 00..b60c5ac1dd4cd0
--- /dev/null
+++ b/Misc/NEWS.d/next/IDLE/2024-01-11-21-26-58.gh-issue-113903.__GLlQ.rst
@@ -0,0 +1 @@
+Fix rare failure of test.test_idle, in test_configdialog.

___
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]


[Python-checkins] [3.12] gh-113903: Fix an IDLE configdialog test (GH-113973) (#113974)

2024-01-11 Thread terryjreedy
https://github.com/python/cpython/commit/d63e4c49d3d1080ff53338fea3b37220161d1891
commit: d63e4c49d3d1080ff53338fea3b37220161d1891
branch: 3.12
author: Miss Islington (bot) <[email protected]>
committer: terryjreedy 
date: 2024-01-12T03:39:45Z
summary:

[3.12] gh-113903: Fix an IDLE configdialog test (GH-113973) (#113974)

test_configdialog.HighPageTest.test_highlight_target_text_mouse fails
if a line of the Highlight tab text sample is not visible. If so, bbox()
in click_char() returns None and the unpacking iteration fails.

This occurred on a Devuan Linux system. Fix by moving the
'see character' call inside click_char, just before the bbox call.

Also, reduce the click_char calls to just one per tag name and
replace the other nested function with a dict comprehension.
(cherry picked from commit c4992f4106aa509375f5beca8dc044a7f6c36a72)

Co-authored-by: Terry Jan Reedy 

files:
A Misc/NEWS.d/next/IDLE/2024-01-11-21-26-58.gh-issue-113903.__GLlQ.rst
M Lib/idlelib/News3.txt
M Lib/idlelib/idle_test/test_configdialog.py

diff --git a/Lib/idlelib/News3.txt b/Lib/idlelib/News3.txt
index dd2a30d4a3bff5..6cd052a9e0c62e 100644
--- a/Lib/idlelib/News3.txt
+++ b/Lib/idlelib/News3.txt
@@ -4,6 +4,8 @@ Released after 2023-10-02
 =
 
 
+gh-113903: Fix rare failure of test.test_idle, in test_configdialog.
+
 gh-113729: Fix the "Help -> IDLE Doc" menu bug in 3.11.7 and 3.12.1.
 
 gh-57795: Enter selected text into the Find box when opening
diff --git a/Lib/idlelib/idle_test/test_configdialog.py 
b/Lib/idlelib/idle_test/test_configdialog.py
index 6f8518a9bb19d0..5099d093382445 100644
--- a/Lib/idlelib/idle_test/test_configdialog.py
+++ b/Lib/idlelib/idle_test/test_configdialog.py
@@ -420,20 +420,14 @@ def test_highlight_target_text_mouse(self):
 # Set highlight_target through clicking highlight_sample.
 eq = self.assertEqual
 d = self.page
-
-elem = {}
-count = 0
 hs = d.highlight_sample
 hs.focus_force()
-hs.see(1.0)
-hs.update_idletasks()
 
-def tag_to_element(elem):
-for element, tag in d.theme_elements.items():
-elem[tag] = element
-
-def click_it(start):
-x, y, dx, dy = hs.bbox(start)
+def click_char(index):
+"Simulate click on character at *index*."
+hs.see(index)
+hs.update_idletasks()
+x, y, dx, dy = hs.bbox(index)
 x += dx // 2
 y += dy // 2
 hs.event_generate('', x=0, y=0)
@@ -441,17 +435,20 @@ def click_it(start):
 hs.event_generate('', x=x, y=y)
 hs.event_generate('', x=x, y=y)
 
-# Flip theme_elements to make the tag the key.
-tag_to_element(elem)
+# Reverse theme_elements to make the tag the key.
+elem = {tag: element for element, tag in d.theme_elements.items()}
 
 # If highlight_sample has a tag that isn't in theme_elements, there
 # will be a KeyError in the test run.
+count = 0
 for tag in hs.tag_names():
-for start_index in hs.tag_ranges(tag)[0::2]:
-count += 1
-click_it(start_index)
+try:
+click_char(hs.tag_nextrange(tag, "1.0")[0])
 eq(d.highlight_target.get(), elem[tag])
+count += 1
 eq(d.set_highlight_target.called, count)
+except IndexError:
+pass  # Skip unused theme_elements tag, like 'sel'.
 
 def test_highlight_sample_double_click(self):
 # Test double click on highlight_sample.
diff --git 
a/Misc/NEWS.d/next/IDLE/2024-01-11-21-26-58.gh-issue-113903.__GLlQ.rst 
b/Misc/NEWS.d/next/IDLE/2024-01-11-21-26-58.gh-issue-113903.__GLlQ.rst
new file mode 100644
index 00..b60c5ac1dd4cd0
--- /dev/null
+++ b/Misc/NEWS.d/next/IDLE/2024-01-11-21-26-58.gh-issue-113903.__GLlQ.rst
@@ -0,0 +1 @@
+Fix rare failure of test.test_idle, in test_configdialog.

___
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]


[Python-checkins] gh-113937 Fix failures in type cache tests due to re-running (GH-113953)

2024-01-11 Thread Fidget-Spinner
https://github.com/python/cpython/commit/e58334e4c9ccbebce6858da1985c1f75a6063d05
commit: e58334e4c9ccbebce6858da1985c1f75a6063d05
branch: main
author: Peter Lazorchak 
committer: Fidget-Spinner 
date: 2024-01-12T13:18:19+08:00
summary:

gh-113937 Fix failures in type cache tests due to re-running (GH-113953)

files:
M Lib/test/test_type_cache.py

diff --git a/Lib/test/test_type_cache.py b/Lib/test/test_type_cache.py
index 95b55009c7187d..295df78a17374a 100644
--- a/Lib/test/test_type_cache.py
+++ b/Lib/test/test_type_cache.py
@@ -67,7 +67,8 @@ class C:
 
 type_assign_version(C)
 orig_version = type_get_version(C)
-self.assertNotEqual(orig_version, 0)
+if orig_version == 0:
+self.skipTest("Could not assign a valid type version")
 
 type_modified(C)
 type_assign_specific_version_unsafe(C, orig_version + 5)
@@ -84,10 +85,11 @@ class TypeCacheWithSpecializationTests(unittest.TestCase):
 def tearDown(self):
 _clear_type_cache()
 
-def _assign_and_check_valid_version(self, user_type):
-type_modified(user_type)
-type_assign_version(user_type)
-self.assertNotEqual(type_get_version(user_type), 0)
+def _assign_valid_version_or_skip(self, type_):
+type_modified(type_)
+type_assign_version(type_)
+if type_get_version(type_) == 0:
+self.skipTest("Could not assign valid type version")
 
 def _assign_and_check_version_0(self, user_type):
 type_modified(user_type)
@@ -98,8 +100,6 @@ def _all_opnames(self, func):
 return set(instr.opname for instr in dis.Bytecode(func, adaptive=True))
 
 def _check_specialization(self, func, arg, opname, *, should_specialize):
-self.assertIn(opname, self._all_opnames(func))
-
 for _ in range(100):
 func(arg)
 
@@ -113,7 +113,7 @@ class A:
 def foo(self):
 pass
 
-self._assign_and_check_valid_version(A)
+self._assign_valid_version_or_skip(A)
 
 def load_foo_1(type_):
 type_.foo
@@ -129,8 +129,8 @@ def load_foo_2(type_):
 self._check_specialization(load_foo_2, A, "LOAD_ATTR", 
should_specialize=False)
 
 def test_class_load_attr_specialization_static_type(self):
-self._assign_and_check_valid_version(str)
-self._assign_and_check_valid_version(bytes)
+self._assign_valid_version_or_skip(str)
+self._assign_valid_version_or_skip(bytes)
 
 def get_capitalize_1(type_):
 return type_.capitalize
@@ -164,7 +164,7 @@ class G:
 def x(self):
 return 9
 
-self._assign_and_check_valid_version(G)
+self._assign_valid_version_or_skip(G)
 
 def load_x_1(instance):
 instance.x
@@ -183,7 +183,7 @@ def test_store_attr_specialization_user_type(self):
 class B:
 __slots__ = ("bar",)
 
-self._assign_and_check_valid_version(B)
+self._assign_valid_version_or_skip(B)
 
 def store_bar_1(type_):
 type_.bar = 10
@@ -203,7 +203,7 @@ class F:
 def __init__(self):
 pass
 
-self._assign_and_check_valid_version(F)
+self._assign_valid_version_or_skip(F)
 
 def call_class_1(type_):
 type_()
@@ -222,7 +222,7 @@ def test_to_bool_specialization_user_type(self):
 class H:
 pass
 
-self._assign_and_check_valid_version(H)
+self._assign_valid_version_or_skip(H)
 
 def to_bool_1(instance):
 not instance

___
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]