Skip to content

Commit 5d8a3e7

Browse files
authored
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.
1 parent beb80d1 commit 5d8a3e7

File tree

2 files changed

+26
-32
lines changed

2 files changed

+26
-32
lines changed

Lib/pathlib/_abc.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -167,13 +167,7 @@ def with_segments(self, *pathsegments):
167167
def __str__(self):
168168
"""Return the string representation of the path, suitable for
169169
passing to system calls."""
170-
paths = self._raw_paths
171-
if len(paths) == 1:
172-
return paths[0]
173-
elif paths:
174-
return self.pathmod.join(*paths)
175-
else:
176-
return ''
170+
return self.pathmod.join(*self._raw_paths)
177171

178172
def as_posix(self):
179173
"""Return the string representation of the path with forward (/)
@@ -838,7 +832,7 @@ def cwd(cls):
838832
# enable users to replace the implementation of 'absolute()' in a
839833
# subclass and benefit from the new behaviour here. This works because
840834
# os.path.abspath('.') == os.getcwd().
841-
return cls().absolute()
835+
return cls('').absolute()
842836

843837
def expanduser(self):
844838
""" Return a new path with expanded ~ and ~user constructs

Lib/test/test_pathlib/test_pathlib_abc.py

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -227,9 +227,9 @@ def test_match_common(self):
227227
self.assertFalse(P('c:/a/B.Py').match('C:/A/*.pY', case_sensitive=True))
228228
self.assertTrue(P('/a/b/c.py').match('/A/*/*.Py', case_sensitive=False))
229229
# Matching against empty path
230-
self.assertFalse(P().match('*'))
231-
self.assertTrue(P().match('**'))
232-
self.assertFalse(P().match('**/*'))
230+
self.assertFalse(P('').match('*'))
231+
self.assertTrue(P('').match('**'))
232+
self.assertFalse(P('').match('**/*'))
233233

234234
def test_parts_common(self):
235235
# `parts` returns a tuple.
@@ -249,8 +249,8 @@ def test_parent_common(self):
249249
p = P('a/b/c')
250250
self.assertEqual(p.parent, P('a/b'))
251251
self.assertEqual(p.parent.parent, P('a'))
252-
self.assertEqual(p.parent.parent.parent, P())
253-
self.assertEqual(p.parent.parent.parent.parent, P())
252+
self.assertEqual(p.parent.parent.parent, P(''))
253+
self.assertEqual(p.parent.parent.parent.parent, P(''))
254254
# Anchored
255255
p = P('/a/b/c')
256256
self.assertEqual(p.parent, P('/a/b'))
@@ -478,20 +478,20 @@ def test_relative_to_common(self):
478478
p = P('a/b')
479479
self.assertRaises(TypeError, p.relative_to)
480480
self.assertRaises(TypeError, p.relative_to, b'a')
481-
self.assertEqual(p.relative_to(P()), P('a/b'))
481+
self.assertEqual(p.relative_to(P('')), P('a/b'))
482482
self.assertEqual(p.relative_to(''), P('a/b'))
483483
self.assertEqual(p.relative_to(P('a')), P('b'))
484484
self.assertEqual(p.relative_to('a'), P('b'))
485485
self.assertEqual(p.relative_to('a/'), P('b'))
486-
self.assertEqual(p.relative_to(P('a/b')), P())
487-
self.assertEqual(p.relative_to('a/b'), P())
488-
self.assertEqual(p.relative_to(P(), walk_up=True), P('a/b'))
486+
self.assertEqual(p.relative_to(P('a/b')), P(''))
487+
self.assertEqual(p.relative_to('a/b'), P(''))
488+
self.assertEqual(p.relative_to(P(''), walk_up=True), P('a/b'))
489489
self.assertEqual(p.relative_to('', walk_up=True), P('a/b'))
490490
self.assertEqual(p.relative_to(P('a'), walk_up=True), P('b'))
491491
self.assertEqual(p.relative_to('a', walk_up=True), P('b'))
492492
self.assertEqual(p.relative_to('a/', walk_up=True), P('b'))
493-
self.assertEqual(p.relative_to(P('a/b'), walk_up=True), P())
494-
self.assertEqual(p.relative_to('a/b', walk_up=True), P())
493+
self.assertEqual(p.relative_to(P('a/b'), walk_up=True), P(''))
494+
self.assertEqual(p.relative_to('a/b', walk_up=True), P(''))
495495
self.assertEqual(p.relative_to(P('a/c'), walk_up=True), P('../b'))
496496
self.assertEqual(p.relative_to('a/c', walk_up=True), P('../b'))
497497
self.assertEqual(p.relative_to(P('a/b/c'), walk_up=True), P('..'))
@@ -517,15 +517,15 @@ def test_relative_to_common(self):
517517
self.assertEqual(p.relative_to(P('/a')), P('b'))
518518
self.assertEqual(p.relative_to('/a'), P('b'))
519519
self.assertEqual(p.relative_to('/a/'), P('b'))
520-
self.assertEqual(p.relative_to(P('/a/b')), P())
521-
self.assertEqual(p.relative_to('/a/b'), P())
520+
self.assertEqual(p.relative_to(P('/a/b')), P(''))
521+
self.assertEqual(p.relative_to('/a/b'), P(''))
522522
self.assertEqual(p.relative_to(P('/'), walk_up=True), P('a/b'))
523523
self.assertEqual(p.relative_to('/', walk_up=True), P('a/b'))
524524
self.assertEqual(p.relative_to(P('/a'), walk_up=True), P('b'))
525525
self.assertEqual(p.relative_to('/a', walk_up=True), P('b'))
526526
self.assertEqual(p.relative_to('/a/', walk_up=True), P('b'))
527-
self.assertEqual(p.relative_to(P('/a/b'), walk_up=True), P())
528-
self.assertEqual(p.relative_to('/a/b', walk_up=True), P())
527+
self.assertEqual(p.relative_to(P('/a/b'), walk_up=True), P(''))
528+
self.assertEqual(p.relative_to('/a/b', walk_up=True), P(''))
529529
self.assertEqual(p.relative_to(P('/a/c'), walk_up=True), P('../b'))
530530
self.assertEqual(p.relative_to('/a/c', walk_up=True), P('../b'))
531531
self.assertEqual(p.relative_to(P('/a/b/c'), walk_up=True), P('..'))
@@ -536,7 +536,7 @@ def test_relative_to_common(self):
536536
self.assertRaises(ValueError, p.relative_to, P('/c'))
537537
self.assertRaises(ValueError, p.relative_to, P('/a/b/c'))
538538
self.assertRaises(ValueError, p.relative_to, P('/a/c'))
539-
self.assertRaises(ValueError, p.relative_to, P())
539+
self.assertRaises(ValueError, p.relative_to, P(''))
540540
self.assertRaises(ValueError, p.relative_to, '')
541541
self.assertRaises(ValueError, p.relative_to, P('a'))
542542
self.assertRaises(ValueError, p.relative_to, P("../a"))
@@ -553,7 +553,7 @@ def test_is_relative_to_common(self):
553553
p = P('a/b')
554554
self.assertRaises(TypeError, p.is_relative_to)
555555
self.assertRaises(TypeError, p.is_relative_to, b'a')
556-
self.assertTrue(p.is_relative_to(P()))
556+
self.assertTrue(p.is_relative_to(P('')))
557557
self.assertTrue(p.is_relative_to(''))
558558
self.assertTrue(p.is_relative_to(P('a')))
559559
self.assertTrue(p.is_relative_to('a/'))
@@ -576,7 +576,7 @@ def test_is_relative_to_common(self):
576576
self.assertFalse(p.is_relative_to(P('/c')))
577577
self.assertFalse(p.is_relative_to(P('/a/b/c')))
578578
self.assertFalse(p.is_relative_to(P('/a/c')))
579-
self.assertFalse(p.is_relative_to(P()))
579+
self.assertFalse(p.is_relative_to(P('')))
580580
self.assertFalse(p.is_relative_to(''))
581581
self.assertFalse(p.is_relative_to(P('a')))
582582

