configtypes: Handle invalid escapes in regexes.

This commit is contained in:
Florian Bruhin 2015-10-01 23:11:48 +02:00
parent e4a216e7cf
commit 16ac3baf2e
2 changed files with 59 additions and 5 deletions

View File

@ -26,6 +26,7 @@ import codecs
import os.path import os.path
import itertools import itertools
import collections import collections
import warnings
from PyQt5.QtCore import QUrl from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QColor, QFont from PyQt5.QtGui import QColor, QFont
@ -45,11 +46,21 @@ BOOLEAN_STATES = {'1': True, 'yes': True, 'true': True, 'on': True,
def _validate_regex(pattern, flags): def _validate_regex(pattern, flags):
try: with warnings.catch_warnings(record=True) as recorded_warnings:
re.compile(pattern, flags) warnings.simplefilter('always')
except re.error as e: try:
raise configexc.ValidationError(pattern, "must be a valid regex - " + re.compile(pattern, flags)
str(e)) except re.error as e:
raise configexc.ValidationError(
pattern, "must be a valid regex - " + str(e))
for w in recorded_warnings:
if (issubclass(w.category, DeprecationWarning) and
str(w.message).startswith('bad escape')):
raise configexc.ValidationError(
pattern, "must be a valid regex - " + str(w.message))
else:
warnings.warn(w.message)
class ValidValues: class ValidValues:

View File

@ -23,6 +23,7 @@ import collections
import itertools import itertools
import os.path import os.path
import base64 import base64
import warnings
import pytest import pytest
from PyQt5.QtCore import QUrl from PyQt5.QtCore import QUrl
@ -1064,6 +1065,22 @@ class TestRegex:
with pytest.raises(configexc.ValidationError): with pytest.raises(configexc.ValidationError):
klass().validate(val) klass().validate(val)
@pytest.mark.parametrize('val', [
r'foo\Xbar',
r'foo\Cbar',
])
def test_validate_maybe_valid(self, klass, val):
"""Those values are valid on some Python versions (and systems?).
On others, they raise a DeprecationWarning because of an invalid
escape. This tests makes sure this gets translated to a
ValidationError.
"""
try:
klass().validate(val)
except configexc.ValidationError:
pass
@pytest.mark.parametrize('val, expected', [ @pytest.mark.parametrize('val, expected', [
(r'foobar', RegexEq(r'foobar')), (r'foobar', RegexEq(r'foobar')),
('', None), ('', None),
@ -1071,6 +1088,16 @@ class TestRegex:
def test_transform_empty(self, klass, val, expected): def test_transform_empty(self, klass, val, expected):
assert klass().transform(val) == expected assert klass().transform(val) == expected
@pytest.mark.parametrize('warning', [
Warning('foo'), DeprecationWarning('foo'),
])
def test_passed_warnings(self, mocker, klass, warning):
m = mocker.patch('qutebrowser.config.configtypes.re')
m.compile.side_effect = lambda *args: warnings.warn(warning)
m.error = re.error
with pytest.raises(type(warning)):
klass().validate('foo')
class TestRegexList: class TestRegexList:
@ -1097,6 +1124,22 @@ class TestRegexList:
with pytest.raises(configexc.ValidationError): with pytest.raises(configexc.ValidationError):
klass().validate(val) klass().validate(val)
@pytest.mark.parametrize('val', [
r'foo\Xbar',
r'foo\Cbar',
])
def test_validate_maybe_valid(self, klass, val):
"""Those values are valid on some Python versions (and systems?).
On others, they raise a DeprecationWarning because of an invalid
escape. This tests makes sure this gets translated to a
ValidationError.
"""
try:
klass().validate(val)
except configexc.ValidationError:
pass
@pytest.mark.parametrize('val, expected', [ @pytest.mark.parametrize('val, expected', [
('foo', [RegexEq('foo')]), ('foo', [RegexEq('foo')]),
('foo,bar,baz', [RegexEq('foo'), RegexEq('bar'), ('foo,bar,baz', [RegexEq('foo'), RegexEq('bar'),