Handle unencodable file paths in config types.
If an user e.g. has a download-directory of ~/föö, but has LC_ALL=C set, we'll get an UnicodeEncodeError when trying to validate it. This is now handled properly by raising a ValidationError. Fixes #562.
This commit is contained in:
parent
330e03d382
commit
fb5fbd09da
@ -833,10 +833,14 @@ class File(BaseType):
|
||||
else:
|
||||
raise configexc.ValidationError(value, "may not be empty!")
|
||||
value = os.path.expanduser(value)
|
||||
if not os.path.isfile(value):
|
||||
raise configexc.ValidationError(value, "must be a valid file!")
|
||||
if not os.path.isabs(value):
|
||||
raise configexc.ValidationError(value, "must be an absolute path!")
|
||||
try:
|
||||
if not os.path.isfile(value):
|
||||
raise configexc.ValidationError(value, "must be a valid file!")
|
||||
if not os.path.isabs(value):
|
||||
raise configexc.ValidationError(
|
||||
value, "must be an absolute path!")
|
||||
except UnicodeEncodeError as e:
|
||||
raise configexc.ValidationError(value, e)
|
||||
|
||||
def transform(self, value):
|
||||
if not value:
|
||||
@ -858,11 +862,15 @@ class Directory(BaseType):
|
||||
raise configexc.ValidationError(value, "may not be empty!")
|
||||
value = os.path.expandvars(value)
|
||||
value = os.path.expanduser(value)
|
||||
if not os.path.isdir(value):
|
||||
raise configexc.ValidationError(value, "must be a valid "
|
||||
"directory!")
|
||||
if not os.path.isabs(value):
|
||||
raise configexc.ValidationError(value, "must be an absolute path!")
|
||||
try:
|
||||
if not os.path.isdir(value):
|
||||
raise configexc.ValidationError(
|
||||
value, "must be a valid directory!")
|
||||
if not os.path.isabs(value):
|
||||
raise configexc.ValidationError(
|
||||
value, "must be an absolute path!")
|
||||
except UnicodeEncodeError as e:
|
||||
raise configexc.ValidationError(value, e)
|
||||
|
||||
def transform(self, value):
|
||||
if not value:
|
||||
@ -1179,18 +1187,21 @@ class UserStyleSheet(File):
|
||||
raise configexc.ValidationError(value, "may not be empty!")
|
||||
value = os.path.expandvars(value)
|
||||
value = os.path.expanduser(value)
|
||||
if not os.path.isabs(value):
|
||||
# probably a CSS, so we don't handle it as filename.
|
||||
# FIXME We just try if it is encodable, maybe we should validate
|
||||
# CSS?
|
||||
# https://github.com/The-Compiler/qutebrowser/issues/115
|
||||
try:
|
||||
value.encode('utf-8')
|
||||
except UnicodeEncodeError as e:
|
||||
raise configexc.ValidationError(value, str(e))
|
||||
return
|
||||
elif not os.path.isfile(value):
|
||||
raise configexc.ValidationError(value, "must be a valid file!")
|
||||
try:
|
||||
if not os.path.isabs(value):
|
||||
# probably a CSS, so we don't handle it as filename.
|
||||
# FIXME We just try if it is encodable, maybe we should
|
||||
# validate CSS?
|
||||
# https://github.com/The-Compiler/qutebrowser/issues/115
|
||||
try:
|
||||
value.encode('utf-8')
|
||||
except UnicodeEncodeError as e:
|
||||
raise configexc.ValidationError(value, str(e))
|
||||
return
|
||||
elif not os.path.isfile(value):
|
||||
raise configexc.ValidationError(value, "must be a valid file!")
|
||||
except UnicodeEncodeError as e:
|
||||
raise configexc.ValidationError(value, e)
|
||||
|
||||
def transform(self, value):
|
||||
path = os.path.expandvars(value)
|
||||
|
@ -1374,6 +1374,13 @@ class FileTests(unittest.TestCase):
|
||||
self.t.validate('~/foobar')
|
||||
os_path.expanduser.assert_called_once_with('~/foobar')
|
||||
|
||||
def test_validate_invalid_encoding(self, os_path):
|
||||
"""Test validate with an invalid encoding, e.g. LC_ALL=C."""
|
||||
os_path.isfile.side_effect = helpers.unicode_encode_err
|
||||
os_path.isabs.side_effect = helpers.unicode_encode_err
|
||||
with self.assertRaises(configexc.ValidationError):
|
||||
self.t.validate('foobar')
|
||||
|
||||
def test_transform(self, os_path):
|
||||
"""Test transform."""
|
||||
os_path.expanduser.side_effect = lambda x: x.replace('~', '/home/foo')
|
||||
@ -1445,6 +1452,13 @@ class DirectoryTests(unittest.TestCase):
|
||||
self.t.validate('$BAR/foobar')
|
||||
os_path.expandvars.assert_called_once_with('$BAR/foobar')
|
||||
|
||||
def test_validate_invalid_encoding(self, os_path):
|
||||
"""Test validate with an invalid encoding, e.g. LC_ALL=C."""
|
||||
os_path.isdir.side_effect = helpers.unicode_encode_err
|
||||
os_path.isabs.side_effect = helpers.unicode_encode_err
|
||||
with self.assertRaises(configexc.ValidationError):
|
||||
self.t.validate('foobar')
|
||||
|
||||
def test_transform(self, os_path):
|
||||
"""Test transform."""
|
||||
os_path.expandvars.side_effect = lambda x: x
|
||||
@ -1879,6 +1893,14 @@ class UserStyleSheetTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.t = configtypes.UserStyleSheet()
|
||||
|
||||
@mock.patch('qutebrowser.config.configtypes.os.path', autospec=True)
|
||||
def test_validate_invalid_encoding(self, os_path):
|
||||
"""Test validate with an invalid encoding, e.g. LC_ALL=C."""
|
||||
os_path.isfile.side_effect = helpers.unicode_encode_err
|
||||
os_path.isabs.side_effect = helpers.unicode_encode_err
|
||||
with self.assertRaises(configexc.ValidationError):
|
||||
self.t.validate('foobar')
|
||||
|
||||
def test_transform_empty(self):
|
||||
"""Test transform with an empty value."""
|
||||
self.assertIsNone(self.t.transform(''))
|
||||
|
@ -29,6 +29,13 @@ from PyQt5.QtWebKitWidgets import QWebPage
|
||||
from PyQt5.QtNetwork import QNetworkAccessManager
|
||||
|
||||
|
||||
unicode_encode_err = UnicodeEncodeError('ascii', # codec
|
||||
'', # object
|
||||
0, # start
|
||||
2, # end
|
||||
'fake exception') # reason
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def environ_set_temp(env):
|
||||
"""Set temporary environment variables.
|
||||
|
Loading…
Reference in New Issue
Block a user