Skip to content

Commit

Permalink
Drop methods from PurePath itself, as it cannot be instantiated.
Browse files Browse the repository at this point in the history
  • Loading branch information
barneygale committed Jun 22, 2023
1 parent 8d12e06 commit e36eb74
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 45 deletions.
62 changes: 31 additions & 31 deletions Lib/pathlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,10 +236,14 @@ def __repr__(self):
return "<{}.parents>".format(type(self._path).__name__)


class _BasePurePath:
"""Base class for manipulating paths using only lexical operations.
class PurePath:
"""Base class for manipulating paths without I/O.
This class does not provide the methods __fspath__, __bytes__ or as_uri.
PurePath represents a filesystem path and offers operations which
don't imply any actual filesystem I/O. Depending on your system,
instantiating a PurePath will return either a PurePosixPath or a
PureWindowsPath object. You can also instantiate either of these classes
directly, regardless of your system.
"""

__slots__ = (
Expand Down Expand Up @@ -283,6 +287,16 @@ class _BasePurePath:
)
_flavour = os.path

def __new__(cls, *args, **kwargs):
"""Construct a PurePath from one or several strings and or existing
PurePath objects. The strings and path objects are combined so as
to yield a canonicalized path, which is incorporated into the
new PurePath object.
"""
if cls is PurePath:
cls = PureWindowsPath if os.name == 'nt' else PurePosixPath
return object.__new__(cls)

def __reduce__(self):
# Using the parts tuple helps share interned path parts
# when pickling related paths.
Expand All @@ -291,7 +305,7 @@ def __reduce__(self):
def __init__(self, *args):
paths = []
for arg in args:
if isinstance(arg, _BasePurePath):
if isinstance(arg, PurePath):
if arg._flavour is ntpath and self._flavour is posixpath:
# GH-103631: Convert separators for backwards compatibility.
paths.extend(path.replace('\\', '/') for path in arg._raw_paths)
Expand Down Expand Up @@ -418,7 +432,7 @@ def _lines(self):
return self._lines_cached

def __eq__(self, other):
if not isinstance(other, _BasePurePath):
if not isinstance(other, PurePath):
return NotImplemented
return self._str_normcase == other._str_normcase and self._flavour is other._flavour

Expand All @@ -430,22 +444,22 @@ def __hash__(self):
return self._hash

def __lt__(self, other):
if not isinstance(other, _BasePurePath) or self._flavour is not other._flavour:
if not isinstance(other, PurePath) or self._flavour is not other._flavour:
return NotImplemented
return self._parts_normcase < other._parts_normcase

def __le__(self, other):
if not isinstance(other, _BasePurePath) or self._flavour is not other._flavour:
if not isinstance(other, PurePath) or self._flavour is not other._flavour:
return NotImplemented
return self._parts_normcase <= other._parts_normcase

def __gt__(self, other):
if not isinstance(other, _BasePurePath) or self._flavour is not other._flavour:
if not isinstance(other, PurePath) or self._flavour is not other._flavour:
return NotImplemented
return self._parts_normcase > other._parts_normcase

def __ge__(self, other):
if not isinstance(other, _BasePurePath) or self._flavour is not other._flavour:
if not isinstance(other, PurePath) or self._flavour is not other._flavour:
return NotImplemented
return self._parts_normcase >= other._parts_normcase

Expand Down Expand Up @@ -680,7 +694,7 @@ def match(self, path_pattern, *, case_sensitive=None):
"""
Return True if this path matches the given pattern.
"""
if not isinstance(path_pattern, _BasePurePath):
if not isinstance(path_pattern, PurePath):
path_pattern = self.with_segments(path_pattern)
if case_sensitive is None:
case_sensitive = _is_case_sensitive(self._flavour)
Expand All @@ -693,27 +707,13 @@ def match(self, path_pattern, *, case_sensitive=None):
raise ValueError("empty pattern")


class PurePath(_BasePurePath):
"""Base class for manipulating paths without I/O.
class _PurePathExt(PurePath):
"""PurePath subclass that adds some non-lexical methods.
PurePath represents a filesystem path and offers operations which
don't imply any actual filesystem I/O. Depending on your system,
instantiating a PurePath will return either a PurePosixPath or a
PureWindowsPath object. You can also instantiate either of these classes
directly, regardless of your system.
This class provides the methods __fspath__, __bytes__ and as_uri.
"""
__slots__ = ()

