Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GH-100479: Add pathlib.PurePath.with_segments() #103975

Merged
merged 24 commits into from
May 5, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
a6fdd0e
Add `pathlib.PurePath.makepath()`; unify path object construction
barneygale Nov 20, 2022
b061747
Fix reST role name.
barneygale Dec 24, 2022
99eb8b1
Move call to `os.getcwd()` back into `Path.cwd()`
barneygale Dec 24, 2022
4759d01
Merge branch 'main' into gh-100479-add-makepath
barneygale Jan 5, 2023
ef6f4c3
Merge branch 'main' into gh-100479-add-makepath
barneygale Apr 3, 2023
595b8ae
Add news blurb.
barneygale Apr 3, 2023
dcfe70a
Merge branch 'main' into gh-100479-add-makepath
barneygale Apr 9, 2023
117fe4b
Add whatsnew entry
barneygale Apr 10, 2023
e75dedc
Merge branch 'main' into gh-100479-add-makepath
barneygale Apr 12, 2023
5a6bd3f
Merge branch 'main' into gh-100479-add-makepath
barneygale Apr 13, 2023
f2f1048
other --> pathsegments
barneygale Apr 24, 2023
3c172fb
Update Lib/pathlib.py
barneygale Apr 24, 2023
4637109
joinpath(*args) --> joinpath(*pathsegments)
barneygale Apr 24, 2023
ae48454
Restore _PathParents
barneygale Apr 25, 2023
e7a8fe3
Add note to `parents` about potential reference cycle.
barneygale Apr 25, 2023
b3bb8bd
makepath() --> __newpath__()
barneygale Apr 28, 2023
cdedc92
Look up `__newpath__` on path type.
barneygale Apr 29, 2023
8341566
`__newpath__` --> `_newpath_`
barneygale Apr 29, 2023
610b0c4
`_newpath_` --> `with_segments`
barneygale May 1, 2023
7f28ed3
`with_segments` --> `with_path`
barneygale May 1, 2023
51fe663
Merge branch 'main' into gh-100479-add-makepath-redux
barneygale May 2, 2023
961e2bf
Revert "`with_segments` --> `with_path`"
barneygale May 4, 2023
39297cf
Merge branch 'main' into gh-100479-add-makepath-redux
barneygale May 5, 2023
4e28944
`*args` --> `*pathsegments`
barneygale May 5, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
with_segments --> with_path
  • Loading branch information
barneygale committed May 1, 2023
commit 7f28ed37eed59a956fe3ead59e466defa38f5936
4 changes: 2 additions & 2 deletions Doc/library/pathlib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,7 @@ Pure paths provide the following methods and properties:
PureWindowsPath('README')


.. method:: PurePath.with_segments(*pathsegments)
.. method:: PurePath.with_path(*pathsegments)

Create a new path object of the same type by combining the given
*pathsegments*. This method is called whenever a derivative path is created,
Expand All @@ -694,7 +694,7 @@ Pure paths provide the following methods and properties:
super().__init__(*args)
self.session_id = session_id

def with_segments(self, *pathsegments):
def with_path(self, *pathsegments):
return type(self)(*pathsegments, session_id=self.session_id)

etc = MyPath('/etc', session_id=42)
Expand Down
2 changes: 1 addition & 1 deletion Doc/whatsnew/3.12.rst
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ pathlib

* Add support for subclassing :class:`pathlib.PurePath` and
:class:`~pathlib.Path`, plus their Posix- and Windows-specific variants.
Subclasses may override the :meth:`~pathlib.PurePath.with_segments` method
Subclasses may override the :meth:`~pathlib.PurePath.with_path` method
to pass information between path instances.

* Add :meth:`~pathlib.Path.walk` for walking the directory trees and generating
Expand Down
30 changes: 15 additions & 15 deletions Lib/pathlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ def __init__(self, *args):
f"not {type(path).__name__!r}")
self._raw_path = path

def with_segments(self, *pathsegments):
def with_path(self, *pathsegments):
"""Construct a new path object from any number of path-like objects.
Subclasses may override this method to customize how new path objects
are created from methods like `iterdir()`.
Expand Down Expand Up @@ -342,7 +342,7 @@ def _load_parts(self):

def _from_parsed_parts(self, drv, root, tail):
path_str = self._format_parsed_parts(drv, root, tail)
path = self.with_segments(path_str)
path = self.with_path(path_str)
path._str = path_str or '.'
path._drv = drv
path._root = root
Expand Down Expand Up @@ -581,7 +581,7 @@ def relative_to(self, other, /, *_deprecated, walk_up=False):
"scheduled for removal in Python {remove}")
warnings._deprecated("pathlib.PurePath.relative_to(*args)", msg,
remove=(3, 14))
other = self.with_segments(other, *_deprecated)
other = self.with_path(other, *_deprecated)
for step, path in enumerate([other] + list(other.parents)):
if self.is_relative_to(path):
break
Expand All @@ -590,7 +590,7 @@ def relative_to(self, other, /, *_deprecated, walk_up=False):
if step and not walk_up:
raise ValueError(f"{str(self)!r} is not in the subpath of {str(other)!r}")
parts = ['..'] * step + self._tail[len(path._tail):]
return self.with_segments(*parts)
return self.with_path(*parts)

def is_relative_to(self, other, /, *_deprecated):
"""Return True if the path is relative to another path or False.
Expand All @@ -601,7 +601,7 @@ def is_relative_to(self, other, /, *_deprecated):
"scheduled for removal in Python {remove}")
warnings._deprecated("pathlib.PurePath.is_relative_to(*args)",
msg, remove=(3, 14))
other = self.with_segments(other, *_deprecated)
other = self.with_path(other, *_deprecated)
return other == self or other in self.parents

