8000 Merge branch 'main' into fetch-restore-objects · python/cpython@3f8b452 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3f8b452

Browse files
authored
Merge branch 'main' into fetch-restore-objects
2 parents 0863f35 + ed55c69 commit 3f8b452

File tree

10 files changed

+166
-76
lines changed

10 files changed

+166
-76
lines changed

Doc/library/itertools.rst

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -886,9 +886,12 @@ which incur interpreter overhead.
886886
except AttributeError:
887887
# Slow path for general iterables
888888
it = islice(iterable, start, None)
889-
for i, element in enumerate(it, start):
890-
if element is value or element == value:
891-
yield i
889+
i = start - 1
890+
try:
891+
while True:
892+
yield (i := i + operator.indexOf(it, value) + 1)
893+
except ValueError:
894+
pass
892895
else:
893896
# Fast path for sequences
894897
i = start - 1

Doc/library/test.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,13 @@ The :mod:`test.support` module defines the following functions:
536536
:func:`doctest.testmod`.
537537

538538

539+
.. function:: get_pagesize()
540+
541+
Get size of a page in bytes.
542+
543+
.. versionadded:: 3.12
544+
545+
539546
.. function:: setswitchinterval(interval)
540547

541548
Set the :func:`sys.setswitchinterval` to the given *interval*. Defines

Lib/test/memory_watchdog.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,13 @@
55
# If the process crashes, reading from the /proc entry will fail with ESRCH.
66

77

8-
import os
98
import sys
109
import time
10+
from test.support import get_pagesize
1111

1212

13-
try:
14-
page_size = os.sysconf('SC_PAGESIZE')
15-
except (ValueError, AttributeError):
16-
try:
17-
page_size = os.sysconf('SC_PAGE_SIZE')
18-
except (ValueError, AttributeError):
19-
page_size = 4096
20-
2113
while True:
14+
page_size = get_pagesize()
2215
sys.stdin.seek(0)
2316
statm = sys.stdin.read()
2417
data = int(statm.split()[5])

Lib/test/support/__init__.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151
# sys
5252
"is_jython", "is_android", "is_emscripten", "is_wasi",
5353
"check_impl_detail", "unix_shell", "setswitchinterval",
54+
# os
55+
"get_pagesize",
5456
# network
5557
"open_urlresource",
5658
# processes
@@ -1893,6 +1895,18 @@ def setswitchinterval(interval):
18931895
return sys.setswitchinterval(interval)
18941896

18951897

1898+
def get_pagesize():
1899+
"""Get size of a page in bytes."""
1900+
try:
1901+
page_size = os.sysconf('SC_PAGESIZE')
1902+
except (ValueError, AttributeError):
1903+
try:
1904+
page_size = os.sysconf('SC_PAGE_SIZE')
1905+
except (ValueError, AttributeError):
1906+
page_size = 4096
1907+
return page_size
1908+
1909+
18961910
@contextlib.contextmanager
18971911
def disable_faulthandler():
18981912
import faulthandler

Lib/test/test_fcntl.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import struct
77
import sys
88
import unittest
9-
from test.support import verbose, cpython_only
9+
from test.support import verbose, cpython_only, get_pagesize
1010
from test.support.import_helper import import_module
1111
from test.support.os_helper import TESTFN, unlink
1212

@@ -201,7 +201,8 @@ def test_fcntl_f_pipesize(self):
201201
# Get the default pipesize with F_GETPIPE_SZ
202202
pipesize_default = fcntl.fcntl(test_pipe_w, fcntl.F_GETPIPE_SZ)
203203
pipesize = pipesize_default // 2 # A new value to detect change.
204-
if pipesize < 512: # the POSIX minimum
204+
pagesize_default = get_pagesize()
205+
if pipesize < pagesize_default: # the POSIX minimum
205206
raise unittest.SkipTest(
206207
'default pipesize too small to perform test.')
207208
fcntl.fcntl(test_pipe_w, fcntl.F_SETPIPE_SZ, pipesize)

Lib/test/test_operator.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,9 @@ def test_indexOf(self):
208208
nan = float("nan")
209209
self.assertEqual(operator.indexOf([nan, nan, 21], nan), 0)
210210
self.assertEqual(operator.indexOf([{}, 1, {}, 2], {}), 0)
211+
it = iter('leave the iterator at exactly the position after the match')
212+
self.assertEqual(operator.indexOf(it, 'a'), 2)
213+
self.assertEqual(next(it), 'v')
211214

212215
def test_invert(self):
213216
operator = self.module

Lib/test/test_subprocess.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,8 @@ def test_pipesizes(self):
717717
os.close(test_pipe_r)
718718
os.close(test_pipe_w)
719719
pipesize = pipesize_default // 2
720-
if pipesize < 512: # the POSIX minimum
720+
pagesize_default = support.get_pagesize()
721+
if pipesize < pagesize_default: # the POSIX minimum
721722
raise unittest.SkipTest(
722723
'default pipesize too small to perform test.')
723724
p = subprocess.Popen(
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Implement ``winreg.QueryValue`` using ``QueryValueEx`` and
2+
``winreg.SetValue`` using ``SetValueEx``. Patch by Max Bachmann.

Modules/_testcapi/code.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,11 @@ test_code_extra(PyObject* self, PyObject *Py_UNUSED(callable))
9292
goto finally;
9393
}
9494
assert ((uintptr_t)extra == 77);
95-
95+
// Revert to initial code extra value.
96+
res = PyUnstable_Code_SetExtra(test_func_code, code_extra_index, NULL);
97+
if (res < 0) {
98+
goto finally;
99+
}
96100
result = Py_NewRef(Py_None);
97101
finally:
98102
Py_XDECREF(test_module);

PC/winreg.c