def __new__(cls, *args, **kwargs):
"""Construct a PurePath from one or several strings and or existing
PurePath objects. The strings and path objects are combined so as
to yield a canonicalized path, which is incorporated into the
new PurePath object.
"""
if cls is PurePath:
cls = PureWindowsPath if os.name == 'nt' else PurePosixPath
return object.__new__(cls)

def __fspath__(self):
return str(self)

Expand Down Expand Up @@ -745,10 +745,10 @@ def as_uri(self):

# Subclassing os.PathLike makes isinstance() checks slower,
# which in turn makes Path construction slower. Register instead!
os.PathLike.register(PurePath)
os.PathLike.register(_PurePathExt)


class PurePosixPath(PurePath):
class PurePosixPath(_PurePathExt):
"""PurePath subclass for non-Windows systems.
On a POSIX system, instantiating a PurePath should return this object.
Expand All @@ -758,7 +758,7 @@ class PurePosixPath(PurePath):
__slots__ = ()


class PureWindowsPath(PurePath):
class PureWindowsPath(_PurePathExt):
"""PurePath subclass for Windows systems.
On a Windows system, instantiating a PurePath should return this object.
Expand All @@ -771,7 +771,7 @@ class PureWindowsPath(PurePath):
# Filesystem-accessing classes


class Path(PurePath):
class Path(_PurePathExt):
"""PurePath subclass that can make system calls.
Path represents a filesystem path but unlike PurePath, also offers
Expand Down
28 changes: 14 additions & 14 deletions Lib/test/test_pathlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@
# Tests for the pure classes.
#

class BasePurePathTest(unittest.TestCase):
cls = pathlib._BasePurePath
class PurePathTest(unittest.TestCase):
cls = pathlib.PurePath

# Keys are canonical paths, values are list of tuples of arguments
# supposed to produce equal paths.
Expand Down Expand Up @@ -79,6 +79,14 @@ def test_constructor_common(self):
self.assertEqual(P(P('a'), P('b'), P('c')), P(FakePath("a/b/c")))
self.assertEqual(P(P('./a:b')), P('./a:b'))

def test_concrete_class(self):
if self.cls is pathlib.PurePath:
expected = pathlib.PureWindowsPath if os.name == 'nt' else pathlib.PurePosixPath
else:
expected = self.cls
p = self.cls('a')
self.assertIs(type(p), expected)

def test_different_flavours_unequal(self):
p = self.cls('a')
if p._flavour is posixpath:
Expand Down Expand Up @@ -737,16 +745,8 @@ def test_pickling_common(self):
self.assertEqual(str(pp), str(p))


class PurePathTest(BasePurePathTest):
cls = pathlib.PurePath

def test_concrete_class(self):
if self.cls is pathlib.PurePath:
expected = pathlib.PureWindowsPath if os.name == 'nt' else pathlib.PurePosixPath
else:
expected = self.cls
p = self.cls('a')
self.assertIs(type(p), expected)
class PurePathExtTest(PurePathTest):
cls = pathlib._PurePathExt

def test_fspath_common(self):
P = self.cls
Expand All @@ -767,7 +767,7 @@ def test_as_uri_common(self):
P().as_uri()


class PurePosixPathTest(PurePathTest):
class PurePosixPathTest(PurePathExtTest):
cls = pathlib.PurePosixPath

def test_drive_root_parts(self):
Expand Down Expand Up @@ -861,7 +861,7 @@ def test_parse_windows_path(self):
self.assertEqual(p, pp)


class PureWindowsPathTest(PurePathTest):
class PureWindowsPathTest(PurePathExtTest):
cls = pathlib.PureWindowsPath

equivalences = PurePathTest.equivalences.copy()
Expand Down

0 comments on commit e36eb74

Please sign in to comment.