From ae86201833cc81f41981f7f3af0fea1f06925abe Mon Sep 17 00:00:00 2001 From: Dan Lenski Date: Wed, 11 Jun 2025 12:30:23 -0700 Subject: [PATCH 1/2] gh-124825: Adding PurePath.erase_parents() to pathlib The `PurePath.erase_parents()` method remove path components referring to parent directories ('..'). Unlike `Pure.resolve()`, this occurs without an attempt to verify the existence or structure of any path components. See discussion in #124825 for use cases, involving lexical normalization and simplification of paths without reference to any particular underlying filesystem. Issue: - gh-124825 --- Lib/pathlib.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 02eb5c25981e31..f753e81f030e4e 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -383,6 +383,27 @@ def with_segments(self, *pathsegments): are created from methods like `iterdir()`. """ return type(self)(*pathsegments) + + def erase_parents(self): + r""" + Remove path components referring to parent directories ('..'), + without any attempt to verify the existence or structure of any + path components. + + If this is a relative path, there may be leftover '..' segments + after erasing parent segments. For example: + + - Path('spam/../../eggs').erase_parents() == Path('../eggs') + + If this is an absolute path, and it reaches the root filesystem + (or the root of a drive or UNC share for Windows paths), + further '..' components will be ignored. For example: + + - Path('/spam/../../../eggs').erase_parents() == Path('/eggs') + - PureWindowsPath(r'c:\spam\..\..\eggs').erase_parents() == PureWindowsPath(r'c:\eggs') + - PureWindowsPath(r'\\server\share\foo\..\..\eggs').erase_parents() == PureWindowsPath(r'\\server\share\eggs') + """ + return type(self)(self._flavour.normpath(self)) @classmethod def _parse_path(cls, path): @@ -479,7 +500,7 @@ def as_uri(self): # It's a posix path => 'file:///etc/hosts' prefix = 'file://' path = str(self) - return prefix + urlquote_from_bytes(os.fsencode(path)) + return prefix + urlquote_from_bytes(os.fsencode(path)) @property def _str_normcase(self): From 1a4be32d2e24a19aed5d62556b7c9254e2c824d5 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Wed, 11 Jun 2025 19:35:24 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2025-06-11-19-35-18.gh-issue-124825.ta9HSE.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2025-06-11-19-35-18.gh-issue-124825.ta9HSE.rst diff --git a/Misc/NEWS.d/next/Library/2025-06-11-19-35-18.gh-issue-124825.ta9HSE.rst b/Misc/NEWS.d/next/Library/2025-06-11-19-35-18.gh-issue-124825.ta9HSE.rst new file mode 100644 index 00000000000000..e0797a435483f3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-06-11-19-35-18.gh-issue-124825.ta9HSE.rst @@ -0,0 +1 @@ +Added :func:`pathlib.PurePath.erase_parents`, which will remove path components referring to parent directories ('..') without any attempt to verify the existence or structure of any path components.