]> granicus.if.org Git - python/commitdiff
Issue #19908: pathlib now joins relative Windows paths correctly when a drive
authorSerhiy Storchaka <storchaka@gmail.com>
Fri, 6 Dec 2013 15:14:12 +0000 (17:14 +0200)
committerSerhiy Storchaka <storchaka@gmail.com>
Fri, 6 Dec 2013 15:14:12 +0000 (17:14 +0200)
is present.  Original patch by Antoine Pitrou.

Lib/pathlib.py
Lib/test/test_pathlib.py
Misc/NEWS

index 73bf9df5b659e1cf5d556775f1f71230fe013322..b404c1f023f470bc00861bc5dba19d0b9858ea7d 100644 (file)
@@ -89,12 +89,16 @@ class _Flavour(object):
         (drive, root, parts) tuples.  Return a new (drive, root, parts) tuple.
         """
         if root2:
-            parts = parts2
-            root = root2
+            if not drv2 and drv:
+                return drv, root2, [drv + root2] + parts2[1:]
+        elif drv2:
+            if drv2 == drv or self.casefold(drv2) == self.casefold(drv):
+                # Same drive => second path is relative to the first
+                return drv, root, parts + parts2[1:]
         else:
-            parts = parts + parts2
-        # XXX raise error if drv and drv2 are different?
-        return drv2 or drv, root, parts
+            # Second path is non-anchored (common case)
+            return drv, root, parts + parts2
+        return drv2, root2, parts2
 
 
 class _WindowsFlavour(_Flavour):
index 2b8b2c1a7d6361ed8ee499e5ab31659bfac84716..4149c9ede123e9a843ab1e52109e7978f581946b 100755 (executable)
@@ -975,6 +975,48 @@ class PureWindowsPathTest(_BasePurePathTest, unittest.TestCase):
         self.assertTrue(P('//a/b/c').is_absolute())
         self.assertTrue(P('//a/b/c/d').is_absolute())
 
+    def test_join(self):
+        P = self.cls
+        p = P('C:/a/b')
+        pp = p.joinpath('x/y')
+        self.assertEqual(pp, P('C:/a/b/x/y'))
+        pp = p.joinpath('/x/y')
+        self.assertEqual(pp, P('C:/x/y'))
+        # Joining with a different drive => the first path is ignored, even
+        # if the second path is relative.
+        pp = p.joinpath('D:x/y')
+        self.assertEqual(pp, P('D:x/y'))
+        pp = p.joinpath('D:/x/y')
+        self.assertEqual(pp, P('D:/x/y'))
+        pp = p.joinpath('//host/share/x/y')
+        self.assertEqual(pp, P('//host/share/x/y'))
+        # Joining with the same drive => the first path is appended to if
+        # the second path is relative.
+        pp = p.joinpath('c:x/y')
+        self.assertEqual(pp, P('C:/a/b/x/y'))
+        pp = p.joinpath('c:/x/y')
+        self.assertEqual(pp, P('C:/x/y'))
+
+    def test_div(self):
+        # Basically the same as joinpath()
+        P = self.cls
+        p = P('C:/a/b')
+        self.assertEqual(p / 'x/y', P('C:/a/b/x/y'))
+        self.assertEqual(p / 'x' / 'y', P('C:/a/b/x/y'))
+        self.assertEqual(p / '/x/y', P('C:/x/y'))
+        self.assertEqual(p / '/x' / 'y', P('C:/x/y'))
+        # Joining with a different drive => the first path is ignored, even
+        # if the second path is relative.
+        self.assertEqual(p / 'D:x/y', P('D:x/y'))
+        self.assertEqual(p / 'D:' / 'x/y', P('D:x/y'))
+        self.assertEqual(p / 'D:/x/y', P('D:/x/y'))
+        self.assertEqual(p / 'D:' / '/x/y', P('D:/x/y'))
+        self.assertEqual(p / '//host/share/x/y', P('//host/share/x/y'))
+        # Joining with the same drive => the first path is appended to if
+        # the second path is relative.
+        self.assertEqual(p / 'C:x/y', P('C:/a/b/x/y'))
+        self.assertEqual(p / 'C:/x/y', P('C:/x/y'))
+
     def test_is_reserved(self):
         P = self.cls
         self.assertIs(False, P('').is_reserved())
index 2d7acddbb1fc84fbec41a0f2eae4fcc6a4bb497f..58c4eec1d9cf2cbf2612f01a5e164ac16f493964 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -18,6 +18,8 @@ Core and Builtins
 Library
 -------
 
+- Issue #19908: pathlib now joins relative Windows paths correctly when a drive
+  is present.  Original patch by Antoine Pitrou.
 
 - Issue #19296: Silence compiler warning in dbm_open