diff options
author | Florian Bruhin <me@the-compiler.org> | 2021-01-04 21:52:44 +0100 |
---|---|---|
committer | Florian Bruhin <me@the-compiler.org> | 2021-01-05 11:19:15 +0100 |
commit | ebb3046822adbeeb6bea10e79669d82420cb7f3b (patch) | |
tree | 6155b259504ff1d0ad56f185865cf25b5dcdd8a6 | |
parent | 40464ebe3df06d88e2f4dc1ffcd7fb8df9e77170 (diff) | |
download | qutebrowser-ebb3046822adbeeb6bea10e79669d82420cb7f3b.tar.gz qutebrowser-ebb3046822adbeeb6bea10e79669d82420cb7f3b.zip |
Add overrides for mimetype -> extension conversion
Python 3.6 gets some of those "wrong":
https://bugs.python.org/issue1043134
This has been fixed in Python 3.7:
https://github.com/python/cpython/pull/14375
The override dict has been generated by copying the types_map from the
current git master:
https://github.com/python/cpython/blob/v3.10.0a3/Lib/mimetypes.py#L414-L547
And then running the following with Python 3.6:
import mimetypes
reverse = {}
for ext, mimetype in types_map.items():
if mimetype not in reverse:
reverse[mimetype] = ext
assert reverse['text/plain'] == '.txt'
for mimetype, ext in reverse.items():
got = mimetypes.guess_extension(mimetype)
if got != ext:
print(f' "{mimetype}": "{ext}", # not {got}')
-rw-r--r-- | qutebrowser/utils/urlutils.py | 2 | ||||
-rw-r--r-- | qutebrowser/utils/utils.py | 35 | ||||
-rw-r--r-- | tests/unit/utils/test_utils.py | 11 |
3 files changed, 47 insertions, 1 deletions
diff --git a/qutebrowser/utils/urlutils.py b/qutebrowser/utils/urlutils.py index b5afe958c..af5c997da 100644 --- a/qutebrowser/utils/urlutils.py +++ b/qutebrowser/utils/urlutils.py @@ -412,7 +412,7 @@ def filename_from_url(url: QUrl, fallback: str = None) -> Optional[str]: if not mimetype: return fallback - ext = mimetypes.guess_extension(mimetype, strict=False) or '' + ext = utils.mimetype_extension(mimetype) or '' return 'download' + ext pathname = posixpath.basename(url.path()) diff --git a/qutebrowser/utils/utils.py b/qutebrowser/utils/utils.py index cf239805c..e49309ef2 100644 --- a/qutebrowser/utils/utils.py +++ b/qutebrowser/utils/utils.py @@ -803,3 +803,38 @@ def parse_duration(duration: str) -> int: hours = float(hours_string.rstrip('h')) milliseconds = int((seconds + minutes * 60 + hours * 3600) * 1000) return milliseconds + + +def mimetype_extension(mimetype: str) -> Optional[str]: + """Get a suitable extension for a given mimetype. + + This mostly delegates to Python's mimetypes.guess_extension(), but backports some + changes (via a simple override dict) which are missing from earlier Python versions. + Most likely, this can be dropped once the minimum Python version is raised to 3.7. + """ + overrides = { + # Added around 3.8 + "application/manifest+json": ".webmanifest", + "application/x-hdf5": ".h5", + + # Added in Python 3.7 + "application/wasm": ".wasm", + + # Wrong values for Python 3.6 + # https://bugs.python.org/issue1043134 + # https://github.com/python/cpython/pull/14375 + "application/octet-stream": ".bin", # not .a + "application/postscript": ".ps", # not .ai + "application/vnd.ms-excel": ".xls", # not .xlb + "application/vnd.ms-powerpoint": ".ppt", # not .pot + "application/xml": ".xsl", # not .rdf + "audio/mpeg": ".mp3", # not .mp2 + "image/jpeg": ".jpg", # not .jpe + "image/tiff": ".tiff", # not .tif + "text/html": ".html", # not .htm + "text/plain": ".txt", # not .bat + "video/mpeg": ".mpeg", # not .m1v + } + if mimetype in overrides: + return overrides[mimetype] + return mimetypes.guess_extension(mimetype, strict=False) diff --git a/tests/unit/utils/test_utils.py b/tests/unit/utils/test_utils.py index 404185548..2b1392664 100644 --- a/tests/unit/utils/test_utils.py +++ b/tests/unit/utils/test_utils.py @@ -867,3 +867,14 @@ def test_parse_duration_hypothesis(duration): utils.parse_duration(duration) except ValueError: pass + + +@pytest.mark.parametrize('mimetype, extension', [ + ('application/pdf', '.pdf'), # handled by Python + ('text/plain', '.txt'), # wrong in Python 3.6, overridden + ('application/manifest+json', '.webmanifest'), # newer + ('text/xul', '.xul'), # strict=False + ('doesnot/exist', None), +]) +def test_mimetype_extension(mimetype, extension): + assert utils.mimetype_extension(mimetype) == extension |