Skip to content

Commit b4ce07d

Browse files
authored
Merge branch 'main' into #130077
2 parents c201c17 + 798f8d3 commit b4ce07d

17 files changed

Lines changed: 139 additions & 63 deletions

File tree

Android/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,10 @@ stderr. Add the `-v` option to also show Gradle output, and non-Python logcat
119119
messages.
120120

121121
Any other arguments on the `android.py test` command line will be passed through
122-
to `python -m test` use `--` to separate them from android.py's own options.
122+
to `python -m test` use `--` to separate them from android.py's own options.
123123
See the [Python Developer's
124124
Guide](https://devguide.python.org/testing/run-write-tests/) for common options
125-
 most of them will work on Android, except for those that involve subprocesses,
125+
most of them will work on Android, except for those that involve subprocesses,
126126
such as `-j`.
127127

128128
Every time you run `android.py test`, changes in pure-Python files in the

Doc/library/itertools.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ Examples Results
7979
``product('ABCD', repeat=2)`` ``AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD``
8080
``permutations('ABCD', 2)`` ``AB AC AD BA BC BD CA CB CD DA DB DC``
8181
``combinations('ABCD', 2)`` ``AB AC AD BC BD CD``
82-
``combinations_with_replacement('ABCD', 2)`` ``AA AB AC AD BB BC BD CC CD DD``
82+
``combinations_with_replacement('ABCD', 2)`` ``AA AB AC AD BB BC BD CC CD DD``
8383
============================================== =============================================================
8484

8585

Doc/library/sqlite3.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1148,7 +1148,7 @@ Connection objects
11481148
the *remaining* number of pages still to be copied,
11491149
and the *total* number of pages.
11501150
Defaults to ``None``.
1151-
:type progress: :term:`callback` | None
1151+
:type progress: :term:`callback` | None
11521152

11531153
:param str name:
11541154
The name of the database to back up.

Doc/whatsnew/3.1.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
when researching a change.
4848
4949
This article explains the new features in Python 3.1, compared to 3.0.
50-
Python 3.1 was released on June 27, 2009.
50+
Python 3.1 was released on June 27, 2009.
5151

5252

5353
PEP 372: Ordered Dictionaries

Doc/whatsnew/3.5.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
when researching a change.
4646
4747
This article explains the new features in Python 3.5, compared to 3.4.
48-
Python 3.5 was released on September 13, 2015.  See the
48+
Python 3.5 was released on September 13, 2015. See the
4949
`changelog <https://docs.python.org/3.5/whatsnew/changelog.html>`_ for a full
5050
list of changes.
5151

Doc/whatsnew/3.6.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
when researching a change.
4646
4747
This article explains the new features in Python 3.6, compared to 3.5.
48-
Python 3.6 was released on December 23, 2016.  See the
48+
Python 3.6 was released on December 23, 2016. See the
4949
`changelog <https://docs.python.org/3.6/whatsnew/changelog.html>`_ for a full
5050
list of changes.
5151

InternalDocs/interpreter.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ snippet decode a complete instruction:
105105
For various reasons we'll get to later (mostly efficiency, given that `EXTENDED_ARG`
106106
is rare) the actual code is different.
107107

108-
## Jumps
108+
## Jumps
109109

110110
Note that when the `switch` statement is reached, `next_instr` (the "instruction offset")
111111
already points to the next instruction.

Lib/pathlib/_abc.py

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@
1212
"""
1313

1414
import functools
15-
import posixpath
15+
from abc import ABC, abstractmethod
1616
from glob import _PathGlobber, _no_recurse_symlinks
17+
from pathlib import PurePath, Path
1718
from pathlib._os import magic_open, CopyReader, CopyWriter
1819

1920

@@ -39,24 +40,32 @@ def _explode_path(path):
3940
return path, names
4041

4142

42-
class JoinablePath:
43-
"""Base class for pure path objects.
43+
class JoinablePath(ABC):
44+
"""Abstract base class for pure path objects.
4445
4546
This class *does not* provide several magic methods that are defined in
46-
its subclass PurePath. They are: __init__, __fspath__, __bytes__,
47+
its implementation PurePath. They are: __init__, __fspath__, __bytes__,
4748
__reduce__, __hash__, __eq__, __lt__, __le__, __gt__, __ge__.
4849
"""
49-
5050
__slots__ = ()
51-
parser = posixpath
5251

52+
@property
53+
@abstractmethod
54+
def parser(self):
55+
"""Implementation of pathlib._types.Parser used for low-level path
56+
parsing and manipulation.
57+
"""
58+
raise NotImplementedError
59+
60+
@abstractmethod
5361
def with_segments(self, *pathsegments):
5462
"""Construct a new path object from any number of path-like objects.
5563
Subclasses may override this method to customize how new path objects
5664
are created from methods like `iterdir()`.
5765
"""
5866
raise NotImplementedError
5967

68+
@abstractmethod
6069
def __str__(self):
6170
"""Return the string representation of the path, suitable for
6271
passing to system calls."""
@@ -198,23 +207,17 @@ def full_match(self, pattern, *, case_sensitive=None):
198207
return match(str(self)) is not None
199208

200209

201-
202210
class ReadablePath(JoinablePath):
203-
"""Base class for concrete path objects.
211+
"""Abstract base class for readable path objects.
204212
205-
This class provides dummy implementations for many methods that derived
206-
classes can override selectively; the default implementations raise
207-
NotImplementedError. The most basic methods, such as stat() and open(),
208-
directly raise NotImplementedError; these basic methods are called by
209-
other methods such as is_dir() and read_text().
210-
211-
The Path class derives this class to implement local filesystem paths.
212-
Users may derive their own classes to implement virtual filesystem paths,
213-
such as paths in archive files or on remote storage systems.
213+
The Path class implements this ABC for local filesystem paths. Users may
214+
create subclasses to implement readable virtual filesystem paths, such as
215+
paths in archive files or on remote storage systems.
214216
"""
215217
__slots__ = ()
216218

217219
@property
220+
@abstractmethod
218221
def info(self):
219222
"""
220223
A PathInfo object that exposes the file type and other file attributes
@@ -254,6 +257,7 @@ def is_symlink(self):
254257
info = self.joinpath().info
255258
return info.is_symlink()
256259

260+
@abstractmethod
257261
def __open_rb__(self, buffering=-1):
258262
"""
259263
Open the file pointed to by this path for reading in binary mode and
@@ -275,6 +279,7 @@ def read_text(self, encoding=None, errors=None, newline=None):
275279
with magic_open(self, mode='r', encoding=encoding, errors=errors, newline=newline) as f:
276280
return f.read()
277281

282+
@abstractmethod
278283
def iterdir(self):
279284
"""Yield path objects of the directory contents.
280285
@@ -348,6 +353,7 @@ def walk(self, top_down=True, on_error=None, follow_symlinks=False):
348353
yield path, dirnames, filenames
349354
paths += [path.joinpath(d) for d in reversed(dirnames)]
350355

356+
@abstractmethod
351357
def readlink(self):
352358
"""
353359
Return the path to which the symbolic link points.
@@ -389,21 +395,30 @@ def copy_into(self, target_dir, *, follow_symlinks=True,
389395

390396

391397
class WritablePath(JoinablePath):
398+
"""Abstract base class for writable path objects.
399+
400+
The Path class implements this ABC for local filesystem paths. Users may
401+
create subclasses to implement writable virtual filesystem paths, such as
402+
paths in archive files or on remote storage systems.
403+
"""
392404
__slots__ = ()
393405

406+
@abstractmethod
394407
def symlink_to(self, target, target_is_directory=False):
395408
"""
396409
Make this path a symlink pointing to the target path.
397410
Note the order of arguments (link, target) is the reverse of os.symlink.
398411
"""
399412
raise NotImplementedError
400413

414+
@abstractmethod
401415
def mkdir(self, mode=0o777, parents=False, exist_ok=False):
402416
"""
403417
Create a new directory at this given path.
404418
"""
405419
raise NotImplementedError
406420

421+
@abstractmethod
407422
def __open_wb__(self, buffering=-1):
408423
"""
409424
Open the file pointed to by this path for writing in binary mode and
@@ -431,3 +446,8 @@ def write_text(self, data, encoding=None, errors=None, newline=None):
431446
return f.write(data)
432447

433448
_copy_writer = property(CopyWriter)
449+
450+
451+
JoinablePath.register(PurePath)
452+
ReadablePath.register(Path)
453+
WritablePath.register(Path)

Lib/pathlib/_local.py

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
grp = None
2121