Lines changed: 122 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,7 @@ Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize)
561561
{
562562
Py_ssize_t i,j;
563563
switch (typ) {
564-
case REG_DWORD:
564+
case REG_DWORD:
565565
{
566566
if (value != Py_None && !PyLong_Check(value)) {
567567
return FALSE;
@@ -585,7 +585,7 @@ Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize)
585585
*retDataSize = sizeof(DWORD);
586586
break;
587587
}
588-
case REG_QWORD:
588+
case REG_QWORD:
589589
{
590590
if (value != Py_None && !PyLong_Check(value)) {
591591
return FALSE;
@@ -1488,53 +1488,77 @@ static PyObject *
14881488
winreg_QueryValue_impl(PyObject *module, HKEY key, const Py_UNICODE *sub_key)
14891489
/*[clinic end generated code: output=c655810ae50c63a9 input=41cafbbf423b21d6]*/
14901490
{
1491-
long rc;
1492-
PyObject *retStr;
1493-
wchar_t *retBuf;
1494-
DWORD bufSize = 0;
1495-
DWORD retSize = 0;
1496-
wchar_t *tmp;
1491+
LONG rc;
1492+
HKEY childKey = key;
1493+
WCHAR buf[256], *pbuf = buf;
1494+
DWORD size = sizeof(buf);
1495+
DWORD type;
1496+
Py_ssize_t length;
1497+
PyObject *result = NULL;
14971498

14981499
if (PySys_Audit("winreg.QueryValue", "nuu",
1499-
(Py_ssize_t)key, sub_key, NULL) < 0) {
1500+
(Py_ssize_t)key, sub_key, NULL) < 0)
1501+
{
15001502
return NULL;
15011503
}
1502-
rc = RegQueryValueW(key, sub_key, NULL, &retSize);
1503-
if (rc == ERROR_MORE_DATA)
1504-
retSize = 256;
1505-
else if (rc != ERROR_SUCCESS)
1506-
return PyErr_SetFromWindowsErrWithFunction(rc,
1504+
1505+
if (key == HKEY_PERFORMANCE_DATA) {
1506+
return PyErr_SetFromWindowsErrWithFunction(ERROR_INVALID_HANDLE,
15071507
"RegQueryValue");
1508+
}
15081509

1509-
bufSize = retSize;
1510-
retBuf = (wchar_t *) PyMem_Malloc(bufSize);
1511-
if (retBuf == NULL)
1512-
return PyErr_NoMemory();
1510+
if (sub_key && sub_key[0]) {
1511+
Py_BEGIN_ALLOW_THREADS
1512+
rc = RegOpenKeyExW(key, sub_key, 0, KEY_QUERY_VALUE, &childKey);
1513+
Py_END_ALLOW_THREADS
1514+
if (rc != ERROR_SUCCESS) {
1515+
return PyErr_SetFromWindowsErrWithFunction(rc, "RegOpenKeyEx");
1516+
}
1517+
}
15131518

15141519
while (1) {
1515-
retSize = bufSize;
1516-
rc = RegQueryValueW(key, sub_key, retBuf, &retSize);
1517-
if (rc != ERROR_MORE_DATA)
1520+
Py_BEGIN_ALLOW_THREADS
1521+
rc = RegQueryValueExW(childKey, NULL, NULL, &type, (LPBYTE)pbuf,
1522+
&size);
1523+
Py_END_ALLOW_THREADS
1524+
if (rc != ERROR_MORE_DATA) {
15181525
break;
1519-
1520-
bufSize *= 2;
1521-
tmp = (wchar_t *) PyMem_Realloc(retBuf, bufSize);
1526+
}
1527+
void *tmp = PyMem_Realloc(pbuf != buf ? pbuf : NULL, size);
15221528
if (tmp == NULL) {
1523-
PyMem_Free(retBuf);
1524-
return PyErr_NoMemory();
1529+
PyErr_NoMemory();
1530+
goto exit;
15251531
}
1526-
retBuf = tmp;
1532+
pbuf = tmp;
15271533
}
15281534

1529-
if (rc != ERROR_SUCCESS) {
1530-
PyMem_Free(retBuf);
1531-
return PyErr_SetFromWindowsErrWithFunction(rc,
1532-
"RegQueryValue");
1535+
if (rc == ERROR_SUCCESS) {
1536+
if (type != REG_SZ) {
1537+
PyErr_SetFromWindowsErrWithFunction(ERROR_INVALID_DATA,
1538+
"RegQueryValue");
1539+
goto exit;
1540+
}
1541+
length = wcsnlen(pbuf, size / sizeof(WCHAR));
1542+
}
1543+
else if (rc == ERROR_FILE_NOT_FOUND) {
1544+
// Return an empty string if there's no default value.
1545+
length = 0;
1546+
}
1547+
else {
1548+
PyErr_SetFromWindowsErrWithFunction(rc, "RegQueryValueEx");
1549+
goto exit;
15331550
}
15341551

1535-
retStr = PyUnicode_FromWideChar(retBuf, wcslen(retBuf));
1536-
PyMem_Free(retBuf);
1537-
return retStr;
1552+
result = PyUnicode_FromWideChar(pbuf, length);
1553+
1554+
exit:
1555+
if (pbuf != buf) {
1556+
PyMem_Free(pbuf);
1557+
}
1558+
if (childKey != key) {
1559+
RegCloseKey(childKey);
1560+
}
1561+
return result;
15381562
}
15391563

15401564

@@ -1687,38 +1711,69 @@ winreg_SetValue_impl(PyObject *module, HKEY key, const Py_UNICODE *sub_key,
16871711
DWORD type, PyObject *value_obj)
16881712
/*[clinic end generated code: output=d4773dc9c372311a input=bf088494ae2d24fd]*/
16891713
{
1690-
Py_ssize_t value_length;
1691-
long rc;
1714+
LONG rc;
1715+
HKEY childKey = key;
1716+
LPWSTR value;
1717+
Py_ssize_t size;
1718+
Py_ssize_t length;
1719+
PyObject *result = NULL;
16921720

16931721
if (type != REG_SZ) {
16941722
PyErr_SetString(PyExc_TypeError, "type must be winreg.REG_SZ");
16951723
return NULL;
16961724
}
16971725

1698-
wchar_t *value = PyUnicode_AsWideCharString(value_obj, &value_length);
1726+
value = PyUnicode_AsWideCharString(value_obj, &length);
16991727
if (value == NULL) {
17001728
return NULL;
17011729
}
1702-
if ((Py_ssize_t)(DWORD)value_length != value_length) {
1730+
1731+
size = (length + 1) * sizeof(WCHAR);
1732+
if ((Py_ssize_t)(DWORD)size != size) {
17031733
PyErr_SetString(PyExc_OverflowError, "value is too long");
1704-
PyMem_Free(value);
1705-
return NULL;
1734+
goto exit;
17061735
}
17071736

17081737
if (PySys_Audit("winreg.SetValue", "nunu#",
17091738
(Py_ssize_t)key, sub_key, (Py_ssize_t)type,
1710-
value, value_length) < 0) {
1711-
PyMem_Free(value);
1712-
return NULL;
1739+
value, length) < 0)
1740+
{
1741+
goto exit;
1742+
}
1743+
1744+
if (key == HKEY_PERFORMANCE_DATA) {
1745+
PyErr_SetFromWindowsErrWithFunction(ERROR_INVALID_HANDLE,
1746+
"RegSetValue");
1747+
goto exit;
1748+
}
1749+
1750+
if (sub_key && sub_key[0]) {
1751+
Py_BEGIN_ALLOW_THREADS
1752+
rc = RegCreateKeyExW(key, sub_key, 0, NULL, 0, KEY_SET_VALUE, NULL,
1753+
&childKey, NULL);
1754+
Py_END_ALLOW_THREADS
1755+
if (rc != ERROR_SUCCESS) {
1756+
PyErr_SetFromWindowsErrWithFunction(rc, "RegCreateKeyEx");
1757+
goto exit;
1758+
}
17131759
}
17141760

17151761
Py_BEGIN_ALLOW_THREADS
1716-
rc = RegSetValueW(key, sub_key, REG_SZ, value, (DWORD)(value_length + 1));
1762+
rc = RegSetValueExW(childKey, NULL, 0, REG_SZ, (LPBYTE)value, (DWORD)size);
17171763
Py_END_ALLOW_THREADS
1764+
if (rc == ERROR_SUCCESS) {
1765+
result = Py_NewRef(Py_None);
1766+
}
1767+
else {
1768+
PyErr_SetFromWindowsErrWithFunction(rc, "RegSetValueEx");
1769+
}
1770+
1771+
exit:
17181772
PyMem_Free(value);
1719-
if (rc != ERROR_SUCCESS)
1720-
return PyErr_SetFromWindowsErrWithFunction(rc, "RegSetValue");
1721-
Py_RETURN_NONE;
1773+
if (childKey != key) {
1774+
RegCloseKey(childKey);
1775+
}
1776+
return result;
17221777
}
17231778

17241779
/*[clinic input]
@@ -1771,32 +1826,39 @@ winreg_SetValueEx_impl(PyObject *module, HKEY key,
17711826
DWORD type, PyObject *value)
17721827
/*[clinic end generated code: output=811b769a66ae11b7 input=900a9e3990bfb196]*/
17731828
{
1774-
BYTE *data;
1775-
DWORD len;
1776-
17771829
LONG rc;
1830+
BYTE *data = NULL;
1831+
DWORD size;
1832+
PyObject *result = NULL;
17781833

1779-
if (!Py2Reg(value, type, &data, &len))
1834+
if (!Py2Reg(value, type, &data, &size))
17801835
{
1781-
if (!PyErr_Occurred())
1836+
if (!PyErr_Occurred()) {
17821837
PyErr_SetString(PyExc_ValueError,
17831838
"Could not convert the data to the specified type.");
1839+
}
17841840
return NULL;
17851841
}
17861842
if (PySys_Audit("winreg.SetValue", "nunO",
17871843
(Py_ssize_t)key, value_name, (Py_ssize_t)type,
1788-
value) < 0) {
1789-
PyMem_Free(data);
1790-
return NULL;
1844+
value) < 0)
1845+
{
1846+< 48DA div class="diff-text-inner"> goto exit;
17911847
}
1848+
17921849
Py_BEGIN_ALLOW_THREADS
1793-
rc = RegSetValueExW(key, value_name, 0, type, data, len);
1850+
rc = RegSetValueExW(key, value_name, 0, type, data, size);
17941851
Py_END_ALLOW_THREADS
1852+
if (rc == ERROR_SUCCESS) {
1853+
result = Py_NewRef(Py_None);
1854+
}
1855+
else {
1856+
PyErr_SetFromWindowsErrWithFunction(rc, "RegSetValueEx");
1857+
}
1858+
1859+
exit:
17951860
PyMem_Free(data);
1796-
if (rc != ERROR_SUCCESS)
1797-
return PyErr_SetFromWindowsErrWithFunction(rc,
1798-
"RegSetValueEx");
1799-
Py_RETURN_NONE;
1861+
return result;
18001862
}
18011863

18021864
/*[clinic input]

0 commit comments

Comments
 (0)
0