mirror of
https://github.com/python/cpython.git
synced 2026-10-28 10:25:05 +08:00
gh-156713: Use the filesystem encoding in nturl2path (GH-156717)
urllib.request.pathname2url() and url2pathname() use the filesystem encoding and error handler since gh-85168, but nturl2path, which implements them on Windows before 3.14, was left unchanged. Paths containing surrogate characters raised UnicodeEncodeError.
This commit is contained in:
1 parent
e7a393797a
commit
01599e203e
3 files changed
+36
-3
No files matched your search
+11
-3
@@ -22,7 +22,10 @@ def url2pathname(url):
|
||||
# ///C:/foo/bar/spam.foo
|
||||
# become
|
||||
# C:\foo\bar\spam.foo
|
||||
import sys
|
||||
import urllib.parse
|
||||
encoding = sys.getfilesystemencoding()
|
||||
errors = sys.getfilesystemencodeerrors()
|
||||
if url[:3] == '///':
|
||||
# URL has an empty authority section, so the path begins on the third
|
||||
# character.
|
||||
@@ -40,7 +43,8 @@ def url2pathname(url):
|
||||
if url[1:2] == '|':
|
||||
# Older URLs use a pipe after a drive letter
|
||||
url = url[:1] + ':' + url[2:]
|
||||
return urllib.parse.unquote(url.replace('/', '\\'))
|
||||
return urllib.parse.unquote(url.replace('/', '\\'),
|
||||
encoding=encoding, errors=errors)
|
||||
|
||||
def pathname2url(p):
|
||||
"""OS-specific conversion from a file system path to a relative URL
|
||||
@@ -50,7 +54,10 @@ def pathname2url(p):
|
||||
# becomes
|
||||
# ///C:/foo/bar/spam.foo
|
||||
import ntpath
|
||||
import sys
|
||||
import urllib.parse
|
||||
encoding = sys.getfilesystemencoding()
|
||||
errors = sys.getfilesystemencodeerrors()
|
||||
# First, clean up some special forms. We are going to sacrifice
|
||||
# the additional information anyway
|
||||
p = p.replace('\\', '/')
|
||||
@@ -65,10 +72,11 @@ def pathname2url(p):
|
||||
# an authority section with a zero-length authority, and a path
|
||||
# section starting with a single slash.
|
||||
drive = f'///{drive}'
|
||||
drive = urllib.parse.quote(drive, safe='/:')
|
||||
drive = urllib.parse.quote(drive, encoding=encoding, errors=errors,
|
||||
safe='/:')
|
||||
elif root:
|
||||
# Add explicitly empty authority to path beginning with one slash.
|
||||
root = f'//{root}'
|
||||
|
||||
tail = urllib.parse.quote(tail)
|
||||
tail = urllib.parse.quote(tail, encoding=encoding, errors=errors)
|
||||
return drive + root + tail
|
||||
@@ -1,4 +1,6 @@
|
||||
import sys
|
||||
import unittest
|
||||
import urllib.parse
|
||||
|
||||
from test.support import warnings_helper
|
||||
|
||||
@@ -58,6 +60,15 @@ class NTURL2PathTest(unittest.TestCase):
|
||||
for url in urls:
|
||||
self.assertEqual(fn(nturl2path.url2pathname(url)), url)
|
||||
|
||||
def test_pathname2url_surrogates(self):
|
||||
# gh-156713: the filesystem encoding and error handler are used,
|
||||
# so that paths containing surrogate characters can be converted.
|
||||
encoding = sys.getfilesystemencoding()
|
||||
errors = sys.getfilesystemencodeerrors()
|
||||
tail = urllib.parse.quote('a\udcff', encoding=encoding, errors=errors)
|
||||
self.assertEqual(nturl2path.pathname2url('C:\\a\udcff'),
|
||||
'///C:/' + tail)
|
||||
|
||||
def test_url2pathname(self):
|
||||
fn = nturl2path.url2pathname
|
||||
self.assertEqual(fn('/'), '\\')
|
||||
@@ -103,5 +114,15 @@ class NTURL2PathTest(unittest.TestCase):
|
||||
self.assertEqual(fn(nturl2path.pathname2url(path)), path)
|
||||
|
||||
|
||||
def test_url2pathname_surrogates(self):
|
||||
# gh-156713: the filesystem encoding and error handler are used, so
|
||||
# that URLs containing percent-encoded surrogates can be converted.
|
||||
encoding = sys.getfilesystemencoding()
|
||||
errors = sys.getfilesystemencodeerrors()
|
||||
url = urllib.parse.quote('a\udcff', encoding=encoding, errors=errors)
|
||||
self.assertEqual(nturl2path.url2pathname('///C:/' + url),
|
||||
'C:\\a\udcff')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,4 @@
|
||||
Fix :func:`!nturl2path.pathname2url` and :func:`!nturl2path.url2pathname`:
|
||||
the filesystem encoding and error handler are now used for percent-encoding
|
||||
and decoding, as in :mod:`urllib.request`. Previously paths containing
|
||||
surrogate characters raised :exc:`UnicodeEncodeError`.
|
||||
Reference in new issue
Block a user