@@ -590,7 +590,7 @@ class PathBaseTest(PurePathBaseTest):
590590

591591
def test_unsupported_operation(self):
592592
P = self.cls
593-
p = self.cls()
593+
p = self.cls('')
594594
e = UnsupportedOperation
595595
self.assertRaises(e, p.stat)
596596
self.assertRaises(e, p.lstat)
@@ -634,13 +634,13 @@ def test_unsupported_operation(self):
634634

635635
def test_as_uri_common(self):
636636
e = UnsupportedOperation
637-
self.assertRaises(e, self.cls().as_uri)
637+
self.assertRaises(e, self.cls('').as_uri)
638638

639639
def test_fspath_common(self):
640-
self.assertRaises(TypeError, os.fspath, self.cls())
640+
self.assertRaises(TypeError, os.fspath, self.cls(''))
641641

642642
def test_as_bytes_common(self):
643-
self.assertRaises(TypeError, bytes, self.cls())
643+
self.assertRaises(TypeError, bytes, self.cls(''))
644644

645645

646646
class DummyPathIO(io.BytesIO):
@@ -993,7 +993,7 @@ def _check(glob, expected):
993993
_check(p.glob("*/"), ["dirA/", "dirB/", "dirC/", "dirE/", "linkB/"])
994994

995995
def test_glob_empty_pattern(self):
996-
p = self.cls()
996+
p = self.cls('')
997997
with self.assertRaisesRegex(ValueError, 'Unacceptable pattern'):
998998
list(p.glob(''))
999999

@@ -1554,7 +1554,7 @@ def _check_complex_symlinks(self, link0_target):
15541554

15551555
# Resolve relative paths.
15561556
try:
1557-
self.cls().absolute()
1557+
self.cls('').absolute()
15581558
except UnsupportedOperation:
15591559
return
15601560
old_path = os.getcwd()

0 commit comments

Comments
 (0)