Skip to content

Commit 61746eb

Browse files
committed
Merge remote-tracking branch 'upstream/main' into ac_add_vectorcall
2 parents 04a148c + 5673748 commit 61746eb

16 files changed

Lines changed: 307 additions & 50 deletions

File tree

Doc/library/inspect.rst

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -424,24 +424,63 @@ attributes (see :ref:`import-mod-attrs` for module attributes):
424424

425425
Return ``True`` if the object is a bound method written in Python.
426426

427+
.. note::
427428

428-
.. function:: ispackage(object)
429+
For example, given this class::
429430

430-
Return ``True`` if the object is a :term:`package`.
431+
>>> class Greeter:
432+
... def say_hello(self):
433+
... print('hello!')
431434

432-
.. versionadded:: 3.14
435+
A bound method (also known as an *instance method*) is created when
436+
accessing ``say_hello`` (a :term:`function` defined in the
437+
``Greeter`` namespace) through an instance of the ``Greeter`` class::
438+
439+
>>> instance = Greeter()
440+
441+
>>> instance.say_hello
442+
<bound method Greeter.say_hello of <__main__.Greeter object ...>>
443+
>>> ismethod(instance.say_hello)
444+
True
445+
>>> isfunction(instance.say_hello)
446+
False
447+
448+
Accessing ``say_hello`` through the ``Greeter`` class will return the
449+
function itself. For this function, :func:`ismethod` will return
450+
``False``, but :func:`isfunction` will return ``True``::
451+
452+
>>> Greeter.say_hello
453+
<function Greeter.say_hello at 0x7f7503854a90>
454+
>>> ismethod(Greeter.say_hello)
455+
False
456+
>>> isfunction(Greeter.say_hello)
457+
True
458+
459+
See :ref:`typesmethods` for details.
433460

434461

435462
.. function:: isfunction(object)
436463

437464
Return ``True`` if the object is a Python function, which includes functions
438465
created by a :term:`lambda` expression.
439466

467+
See the note for :func:`~inspect.ismethod` for an example.
468+
469+
470+
.. function:: ispackage(object)
471+
472+
Return ``True`` if the object is a :term:`package`.
473+
474+
.. versionadded:: 3.14
475+
440476

441477
.. function:: isgeneratorfunction(object)
442478

443479
Return ``True`` if the object is a Python generator function.
444480

481+
It also returns ``True`` for bound methods created from Python generator functions
482+
(see :ref:`typesmethods` for more information).
483+
445484
.. versionchanged:: 3.8
446485
Functions wrapped in :func:`functools.partial` now return ``True`` if the
447486
wrapped function is a Python generator function.

Doc/library/os.rst

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2549,7 +2549,8 @@ features:
25492549
Windows now handles a *mode* of ``0o700``.
25502550

25512551

2552-
.. function:: makedirs(name, mode=0o777, exist_ok=False)
2552+
.. function:: makedirs(name, mode=0o777, exist_ok=False, *, \
2553+
parent_mode=None)
25532554

25542555
.. index::
25552556
single: directory; creating
@@ -2567,6 +2568,12 @@ features:
25672568
If *exist_ok* is ``False`` (the default), a :exc:`FileExistsError` is
25682569
raised if the target directory already exists.
25692570