2222
from pathlib._os import LocalCopyReader, LocalCopyWriter, PathInfo, DirEntryInfo
23-
from pathlib._abc import JoinablePath, ReadablePath, WritablePath
2423

2524

2625
__all__ = [
@@ -65,7 +64,7 @@ def __repr__(self):
6564
return "<{}.parents>".format(type(self._path).__name__)
6665

6766

68-
class PurePath(JoinablePath):
67+
class PurePath:
6968
"""Base class for manipulating paths without I/O.
7069
7170
PurePath represents a filesystem path and offers operations which
@@ -409,6 +408,31 @@ def with_name(self, name):
409408
tail[-1] = name
410409
return self._from_parsed_parts(self.drive, self.root, tail)
411410

411+
def with_stem(self, stem):
412+
"""Return a new path with the stem changed."""
413+
suffix = self.suffix
414+
if not suffix:
415+
return self.with_name(stem)
416+
elif not stem:
417+
# If the suffix is non-empty, we can't make the stem empty.
418+
raise ValueError(f"{self!r} has a non-empty suffix")
419+
else:
420+
return self.with_name(stem + suffix)
421+
422+
def with_suffix(self, suffix):
423+
"""Return a new path with the file suffix changed. If the path
424+
has no suffix, add given suffix. If the given suffix is an empty
425+
string, remove the suffix from the path.
426+
"""
427+
stem = self.stem
428+
if not stem:
429+
# If the stem is empty, we can't make the suffix non-empty.
430+
raise ValueError(f"{self!r} has an empty name")
431+
elif suffix and not suffix.startswith('.'):
432+
raise ValueError(f"Invalid suffix {suffix!r}")
433+
else:
434+
return self.with_name(stem + suffix)
435+
412436
@property
413437
def stem(self):
414438
"""The final path component, minus its last suffix."""
@@ -584,7 +608,7 @@ class PureWindowsPath(PurePath):
584608
__slots__ = ()
585609

586610

587-
class Path(WritablePath, ReadablePath, PurePath):
611+
class Path(PurePath):
588612
"""PurePath subclass that can make system calls.
589613
590614
Path represents a filesystem path but unlike PurePath, also offers
@@ -1058,6 +1082,37 @@ def replace(self, target):
10581082
_copy_reader = property(LocalCopyReader)
10591083
_copy_writer = property(LocalCopyWriter)
10601084

1085+
def copy(self, target, follow_symlinks=True, dirs_exist_ok=False,
1086+
preserve_metadata=False):
1087+
"""
1088+
Recursively copy this file or directory tree to the given destination.
1089+
"""
1090+
if not hasattr(target, '_copy_writer'):
1091+
target = self.with_segments(target)
1092+
1093+
# Delegate to the target path's CopyWriter object.
1094+
try:
1095+
create = target._copy_writer._create
1096+
except AttributeError:
1097+
raise TypeError(f"Target is not writable: {target}") from None
1098+
return create(self, follow_symlinks, dirs_exist_ok, preserve_metadata)
1099+
1100+
def copy_into(self, target_dir, *, follow_symlinks=True,
1101+
dirs_exist_ok=False, preserve_metadata=False):
1102+
"""
1103+
Copy this file or directory tree into the given existing directory.
1104+
"""
1105+
name = self.name
1106+
if not name:
1107+
raise ValueError(f"{self!r} has an empty name")
1108+
elif hasattr(target_dir, '_copy_writer'):
1109+
target = target_dir / name
1110+
else:
1111+
target = self.with_segments(target_dir, name)
1112+
return self.copy(target, follow_symlinks=follow_symlinks,
1113+
dirs_exist_ok=dirs_exist_ok,
1114+
preserve_metadata=preserve_metadata)
1115+
10611116
def move(self, target):
10621117
"""
10631118
Recursively move this file or directory tree to the given destination.

Lib/test/clinic.test.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3976,7 +3976,7 @@ test_preprocessor_guarded_if_with_continuation_impl(PyObject *module)
39763976
/*[clinic end generated code: output=3d0712ca9e2d15b9 input=4a956fd91be30284]*/
39773977
#endif
39783978

3979-
#if CONDITION_E || CONDITION_F
3979+
#if CONDITION_E || CONDITION_F
39803980
#warning "different type of CPP directive"
39813981
/*[clinic input]
39823982
test_preprocessor_guarded_if_e_or_f

0 commit comments

Comments
 (0)