diff --git a/qutebrowser/browser/qutescheme.py b/qutebrowser/browser/qutescheme.py index 41d2cabaf..dc952f0f8 100644 --- a/qutebrowser/browser/qutescheme.py +++ b/qutebrowser/browser/qutescheme.py @@ -29,7 +29,6 @@ import json import os import time import textwrap -import mimetypes import urllib import collections import base64 @@ -368,8 +367,7 @@ def qute_help(url): bdata = utils.read_file(path, binary=True) except OSError as e: raise SchemeOSError(e) - mimetype, _encoding = mimetypes.guess_type(urlpath) - assert mimetype is not None, url + mimetype = utils.guess_mimetype(urlpath) return mimetype, bdata try: @@ -527,9 +525,7 @@ def qute_pdfjs(url): filename = QUrlQuery(url).queryItemValue('filename') with open(filename, 'rb') as f: data = f.read() - mimetype, _encoding = mimetypes.guess_type(filename) - if mimetype is None: - mimetype = 'application/octet-stream' + mimetype = utils.guess_mimetype(filename, fallback=True) return mimetype, data if url.path() == '/web/viewer.html': @@ -547,7 +543,5 @@ def qute_pdfjs(url): "pdfjs resource requested but not found: {}".format(e.path)) raise NotFoundError("Can't find pdfjs resource '{}'".format(e.path)) else: - mimetype, _encoding = mimetypes.guess_type(url.fileName()) - if mimetype is None: - mimetype = 'application/octet-stream' + mimetype = utils.guess_mimetype(url.fileName(), fallback=True) return mimetype, data diff --git a/qutebrowser/utils/jinja.py b/qutebrowser/utils/jinja.py index b06444f93..d2ddfaeb7 100644 --- a/qutebrowser/utils/jinja.py +++ b/qutebrowser/utils/jinja.py @@ -22,7 +22,6 @@ import os import os.path import contextlib -import mimetypes import html import jinja2 @@ -108,9 +107,8 @@ class Environment(jinja2.Environment): """Get a data: url for the broken qutebrowser logo.""" data = utils.read_file(path, binary=True) filename = utils.resource_filename(path) - mimetype = mimetypes.guess_type(filename) - assert mimetype is not None, path - return urlutils.data_url(mimetype[0], data).toString() + mimetype = utils.guess_mimetype(filename) + return urlutils.data_url(mimetype, data).toString() def getattr(self, obj, attribute): """Override jinja's getattr() to be less clever. diff --git a/qutebrowser/utils/utils.py b/qutebrowser/utils/utils.py index fe255331d..e9d4c3659 100644 --- a/qutebrowser/utils/utils.py +++ b/qutebrowser/utils/utils.py @@ -33,6 +33,7 @@ import contextlib import socket import shlex import glob +import mimetypes from PyQt5.QtCore import QUrl from PyQt5.QtGui import QColor, QClipboard, QDesktopServices @@ -683,3 +684,19 @@ def chunk(elems, n): raise ValueError("n needs to be at least 1!") for i in range(0, len(elems), n): yield elems[i:i + n] + + +def guess_mimetype(filename, fallback=False): + """Guess a mimetype based on a filename. + + Args: + filename: The filename to check. + fallback: Fall back to application/octet-stream if unknown. + """ + mimetype, _encoding = mimetypes.guess_type(filename) + if mimetype is None: + if fallback: + return 'application/octet-stream' + else: + raise ValueError("Got None mimetype for {}".format(filename)) + return mimetype diff --git a/tests/unit/utils/test_utils.py b/tests/unit/utils/test_utils.py index 550213386..e8a96d448 100644 --- a/tests/unit/utils/test_utils.py +++ b/tests/unit/utils/test_utils.py @@ -816,3 +816,16 @@ def test_chunk(elems, n, expected): def test_chunk_invalid(n): with pytest.raises(ValueError): list(utils.chunk([], n)) + + +@pytest.mark.parametrize('filename, expected', [ + ('test.jpg', 'image/jpeg'), + ('test.blabla', 'application/octet-stream'), +]) +def test_guess_mimetype(filename, expected): + assert utils.guess_mimetype(filename, fallback=True) == expected + + +def test_guess_mimetype_no_fallback(): + with pytest.raises(ValueError): + utils.guess_mimetype('test.blabla')