Skip to content

Commit 9b4d273

Browse files
committed
Merge remote-tracking branch 'upstream/main' into pythongh-111968-tuple
2 parents 9fc2dd6 + c65ae26 commit 9b4d273

File tree

16 files changed

+148
-24
lines changed

16 files changed

+148
-24
lines changed

Doc/howto/descriptor.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1250,7 +1250,7 @@ instance::
12501250
<function D.f at 0x00C45070>
12511251

12521252
>>> d.f.__self__
1253-
<__main__.D object at 0x1012e1f98>
1253+
<__main__.D object at 0x00B18C90>
12541254

12551255
If you have ever wondered where *self* comes from in regular methods or where
12561256
*cls* comes from in class methods, this is it!

Doc/library/msvcrt.rst

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,14 @@ File Operations
7575
.. function:: open_osfhandle(handle, flags)
7676

7777
Create a C runtime file descriptor from the file handle *handle*. The *flags*
78-
parameter should be a bitwise OR of :const:`os.O_APPEND`, :const:`os.O_RDONLY`,
79-
and :const:`os.O_TEXT`. The returned file descriptor may be used as a parameter
78+
parameter should be a bitwise OR of :const:`os.O_APPEND`,
79+
:const:`os.O_RDONLY`, :const:`os.O_TEXT` and :const:`os.O_NOINHERIT`.
80+
The returned file descriptor may be used as a parameter
8081
to :func:`os.fdopen` to create a file object.
8182

83+
The file descriptor is inheritable by default. Pass :const:`os.O_NOINHERIT`
84+
flag to make it non inheritable.
85+
8286
.. audit-event:: msvcrt.open_osfhandle handle,flags msvcrt.open_osfhandle
8387

8488

Include/internal/pycore_freelist.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ struct _Py_float_state {
6161

6262
typedef struct _Py_freelist_state {
6363
struct _Py_float_state float_state;
64-
struct _Py_list_state list;
6564
struct _Py_tuple_state tuple_state;
65+
struct _Py_list_state list_state;
6666
} _PyFreeListState;
6767

6868
#ifdef __cplusplus

Include/internal/pycore_gc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ static inline void _PyGC_SET_FINALIZED(PyObject *op) {
122122
PyGC_Head *gc = _Py_AS_GC(op);
123123
_PyGCHead_SET_FINALIZED(gc);
124124
}
125+
static inline void _PyGC_CLEAR_FINALIZED(PyObject *op) {
126+
PyGC_Head *gc = _Py_AS_GC(op);
127+
gc->_gc_prev &= ~_PyGC_PREV_MASK_FINALIZED;
128+
}
125129

126130

127131
/* GC runtime state */

Lib/test/test_asyncgen.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1701,6 +1701,14 @@ def test_asend(self):
17011701
async def gen():
17021702
yield 1
17031703

1704+
# gh-113753: asend objects allocated from a free-list should warn.
1705+
# Ensure there is a finalized 'asend' object ready to be reused.
1706+
try:
1707+
g = gen()
1708+
g.asend(None).send(None)
1709+
except StopIteration:
1710+
pass
1711+
17041712
msg = f"coroutine method 'asend' of '{gen.__qualname__}' was never awaited"
17051713
with self.assertWarnsRegex(RuntimeWarning, msg):
17061714
g = gen()

Lib/test/test_builtin.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -629,8 +629,8 @@ def __dir__(self):
629629

630630
def test___ne__(self):
631631
self.assertFalse(None.__ne__(None))
632-
self.assertTrue(None.__ne__(0))
633-
self.assertTrue(None.__ne__("abc"))
632+
self.assertIs(None.__ne__(0), NotImplemented)
633+
self.assertIs(None.__ne__("abc"), NotImplemented)
634634

635635
def test_divmod(self):
636636
self.assertEqual(divmod(12, 7), (1, 5))

Lib/test/test_os.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4485,6 +4485,61 @@ def test_openpty(self):
44854485
self.assertEqual(os.get_inheritable(master_fd), False)
44864486
self.assertEqual(os.get_inheritable(slave_fd), False)
44874487

4488+
@unittest.skipUnless(hasattr(os, 'spawnl'), "need os.openpty()")
4489+
def test_pipe_spawnl(self):
4490+
# gh-77046: On Windows, os.pipe() file descriptors must be created with
4491+
# _O_NOINHERIT to make them non-inheritable. UCRT has no public API to
4492+
# get (_osfile(fd) & _O_NOINHERIT), so use a functional test.
4493+
#
4494+
# Make sure that fd is not inherited by a child process created by
4495+
# os.spawnl(): get_osfhandle() and dup() must fail with EBADF.
4496+
4497+
fd, fd2 = os.pipe()
4498+
self.addCleanup(os.close, fd)
4499+
self.addCleanup(os.close, fd2)
4500+
4501+
code = textwrap.dedent(f"""
4502+
import errno
4503+
import os
4504+
import test.support
4505+
try:
4506+
import msvcrt
4507+
except ImportError:
4508+
msvcrt = None
4509+
4510+
fd = {fd}
4511+
4512+
with test.support.SuppressCrashReport():
4513+
if msvcrt is not None:
4514+
try:
4515+
handle = msvcrt.get_osfhandle(fd)
4516+
except OSError as exc:
4517+
if exc.errno != errno.EBADF:
4518+
raise
4519+
# get_osfhandle(fd) failed with EBADF as expected
4520+
else:
4521+
raise Exception("get_osfhandle() must fail")
4522+
4523+
try:
4524+
fd3 = os.dup(fd)
4525+
except OSError as exc:
4526+
if exc.errno != errno.EBADF:
4527+
raise
4528+
# os.dup(fd) failed with EBADF as expected
4529+
else:
4530+
os.close(fd3)
4531+
raise Exception("dup must fail")
4532+
""")
4533+
4534+
filename = os_helper.TESTFN
4535+
self.addCleanup(os_helper.unlink, os_helper.TESTFN)
4536+
with open(filename, "w") as fp:
4537+
print(code, file=fp, end="")
4538+
4539+
cmd = [sys.executable, filename]
4540+
exitcode = os.spawnl(os.P_WAIT, cmd[0], *cmd)
4541+
self.assertEqual(exitcode, 0)
4542+
44884543

44894544
class PathTConverterTests(unittest.TestCase):
44904545
# tuples of (function name, allows fd arguments, additional arguments to

Lib/test/test_subprocess.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -835,16 +835,25 @@ def is_env_var_to_ignore(n):
835835
if not is_env_var_to_ignore(k)]
836836
self.assertEqual(child_env_names, [])
837837

