| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent e7a3937 commit 01599e2
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -22,7 +22,10 @@ def url2pathname(url): | |||
| 22 | 22 | # ///C:/foo/bar/spam.foo | |
| 23 | 23 | # become | |
| 24 | 24 | # C:\foo\bar\spam.foo | |
| 25 | + import sys | ||
| 25 | 26 | import urllib.parse | |
| 27 | + encoding = sys.getfilesystemencoding() | ||
| 28 | + errors = sys.getfilesystemencodeerrors() | ||
| 26 | 29 | if url[:3] == '///': | |
| 27 | 30 | # URL has an empty authority section, so the path begins on the third | |
| 28 | 31 | # character. | |
@@ -40,7 +43,8 @@ def url2pathname(url): | |||
| 40 | 43 | if url[1:2] == '|': | |
| 41 | 44 | # Older URLs use a pipe after a drive letter | |
| 42 | 45 | url = url[:1] + ':' + url[2:] | |
| 43 | - return urllib.parse.unquote(url.replace('/', '\\')) | ||
| 46 | + return urllib.parse.unquote(url.replace('/', '\\'), | ||
| 47 | + encoding=encoding, errors=errors) | ||
| 44 | 48 | ||
| 45 | 49 | def pathname2url(p): | |
| 46 | 50 | """OS-specific conversion from a file system path to a relative URL | |
@@ -50,7 +54,10 @@ def pathname2url(p): | |||
| 50 | 54 | # becomes | |
| 51 | 55 | # ///C:/foo/bar/spam.foo | |
| 52 | 56 | import ntpath | |
| 57 | + import sys | ||
| 53 | 58 | import urllib.parse | |
| 59 | + encoding = sys.getfilesystemencoding() | ||
| 60 | + errors = sys.getfilesystemencodeerrors() | ||
| 54 | 61 | # First, clean up some special forms. We are going to sacrifice | |
| 55 | 62 | # the additional information anyway | |
| 56 | 63 | p = p.replace('\\', '/') | |
@@ -65,10 +72,11 @@ def pathname2url(p): | |||
| 65 | 72 | # an authority section with a zero-length authority, and a path | |
| 66 | 73 | # section starting with a single slash. | |
| 67 | 74 | drive = f'///{drive}' | |
| 68 | - drive = urllib.parse.quote(drive, safe='/:') | ||
| 75 | + drive = urllib.parse.quote(drive, encoding=encoding, errors=errors, | ||
| 76 | + safe='/:') | ||
| 69 | 77 | elif root: | |
| 70 | 78 | # Add explicitly empty authority to path beginning with one slash. | |
| 71 | 79 | root = f'//{root}' | |
| 72 | 80 | ||
| 73 | - tail = urllib.parse.quote(tail) | ||
| 81 | + tail = urllib.parse.quote(tail, encoding=encoding, errors=errors) | ||
| 74 | 82 | return drive + root + tail | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,4 +1,6 @@ | |||
| 1 | + import sys | ||
| 1 | 2 | import unittest | |
| 3 | + import urllib.parse | ||
| 2 | 4 | ||
| 3 | 5 | from test.support import warnings_helper | |
| 4 | 6 | ||
@@ -58,6 +60,15 @@ def test_pathname2url(self): | |||
| 58 | 60 | for url in urls: | |
| 59 | 61 | self.assertEqual(fn(nturl2path.url2pathname(url)), url) | |
| 60 | 62 | ||
| 63 | + def test_pathname2url_surrogates(self): | ||
| 64 | + # gh-156713: the filesystem encoding and error handler are used, | ||
| 65 | + # so that paths containing surrogate characters can be converted. | ||
| 66 | + encoding = sys.getfilesystemencoding() | ||
| 67 | + errors = sys.getfilesystemencodeerrors() | ||
| 68 | + tail = urllib.parse.quote('a\udcff', encoding=encoding, errors=errors) | ||
| 69 | + self.assertEqual(nturl2path.pathname2url('C:\\a\udcff'), | ||
| 70 | + '///C:/' + tail) | ||
| 71 | + | ||
| 61 | 72 | def test_url2pathname(self): | |
| 62 | 73 | fn = nturl2path.url2pathname | |
| 63 | 74 | self.assertEqual(fn('/'), '\\') | |
@@ -103,5 +114,15 @@ def test_url2pathname(self): | |||
| 103 | 114 | self.assertEqual(fn(nturl2path.pathname2url(path)), path) | |
| 104 | 115 | ||
| 105 | 116 | ||
| 117 | + def test_url2pathname_surrogates(self): | ||
| 118 | + # gh-156713: the filesystem encoding and error handler are used, so | ||
| 119 | + # that URLs containing percent-encoded surrogates can be converted. | ||
| 120 | + encoding = sys.getfilesystemencoding() | ||
| 121 | + errors = sys.getfilesystemencodeerrors() | ||
| 122 | + url = urllib.parse.quote('a\udcff', encoding=encoding, errors=errors) | ||
| 123 | + self.assertEqual(nturl2path.url2pathname('///C:/' + url), | ||
| 124 | + 'C:\\a\udcff') | ||
| 125 | + | ||
| 126 | + | ||
| 106 | 127 | if __name__ == '__main__': | |
| 107 | 128 | unittest.main() | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,4 @@ | |||
| 1 | + Fix :func:`!nturl2path.pathname2url` and :func:`!nturl2path.url2pathname`: | ||
| 2 | + the filesystem encoding and error handler are now used for percent-encoding | ||
| 3 | + and decoding, as in :mod:`urllib.request`. Previously paths containing | ||
| 4 | + surrogate characters raised :exc:`UnicodeEncodeError`. | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments