From 5cb33c5820762e7821e16c11fa4a09a51e190e34 Mon Sep 17 00:00:00 2001 From: hai shi Date: Sun, 28 Jul 2019 01:55:37 +0800 Subject: [PATCH 1/6] add a is_realative_to function in pathlib module --- Doc/library/pathlib.rst | 12 ++++++++++++ Lib/pathlib.py | 9 +++++++++ Lib/test/test_pathlib.py | 15 +++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index 166de8de1f062e..b8e8a410f28d5e 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -539,6 +539,18 @@ Pure paths provide the following methods and properties: ValueError: '/etc/passwd' does not start with '/usr' +.. method:: PurePath.is_relative_to(*other) + + Compute the boolean result that this path is relative to the path + represented by *other* or not. + + >>> p = PurePosixPath('/etc/passwd') + >>> p.is_relative_to('/etc') + True + >>> p.is_relative_to('/usr') + False + + .. method:: PurePath.with_name(name) Return a new path with the :attr:`name` changed. If the original path diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 6369c4b2218d33..0a86e12630462c 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -886,6 +886,15 @@ def relative_to(self, *other): return self._from_parsed_parts('', root if n == 1 else '', abs_parts[n:]) + def is_relative_to(self, *other): + """Return True if the path is relative to another path or False. + """ + try: + self.relative_to(*other) + return True + except ValueError: + return False + @property def parts(self): """An object providing sequence-like access to the diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 069467a8459f00..58945ca644178d 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -619,6 +619,21 @@ def test_relative_to_common(self): self.assertRaises(ValueError, p.relative_to, '') self.assertRaises(ValueError, p.relative_to, P('a')) + def test_is_relative_to(self): + P = self.cls + 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())) + # With several args. + self.assertTrue(p.is_relative_to('a', 'b')) + # Unrelated paths. + 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('/a'))) + self.assertFalse(p.is_relative_to('/a')) + def test_pickling_common(self): P = self.cls p = P('/a/b') From d5c4f8ec1447aae0e917530b97a082542da9f520 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sat, 27 Jul 2019 18:00:44 +0000 Subject: [PATCH 2/6] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NEWS.d/next/Library/2019-07-27-18-00-43.bpo-37689.glEmZi.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2019-07-27-18-00-43.bpo-37689.glEmZi.rst diff --git a/Misc/NEWS.d/next/Library/2019-07-27-18-00-43.bpo-37689.glEmZi.rst b/Misc/NEWS.d/next/Library/2019-07-27-18-00-43.bpo-37689.glEmZi.rst new file mode 100644 index 00000000000000..f402a69eceef7c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-27-18-00-43.bpo-37689.glEmZi.rst @@ -0,0 +1 @@ +Add an is_relative_to() in PurePath class to compute a path is relative to the path or not. \ No newline at end of file From 92657049084ffa33f5b21ec57584dc98b11fa328 Mon Sep 17 00:00:00 2001 From: hai shi Date: Sun, 28 Jul 2019 17:02:55 +0800 Subject: [PATCH 3/6] update descr of is_relative_to() --- Doc/library/pathlib.rst | 8 +++++--- .../next/Library/2019-07-27-18-00-43.bpo-37689.glEmZi.rst | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index b8e8a410f28d5e..095d0bd04f8e0b 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -541,15 +541,17 @@ Pure paths provide the following methods and properties: .. method:: PurePath.is_relative_to(*other) - Compute the boolean result that this path is relative to the path - represented by *other* or not. + Return the boolean result that this path is relative to *other* path. - >>> p = PurePosixPath('/etc/passwd') + >>> from pathlib import PurePath + >>> p = PurePath('/etc/passwd') >>> p.is_relative_to('/etc') True >>> p.is_relative_to('/usr') False + .. versionadded:: 3.9 + .. method:: PurePath.with_name(name) diff --git a/Misc/NEWS.d/next/Library/2019-07-27-18-00-43.bpo-37689.glEmZi.rst b/Misc/NEWS.d/next/Library/2019-07-27-18-00-43.bpo-37689.glEmZi.rst index f402a69eceef7c..2787f9e849c20b 100644 --- a/Misc/NEWS.d/next/Library/2019-07-27-18-00-43.bpo-37689.glEmZi.rst +++ b/Misc/NEWS.d/next/Library/2019-07-27-18-00-43.bpo-37689.glEmZi.rst @@ -1 +1 @@ -Add an is_relative_to() in PurePath class to compute a path is relative to the path or not. \ No newline at end of file +Add :meth:`is_relative_to` in :class:`PurePath` to determine whether or not one path is relative to another. From 62eac3a4a6a367d68071e5ac19b800e0d1fc5c94 Mon Sep 17 00:00:00 2001 From: hai shi Date: Mon, 29 Jul 2019 23:31:50 +0800 Subject: [PATCH 4/6] update test cases and desc --- Doc/library/pathlib.rst | 28 +++++++-------- Lib/test/test_pathlib.py | 76 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 88 insertions(+), 16 deletions(-) diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index 095d0bd04f8e0b..e232fb81fe93a3 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -462,6 +462,20 @@ Pure paths provide the following methods and properties: True +.. method:: PurePath.is_relative_to(*other) + + Return whether or not this path is relative to the *other* path. + + >>> from pathlib import PurePath + >>> p = PurePath('/etc/passwd') + >>> p.is_relative_to('/etc') + True + >>> p.is_relative_to('/usr') + False + + .. versionadded:: 3.9 + + .. method:: PurePath.is_reserved() With :class:`PureWindowsPath`, return ``True`` if the path is considered @@ -539,20 +553,6 @@ Pure paths provide the following methods and properties: ValueError: '/etc/passwd' does not start with '/usr' -.. method:: PurePath.is_relative_to(*other) - - Return the boolean result that this path is relative to *other* path. - - >>> from pathlib import PurePath - >>> p = PurePath('/etc/passwd') - >>> p.is_relative_to('/etc') - True - >>> p.is_relative_to('/usr') - False - - .. versionadded:: 3.9 - - .. method:: PurePath.with_name(name) Return a new path with the :attr:`name` changed. If the original path diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 58945ca644178d..f372d191a15fbe 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -619,12 +619,17 @@ def test_relative_to_common(self): self.assertRaises(ValueError, p.relative_to, '') self.assertRaises(ValueError, p.relative_to, P('a')) - def test_is_relative_to(self): + def test_is_relative_to_common(self): P = self.cls 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('')) + self.assertTrue(p.is_relative_to(P('a'))) + self.assertTrue(p.is_relative_to('a/')) + self.assertTrue(p.is_relative_to(P('a/b'))) + self.assertTrue(p.is_relative_to('a/b')) # With several args. self.assertTrue(p.is_relative_to('a', 'b')) # Unrelated paths. @@ -632,7 +637,21 @@ def test_is_relative_to(self): 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('/a'))) - self.assertFalse(p.is_relative_to('/a')) + p = P('/a/b') + 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')) + self.assertTrue(p.is_relative_to('/a/')) + self.assertTrue(p.is_relative_to(P('/a/b'))) + self.assertTrue(p.is_relative_to('/a/b')) + # Unrelated paths. + 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('')) + self.assertFalse(p.is_relative_to(P('a'))) def test_pickling_common(self): P = self.cls @@ -1077,6 +1096,59 @@ def test_relative_to(self): self.assertRaises(ValueError, p.relative_to, P('//z/Share/Foo')) self.assertRaises(ValueError, p.relative_to, P('//Server/z/Foo')) + def test_is_relative_to(self): + P = self.cls + p = P('C:Foo/Bar') + self.assertTrue(p.is_relative_to(P('c:'))) + self.assertTrue(p.is_relative_to('c:')) + self.assertTrue(p.is_relative_to(P('c:foO'))) + self.assertTrue(p.is_relative_to('c:foO')) + self.assertTrue(p.is_relative_to('c:foO/')) + self.assertTrue(p.is_relative_to(P('c:foO/baR'))) + self.assertTrue(p.is_relative_to('c:foO/baR')) + # Unrelated paths. + self.assertFalse(p.is_relative_to(P())) + self.assertFalse(p.is_relative_to('')) + self.assertFalse(p.is_relative_to(P('d:'))) + self.assertFalse(p.is_relative_to(P('/'))) + self.assertFalse(p.is_relative_to(P('Foo'))) + self.assertFalse(p.is_relative_to(P('/Foo'))) + self.assertFalse(p.is_relative_to(P('C:/Foo'))) + self.assertFalse(p.is_relative_to(P('C:Foo/Bar/Baz'))) + self.assertFalse(p.is_relative_to(P('C:Foo/Baz'))) + p = P('C:/Foo/Bar') + self.assertTrue(p.is_relative_to('c:')) + self.assertTrue(p.is_relative_to(P('c:/'))) + self.assertTrue(p.is_relative_to(P('c:/foO'))) + self.assertTrue(p.is_relative_to('c:/foO/')) + self.assertTrue(p.is_relative_to(P('c:/foO/baR'))) + self.assertTrue(p.is_relative_to('c:/foO/baR')) + # Unrelated paths. + self.assertFalse(p.is_relative_to(P('C:/Baz'))) + self.assertFalse(p.is_relative_to(P('C:/Foo/Bar/Baz'))) + self.assertFalse(p.is_relative_to(P('C:/Foo/Baz'))) + self.assertFalse(p.is_relative_to(P('C:Foo'))) + self.assertFalse(p.is_relative_to(P('d:'))) + self.assertFalse(p.is_relative_to(P('d:/'))) + self.assertFalse(p.is_relative_to(P('/'))) + self.assertFalse(p.is_relative_to(P('/Foo'))) + self.assertFalse(p.is_relative_to(P('//C/Foo'))) + # UNC paths. + p = P('//Server/Share/Foo/Bar') + self.assertTrue(p.is_relative_to(P('//sErver/sHare'))) + self.assertTrue(p.is_relative_to('//sErver/sHare')) + self.assertTrue(p.is_relative_to('//sErver/sHare/')) + self.assertTrue(p.is_relative_to(P('//sErver/sHare/Foo'))) + self.assertTrue(p.is_relative_to('//sErver/sHare/Foo')) + self.assertTrue(p.is_relative_to('//sErver/sHare/Foo/')) + self.assertTrue(p.is_relative_to(P('//sErver/sHare/Foo/Bar'))) + self.assertTrue(p.is_relative_to('//sErver/sHare/Foo/Bar')) + # Unrelated paths. + self.assertFalse(p.is_relative_to(P('/Server/Share/Foo'))) + self.assertFalse(p.is_relative_to(P('c:/Server/Share/Foo'))) + self.assertFalse(p.is_relative_to(P('//z/Share/Foo'))) + self.assertFalse(p.is_relative_to(P('//Server/z/Foo'))) + def test_is_absolute(self): P = self.cls # Under NT, only paths with both a drive and a root are absolute. From 3a42052f7723531fc07abc331b27e70546823b47 Mon Sep 17 00:00:00 2001 From: hai shi Date: Tue, 13 Aug 2019 22:47:14 +0800 Subject: [PATCH 5/6] update docs --- Doc/library/pathlib.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index e232fb81fe93a3..1af5261ca43719 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -466,7 +466,6 @@ Pure paths provide the following methods and properties: Return whether or not this path is relative to the *other* path. - >>> from pathlib import PurePath >>> p = PurePath('/etc/passwd') >>> p.is_relative_to('/etc') True From 9939817b13c9452a06c65c7479f727e656ffdf65 Mon Sep 17 00:00:00 2001 From: hai shi Date: Wed, 14 Aug 2019 01:00:38 +0800 Subject: [PATCH 6/6] import PurePath in testsetup --- Doc/library/pathlib.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index 1af5261ca43719..33fac5f6972583 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -273,7 +273,7 @@ Methods and properties .. testsetup:: - from pathlib import PurePosixPath, PureWindowsPath + from pathlib import PurePath, PurePosixPath, PureWindowsPath Pure paths provide the following methods and properties: