Skip to content

Commit fec7702

Browse files
committed
Merge branch 'main' into pythongh-73435-pathlib-match-recursive
2 parents 8959dfd + ace676e commit fec7702

31 files changed

+560
-101
lines changed

.github/workflows/build.yml

+24-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ permissions:
2828
contents: read
2929

3030
concurrency:
31-
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
31+
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}-reusable
3232
cancel-in-progress: true
3333

3434
jobs:
@@ -37,6 +37,7 @@ jobs:
3737
runs-on: ubuntu-latest
3838
timeout-minutes: 10
3939
outputs:
40+
run-docs: ${{ steps.docs-changes.outputs.run-docs || false }}
4041
run_tests: ${{ steps.check.outputs.run_tests }}
4142
run_hypothesis: ${{ steps.check.outputs.run_hypothesis }}
4243
config_hash: ${{ steps.config_hash.outputs.hash }}
@@ -79,6 +80,28 @@ jobs:
7980
id: config_hash
8081
run: |
8182
echo "hash=${{ hashFiles('configure', 'configure.ac', '.github/workflows/build.yml') }}" >> $GITHUB_OUTPUT
83+
- name: Get a list of the changed documentation-related files
84+
if: github.event_name == 'pull_request'
85+
id: changed-docs-files
86+
uses: Ana06/get-changed-files@v2.2.0
87+
with:
88+
filter: |
89+
Doc/**
90+
Misc/**
91+
.github/workflows/reusable-docs.yml
92+
- name: Check for docs changes
93+
if: >-
94+
github.event_name == 'pull_request'
95+
&& steps.changed-docs-files.outputs.added_modified_renamed != ''
96+
id: docs-changes
97+
run: |
98+
echo "run-docs=true" >> "${GITHUB_OUTPUT}"
99+
100+
check-docs:
101+
name: Docs
102+
needs: check_source
103+
if: fromJSON(needs.check_source.outputs.run-docs)
104+
uses: ./.github/workflows/reusable-docs.yml
82105

83106
check_generated_files:
84107
name: 'Check if generated files are up to date'

.github/workflows/doc.yml .github/workflows/reusable-docs.yml

+1-24
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,8 @@
11
name: Docs
22

33
on:
4+
workflow_call:
45
workflow_dispatch:
5-
#push:
6-
# branches:
7-
# - 'main'
8-
# - '3.12'
9-
# - '3.11'
10-
# - '3.10'
11-
# - '3.9'
12-
# - '3.8'
13-
# - '3.7'
14-
# paths:
15-
# - 'Doc/**'
16-
pull_request:
17-
branches:
18-
- 'main'
19-
- '3.12'
20-
- '3.11'
21-
- '3.10'
22-
- '3.9'
23-
- '3.8'
24-
- '3.7'
25-
paths:
26-
- 'Doc/**'
27-
- 'Misc/**'
28-
- '.github/workflows/doc.yml'
296

307
permissions:
318
contents: read

Doc/c-api/structures.rst

+6-6
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ Accessing attributes of extension types
395395
396396
The string should be static, no copy is made of it.
397397
398-
.. c:member:: Py_ssize_t PyMemberDef.offset
398+
.. c:member:: Py_ssize_t offset
399399
400400
The offset in bytes that the member is located on the type’s object struct.
401401
@@ -625,23 +625,23 @@ Defining Getters and Setters
625625
Structure to define property-like access for a type. See also description of
626626
the :c:member:`PyTypeObject.tp_getset` slot.
627627
628-
.. c:member:: const char* PyGetSetDef.name
628+
.. c:member:: const char* name
629629
630630
attribute name
631631
632-
.. c:member:: getter PyGetSetDef.get
632+
.. c:member:: getter get
633633
634634
C function to get the attribute.
635635
636-
.. c:member:: setter PyGetSetDef.set
636+
.. c:member:: setter set
637637
638638
Optional C function to set or delete the attribute, if omitted the attribute is readonly.
639639
640-
.. c:member:: const char* PyGetSetDef.doc
640+
.. c:member:: const char* doc
641641
642642
optional docstring
643643
644-
.. c:member:: void* PyGetSetDef.closure
644+
.. c:member:: void* closure
645645
646646
Optional function pointer, providing additional data for getter and setter.
647647

Doc/c-api/type.rst

+17-2
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,15 @@ The following functions and structs are used to create
349349
:c:member:`~PyTypeObject.tp_new` is deprecated and in Python 3.14+ it
350350
will be no longer allowed.
351351
352+
.. raw:: html
353+
354+
<!-- Keep old URL fragments working (see gh-97908) -->
355+
<span id='c.PyType_Spec.PyType_Spec.name'></span>
356+
<span id='c.PyType_Spec.PyType_Spec.basicsize'></span>
357+
<span id='c.PyType_Spec.PyType_Spec.itemsize'></span>
358+
<span id='c.PyType_Spec.PyType_Spec.flags'></span>
359+
<span id='c.PyType_Spec.PyType_Spec.slots'></span>
360+
352361
.. c:type:: PyType_Spec
353362
354363
Structure defining a type's behavior.
@@ -410,12 +419,18 @@ The following functions and structs are used to create
410419
411420
Each slot ID should be specified at most once.
412421
422+
.. raw:: html
423+
424+
<!-- Keep old URL fragments working (see gh-97908) -->
425+
<span id='c.PyType_Slot.PyType_Slot.slot'></span>
426+
<span id='c.PyType_Slot.PyType_Slot.pfunc'></span>
427+
413428
.. c:type:: PyType_Slot
414429
415430
Structure defining optional functionality of a type, containing a slot ID
416431
and a value pointer.
417432
418-
.. c:member:: int PyType_Slot.slot
433+
.. c:member:: int slot
419434
420435
A slot ID.
421436
@@ -459,7 +474,7 @@ The following functions and structs are used to create
459474
:c:member:`~PyBufferProcs.bf_releasebuffer` are now available
460475
under the limited API.
461476
462-
.. c:member:: void *PyType_Slot.pfunc
477+
.. c:member:: void *pfunc
463478
464479
The desired value of the slot. In most cases, this is a pointer
465480
to a function.

Doc/library/os.path.rst

+18
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,24 @@ the :mod:`glob` module.)
304304
Accepts a :term:`path-like object`.
305305

306306

307+
.. function:: isdevdrive(path)
308+
309+
Return ``True`` if pathname *path* is located on a Windows Dev Drive.
310+
A Dev Drive is optimized for developer scenarios, and offers faster
311+
performance for reading and writing files. It is recommended for use for
312+
source code, temporary build directories, package caches, and other
313+
IO-intensive operations.
314+
315+
May raise an error for an invalid path, for example, one without a
316+
recognizable drive, but returns ``False`` on platforms that do not support
317+
Dev Drives. See `the Windows documentation <https://learn.microsoft.com/windows/dev-drive/>`_
318+
for information on enabling and creating Dev Drives.
319+
320+
.. availability:: Windows.
321+
322+
.. versionadded:: 3.12
323+
324+
307325
.. function:: join(path, *paths)
308326

309327
Join one or more path segments intelligently. The return value is the

Doc/library/pathlib.rst

+18-2
Original file line numberDiff line numberDiff line change
@@ -896,7 +896,7 @@ call fails (for example because the path doesn't exist).
896896
.. versionadded:: 3.5
897897

898898

899-
.. method:: Path.glob(pattern, *, case_sensitive=None)
899+
.. method:: Path.glob(pattern, *, case_sensitive=None, follow_symlinks=None)
900900

901901
Glob the given relative *pattern* in the directory represented by this path,
902902
yielding all matching files (of any kind)::
@@ -922,6 +922,11 @@ call fails (for example because the path doesn't exist).
922922
typically, case-sensitive on POSIX, and case-insensitive on Windows.
923923
Set *case_sensitive* to ``True`` or ``False`` to override this behaviour.
924924

925+
By default, or when the *follow_symlinks* keyword-only argument is set to
926+
``None``, this method follows symlinks except when expanding "``**``"
927+
wildcards. Set *follow_symlinks* to ``True`` to always follow symlinks, or
928+
``False`` to treat all symlinks as files.
929+
925930
.. note::
926931
Using the "``**``" pattern in large directory trees may consume
927932
an inordinate amount of time.
@@ -935,6 +940,9 @@ call fails (for example because the path doesn't exist).
935940
.. versionadded:: 3.12
936941
The *case_sensitive* argument.
937942

943+
.. versionadded:: 3.13
944+
The *follow_symlinks* argument.
945+
938946
.. method:: Path.group()
939947

940948
Return the name of the group owning the file. :exc:`KeyError` is raised
@@ -1320,7 +1328,7 @@ call fails (for example because the path doesn't exist).
13201328
.. versionadded:: 3.6
13211329
The *strict* argument (pre-3.6 behavior is strict).
13221330

1323-
.. method:: Path.rglob(pattern, *, case_sensitive=None)
1331+
.. method:: Path.rglob(pattern, *, case_sensitive=None, follow_symlinks=None)
13241332

13251333
Glob the given relative *pattern* recursively. This is like calling
13261334
:func:`Path.glob` with "``**/``" added in front of the *pattern*, where
@@ -1338,6 +1346,11 @@ call fails (for example because the path doesn't exist).
13381346
typically, case-sensitive on POSIX, and case-insensitive on Windows.
13391347
Set *case_sensitive* to ``True`` or ``False`` to override this behaviour.
13401348

1349+
By default, or when the *follow_symlinks* keyword-only argument is set to
1350+
``None``, this method follows symlinks except when expanding "``**``"
1351+
wildcards. Set *follow_symlinks* to ``True`` to always follow symlinks, or
1352+
``False`` to treat all symlinks as files.
1353+
13411354
.. audit-event:: pathlib.Path.rglob self,pattern pathlib.Path.rglob
13421355

13431356
.. versionchanged:: 3.11
@@ -1347,6 +1360,9 @@ call fails (for example because the path doesn't exist).
13471360
.. versionadded:: 3.12
13481361
The *case_sensitive* argument.
13491362

1363+
.. versionadded:: 3.13
1364+
The *follow_symlinks* argument.
1365+
13501366
.. method:: Path.rmdir()
13511367

13521368
Remove this directory. The directory must be empty.

Doc/whatsnew/3.12.rst

+39-7
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,36 @@ typed dictionaries::
272272

273273
See :pep:`692` for more details.
274274

275-
(PEP written by Franek Magiera)
275+
(Contributed by Franek Magiera in :gh:`103629`.)
276+
277+
PEP 698: Override Decorator for Static Typing
278+
---------------------------------------------
279+
280+
A new decorator :func:`typing.override` has been added to the :mod:`typing`
281+
module. It indicates to type checkers that the method is intended to override
282+
a method in a superclass. This allows type checkers to catch mistakes where
283+
a method that is intended to override something in a base class
284+
does not in fact do so.
285+
286+
Example::
287+
288+
from typing import override
289+
290+
class Base:
291+
def get_color(self) -> str:
292+
return "blue"
293+
294+
class GoodChild(Base):
295+
@override # ok: overrides Base.get_color
296+
def get_color(self) -> str:
297+
return "yellow"
298+
299+
class BadChild(Base):
300+
@override # type checker error: does not override Base.get_color
301+
def get_colour(self) -> str:
302+
return "red"
303+
304+
(Contributed by Steven Troxler in :gh:`101561`.)
276305

277306
.. _whatsnew312-pep695:
278307

@@ -772,11 +801,6 @@ tempfile
772801
typing
773802
------
774803

775-
* Add :func:`typing.override`, an override decorator telling to static type
776-
checkers to verify that a method overrides some method or attribute of the
777-
same name on a base class, as per :pep:`698`. (Contributed by Steven Troxler in
778-
:gh:`101564`.)
779-
780804
* :func:`isinstance` checks against
781805
:func:`runtime-checkable protocols <typing.runtime_checkable>` now use
782806
:func:`inspect.getattr_static` rather than :func:`hasattr` to lookup whether
@@ -821,6 +845,13 @@ typing
821845
or more members may be slower than in Python 3.11. (Contributed by Alex
822846
Waygood in :gh:`74690` and :gh:`103193`.)
823847

848+
* All :data:`typing.TypedDict` and :data:`typing.NamedTuple` classes now have the
849+
``__orig_bases__`` attribute. (Contributed by Adrian Garcia Badaracco in
850+
:gh:`103699`.)
851+
852+
* Add ``frozen_default`` parameter to :func:`typing.dataclass_transform`.
853+
(Contributed by Erik De Bonte in :gh:`99957`.)
854+
824855
sys
825856
---
826857

@@ -1015,8 +1046,9 @@ APIs:
10151046
* :func:`locale.getdefaultlocale` (:gh:`90817`)
10161047
* :meth:`!turtle.RawTurtle.settiltangle` (:gh:`50096`)
10171048
* :func:`!unittest.findTestCases` (:gh:`50096`)
1018-
* :func:`!unittest.makeSuite` (:gh:`50096`)
10191049
* :func:`!unittest.getTestCaseNames` (:gh:`50096`)
1050+
* :func:`!unittest.makeSuite` (:gh:`50096`)
1051+
* :meth:`!unittest.TestProgram.usageExit` (:gh:`67048`)
10201052
* :class:`!webbrowser.MacOSX` (:gh:`86421`)
10211053
* :class:`classmethod` descriptor chaining (:gh:`89519`)
10221054

Doc/whatsnew/3.13.rst

+8
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ pathlib
9393
* Add support for recursive wildcards in :meth:`pathlib.PurePath.match`.
9494
(Contributed by Barney Gale in :gh:`73435`.)
9595

96+
* Add *follow_symlinks* keyword-only argument to :meth:`pathlib.Path.glob` and
97+
:meth:`~pathlib.Path.rglob`.
98+
(Contributed by Barney Gale in :gh:`77609`.)
9699

97100
Optimizations
98101
=============
@@ -262,11 +265,16 @@ Removed
262265
or `python-magic <https://pypi.org/project/python-magic/>`_ instead.
263266
(Contributed by Victor Stinner in :gh:`104773`.)
264267

268+
* Remove the untested and undocumented :meth:`!unittest.TestProgram.usageExit`
269+
method, deprecated in Python 3.11.
270+
(Contributed by Hugo van Kemenade in :gh:`104992`.)
271+
265272
* Remove the :mod:`!tkinter.tix` module, deprecated in Python 3.6. The
266273
third-party Tix library which the module wrapped is unmaintained.
267274
(Contributed by Zachary Ware in :gh:`75552`.)
268275

269276

277+
270278
Porting to Python 3.13
271279
======================
272280

Lib/inspect.py

+8
Original file line numberDiff line numberDiff line change
@@ -1242,6 +1242,14 @@ def getblock(lines):
12421242
blockfinder.tokeneater(*_token)
12431243
except (EndOfBlock, IndentationError):
12441244
pass
1245+
except SyntaxError as e:
1246+
if "unmatched" not in e.msg:
1247+
raise e from None
1248+
_, *_token_info = _token
1249+
try:
1250+
blockfinder.tokeneater(tokenize.NEWLINE, *_token_info)
1251+
except (EndOfBlock, IndentationError):
1252+
pass
12451253
return lines[:blockfinder.last]
12461254

12471255
def getsourcelines(object):

Lib/ntpath.py

+16
Original file line numberDiff line numberDiff line change
@@ -867,3 +867,19 @@ def commonpath(paths):
867867
except ImportError:
868868
# Use genericpath.* as imported above
869869
pass
870+
871+
872+
try:
873+
from nt import _path_isdevdrive
874+
except ImportError:
875+
def isdevdrive(path):
876+
"""Determines whether the specified path is on a Windows Dev Drive."""
877+
# Never a Dev Drive
878+
return False
879+
else:
880+
def isdevdrive(path):
881+
"""Determines whether the specified path is on a Windows Dev Drive."""
882+
try:
883+
return _path_isdevdrive(abspath(path))
884+
except OSError:
885+
return False

0 commit comments

Comments
 (0)