Skip to content

Commit 0ed23a5

Browse files
committed
GH-126601: pathname2url(): handle NTFS alternate data streams
Adjust `pathname2url()` to encode embedded colon characters in Windows paths, rather than bailing out with an `OSError`.
1 parent bf224bd commit 0ed23a5

File tree

3 files changed

+11
-12
lines changed

3 files changed

+11
-12
lines changed

Lib/nturl2path.py

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ def pathname2url(p):
4141
# C:\foo\bar\spam.foo
4242
# becomes
4343
# ///C:/foo/bar/spam.foo
44+
import ntpath
4445
import urllib.parse
4546
# First, clean up some special forms. We are going to sacrifice
4647
# the additional information anyway
@@ -49,16 +50,10 @@ def pathname2url(p):
4950
p = p[4:]
5051
if p[:4].upper() == 'UNC/':
5152
p = '//' + p[4:]
52-
elif p[1:2] != ':':
53-
raise OSError('Bad path: ' + p)
54-
if not ':' in p:
53+
drive, tail = ntpath.splitdrive(p)
54+
if drive[1:2] != ':':
5555
# No DOS drive specified, just quote the pathname
5656
return urllib.parse.quote(p)
57-
comp = p.split(':', maxsplit=2)
58-
if len(comp) != 2 or len(comp[0]) > 1:
59-
error = 'Bad path: ' + p
60-
raise OSError(error)
61-
62-
drive = urllib.parse.quote(comp[0].upper())
63-
tail = urllib.parse.quote(comp[1])
57+
drive = urllib.parse.quote(drive[0].upper())
58+
tail = urllib.parse.quote(tail)
6459
return '///' + drive + ':' + tail

Lib/test/test_urllib.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1533,8 +1533,9 @@ def test_pathname2url_win(self):
15331533
self.assertEqual(fn('C:\\a\\b%#c'), '///C:/a/b%25%23c')
15341534
self.assertEqual(fn('C:\\a\\b\xe9'), '///C:/a/b%C3%A9')
15351535
self.assertEqual(fn('C:\\foo\\bar\\spam.foo'), "///C:/foo/bar/spam.foo")
1536-
# Long drive letter
1537-
self.assertRaises(IOError, fn, "XX:\\")
1536+
# NTFS alternate data streams
1537+
self.assertEqual(fn('C:\\foo:bar'), '///C:/foo%3Abar')
1538+
self.assertEqual(fn('foo:bar'), 'foo%3Abar')
15381539
# No drive letter
15391540
self.assertEqual(fn("\\folder\\test\\"), '/folder/test/')
15401541
self.assertEqual(fn("\\\\folder\\test\\"), '//folder/test/')
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix issue where :func:`urllib.request.pathname2url` raised :exc:`OSError`
2+
when given a Windows path containing a colon character not following a
3+
drive letter, such as before an NTFS alternate data stream.

0 commit comments

Comments
 (0)