summaryrefslogtreecommitdiffstats
path: root/Lib/pathlib/__init__.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/pathlib/__init__.py')
-rw-r--r--Lib/pathlib/__init__.py60
1 files changed, 60 insertions, 0 deletions
diff --git a/Lib/pathlib/__init__.py b/Lib/pathlib/__init__.py
index e70cfe9..f14d35b 100644
--- a/Lib/pathlib/__init__.py
+++ b/Lib/pathlib/__init__.py
@@ -33,6 +33,15 @@ __all__ = [
]
+# Reference for Windows paths can be found at
+# https://learn.microsoft.com/en-gb/windows/win32/fileio/naming-a-file .
+_WIN_RESERVED_NAMES = frozenset(
+ {'CON', 'PRN', 'AUX', 'NUL', 'CONIN$', 'CONOUT$'} |
+ {f'COM{c}' for c in '123456789\xb9\xb2\xb3'} |
+ {f'LPT{c}' for c in '123456789\xb9\xb2\xb3'}
+)
+
+
class _PathParents(Sequence):
"""This object provides sequence-like access to the logical ancestors
of a path. Don't try to construct it yourself."""
@@ -76,6 +85,10 @@ class PurePath(_abc.PurePathBase):
"""
__slots__ = (
+ # The `_raw_paths` slot stores unnormalized string paths. This is set
+ # in the `__init__()` method.
+ '_raw_paths',
+
# The `_drv`, `_root` and `_tail_cached` slots store parsed and
# normalized parts of the path. They are set when any of the `drive`,
# `root` or `_tail` properties are accessed for the first time. The
@@ -141,6 +154,26 @@ class PurePath(_abc.PurePathBase):
# Avoid calling super().__init__, as an optimisation
self._raw_paths = paths
+ def joinpath(self, *pathsegments):
+ """Combine this path with one or several arguments, and return a
+ new path representing either a subpath (if all arguments are relative
+ paths) or a totally different path (if one of the arguments is
+ anchored).
+ """
+ return self.with_segments(self, *pathsegments)
+
+ def __truediv__(self, key):
+ try:
+ return self.with_segments(self, key)
+ except TypeError:
+ return NotImplemented
+
+ def __rtruediv__(self, key):
+ try:
+ return self.with_segments(key, self)
+ except TypeError:
+ return NotImplemented
+
def __reduce__(self):
# Using the parts tuple helps share interned path parts
# when pickling related paths.
@@ -386,6 +419,33 @@ class PurePath(_abc.PurePathBase):
other = self.with_segments(other)
return other == self or other in self.parents
+ def is_absolute(self):
+ """True if the path is absolute (has both a root and, if applicable,
+ a drive)."""
+ if self.pathmod is posixpath:
+ # Optimization: work with raw paths on POSIX.
+ for path in self._raw_paths:
+ if path.startswith('/'):
+ return True
+ return False
+ return self.pathmod.isabs(self)
+
+ def is_reserved(self):
+ """Return True if the path contains one of the special names reserved
+ by the system, if any."""
+ if self.pathmod is not ntpath or not self.name:
+ return False
+
+ # NOTE: the rules for reserved names seem somewhat complicated
+ # (e.g. r"..\NUL" is reserved but not r"foo\NUL" if "foo" does not
+ # exist). We err on the side of caution and return True for paths
+ # which are not considered reserved by Windows.
+ if self.drive.startswith('\\\\'):
+ # UNC paths are never reserved.
+ return False
+ name = self.name.partition('.')[0].partition(':')[0].rstrip(' ')
+ return name.upper() in _WIN_RESERVED_NAMES
+
def as_uri(self):
"""Return the path as a URI."""
if not self.is_absolute():