diff --git a/Lib/pathlib.py b/Lib/pathlib.py index c48cff307083a8..8f2532f8119aab 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -274,7 +274,7 @@ def _parse_path(cls, path): elif len(drv_parts) == 6: # e.g. //?/unc/server/share root = sep - parsed = [sys.intern(str(x)) for x in rel.split(sep) if x and x != '.'] + parsed = [x for x in rel.split(sep) if x and x != '.'] return drv, root, parsed def _load_parts(self): @@ -606,7 +606,7 @@ def __init__(self, *args): def __reduce__(self): # Using the parts tuple helps share interned path parts # when pickling related paths. - return (self.__class__, self.parts) + return (self.__class__, tuple(self._raw_paths)) def __fspath__(self): return str(self) diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 1b10d6c2f0cb19..f3b550de297178 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -695,14 +695,19 @@ def test_is_relative_to_common(self): def test_pickling_common(self): P = self.cls - p = P('/a/b') - for proto in range(0, pickle.HIGHEST_PROTOCOL + 1): - dumped = pickle.dumps(p, proto) - pp = pickle.loads(dumped) - self.assertIs(pp.__class__, p.__class__) - self.assertEqual(pp, p) - self.assertEqual(hash(pp), hash(p)) - self.assertEqual(str(pp), str(p)) + paths = [ + P('a'), P('a', 'b'), P('a/b'), P('a', 'b', 'c'), P('a/b/c'), + P('/'), P('/a', 'b'), P('/a/b'), P('/a', 'b', 'c'), P('/a/b/c'), + ] + for p in paths: + with self.subTest(path=p): + for proto in range(0, pickle.HIGHEST_PROTOCOL + 1): + dumped = pickle.dumps(p, proto) + pp = pickle.loads(dumped) + self.assertIs(pp.__class__, p.__class__) + self.assertEqual(pp, p) + self.assertEqual(hash(pp), hash(p)) + self.assertEqual(str(pp), str(p)) def test_fspath_common(self): P = self.cls @@ -2545,22 +2550,6 @@ def test_is_char_device_false(self): self.assertIs((P / 'fileA\udfff').is_char_device(), False) self.assertIs((P / 'fileA\x00').is_char_device(), False) - def test_pickling_common(self): - p = self.cls(BASE, 'fileA') - for proto in range(0, pickle.HIGHEST_PROTOCOL + 1): - dumped = pickle.dumps(p, proto) - pp = pickle.loads(dumped) - self.assertEqual(pp.stat(), p.stat()) - - def test_parts_interning(self): - P = self.cls - p = P('/usr/bin/foo') - q = P('/usr/local/bin') - # 'usr' - self.assertIs(p.parts[1], q.parts[1]) - # 'bin' - self.assertIs(p.parts[2], q.parts[3]) - def _check_complex_symlinks(self, link0_target): if not self.can_symlink: self.skipTest("symlinks required") diff --git a/Misc/NEWS.d/next/Library/2023-12-07-20-05-54.gh-issue-112855.ph4ehh.rst b/Misc/NEWS.d/next/Library/2023-12-07-20-05-54.gh-issue-112855.ph4ehh.rst new file mode 100644 index 00000000000000..6badc7a9dc1c94 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-07-20-05-54.gh-issue-112855.ph4ehh.rst @@ -0,0 +1,2 @@ +Speed up pickling of :class:`pathlib.PurePath` objects. Patch by Barney +Gale.