838+
@unittest.skipIf(sysconfig.get_config_var('Py_ENABLE_SHARED') == 1,
839+
'The Python shared library cannot be loaded '
840+
'without some system environments.')
841+
@unittest.skipIf(check_sanitizer(address=True),
842+
'AddressSanitizer adds to the environment.')
838843
def test_one_environment_variable(self):
839844
newenv = {'fruit': 'orange'}
840845
cmd = [sys.executable, '-c',
841846
'import sys,os;'
842847
'sys.stdout.write("fruit="+os.getenv("fruit"))']
843848
if sys.platform == "win32":
844849
cmd = ["CMD", "/c", "SET", "fruit"]
845-
with subprocess.Popen(cmd, stdout=subprocess.PIPE, env=newenv) as p:
846-
stdout, _ = p.communicate()
847-
self.assertTrue(stdout.startswith(b"fruit=orange"))
850+
with subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=newenv) as p:
851+
stdout, stderr = p.communicate()
852+
if p.returncode and support.verbose:
853+
print("STDOUT:", stdout.decode("ascii", "replace"))
854+
print("STDERR:", stderr.decode("ascii", "replace"))
855+
self.assertEqual(p.returncode, 0)
856+
self.assertEqual(stdout.strip(), b"fruit=orange")
848857

849858
def test_invalid_cmd(self):
850859
# null character in the command name

Lib/test/test_zipfile/test_core.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2272,6 +2272,7 @@ def test_decompress_without_3rd_party_library(self):
22722272
with zipfile.ZipFile(zip_file) as zf:
22732273
self.assertRaises(RuntimeError, zf.extract, 'a.txt')
22742274

2275+
@requires_zlib()
22752276
def test_full_overlap(self):
22762277
data = (
22772278
b'PK\x03\x04\x14\x00\x00\x00\x08\x00\xa0lH\x05\xe2\x1e'
@@ -2300,6 +2301,7 @@ def test_full_overlap(self):
23002301
with self.assertRaisesRegex(zipfile.BadZipFile, 'File name.*differ'):
23012302
zipf.read('b')
23022303

2304+
@requires_zlib()
23032305
def test_quoted_overlap(self):
23042306
data = (
23052307
b'PK\x03\x04\x14\x00\x00\x00\x08\x00\xa0lH\x05Y\xfc'
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix an issue where the finalizer of ``PyAsyncGenASend`` objects might not be
2+
called if they were allocated from a free list.

0 commit comments

Comments
 (0)