From 7ecac07e7be78817ec12ee5839abb5706379014c Mon Sep 17 00:00:00 2001 From: Joshua Cannon Date: Fri, 14 Dec 2018 13:11:39 -0600 Subject: [PATCH 1/6] Added slice support to PathLib parents attribute. --- Lib/pathlib.py | 2 ++ Lib/test/test_pathlib.py | 25 +++++++++++++++++++ Misc/ACKS | 1 + .../2018-12-14-13-29-17.bpo-35498.LEJHl7.rst | 1 + 4 files changed, 29 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2018-12-14-13-29-17.bpo-35498.LEJHl7.rst diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 89dffa5561a7a5..20443c33f0b390 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -583,6 +583,8 @@ def __len__(self): return len(self._parts) def __getitem__(self, idx): + if isinstance(idx, slice): + return [self[i] for i in range(*idx.indices(len(self)))] if idx < 0 or idx >= len(self): raise IndexError(idx) return self._pathcls._from_parsed_parts(self._drv, self._root, diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index d3fd4bd9e6b7ef..1d3b8a62bf210c 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -436,6 +436,11 @@ def test_parents_common(self): self.assertEqual(par[0], P('a/b')) self.assertEqual(par[1], P('a')) self.assertEqual(par[2], P('.')) + self.assertEqual(par[0:1], [P('a/b')]) + self.assertEqual(par[:2], [P('a/b'), P('a')]) + self.assertEqual(par[:-1], [P('a/b'), P('a')]) + self.assertEqual(par[1:], [P('a'), P('.')]) + self.assertEqual(par[::2], [P('a/b'), P('.')]) self.assertEqual(list(par), [P('a/b'), P('a'), P('.')]) with self.assertRaises(IndexError): par[-1] @@ -450,6 +455,11 @@ def test_parents_common(self): self.assertEqual(par[0], P('/a/b')) self.assertEqual(par[1], P('/a')) self.assertEqual(par[2], P('/')) + self.assertEqual(par[0:1], [P('/a/b')]) + self.assertEqual(par[:2], [P('/a/b'), P('/a')]) + self.assertEqual(par[:-1], [P('/a/b'), P('/a')]) + self.assertEqual(par[1:], [P('/a'), P('/')]) + self.assertEqual(par[::2], [P('/a/b'), P('/')]) self.assertEqual(list(par), [P('/a/b'), P('/a'), P('/')]) with self.assertRaises(IndexError): par[3] @@ -850,6 +860,11 @@ def test_parents(self): self.assertEqual(len(par), 2) self.assertEqual(par[0], P('z:a')) self.assertEqual(par[1], P('z:')) + self.assertEqual(par[0:1], [P('z:a')]) + self.assertEqual(par[:-1], [P('z:a')]) + self.assertEqual(par[:2], [P('z:a'), P('z:')]) + self.assertEqual(par[1:], [P('z:')]) + self.assertEqual(par[::2], [P('z:a')]) self.assertEqual(list(par), [P('z:a'), P('z:')]) with self.assertRaises(IndexError): par[2] @@ -858,6 +873,11 @@ def test_parents(self): self.assertEqual(len(par), 2) self.assertEqual(par[0], P('z:/a')) self.assertEqual(par[1], P('z:/')) + self.assertEqual(par[0:1], [P('z:/a')]) + self.assertEqual(par[0:-1], [P('z:/a')]) + self.assertEqual(par[:2], [P('z:/a'), P('z:/')]) + self.assertEqual(par[1:], [P('z:/')]) + self.assertEqual(par[::2], [P('z:/a')]) self.assertEqual(list(par), [P('z:/a'), P('z:/')]) with self.assertRaises(IndexError): par[2] @@ -866,6 +886,11 @@ def test_parents(self): self.assertEqual(len(par), 2) self.assertEqual(par[0], P('//a/b/c')) self.assertEqual(par[1], P('//a/b')) + self.assertEqual(par[0:1], [P('//a/b/c')]) + self.assertEqual(par[0:-1], [P('//a/b/c')]) + self.assertEqual(par[:2], [P('//a/b/c'), P('//a/b')]) + self.assertEqual(par[1:], [P('//a/b')]) + self.assertEqual(par[::2], [P('//a/b/c')]) self.assertEqual(list(par), [P('//a/b/c'), P('//a/b')]) with self.assertRaises(IndexError): par[2] diff --git a/Misc/ACKS b/Misc/ACKS index 3e5fa0a2facc57..892a957cdd0032 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -246,6 +246,7 @@ Arnaud Calmettes Daniel Calvelo Tony Campbell Brett Cannon +Joshua Cannon Tristan Carel Mike Carlton Pierre Carrier diff --git a/Misc/NEWS.d/next/Library/2018-12-14-13-29-17.bpo-35498.LEJHl7.rst b/Misc/NEWS.d/next/Library/2018-12-14-13-29-17.bpo-35498.LEJHl7.rst new file mode 100644 index 00000000000000..6fd8ee385091f0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-12-14-13-29-17.bpo-35498.LEJHl7.rst @@ -0,0 +1 @@ +Add slice support to :meth:`PathLib._PathParents.__getitem__`. From 08dae4f9272dd444f95fbf2a7d92edb9124018e9 Mon Sep 17 00:00:00 2001 From: Joshua Cannon Date: Thu, 19 Nov 2020 13:55:47 -0600 Subject: [PATCH 2/6] Update Lib/pathlib.py Co-authored-by: Paul Ganssle --- Lib/pathlib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 20443c33f0b390..6e62b08093b8ba 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -584,7 +584,7 @@ def __len__(self): def __getitem__(self, idx): if isinstance(idx, slice): - return [self[i] for i in range(*idx.indices(len(self)))] + return tuple(self[i] for i in range(*idx.indices(len(self)))) if idx < 0 or idx >= len(self): raise IndexError(idx) return self._pathcls._from_parsed_parts(self._drv, self._root, From 9e49f1c2c6609f7f65d9e39104eebd812886991c Mon Sep 17 00:00:00 2001 From: Joshua Cannon Date: Thu, 19 Nov 2020 15:49:23 -0600 Subject: [PATCH 3/6] Add reverse slice tests --- Lib/test/test_pathlib.py | 59 ++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 1554a4ab9dabc8..34aa64cdc07e96 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -440,12 +440,13 @@ def test_parents_common(self): self.assertEqual(par[0], P('a/b')) self.assertEqual(par[1], P('a')) self.assertEqual(par[2], P('.')) - self.assertEqual(par[0:1], [P('a/b')]) - self.assertEqual(par[:2], [P('a/b'), P('a')]) - self.assertEqual(par[:-1], [P('a/b'), P('a')]) - self.assertEqual(par[1:], [P('a'), P('.')]) - self.assertEqual(par[::2], [P('a/b'), P('.')]) - self.assertEqual(list(par), [P('a/b'), P('a'), P('.')]) + self.assertEqual(par[0:1], (P('a/b'),)) + self.assertEqual(par[:2], (P('a/b'), P('a'))) + self.assertEqual(par[:-1], (P('a/b'), P('a'))) + self.assertEqual(par[1:], (P('a'), P('.'))) + self.assertEqual(par[::2], (P('a/b'), P('.'))) + self.assertEqual(par[::-1], (P('.'), P('a/b'))) + self.assertEqual(list(par), (P('a/b'), P('a'), P('.'))) with self.assertRaises(IndexError): par[-1] with self.assertRaises(IndexError): @@ -459,12 +460,13 @@ def test_parents_common(self): self.assertEqual(par[0], P('/a/b')) self.assertEqual(par[1], P('/a')) self.assertEqual(par[2], P('/')) - self.assertEqual(par[0:1], [P('/a/b')]) - self.assertEqual(par[:2], [P('/a/b'), P('/a')]) - self.assertEqual(par[:-1], [P('/a/b'), P('/a')]) - self.assertEqual(par[1:], [P('/a'), P('/')]) - self.assertEqual(par[::2], [P('/a/b'), P('/')]) - self.assertEqual(list(par), [P('/a/b'), P('/a'), P('/')]) + self.assertEqual(par[0:1], (P('/a/b'),)) + self.assertEqual(par[:2], (P('/a/b'), P('/a'))) + self.assertEqual(par[:-1], (P('/a/b'), P('/a'))) + self.assertEqual(par[1:], (P('/a'), P('/'))) + self.assertEqual(par[::2], (P('/a/b'), P('/'))) + self.assertEqual(par[::-1], (P('/'), P('/a/b'))) + self.assertEqual(list(par), (P('/a/b'), P('/a'), P('/'))) with self.assertRaises(IndexError): par[3] @@ -915,11 +917,12 @@ def test_parents(self): self.assertEqual(len(par), 2) self.assertEqual(par[0], P('z:a')) self.assertEqual(par[1], P('z:')) - self.assertEqual(par[0:1], [P('z:a')]) - self.assertEqual(par[:-1], [P('z:a')]) - self.assertEqual(par[:2], [P('z:a'), P('z:')]) - self.assertEqual(par[1:], [P('z:')]) - self.assertEqual(par[::2], [P('z:a')]) + self.assertEqual(par[0:1], (P('z:a'),)) + self.assertEqual(par[:-1], (P('z:a'),)) + self.assertEqual(par[:2], (P('z:a'), P('z:'))) + self.assertEqual(par[1:], (P('z:'),)) + self.assertEqual(par[::2], (P('z:a'),)) + self.assertEqual(par[::-1], (P('z:a'),)) self.assertEqual(list(par), [P('z:a'), P('z:')]) with self.assertRaises(IndexError): par[2] @@ -928,11 +931,12 @@ def test_parents(self): self.assertEqual(len(par), 2) self.assertEqual(par[0], P('z:/a')) self.assertEqual(par[1], P('z:/')) - self.assertEqual(par[0:1], [P('z:/a')]) - self.assertEqual(par[0:-1], [P('z:/a')]) - self.assertEqual(par[:2], [P('z:/a'), P('z:/')]) - self.assertEqual(par[1:], [P('z:/')]) - self.assertEqual(par[::2], [P('z:/a')]) + self.assertEqual(par[0:1], (P('z:/a'),)) + self.assertEqual(par[0:-1], (P('z:/a'),)) + self.assertEqual(par[:2], (P('z:/a'), P('z:/'))) + self.assertEqual(par[1:], (P('z:/'),)) + self.assertEqual(par[::2], (P('z:/a'),)) + self.assertEqual(par[::-1], (P('z:/a'),)) self.assertEqual(list(par), [P('z:/a'), P('z:/')]) with self.assertRaises(IndexError): par[2] @@ -941,11 +945,12 @@ def test_parents(self): self.assertEqual(len(par), 2) self.assertEqual(par[0], P('//a/b/c')) self.assertEqual(par[1], P('//a/b')) - self.assertEqual(par[0:1], [P('//a/b/c')]) - self.assertEqual(par[0:-1], [P('//a/b/c')]) - self.assertEqual(par[:2], [P('//a/b/c'), P('//a/b')]) - self.assertEqual(par[1:], [P('//a/b')]) - self.assertEqual(par[::2], [P('//a/b/c')]) + self.assertEqual(par[0:1], (P('//a/b/c'),)) + self.assertEqual(par[0:-1], (P('//a/b/c'),)) + self.assertEqual(par[:2], (P('//a/b/c'), P('//a/b'))) + self.assertEqual(par[1:], (P('//a/b'),)) + self.assertEqual(par[::2], (P('//a/b/c'),)) + self.assertEqual(par[::-1], (P('//a/b/c'),)) self.assertEqual(list(par), [P('//a/b/c'), P('//a/b')]) with self.assertRaises(IndexError): par[2] From c76fb8fbdab5a32e77675e3c9a9913fd07fc06f7 Mon Sep 17 00:00:00 2001 From: Joshua Cannon Date: Thu, 19 Nov 2020 16:03:39 -0600 Subject: [PATCH 4/6] Update the rsts --- Doc/library/pathlib.rst | 2 ++ Doc/whatsnew/3.10.rst | 6 ++++++ .../next/Library/2018-12-14-13-29-17.bpo-35498.LEJHl7.rst | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index 9de72bb725c758..2071e7ed5f4bfe 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -336,6 +336,8 @@ Pure paths provide the following methods and properties: >>> p.parents[2] PureWindowsPath('c:/') + .. versionchanged:: 3.10 + Slice support was added. .. data:: PurePath.parent diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index ad0ec4def0b70b..3f58329687ebf4 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -244,6 +244,12 @@ descriptors without copying between kernel address space and user address space, where one of the file descriptors must refer to a pipe. (Contributed by Pablo Galindo in :issue:`41625`.) +pathlib +------- + +Added slice support to :meth:`~pathlib.Path.parents`. +(Contributed by Joshua Cannon in :issue:`35498`) + py_compile ---------- diff --git a/Misc/NEWS.d/next/Library/2018-12-14-13-29-17.bpo-35498.LEJHl7.rst b/Misc/NEWS.d/next/Library/2018-12-14-13-29-17.bpo-35498.LEJHl7.rst index 6fd8ee385091f0..fb24ce027c2186 100644 --- a/Misc/NEWS.d/next/Library/2018-12-14-13-29-17.bpo-35498.LEJHl7.rst +++ b/Misc/NEWS.d/next/Library/2018-12-14-13-29-17.bpo-35498.LEJHl7.rst @@ -1 +1 @@ -Add slice support to :meth:`PathLib._PathParents.__getitem__`. +Add slice support to :meth:`~pathlib.Path.parents`. From 6ee7f674fd42eb9429a6185b74f3e1c8ed6d784f Mon Sep 17 00:00:00 2001 From: Joshua Cannon Date: Thu, 19 Nov 2020 16:05:32 -0600 Subject: [PATCH 5/6] Fix reverse slice tests --- Lib/test/test_pathlib.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 34aa64cdc07e96..19ab8102b0770c 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -445,7 +445,7 @@ def test_parents_common(self): self.assertEqual(par[:-1], (P('a/b'), P('a'))) self.assertEqual(par[1:], (P('a'), P('.'))) self.assertEqual(par[::2], (P('a/b'), P('.'))) - self.assertEqual(par[::-1], (P('.'), P('a/b'))) + self.assertEqual(par[::-1], (P('.'), P('a'), P('a/b'))) self.assertEqual(list(par), (P('a/b'), P('a'), P('.'))) with self.assertRaises(IndexError): par[-1] @@ -465,7 +465,7 @@ def test_parents_common(self): self.assertEqual(par[:-1], (P('/a/b'), P('/a'))) self.assertEqual(par[1:], (P('/a'), P('/'))) self.assertEqual(par[::2], (P('/a/b'), P('/'))) - self.assertEqual(par[::-1], (P('/'), P('/a/b'))) + self.assertEqual(par[::-1], (P('/'), P('/a'), P('/a/b'))) self.assertEqual(list(par), (P('/a/b'), P('/a'), P('/'))) with self.assertRaises(IndexError): par[3] @@ -922,7 +922,7 @@ def test_parents(self): self.assertEqual(par[:2], (P('z:a'), P('z:'))) self.assertEqual(par[1:], (P('z:'),)) self.assertEqual(par[::2], (P('z:a'),)) - self.assertEqual(par[::-1], (P('z:a'),)) + self.assertEqual(par[::-1], (P('z:'), P('z:a'))) self.assertEqual(list(par), [P('z:a'), P('z:')]) with self.assertRaises(IndexError): par[2] @@ -936,7 +936,7 @@ def test_parents(self): self.assertEqual(par[:2], (P('z:/a'), P('z:/'))) self.assertEqual(par[1:], (P('z:/'),)) self.assertEqual(par[::2], (P('z:/a'),)) - self.assertEqual(par[::-1], (P('z:/a'),)) + self.assertEqual(par[::-1], (P('z:/'), P('z:/a'),)) self.assertEqual(list(par), [P('z:/a'), P('z:/')]) with self.assertRaises(IndexError): par[2] @@ -950,7 +950,7 @@ def test_parents(self): self.assertEqual(par[:2], (P('//a/b/c'), P('//a/b'))) self.assertEqual(par[1:], (P('//a/b'),)) self.assertEqual(par[::2], (P('//a/b/c'),)) - self.assertEqual(par[::-1], (P('//a/b/c'),)) + self.assertEqual(par[::-1], (P('//a/b'), P('//a/b/c'))) self.assertEqual(list(par), [P('//a/b/c'), P('//a/b')]) with self.assertRaises(IndexError): par[2] From c22c466ee056ae127d50fe56931b4d8b599827d7 Mon Sep 17 00:00:00 2001 From: Joshua Cannon Date: Thu, 19 Nov 2020 16:18:48 -0600 Subject: [PATCH 6/6] Fix list tests to use brackets again (oops) --- Lib/test/test_pathlib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 19ab8102b0770c..f1451796b6427d 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -446,7 +446,7 @@ def test_parents_common(self): self.assertEqual(par[1:], (P('a'), P('.'))) self.assertEqual(par[::2], (P('a/b'), P('.'))) self.assertEqual(par[::-1], (P('.'), P('a'), P('a/b'))) - self.assertEqual(list(par), (P('a/b'), P('a'), P('.'))) + self.assertEqual(list(par), [P('a/b'), P('a'), P('.')]) with self.assertRaises(IndexError): par[-1] with self.assertRaises(IndexError): @@ -466,7 +466,7 @@ def test_parents_common(self): self.assertEqual(par[1:], (P('/a'), P('/'))) self.assertEqual(par[::2], (P('/a/b'), P('/'))) self.assertEqual(par[::-1], (P('/'), P('/a'), P('/a/b'))) - self.assertEqual(list(par), (P('/a/b'), P('/a'), P('/'))) + self.assertEqual(list(par), [P('/a/b'), P('/a'), P('/')]) with self.assertRaises(IndexError): par[3]