@property
Expand All @@ -619,7 +619,7 @@ def joinpath(self, *pathsegments):
paths) or a totally different path (if one of the arguments is
anchored).
"""
return self.with_segments(self._raw_path, *pathsegments)
return self.with_path(self._raw_path, *pathsegments)

def __truediv__(self, key):
try:
Expand All @@ -629,7 +629,7 @@ def __truediv__(self, key):

def __rtruediv__(self, key):
try:
return self.with_segments(key, self._raw_path)
return self.with_path(key, self._raw_path)
except TypeError:
return NotImplemented

Expand Down Expand Up @@ -678,7 +678,7 @@ def match(self, path_pattern):
"""
Return True if this path matches the given pattern.
"""
pat = self.with_segments(path_pattern)
pat = self.with_path(path_pattern)
if not pat.parts:
raise ValueError("empty pattern")
pat_parts = pat._parts_normcase
Expand Down Expand Up @@ -753,7 +753,7 @@ def _make_child_relpath(self, name):
path_str = f'{path_str}{name}'
else:
path_str = name
path = self.with_segments(path_str)
path = self.with_path(path_str)
path._str = path_str
path._drv = self.drive
path._root = self.root
Expand Down Expand Up @@ -803,7 +803,7 @@ def samefile(self, other_path):
try:
other_st = other_path.stat()
except AttributeError:
other_st = self.with_segments(other_path).stat()
other_st = self.with_path(other_path).stat()
return self._flavour.samestat(st, other_st)

def iterdir(self):
Expand Down Expand Up @@ -865,7 +865,7 @@ def absolute(self):
cwd = self._flavour.abspath(self.drive)
else:
cwd = os.getcwd()
return self.with_segments(cwd, self._raw_path)
return self.with_path(cwd, self._raw_path)

def resolve(self, strict=False):
"""
Expand All @@ -883,7 +883,7 @@ def check_eloop(e):
except OSError as e:
check_eloop(e)
raise
p = self.with_segments(s)
p = self.with_path(s)

# In non-strict mode, realpath() doesn't raise on symlink loops.
# Ensure we get an exception by calling stat()
Expand Down Expand Up @@ -973,7 +973,7 @@ def readlink(self):
"""
if not hasattr(os, "readlink"):
raise NotImplementedError("os.readlink() not available on this system")
return self.with_segments(os.readlink(self))
return self.with_path(os.readlink(self))

def touch(self, mode=0o666, exist_ok=True):
"""
Expand Down Expand Up @@ -1062,7 +1062,7 @@ def rename(self, target):
Returns the new Path instance pointing to the target path.
"""
os.rename(self, target)
return self.with_segments(target)
return self.with_path(target)

def replace(self, target):
"""
Expand All @@ -1075,7 +1075,7 @@ def replace(self, target):
Returns the new Path instance pointing to the target path.
"""
os.replace(self, target)
return self.with_segments(target)
return self.with_path(target)

def symlink_to(self, target, target_is_directory=False):
"""
Expand Down
10 changes: 5 additions & 5 deletions Lib/test/test_pathlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def __init__(self, *args, session_id):
super().__init__(*args)
self.session_id = session_id

def with_segments(self, *args):
def with_path(self, *args):
return type(self)(*args, session_id=self.session_id)


Expand Down Expand Up @@ -122,7 +122,7 @@ def test_str_subclass_common(self):
self._check_str_subclass('a/b.txt')
self._check_str_subclass('/a/b.txt')

def test_with_segments_common(self):
def test_with_path_common(self):
class P(_BasePurePathSubclass, self.cls):
pass
p = P('foo', 'bar', session_id=42)
Expand All @@ -132,7 +132,7 @@ class P(_BasePurePathSubclass, self.cls):
self.assertEqual(42, p.with_name('foo').session_id)
self.assertEqual(42, p.with_stem('foo').session_id)
self.assertEqual(42, p.with_suffix('.foo').session_id)
self.assertEqual(42, p.with_segments('foo').session_id)
self.assertEqual(42, p.with_path('foo').session_id)
self.assertEqual(42, p.relative_to('foo').session_id)
self.assertEqual(42, p.parent.session_id)
for parent in p.parents:
Expand Down Expand Up @@ -1625,13 +1625,13 @@ def test_home(self):
env['HOME'] = os.path.join(BASE, 'home')
self._test_home(self.cls.home())

def test_with_segments(self):
def test_with_path(self):
class P(_BasePurePathSubclass, self.cls):
pass
p = P(BASE, session_id=42)
self.assertEqual(42, p.absolute().session_id)
self.assertEqual(42, p.resolve().session_id)
self.assertEqual(42, p.with_segments('~').expanduser().session_id)
self.assertEqual(42, p.with_path('~').expanduser().session_id)
self.assertEqual(42, (p / 'fileA').rename(p / 'fileB').session_id)
self.assertEqual(42, (p / 'fileB').replace(p / 'fileA').session_id)
if os_helper.can_symlink():
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Add :meth:`pathlib.PurePath.with_segments`, which creates a path object from
Add :meth:`pathlib.PurePath.with_path`, which creates a path object from
arguments. This method is called whenever a derivative path is created, such
as from :attr:`pathlib.PurePath.parent`. Subclasses may override this method
to share information between path objects.