2571+
If *parent_mode* is not ``None``, it is used as the mode for any
2572+
newly-created, intermediate-level directories. Like *mode*, it is
2573+
combined with the process's umask value; see :ref:`the mkdir()
2574+
description <mkdir_modebits>`. Otherwise, intermediate directories are
2575+
created with the default mode, which is also subject to the umask.
2576+
25702577
.. note::
25712578

25722579
:func:`makedirs` will become confused if the path elements to create
@@ -2593,6 +2600,11 @@ features:
25932600
The *mode* argument no longer affects the file permission bits of
25942601
newly created intermediate-level directories.
25952602

2603+
.. versionadded:: 3.15
2604+
The *parent_mode* parameter. To match the behavior from Python 3.6 and
2605+
earlier (where *mode* was applied to all created directories), pass
2606+
``parent_mode=mode``.
2607+
25962608

25972609
.. function:: mkfifo(path, mode=0o666, *, dir_fd=None)
25982610

Doc/library/pathlib.rst

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1518,7 +1518,8 @@ Creating files and directories
15181518
:meth:`~Path.write_bytes` methods are often used to create files.
15191519

15201520

1521-
.. method:: Path.mkdir(mode=0o777, parents=False, exist_ok=False)
1521+
.. method:: Path.mkdir(mode=0o777, parents=False, exist_ok=False, *, \
1522+
parent_mode=None)
15221523

15231524
Create a new directory at this given path. If *mode* is given, it is
15241525
combined with the process's ``umask`` value to determine the file mode
@@ -1529,6 +1530,12 @@ Creating files and directories
15291530
as needed; they are created with the default permissions without taking
15301531
*mode* into account (mimicking the POSIX ``mkdir -p`` command).
15311532

1533+
If *parent_mode* is not ``None``, it is used as the mode for any
1534+
newly-created, intermediate-level directories when *parents* is true.
1535+
Like *mode*, it is combined with the process's ``umask`` value.
1536+
Otherwise, intermediate directories are created with the default
1537+
permissions (also subject to the umask).
1538+
15321539
If *parents* is false (the default), a missing parent raises
15331540
:exc:`FileNotFoundError`.
15341541

@@ -1542,6 +1549,9 @@ Creating files and directories
15421549
.. versionchanged:: 3.5
15431550
The *exist_ok* parameter was added.
15441551

1552+
.. versionadded:: 3.15
1553+
The *parent_mode* parameter.
1554+
15451555

15461556
.. method:: Path.symlink_to(target, target_is_directory=False)
15471557

Doc/whatsnew/3.15.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,6 +1285,10 @@ os
12851285
glibc versions 2.28 and later.
12861286
(Contributed by Jeffrey Bosboom and Victor Stinner in :gh:`83714`.)
12871287

1288+
* :func:`os.makedirs` function now has a *parent_mode* parameter that allows
1289+
specifying the mode for intermediate directories. This can be used to match
1290+
the behavior from Python 3.6 and earlier by passing ``parent_mode=mode``.
1291+
(Contributed by Zackery Spytz and Gregory P. Smith in :gh:`86533`.)
12881292

12891293
os.path
12901294
-------
@@ -2057,6 +2061,10 @@ importlib.resources
20572061
pathlib
20582062
-------
20592063

2064+
* :meth:`pathlib.Path.mkdir` now has a *parent_mode* parameter that allows
2065+
specifying the mode for intermediate directories when ``parents=True``.
2066+
(Contributed by Gregory P. Smith in :gh:`86533`.)
2067+
20602068
* Removed deprecated :meth:`!pathlib.PurePath.is_reserved`.
20612069
Use :func:`os.path.isreserved` to detect reserved paths on Windows.
20622070
(Contributed by Nikita Sobolev in :gh:`133875`.)

Lib/multiprocessing/connection.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
default_family = 'AF_INET'
5151
families = ['AF_INET']
5252

53-
if hasattr(socket, 'AF_UNIX'):
53+
if hasattr(socket, 'AF_UNIX') and sys.platform != 'cygwin':
5454
default_family = 'AF_UNIX'
5555
families += ['AF_UNIX']
5656

Lib/multiprocessing/context.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,10 @@ def _check_available(self):
326326
_concrete_contexts = {
327327
'fork': ForkContext(),
328328
'spawn': SpawnContext(),
329-
'forkserver': ForkServerContext(),
330329
}
330+
if reduction.HAVE_SEND_HANDLE:
331+
_concrete_contexts['forkserver'] = ForkServerContext()
332+
331333
# bpo-33725: running arbitrary code after fork() is no longer reliable
332334
# on macOS since macOS 10.14 (Mojave). Use spawn by default instead.
333335
# gh-84559: We changed everyones default to a thread safeish one in 3.14.

Lib/os.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,22 +219,29 @@ def _add(str, fn):
219219
# Super directory utilities.
220220
# (Inspired by Eric Raymond; the doc strings are mostly his)
221221

222-
def makedirs(name, mode=0o777, exist_ok=False):
223-
"""makedirs(name [, mode=0o777][, exist_ok=False])
222+
def makedirs(name, mode=0o777, exist_ok=False, *, parent_mode=None):
223+
"""makedirs(name [, mode=0o777][, exist_ok=False][, parent_mode=None])
224224
225225
Super-mkdir; create a leaf directory and all intermediate ones. Works like
226226
mkdir, except that any intermediate path segment (not just the rightmost)
227227
will be created if it does not exist. If the target directory already
228228
exists, raise an OSError if exist_ok is False. Otherwise no exception is
229-
raised. This is recursive.
229+
raised. If parent_mode is not None, it will be used as the mode for any
230+
newly-created, intermediate-level directories. Otherwise, intermediate
231+
directories are created with the default permissions (respecting umask).
232+
This is recursive.
230233
231234
"""
232235
head, tail = path.split(name)
233236
if not tail:
234237
head, tail = path.split(head)
235238
if head and tail and not path.exists(head):
236239
try:
237-
makedirs(head, exist_ok=exist_ok)
240+
if parent_mode is not None:
241+
makedirs(head, mode=parent_mode, exist_ok=exist_ok,
242+
parent_mode=parent_mode)
243+
else:
244+
makedirs(head, exist_ok=exist_ok)
238245
except FileExistsError:
239246
# Defeats race condition when another thread created the path
240247
pass

Lib/pathlib/__init__.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,7 +1204,7 @@ def touch(self, mode=0o666, exist_ok=True):
12041204
fd = os.open(self, flags, mode)
12051205
os.close(fd)
12061206

1207-
def mkdir(self, mode=0o777, parents=False, exist_ok=False):
1207+
def mkdir(self, mode=0o777, parents=False, exist_ok=False, *, parent_mode=None):
12081208
"""
12091209
Create a new directory at this given path.
12101210
"""
@@ -1213,7 +1213,11 @@ def mkdir(self, mode=0o777, parents=False, exist_ok=False):
12131213
except FileNotFoundError:
12141214
if not parents or self.parent == self:
12151215
raise
1216-
self.parent.mkdir(parents=True, exist_ok=True)
1216+
if parent_mode is not None:
1217+
self.parent.mkdir(mode=parent_mode, parents=True, exist_ok=True,
1218+
parent_mode=parent_mode)
1219+
else:
1220+
self.parent.mkdir(parents=True, exist_ok=True)
12171221
self.mkdir(mode, parents=False, exist_ok=exist_ok)
12181222
except OSError:
12191223
# Cannot rely on checking for EEXIST, since the operating system

Lib/test/_test_multiprocessing.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6143,7 +6143,10 @@ def test_preload_resources(self):
61436143
@only_run_in_spawn_testsuite("avoids redundant testing.")
61446144
def test_mixed_startmethod(self):
61456145
# Fork-based locks cannot be used with spawned process
6146-
for process_method in ["spawn", "forkserver"]:
6146+
test_methods = ["spawn"]
6147+
if "forkserver" in multiprocessing.get_all_start_methods():
6148+
test_methods.append("forkserver")
6149+
for process_method in test_methods:
61476150
queue = multiprocessing.get_context("fork").Queue()
61486151
process_ctx = multiprocessing.get_context(process_method)
61496152
p = process_ctx.Process(target=close_queue, args=(queue,))
@@ -6152,7 +6155,7 @@ def test_mixed_startmethod(self):
61526155
p.start()
61536156

61546157
# non-fork-based locks can be used with all other start methods
6155-
for queue_method in ["spawn", "forkserver"]:
6158+
for queue_method in test_methods:
61566159
for process_method in multiprocessing.get_all_start_methods():
61576160
queue = multiprocessing.get_context(queue_method).Queue()
61586161
process_ctx = multiprocessing.get_context(process_method)

Lib/test/test_logging.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4065,11 +4065,7 @@ def test_config_reject_simple_queue_handler_multiprocessing_context(self):
40654065
# and thus cannot be used as a queue-like object (gh-124653)
40664066

40674067
import multiprocessing
4068-
4069-
if support.MS_WINDOWS:
4070-
start_methods = ['spawn']
4071-
else:
4072-
start_methods = ['spawn', 'fork', 'forkserver']
4068+
start_methods = multiprocessing.get_all_start_methods()
40734069

40744070
for start_method in start_methods:
40754071
with self.subTest(start_method=start_method):
@@ -4085,10 +4081,8 @@ def test_config_reject_simple_queue_handler_multiprocessing_context(self):
40854081
" assertions in multiprocessing")
40864082
def test_config_queue_handler_multiprocessing_context(self):
40874083
# regression test for gh-121723
4088-
if support.MS_WINDOWS:
4089-
start_methods = ['spawn']
4090-
else:
4091-
start_methods = ['spawn', 'fork', 'forkserver']
4084+
import multiprocessing
4085+
start_methods = multiprocessing.get_all_start_methods()
40924086
for start_method in start_methods:
40934087
with self.subTest(start_method=start_method):
40944088
ctx = multiprocessing.get_context(start_method)

0 commit comments

Comments
 (0)