From 5d8a3e74b51a59752f24cb869e7daa065b673f83 Mon Sep 17 00:00:00 2001 From: Barney Gale Date: Wed, 10 Jan 2024 01:12:58 +0000 Subject: pathlib ABCs: Require one or more initialiser arguments (#113885) Refuse to guess what a user means when they initialise a pathlib ABC without any positional arguments. In mainline pathlib it's normalised to `.`, but in the ABCs this guess isn't appropriate; for example, the path type may not represent the current directory as `.`, or may have no concept of a "current directory" at all. --- Lib/pathlib/_abc.py | 10 ++----- Lib/test/test_pathlib/test_pathlib_abc.py | 48 +++++++++++++++---------------- 2 files changed, 26 insertions(+), 32 deletions(-) diff --git a/Lib/pathlib/_abc.py b/Lib/pathlib/_abc.py index 6a19284..2fc087d 100644 --- a/Lib/pathlib/_abc.py +++ b/Lib/pathlib/_abc.py @@ -167,13 +167,7 @@ class PurePathBase: def __str__(self): """Return the string representation of the path, suitable for passing to system calls.""" - paths = self._raw_paths - if len(paths) == 1: - return paths[0] - elif paths: - return self.pathmod.join(*paths) - else: - return '' + return self.pathmod.join(*self._raw_paths) def as_posix(self): """Return the string representation of the path with forward (/) @@ -838,7 +832,7 @@ class PathBase(PurePathBase): # enable users to replace the implementation of 'absolute()' in a # subclass and benefit from the new behaviour here. This works because # os.path.abspath('.') == os.getcwd(). - return cls().absolute() + return cls('').absolute() def expanduser(self): """ Return a new path with expanded ~ and ~user constructs diff --git a/Lib/test/test_pathlib/test_pathlib_abc.py b/Lib/test/test_pathlib/test_pathlib_abc.py index 7c8a0f4..14df1e6 100644 --- a/Lib/test/test_pathlib/test_pathlib_abc.py +++ b/Lib/test/test_pathlib/test_pathlib_abc.py @@ -227,9 +227,9 @@ class DummyPurePathTest(unittest.TestCase): self.assertFalse(P('c:/a/B.Py').match('C:/A/*.pY', case_sensitive=True)) self.assertTrue(P('/a/b/c.py').match('/A/*/*.Py', case_sensitive=False)) # Matching against empty path - self.assertFalse(P().match('*')) - self.assertTrue(P().match('**')) - self.assertFalse(P().match('**/*')) + self.assertFalse(P('').match('*')) + self.assertTrue(P('').match('**')) + self.assertFalse(P('').match('**/*')) def test_parts_common(self): # `parts` returns a tuple. @@ -249,8 +249,8 @@ class DummyPurePathTest(unittest.TestCase): p = P('a/b/c') self.assertEqual(p.parent, P('a/b')) self.assertEqual(p.parent.parent, P('a')) - self.assertEqual(p.parent.parent.parent, P()) - self.assertEqual(p.parent.parent.parent.parent, P()) + self.assertEqual(p.parent.parent.parent, P('')) + self.assertEqual(p.parent.parent.parent.parent, P('')) # Anchored p = P('/a/b/c') self.assertEqual(p.parent, P('/a/b')) @@ -478,20 +478,20 @@ class DummyPurePathTest(unittest.TestCase): p = P('a/b') self.assertRaises(TypeError, p.relative_to) self.assertRaises(TypeError, p.relative_to, b'a') - self.assertEqual(p.relative_to(P()), P('a/b')) + self.assertEqual(p.relative_to(P('')), P('a/b')) self.assertEqual(p.relative_to(''), P('a/b')) self.assertEqual(p.relative_to(P('a')), P('b')) self.assertEqual(p.relative_to('a'), P('b')) self.assertEqual(p.relative_to('a/'), P('b')) - self.assertEqual(p.relative_to(P('a/b')), P()) - self.assertEqual(p.relative_to('a/b'), P()) - self.assertEqual(p.relative_to(P(), walk_up=True), P('a/b')) + self.assertEqual(p.relative_to(P('a/b')), P('')) + self.assertEqual(p.relative_to('a/b'), P('')) + self.assertEqual(p.relative_to(P(''), walk_up=True), P('a/b')) self.assertEqual(p.relative_to('', walk_up=True), P('a/b')) self.assertEqual(p.relative_to(P('a'), walk_up=True), P('b')) self.assertEqual(p.relative_to('a', walk_up=True), P('b')) self.assertEqual(p.relative_to('a/', walk_up=True), P('b')) - self.assertEqual(p.relative_to(P('a/b'), walk_up=True), P()) - self.assertEqual(p.relative_to('a/b', walk_up=True), P()) + self.assertEqual(p.relative_to(P('a/b'), walk_up=True), P('')) + self.assertEqual(p.relative_to('a/b', walk_up=True), P('')) self.assertEqual(p.relative_to(P('a/c'), walk_up=True), P('../b')) self.assertEqual(p.relative_to('a/c', walk_up=True), P('../b')) self.assertEqual(p.relative_to(P('a/b/c'), walk_up=True), P('..')) @@ -517,15 +517,15 @@ class DummyPurePathTest(unittest.TestCase): self.assertEqual(p.relative_to(P('/a')), P('b')) self.assertEqual(p.relative_to('/a'), P('b')) self.assertEqual(p.relative_to('/a/'), P('b')) - self.assertEqual(p.relative_to(P('/a/b')), P()) - self.assertEqual(p.relative_to('/a/b'), P()) + self.assertEqual(p.relative_to(P('/a/b')), P('')) + self.assertEqual(p.relative_to('/a/b'), P('')) self.assertEqual(p.relative_to(P('/'), walk_up=True), P('a/b')) self.assertEqual(p.relative_to('/', walk_up=True), P('a/b')) self.assertEqual(p.relative_to(P('/a'), walk_up=True), P('b')) self.assertEqual(p.relative_to('/a', walk_up=True), P('b')) self.assertEqual(p.relative_to('/a/', walk_up=True), P('b')) - self.assertEqual(p.relative_to(P('/a/b'), walk_up=True), P()) - self.assertEqual(p.relative_to('/a/b', walk_up=True), P()) + self.assertEqual(p.relative_to(P('/a/b'), walk_up=True), P('')) + self.assertEqual(p.relative_to('/a/b', walk_up=True), P('')) self.assertEqual(p.relative_to(P('/a/c'), walk_up=True), P('../b')) self.assertEqual(p.relative_to('/a/c', walk_up=True), P('../b')) self.assertEqual(p.relative_to(P('/a/b/c'), walk_up=True), P('..')) @@ -536,7 +536,7 @@ class DummyPurePathTest(unittest.TestCase): self.assertRaises(ValueError, p.relative_to, P('/c')) self.assertRaises(ValueError, p.relative_to, P('/a/b/c')) self.assertRaises(ValueError, p.relative_to, P('/a/c')) - self.assertRaises(ValueError, p.relative_to, P()) + self.assertRaises(ValueError, p.relative_to, P('')) self.assertRaises(ValueError, p.relative_to, '') self.assertRaises(ValueError, p.relative_to, P('a')) self.assertRaises(ValueError, p.relative_to, P("../a")) @@ -553,7 +553,7 @@ class DummyPurePathTest(unittest.TestCase): p = P('a/b') self.assertRaises(TypeError, p.is_relative_to) self.assertRaises(TypeError, p.is_relative_to, b'a') - self.assertTrue(p.is_relative_to(P())) + self.assertTrue(p.is_relative_to(P(''))) self.assertTrue(p.is_relative_to('')) self.assertTrue(p.is_relative_to(P('a'))) self.assertTrue(p.is_relative_to('a/')) @@ -576,7 +576,7 @@ class DummyPurePathTest(unittest.TestCase): self.assertFalse(p.is_relative_to(P('/c'))) self.assertFalse(p.is_relative_to(P('/a/b/c'))) self.assertFalse(p.is_relative_to(P('/a/c'))) - self.assertFalse(p.is_relative_to(P())) + self.assertFalse(p.is_relative_to(P(''))) self.assertFalse(p.is_relative_to('')) self.assertFalse(p.is_relative_to(P('a'))) @@ -590,7 +590,7 @@ class PathBaseTest(PurePathBaseTest): def test_unsupported_operation(self): P = self.cls - p = self.cls() + p = self.cls('') e = UnsupportedOperation self.assertRaises(e, p.stat) self.assertRaises(e, p.lstat) @@ -634,13 +634,13 @@ class PathBaseTest(PurePathBaseTest): def test_as_uri_common(self): e = UnsupportedOperation - self.assertRaises(e, self.cls().as_uri) + self.assertRaises(e, self.cls('').as_uri) def test_fspath_common(self): - self.assertRaises(TypeError, os.fspath, self.cls()) + self.assertRaises(TypeError, os.fspath, self.cls('')) def test_as_bytes_common(self): - self.assertRaises(TypeError, bytes, self.cls()) + self.assertRaises(TypeError, bytes, self.cls('')) class DummyPathIO(io.BytesIO): @@ -993,7 +993,7 @@ class DummyPathTest(DummyPurePathTest): _check(p.glob("*/"), ["dirA/", "dirB/", "dirC/", "dirE/", "linkB/"]) def test_glob_empty_pattern(self): - p = self.cls() + p = self.cls('') with self.assertRaisesRegex(ValueError, 'Unacceptable pattern'): list(p.glob('')) @@ -1554,7 +1554,7 @@ class DummyPathTest(DummyPurePathTest): # Resolve relative paths. try: - self.cls().absolute() + self.cls('').absolute() except UnsupportedOperation: return old_path = os.getcwd() -- cgit v0.12