mirror of
https://github.com/python/cpython.git
synced 2025-10-26 19:24:34 +00:00
GH-113528: Deoptimise pathlib._abc.PurePathBase (#113559)
Apply pathlib's normalization and performance tuning in `pathlib.PurePath`, but not `pathlib._abc.PurePathBase`. With this change, the pathlib ABCs do not normalize away alternate path separators, empty segments, or dot segments. A single string given to the initialiser will round-trip by default, i.e. `str(PurePathBase(my_string)) == my_string`. Implementors can set their own path domain-specific normalization scheme by overriding `__str__()` Eliminating path normalization makes maintaining and caching the path's parts and string representation both optional and not very useful, so this commit moves the `_drv`, `_root`, `_tail_cached` and `_str` slots from `PurePathBase` to `PurePath`. Only `_raw_paths` and `_resolving` slots remain in `PurePathBase`. This frees the ABCs from the burden of some of pathlib's hardest-to-understand code.
This commit is contained in:
parent
57bdc6c30d
commit
beb80d11ec
4 changed files with 195 additions and 140 deletions
|
|
@ -140,6 +140,8 @@ def test_empty_path(self):
|
|||
# The empty path points to '.'
|
||||
p = self.cls('')
|
||||
self.assertEqual(str(p), '.')
|
||||
# Special case for the empty path.
|
||||
self._check_str('.', ('',))
|
||||
|
||||
def test_parts_interning(self):
|
||||
P = self.cls
|
||||
|
|
@ -300,6 +302,40 @@ def test_repr_roundtrips(self):
|
|||
self.assertEqual(q, p)
|
||||
self.assertEqual(repr(q), r)
|
||||
|
||||
def test_name_empty(self):
|
||||
P = self.cls
|
||||
self.assertEqual(P('').name, '')
|
||||
self.assertEqual(P('.').name, '')
|
||||
self.assertEqual(P('/a/b/.').name, 'b')
|
||||
|
||||
def test_stem_empty(self):
|
||||
P = self.cls
|
||||
self.assertEqual(P('').stem, '')
|
||||
self.assertEqual(P('.').stem, '')
|
||||
|
||||
def test_with_name_empty(self):
|
||||
P = self.cls
|
||||
self.assertRaises(ValueError, P('').with_name, 'd.xml')
|
||||
self.assertRaises(ValueError, P('.').with_name, 'd.xml')
|
||||
self.assertRaises(ValueError, P('/').with_name, 'd.xml')
|
||||
self.assertRaises(ValueError, P('a/b').with_name, '')
|
||||
self.assertRaises(ValueError, P('a/b').with_name, '.')
|
||||
|
||||
def test_with_stem_empty(self):
|
||||
P = self.cls
|
||||
self.assertRaises(ValueError, P('').with_stem, 'd')
|
||||
self.assertRaises(ValueError, P('.').with_stem, 'd')
|
||||
self.assertRaises(ValueError, P('/').with_stem, 'd')
|
||||
self.assertRaises(ValueError, P('a/b').with_stem, '')
|
||||
self.assertRaises(ValueError, P('a/b').with_stem, '.')
|
||||
|
||||
def test_with_suffix_empty(self):
|
||||
# Path doesn't have a "filename" component.
|
||||
P = self.cls
|
||||
self.assertRaises(ValueError, P('').with_suffix, '.gz')
|
||||
self.assertRaises(ValueError, P('.').with_suffix, '.gz')
|
||||
self.assertRaises(ValueError, P('/').with_suffix, '.gz')
|
||||
|
||||
def test_relative_to_several_args(self):
|
||||
P = self.cls
|
||||
p = P('a/b')
|
||||
|
|
@ -313,6 +349,11 @@ def test_is_relative_to_several_args(self):
|
|||
with self.assertWarns(DeprecationWarning):
|
||||
p.is_relative_to('a', 'b')
|
||||
|
||||
def test_match_empty(self):
|
||||
P = self.cls
|
||||
self.assertRaises(ValueError, P('a').match, '')
|
||||
self.assertRaises(ValueError, P('a').match, '.')
|
||||
|
||||
|
||||
class PurePosixPathTest(PurePathTest):
|
||||
cls = pathlib.PurePosixPath
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue