Skip to content

Commit cdc31b6

Browse files
generatedunixname1734921407115435meta-codesync[bot]
authored andcommitted
Sync pre-release CPython 3.15 branch from GitHub (2026-08-05)
Summary: Imported python/cpython `3.15.0rc1+dev` from upstream rev [`f20b504`](https://www.github.com/python/cpython/commit/f20b504b17d1b35a1404b80ff3578dc9e4762660) (committed 2026-08-05 09:14:03+00:00). # Commit Info - Base: (`3.15.0rc1+dev`) - [`eea1a49`](https://www.github.com/python/cpython/commit/eea1a49f690a3c9c49a27fee9a1935c5b4ed54f2) (commit date: 2026-08-04 13:41:23+00:00) - Imported: (`3.15.0rc1+dev`) - [`f20b504`](https://www.github.com/python/cpython/commit/f20b504b17d1b35a1404b80ff3578dc9e4762660) (commit date: 2026-08-05 09:14:03+00:00) # Noteworthy file changes - Stdlib files (1 added, 1 removed) - Low-signal files (3 added) (NEWS.d, docs, .github) Complete list of added/removed files: https://www.internalfb.com/intern/everpaste/?color=0&handle=GJKLiyAz0G4CHmYFAMNOgWdxs2ofbr0LAAAz Differential Revision: D115002646 fbshipit-source-id: 308bf0a3ede2ef430c22f0a2e086a1edb6c12d42
1 parent 15acc21 commit cdc31b6

11 files changed

Lines changed: 143 additions & 27 deletions

File tree

Doc/library/os.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1448,7 +1448,7 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo
14481448
Return a pair of file descriptors ``(r, w)`` usable for reading and writing,
14491449
respectively.
14501450

1451-
.. availability:: Unix, not WASI, not macOS, not iOS.
1451+
.. availability:: Unix, macOS >= 27.0, not WASI, not iOS.
14521452

14531453
.. versionadded:: 3.3
14541454

Lib/argparse.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1968,6 +1968,9 @@ def _prog_name(prog=None):
19681968
if modspec is None:
19691969
# simple script
19701970
return _os.path.basename(arg0)
1971+
if modspec.name != '__main__' and arg0 != modspec.origin:
1972+
# named module executed as main without altering sys.argv[0]
1973+
return _os.path.basename(arg0)
19711974
py = _os.path.basename(_sys.executable)
19721975
if modspec.name != '__main__':
19731976
# imported module or package

Lib/ensurepip/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111

1212
__all__ = ["version", "bootstrap"]
13-
_PIP_VERSION = "26.2"
13+
_PIP_VERSION = "26.2.1"
1414

1515
# Directory of system wheel packages. Some Linux distribution packaging
1616
# policies recommend against bundling dependencies. For example, Fedora
1.73 MB
Binary file not shown.

Lib/test/test_argparse.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7341,6 +7341,19 @@ def test_module(self, compiled=False):
73417341
def test_module_compiled(self):
73427342
self.test_module(compiled=True)
73437343

7344+
def test_module_as_main_without_altering_argv(self):
7345+
basename = 'module' + os_helper.FS_NONASCII
7346+
modulename = f'{self.dirname}.{basename}'
7347+
self.make_script(self.dirname, basename)
7348+
runner_source = textwrap.dedent(f'''\
7349+
import runpy
7350+
runpy._run_module_as_main({modulename!r}, alter_argv=False)
7351+
''')
7352+
runner = script_helper.make_script(
7353+
self.dirname, 'runner', runner_source)
7354+
self.check_usage(os.path.basename(runner), runner,
7355+
PYTHONPATH=os.curdir)
7356+
73447357
def test_package(self, compiled=False):
73457358
basename = 'subpackage' + os_helper.FS_NONASCII
73467359
packagename = f'{self.dirname}.{basename}'

Lib/test/test_os/test_posix.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2350,6 +2350,22 @@ def test_pwritev(self):
23502350
self.assertNotHasAttr(os, "pwritev")
23512351
self.assertNotHasAttr(os, "preadv")
23522352

2353+
def test_pipe2(self):
2354+
self._verify_available("HAVE_PIPE2")
2355+
if self.mac_ver >= (27, 0):
2356+
self.assertHasAttr(os, "pipe2")
2357+
else:
2358+
self.assertNotHasAttr(os, "pipe2")
2359+
2360+
def test_dup3(self):
2361+
self._verify_available("HAVE_DUP3")
2362+
r, w = os.pipe()
2363+
self.addCleanup(os.close, r)
2364+
self.addCleanup(os.close, w)
2365+
# Must not crash even when dup3 unavailable at runtime.
2366+
# os.dup2 returns fd2 (here w); do not double-close.
2367+
os.dup2(r, w, inheritable=False)
2368+
23532369
def test_stat(self):
23542370
self._verify_available("HAVE_FSTATAT")
23552371
if self.mac_ver >= (10, 10):
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
On macOS, add run-time checks around the syscalls :manpage:`pipe2 (2)` and
2+
:manpage:`dup3 (2)`, in addition to the existing build-time checks. This
3+
means that Python built on macOS 27 (where these calls are available) can
4+
run on macOS 26 (where they aren't).
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Bump the version of pip bundled in ensurepip to version 26.2.1
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix :class:`argparse.ArgumentParser` to preserve the program name from
2+
``sys.argv[0]`` when a named module is executed as the main program without
3+
replacing ``sys.argv[0]``.

Modules/posixmodule.c

Lines changed: 98 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,8 @@ static const unsigned int _Py_STATX_KNOWN = (STATX_BASIC_STATS | STATX_BTIME
504504
# define HAVE_MKFIFOAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
505505
# define HAVE_MKNODAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
506506
# define HAVE_PTSNAME_R_RUNTIME __builtin_available(macOS 10.13.4, iOS 11.3, tvOS 11.3, watchOS 4.3, *)
507+
# define HAVE_DUP3_RUNTIME __builtin_available(macOS 27.0, *)
508+
# define HAVE_PIPE2_RUNTIME __builtin_available(macOS 27.0, *)
507509

508510
# define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
509511

@@ -589,6 +591,14 @@ static const unsigned int _Py_STATX_KNOWN = (STATX_BASIC_STATS | STATX_BTIME
589591
# define HAVE_PTSNAME_R_RUNTIME (ptsname_r != NULL)
590592
# endif
591593

594+
# ifdef HAVE_DUP3
595+
# define HAVE_DUP3_RUNTIME (dup3 != NULL)
596+
# endif
597+
598+
# ifdef HAVE_PIPE2
599+
# define HAVE_PIPE2_RUNTIME (pipe2 != NULL)
600+
# endif
601+
592602
#endif
593603

594604
#ifdef HAVE_FUTIMESAT
@@ -619,6 +629,8 @@ static const unsigned int _Py_STATX_KNOWN = (STATX_BASIC_STATS | STATX_BTIME
619629
# define HAVE_MKFIFOAT_RUNTIME 1
620630
# define HAVE_MKNODAT_RUNTIME 1
621631
# define HAVE_PTSNAME_R_RUNTIME 1
632+
# define HAVE_DUP3_RUNTIME 1
633+
# define HAVE_PIPE2_RUNTIME 1
622634
#endif
623635

624636

@@ -11833,11 +11845,16 @@ os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
1183311845
/*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
1183411846
{
1183511847
int res = 0;
11836-
#if defined(HAVE_DUP3) && \
11837-
!(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
11838-
/* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
11839-
static int dup3_works = -1;
11840-
#endif
11848+
11849+
/* dup3() is available on Linux 2.6.27+ and glibc 2.9 and macOS 27.0;
11850+
* it needs runtime detection for the case of running on older kernels.
11851+
* Values: -1: unknown; 0: doesn't work; 1: works
11852+
* For thread safety, use a process-global with one read & one store,
11853+
* both relaxed. (It's fine if two threads race and do the detection
11854+
* simultaneously; they should get the same result.)
11855+
*/
11856+
static int dup3_works_atomic = -1;
11857+
(void) dup3_works_atomic; // unused on some platforms
1184111858

1184211859
/* dup2() can fail with EINTR if the target FD is already open, because it
1184311860
* then has to be closed. See os_close_impl() for why we don't handle EINTR
@@ -11876,18 +11893,27 @@ os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
1187611893
#else
1187711894

1187811895
#ifdef HAVE_DUP3
11896+
int dup3_works = FT_ATOMIC_LOAD_INT_RELAXED(dup3_works_atomic);
1187911897
if (!inheritable && dup3_works != 0) {
11880-
Py_BEGIN_ALLOW_THREADS
11881-
res = dup3(fd, fd2, O_CLOEXEC);
11882-
Py_END_ALLOW_THREADS
11883-
if (res < 0) {
11884-
if (dup3_works == -1)
11885-
dup3_works = (errno != ENOSYS);
11886-
if (dup3_works) {
11887-
posix_error();
11888-
return -1;
11898+
if (HAVE_DUP3_RUNTIME) {
11899+
Py_BEGIN_ALLOW_THREADS
11900+
res = dup3(fd, fd2, O_CLOEXEC);
11901+
Py_END_ALLOW_THREADS
11902+
if (res < 0) {
11903+
if (dup3_works == -1) {
11904+
dup3_works = (errno != ENOSYS);
11905+
FT_ATOMIC_STORE_INT_RELAXED(dup3_works_atomic, dup3_works);
11906+
}
11907+
if (dup3_works) {
11908+
posix_error();
11909+
return -1;
11910+
}
1188911911
}
1189011912
}
11913+
else {
11914+
dup3_works = 0;
11915+
FT_ATOMIC_STORE_INT_RELAXED(dup3_works_atomic, dup3_works);
11916+
}
1189111917
}
1189211918

1189311919
if (inheritable || dup3_works == 0)
@@ -12728,7 +12754,13 @@ os_pipe_impl(PyObject *module)
1272812754
SECURITY_ATTRIBUTES attr;
1272912755
BOOL ok;
1273012756
#else
12731-
int res;
12757+
int res = -1;
12758+
12759+
/* pipe2() is available on some newer linux/glibc & macOS;
12760+
* use the same runtime detection as for dup3 above.
12761+
*/
12762+
static int pipe2_works_atomic = -1;
12763+
(void) pipe2_works_atomic; // unused on some platforms
1273212764
#endif
1273312765

1273412766
#ifdef MS_WINDOWS
@@ -12754,11 +12786,30 @@ os_pipe_impl(PyObject *module)
1275412786
#else
1275512787

1275612788
#ifdef HAVE_PIPE2
12757-
Py_BEGIN_ALLOW_THREADS
12758-
res = pipe2(fds, O_CLOEXEC);
12759-
Py_END_ALLOW_THREADS
12789+
int pipe2_works = FT_ATOMIC_LOAD_INT_RELAXED(pipe2_works_atomic);
12790+
if (pipe2_works != 0) {
12791+
if (HAVE_PIPE2_RUNTIME) {
12792+
Py_BEGIN_ALLOW_THREADS
12793+
res = pipe2(fds, O_CLOEXEC);
12794+
Py_END_ALLOW_THREADS
12795+
if (pipe2_works == -1) {
12796+
if (res != 0 && errno == ENOSYS) {
12797+
pipe2_works = 0;
12798+
}
12799+
else {
12800+
// pipe2 is present but this call failed
12801+
pipe2_works = 1;
12802+
}
12803+
FT_ATOMIC_STORE_INT_RELAXED(pipe2_works_atomic, pipe2_works);
12804+
}
12805+
}
12806+
else {
12807+
pipe2_works = 0;
12808+
FT_ATOMIC_STORE_INT_RELAXED(pipe2_works_atomic, pipe2_works);
12809+
}
12810+
}
1276012811

12761-
if (res != 0 && errno == ENOSYS)
12812+
if (pipe2_works == 0)
1276212813
{
1276312814
#endif
1276412815
Py_BEGIN_ALLOW_THREADS
@@ -12781,8 +12832,9 @@ os_pipe_impl(PyObject *module)
1278112832
}
1278212833
#endif
1278312834

12784-
if (res != 0)
12835+
if (res != 0) {
1278512836
return PyErr_SetFromErrno(PyExc_OSError);
12837+
}
1278612838
#endif /* !MS_WINDOWS */
1278712839
return Py_BuildValue("(ii)", fds[0], fds[1]);
1278812840
}
@@ -12812,9 +12864,17 @@ os_pipe2_impl(PyObject *module, int flags)
1281212864
int fds[2];
1281312865
int res;
1281412866

12815-
res = pipe2(fds, flags);
12816-
if (res != 0)
12867+
if (HAVE_PIPE2_RUNTIME) {
12868+
res = pipe2(fds, flags);
12869+
}
12870+
else {
12871+
res = -1;
12872+
errno = ENOSYS;
12873+
}
12874+
if (res != 0) {
1281712875
return posix_error();
12876+
}
12877+
1281812878
return Py_BuildValue("(ii)", fds[0], fds[1]);
1281912879
}
1282012880
#endif /* HAVE_PIPE2 */
@@ -18803,6 +18863,22 @@ posixmodule_exec(PyObject *m)
1880318863
}
1880418864
#endif
1880518865

18866+
#if HAVE_PIPE2
18867+
if (HAVE_PIPE2_RUNTIME) {
18868+
// Do nothing. (`__builtin_available` doesn't allow `!`; see
18869+
// "using negations" in a comment above.)
18870+
}
18871+
else {
18872+
PyObject* dct = PyModule_GetDict(m);
18873+
if (dct == NULL) {
18874+
return -1;
18875+
}
18876+
if (PyDict_PopString(dct, "pipe2", NULL) < 0) {
18877+
return -1;
18878+
}
18879+
}
18880+
#endif
18881+
1880618882
/* Initialize environ dictionary */
1880718883
if (PyModule_Add(m, "environ", convertenviron()) != 0) {
1880818884
return -1;

0 commit comments

Comments
 (0)