Skip to content

Commit 033baf5

Browse files
committed
GH-125866: Add tests for nturl2path module
Add `tests.test_nturl2path` to exercise `nturl2path`. `nturl2path` is currently used by `urllib` and tested by `test_urllib`, but that will change when we deprecate `nturl2path` and add support for Windows paths/URLs in `urllib` itself.
1 parent 563ab5c commit 033baf5

File tree

2 files changed

+104
-1
lines changed

2 files changed

+104
-1
lines changed

Lib/nturl2path.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
This module only exists to provide OS-specific code
44
for urllib.requests, thus do not use directly.
55
"""
6-
# Testing is done through test_urllib.
6+
# Testing is done through test_nturl2path.
77

88
def url2pathname(url):
99
"""OS-specific conversion from a relative URL of the 'file' scheme

Lib/test/test_nturl2path.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import nturl2path
2+
import unittest
3+
4+
5+
class NTURL2PathTest(unittest.TestCase):
6+
"""Test pathname2url() and url2pathname()"""
7+
8+
def test_basic(self):
9+
# Make sure simple tests pass
10+
expected_path = r"parts\of\a\path"
11+
expected_url = "parts/of/a/path"
12+
result = nturl2path.pathname2url(expected_path)
13+
self.assertEqual(expected_url, result,
14+
"pathname2url() failed; %s != %s" %
15+
(result, expected_url))
16+
result = nturl2path.url2pathname(expected_url)
17+
self.assertEqual(expected_path, result,
18+
"url2pathame() failed; %s != %s" %
19+
(result, expected_path))
20+
21+
def test_pathname2url(self):
22+
# Test special prefixes are correctly handled in pathname2url()
23+
fn = nturl2path.pathname2url
24+
self.assertEqual(fn('\\\\?\\C:\\dir'), '///C:/dir')
25+
self.assertEqual(fn('\\\\?\\unc\\server\\share\\dir'), '//server/share/dir')
26+
self.assertEqual(fn("C:"), '///C:')
27+
self.assertEqual(fn("C:\\"), '///C:/')
28+
self.assertEqual(fn('c:\\a\\b.c'), '///c:/a/b.c')
29+
self.assertEqual(fn('C:\\a\\b.c'), '///C:/a/b.c')
30+
self.assertEqual(fn('C:\\a\\b.c\\'), '///C:/a/b.c/')
31+
self.assertEqual(fn('C:\\a\\\\b.c'), '///C:/a//b.c')
32+
self.assertEqual(fn('C:\\a\\b%#c'), '///C:/a/b%25%23c')
33+
self.assertEqual(fn('C:\\a\\b\xe9'), '///C:/a/b%C3%A9')
34+
self.assertEqual(fn('C:\\foo\\bar\\spam.foo'), "///C:/foo/bar/spam.foo")
35+
# NTFS alternate data streams
36+
self.assertEqual(fn('C:\\foo:bar'), '///C:/foo%3Abar')
37+
self.assertEqual(fn('foo:bar'), 'foo%3Abar')
38+
# No drive letter
39+
self.assertEqual(fn("\\folder\\test\\"), '///folder/test/')
40+
self.assertEqual(fn("\\\\folder\\test\\"), '//folder/test/')
41+
self.assertEqual(fn("\\\\\\folder\\test\\"), '///folder/test/')
42+
self.assertEqual(fn('\\\\some\\share\\'), '//some/share/')
43+
self.assertEqual(fn('\\\\some\\share\\a\\b.c'), '//some/share/a/b.c')
44+
self.assertEqual(fn('\\\\some\\share\\a\\b%#c\xe9'), '//some/share/a/b%25%23c%C3%A9')
45+
# Alternate path separator
46+
self.assertEqual(fn('C:/a/b.c'), '///C:/a/b.c')
47+
self.assertEqual(fn('//some/share/a/b.c'), '//some/share/a/b.c')
48+
self.assertEqual(fn('//?/C:/dir'), '///C:/dir')
49+
self.assertEqual(fn('//?/unc/server/share/dir'), '//server/share/dir')
50+
# Round-tripping
51+
urls = ['///C:',
52+
'///folder/test/',
53+
'///C:/foo/bar/spam.foo']
54+
for url in urls:
55+
self.assertEqual(fn(nturl2path.url2pathname(url)), url)
56+
57+
def test_url2pathname(self):
58+
fn = nturl2path.url2pathname
59+
self.assertEqual(fn('/C:/'), 'C:\\')
60+
self.assertEqual(fn("///C|"), 'C:')
61+
self.assertEqual(fn("///C:"), 'C:')
62+
self.assertEqual(fn('///C:/'), 'C:\\')
63+
self.assertEqual(fn('/C|//'), 'C:\\\\')
64+
self.assertEqual(fn('///C|/path'), 'C:\\path')
65+
# No DOS drive
66+
self.assertEqual(fn("///C/test/"), '\\C\\test\\')
67+
self.assertEqual(fn("////C/test/"), '\\\\C\\test\\')
68+
# DOS drive paths
69+
self.assertEqual(fn('c:/path/to/file'), 'c:\\path\\to\\file')
70+
self.assertEqual(fn('C:/path/to/file'), 'C:\\path\\to\\file')
71+
self.assertEqual(fn('C:/path/to/file/'), 'C:\\path\\to\\file\\')
72+
self.assertEqual(fn('C:/path/to//file'), 'C:\\path\\to\\\\file')
73+
self.assertEqual(fn('C|/path/to/file'), 'C:\\path\\to\\file')
74+
self.assertEqual(fn('/C|/path/to/file'), 'C:\\path\\to\\file')
75+
self.assertEqual(fn('///C|/path/to/file'), 'C:\\path\\to\\file')
76+
self.assertEqual(fn("///C|/foo/bar/spam.foo"), 'C:\\foo\\bar\\spam.foo')
77+
# Colons in URI
78+
self.assertEqual(fn('///\u00e8|/'), '\u00e8:\\')
79+
self.assertEqual(fn('//host/share/spam.txt:eggs'), '\\\\host\\share\\spam.txt:eggs')
80+
self.assertEqual(fn('///c:/spam.txt:eggs'), 'c:\\spam.txt:eggs')
81+
# UNC paths
82+
self.assertEqual(fn('//server/path/to/file'), '\\\\server\\path\\to\\file')
83+
self.assertEqual(fn('////server/path/to/file'), '\\\\server\\path\\to\\file')
84+
self.assertEqual(fn('/////server/path/to/file'), '\\\\server\\path\\to\\file')
85+
# Localhost paths
86+
self.assertEqual(fn('//localhost/C:/path/to/file'), 'C:\\path\\to\\file')
87+
self.assertEqual(fn('//localhost/C|/path/to/file'), 'C:\\path\\to\\file')
88+
self.assertEqual(fn('//localhost/path/to/file'), '\\path\\to\\file')
89+
self.assertEqual(fn('//localhost//server/path/to/file'), '\\\\server\\path\\to\\file')
90+
# Percent-encoded forward slashes are preserved for backwards compatibility
91+
self.assertEqual(fn('C:/foo%2fbar'), 'C:\\foo/bar')
92+
self.assertEqual(fn('//server/share/foo%2fbar'), '\\\\server\\share\\foo/bar')
93+
# Round-tripping
94+
paths = ['C:',
95+
r'\C\test\\',
96+
r'C:\foo\bar\spam.foo']
97+
for path in paths:
98+
self.assertEqual(fn(nturl2path.pathname2url(path)), path)
99+
100+
101+
102+
if __name__ == '__main__':
103+
unittest.main()

0 commit comments

Comments
 (0)