Merge branch 'log-javascript-console' of https://github.com/flv0/qutebrowser into flv0-log-javascript-console

This commit is contained in:
Florian Bruhin 2015-11-28 21:12:25 +01:00
commit c236e70920
3 changed files with 173 additions and 186 deletions

View File

@ -209,7 +209,22 @@ def data(readonly=False):
"be used."), "be used."),
('new-instance-open-target', ('new-instance-open-target',
SettingValue(typ.NewInstanceOpenTarget(), 'tab'), SettingValue(typ.String(
valid_values=typ.ValidValues(
('tab', "Open a new tab in the existing "
"window and activate the window."),
('tab-bg', "Open a new background tab in the "
"existing window and activate the "
"window."),
('tab-silent', "Open a new tab in the existing "
"window without activating "
"the window."),
('tab-bg-silent', "Open a new background tab "
"in the existing window "
"without activating the "
"window."),
('window', "Open in a new window.")
)), 'tab'),
"How to open links in an existing instance if a new one is " "How to open links in an existing instance if a new one is "
"launched."), "launched."),
@ -227,7 +242,10 @@ def data(readonly=False):
"last loaded session."), "last loaded session."),
('url-incdec-segments', ('url-incdec-segments',
SettingValue(typ.URLSegmentList(), 'path,query'), SettingValue(
typ.FlagList(valid_values=typ.ValidValues(
'host', 'path', 'query', 'anchor')),
'path,query'),
"The URL segments where `:navigate increment/decrement` will " "The URL segments where `:navigate increment/decrement` will "
"search for a number."), "search for a number."),
@ -345,7 +363,15 @@ def data(readonly=False):
"Value to send in the `accept-language` header."), "Value to send in the `accept-language` header."),
('referer-header', ('referer-header',
SettingValue(typ.Referer(), 'same-domain'), SettingValue(typ.String(
valid_values=typ.ValidValues(
('always', "Always send."),
('never', "Never send; this is not recommended,"
" as some sites may break."),
('same-domain', "Only send for the same domain."
" This will still protect your privacy, but"
" shouldn't break any sites.")
)), 'same-domain'),
"Send the Referer header"), "Send the Referer header"),
('user-agent', ('user-agent',
@ -379,7 +405,12 @@ def data(readonly=False):
"Automatically open completion when typing."), "Automatically open completion when typing."),
('download-path-suggestion', ('download-path-suggestion',
SettingValue(typ.DownloadPathSuggestion(), 'path'), SettingValue(
typ.String(valid_values=typ.ValidValues(
('path', "Show only the download path."),
('filename', "Show only download filename."),
('both', "Show download path and filename."))),
'path'),
"What to display in the download filename input."), "What to display in the download filename input."),
('timestamp-format', ('timestamp-format',
@ -452,7 +483,13 @@ def data(readonly=False):
"element is focused after page load."), "element is focused after page load."),
('forward-unbound-keys', ('forward-unbound-keys',
SettingValue(typ.ForwardUnboundKeys(), 'auto'), SettingValue(typ.String(
valid_values=typ.ValidValues(
('all', "Forward all unbound keys."),
('auto', "Forward unbound non-alphanumeric "
"keys."),
('none', "Don't forward any keys.")
)), 'auto'),
"Whether to forward unbound keys to the webview in normal mode."), "Whether to forward unbound keys to the webview in normal mode."),
('spatial-navigation', ('spatial-navigation',
@ -502,11 +539,26 @@ def data(readonly=False):
"How new tabs opened explicitly are positioned."), "How new tabs opened explicitly are positioned."),
('last-close', ('last-close',
SettingValue(typ.LastClose(), 'ignore'), SettingValue(typ.String(
valid_values=typ.ValidValues(
('ignore', "Don't do anything."),
('blank', "Load a blank page."),
('startpage', "Load the start page."),
('default-page', "Load the default page."),
('close', "Close the window.")
)), 'ignore'),
"Behavior when the last tab is closed."), "Behavior when the last tab is closed."),
('show', ('show',
SettingValue(typ.TabBarShow(), 'always'), SettingValue(
typ.String(valid_values=typ.ValidValues(
('always', "Always show the tab bar."),
('never', "Always hide the tab bar."),
('multiple', "Hide the tab bar if only one tab "
"is open."),
('switching', "Show the tab bar when switching "
"tabs.")
)), 'always'),
"When to show the tab bar"), "When to show the tab bar"),
('show-switching-delay', ('show-switching-delay',
@ -523,7 +575,12 @@ def data(readonly=False):
"Whether tabs should be movable."), "Whether tabs should be movable."),
('close-mouse-button', ('close-mouse-button',
SettingValue(typ.CloseButton(), 'middle'), SettingValue(typ.String(
valid_values=typ.ValidValues(
('right', "Close tabs on right-click."),
('middle', "Close tabs on middle-click."),
('none', "Don't close tabs using the mouse.")
)), 'middle'),
"On which mouse button to close tabs."), "On which mouse button to close tabs."),
('position', ('position',
@ -731,7 +788,16 @@ def data(readonly=False):
"local urls."), "local urls."),
('cookies-accept', ('cookies-accept',
SettingValue(typ.AcceptCookies(), 'no-3rdparty'), SettingValue(typ.String(
valid_values=typ.ValidValues(
('all', "Accept all cookies."),
('no-3rdparty', "Accept cookies from the same"
" origin only."),
('no-unknown-3rdparty', "Accept cookies from "
"the same origin only, unless a cookie is "
"already set for the domain."),
('never', "Don't accept cookies at all.")
)), 'no-3rdparty'),
"Control which cookies to accept."), "Control which cookies to accept."),
('cookies-store', ('cookies-store',
@ -779,7 +845,12 @@ def data(readonly=False):
"Opacity for hints."), "Opacity for hints."),
('mode', ('mode',
SettingValue(typ.HintMode(), 'letter'), SettingValue(typ.String(
valid_values=typ.ValidValues(
('number', "Use numeric hints."),
('letter', "Use the chars in the hints -> "
"chars setting.")
)), 'letter'),
"Mode to use for hints."), "Mode to use for hints."),
('chars', ('chars',

View File

@ -121,11 +121,11 @@ class BaseType:
mentioned in the config file. mentioned in the config file.
""" """
valid_values = None
special = False special = False
def __init__(self, none_ok=False): def __init__(self, none_ok=False):
self.none_ok = none_ok self.none_ok = none_ok
self.valid_values = None
def _basic_validation(self, value): def _basic_validation(self, value):
"""Do some basic validation for the value (empty, non-printable chars). """Do some basic validation for the value (empty, non-printable chars).
@ -216,11 +216,10 @@ class MappingType(BaseType):
MAPPING = {} MAPPING = {}
def __init__(self, none_ok=False): def __init__(self, none_ok=False,
valid_values=None):
super().__init__(none_ok) super().__init__(none_ok)
if list(sorted(self.MAPPING)) != list(sorted(self.valid_values)): self.valid_values = valid_values
raise ValueError("Mapping {!r} doesn't match valid values "
"{!r}".format(self.MAPPING, self.valid_values))
def validate(self, value): def validate(self, value):
super().validate(value.lower()) super().validate(value.lower())
@ -243,8 +242,10 @@ class String(BaseType):
""" """
def __init__(self, minlen=None, maxlen=None, forbidden=None, def __init__(self, minlen=None, maxlen=None, forbidden=None,
none_ok=False, completions=None): none_ok=False, completions=None, valid_values=None):
super().__init__(none_ok) super().__init__(none_ok)
self.valid_values = valid_values
if minlen is not None and minlen < 1: if minlen is not None and minlen < 1:
raise ValueError("minlen ({}) needs to be >= 1!".format(minlen)) raise ValueError("minlen ({}) needs to be >= 1!".format(minlen))
elif maxlen is not None and maxlen < 1: elif maxlen is not None and maxlen < 1:
@ -280,6 +281,10 @@ class List(BaseType):
"""Base class for a (string-)list setting.""" """Base class for a (string-)list setting."""
def __init__(self, none_ok=False, valid_values=None):
super().__init__(none_ok)
self.valid_values = valid_values
def transform(self, value): def transform(self, value):
if not value: if not value:
return None return None
@ -351,7 +356,9 @@ class Bool(BaseType):
"""Base class for a boolean setting.""" """Base class for a boolean setting."""
valid_values = ValidValues('true', 'false') def __init__(self, none_ok=False):
super().__init__(none_ok)
self.valid_values = ValidValues('true', 'false')
def transform(self, value): def transform(self, value):
if not value: if not value:
@ -371,7 +378,9 @@ class BoolAsk(Bool):
"""A yes/no/ask question.""" """A yes/no/ask question."""
valid_values = ValidValues('true', 'false', 'ask') def __init__(self, none_ok=False):
super().__init__(none_ok)
self.valid_values = ValidValues('true', 'false', 'ask')
def transform(self, value): def transform(self, value):
if value.lower() == 'ask': if value.lower() == 'ask':
@ -650,10 +659,15 @@ class ColorSystem(MappingType):
"""Color systems for interpolation.""" """Color systems for interpolation."""
special = True special = True
valid_values = ValidValues(('rgb', "Interpolate in the RGB color system."),
('hsv', "Interpolate in the HSV color system."), def __init__(self, none_ok=False):
('hsl', "Interpolate in the HSL color system."), super().__init__(
('none', "Don't show a gradient.")) none_ok,
valid_values=ValidValues(
('rgb', "Interpolate in the RGB color system."),
('hsv', "Interpolate in the HSV color system."),
('hsl', "Interpolate in the HSL color system."),
('none', "Don't show a gradient.")))
MAPPING = { MAPPING = {
'rgb': QColor.Rgb, 'rgb': QColor.Rgb,
@ -1087,23 +1101,11 @@ class ShellCommand(BaseType):
return shlex.split(value) return shlex.split(value)
class HintMode(BaseType):
"""Base class for the hints -> mode setting."""
special = True
valid_values = ValidValues(('number', "Use numeric hints."),
('letter', "Use the chars in the hints -> "
"chars setting."))
class Proxy(BaseType): class Proxy(BaseType):
"""A proxy URL or special value.""" """A proxy URL or special value."""
special = True special = True
valid_values = ValidValues(('system', "Use the system wide proxy."),
('none', "Don't use any proxy"))
PROXY_TYPES = { PROXY_TYPES = {
'http': QNetworkProxy.HttpProxy, 'http': QNetworkProxy.HttpProxy,
@ -1111,6 +1113,12 @@ class Proxy(BaseType):
'socks5': QNetworkProxy.Socks5Proxy, 'socks5': QNetworkProxy.Socks5Proxy,
} }
def __init__(self, none_ok=False):
super().__init__(none_ok)
self.valid_values = ValidValues(
('system', "Use the system wide proxy."),
('none', "Don't use any proxy"))
def validate(self, value): def validate(self, value):
self._basic_validation(value) self._basic_validation(value)
if not value: if not value:
@ -1297,13 +1305,14 @@ class AutoSearch(BaseType):
"""Whether to start a search when something else than a URL is entered.""" """Whether to start a search when something else than a URL is entered."""
special = True special = True
valid_values = ValidValues(('naive', "Use simple/naive check."),
('dns', "Use DNS requests (might be slow!)."),
('false', "Never search automatically."))
def __init__(self, none_ok=False): def __init__(self, none_ok=False):
super().__init__(none_ok) super().__init__(none_ok)
self.booltype = Bool(none_ok=none_ok) self.booltype = Bool(none_ok=none_ok)
self.valid_values = ValidValues(
('naive', "Use simple/naive check."),
('dns', "Use DNS requests (might be slow!)."),
('false', "Never search automatically."))
def validate(self, value): def validate(self, value):
self._basic_validation(value) self._basic_validation(value)
@ -1330,8 +1339,6 @@ class Position(MappingType):
"""The position of the tab bar.""" """The position of the tab bar."""
valid_values = ValidValues('top', 'bottom', 'left', 'right')
MAPPING = { MAPPING = {
'top': QTabWidget.North, 'top': QTabWidget.North,
'bottom': QTabWidget.South, 'bottom': QTabWidget.South,
@ -1339,12 +1346,19 @@ class Position(MappingType):
'right': QTabWidget.East, 'right': QTabWidget.East,
} }
def __init__(self, none_ok=False):
super().__init__(
none_ok,
valid_values=ValidValues('top', 'bottom', 'left', 'right'))
class VerticalPosition(BaseType): class VerticalPosition(BaseType):
"""The position of the download bar.""" """The position of the download bar."""
valid_values = ValidValues('top', 'bottom') def __init__(self, none_ok=False):
super().__init__(none_ok)
self.valid_values = ValidValues('top', 'bottom')
class UrlList(List): class UrlList(List):
@ -1389,10 +1403,6 @@ class SelectOnRemove(MappingType):
"""Which tab to select when the focused tab is removed.""" """Which tab to select when the focused tab is removed."""
special = True special = True
valid_values = ValidValues(
('left', "Select the tab on the left."),
('right', "Select the tab on the right."),
('previous', "Select the previously selected tab."))
MAPPING = { MAPPING = {
'left': QTabBar.SelectLeftTab, 'left': QTabBar.SelectLeftTab,
@ -1400,31 +1410,13 @@ class SelectOnRemove(MappingType):
'previous': QTabBar.SelectPreviousTab, 'previous': QTabBar.SelectPreviousTab,
} }
def __init__(self, none_ok=False):
class LastClose(BaseType): super().__init__(
none_ok,
"""Behavior when the last tab is closed.""" valid_values=ValidValues(
('left', "Select the tab on the left."),
special = True ('right', "Select the tab on the right."),
valid_values = ValidValues(('ignore', "Don't do anything."), ('previous', "Select the previously selected tab.")))
('blank', "Load a blank page."),
('startpage', "Load the start page."),
('default-page', "Load the default page."),
('close', "Close the window."))
class AcceptCookies(BaseType):
"""Control which cookies to accept."""
special = True
valid_values = ValidValues(('all', "Accept all cookies."),
('no-3rdparty', "Accept cookies from the same"
" origin only."),
('no-unknown-3rdparty', "Accept cookies from "
"the same origin only, unless a cookie is "
"already set for the domain."),
('never', "Don't accept cookies at all."))
class ConfirmQuit(FlagList): class ConfirmQuit(FlagList):
@ -1432,15 +1424,20 @@ class ConfirmQuit(FlagList):
"""Whether to display a confirmation when the window is closed.""" """Whether to display a confirmation when the window is closed."""
special = True special = True
valid_values = ValidValues(('always', "Always show a confirmation."),
('multiple-tabs', "Show a confirmation if "
"multiple tabs are opened."),
('downloads', "Show a confirmation if "
"downloads are running"),
('never', "Never show a confirmation."))
# Values that can be combined with commas # Values that can be combined with commas
combinable_values = ('multiple-tabs', 'downloads') combinable_values = ('multiple-tabs', 'downloads')
def __init__(self, none_ok=False):
super().__init__(none_ok)
self.valid_values = ValidValues(
('always', "Always show a confirmation."),
('multiple-tabs', "Show a confirmation if "
"multiple tabs are opened."),
('downloads', "Show a confirmation if "
"downloads are running"),
('never', "Never show a confirmation."))
def validate(self, value): def validate(self, value):
super().validate(value) super().validate(value)
if not value: if not value:
@ -1457,36 +1454,19 @@ class ConfirmQuit(FlagList):
value, "List cannot contain always!") value, "List cannot contain always!")
class ForwardUnboundKeys(BaseType):
"""Whether to forward unbound keys."""
special = True
valid_values = ValidValues(('all', "Forward all unbound keys."),
('auto', "Forward unbound non-alphanumeric "
"keys."),
('none', "Don't forward any keys."))
class CloseButton(BaseType):
"""Mouse button used to close tabs."""
special = True
valid_values = ValidValues(('right', "Close tabs on right-click."),
('middle', "Close tabs on middle-click."),
('none', "Don't close tabs using the mouse."))
class NewTabPosition(BaseType): class NewTabPosition(BaseType):
"""How new tabs are positioned.""" """How new tabs are positioned."""
special = True special = True
valid_values = ValidValues(('left', "On the left of the current tab."),
('right', "On the right of the current tab."), def __init__(self, none_ok=False):
('first', "At the left end."), super().__init__(none_ok)
('last', "At the right end.")) self.valid_values = ValidValues(
('left', "On the left of the current tab."),
('right', "On the right of the current tab."),
('first', "At the left end."),
('last', "At the right end."))
class IgnoreCase(Bool): class IgnoreCase(Bool):
@ -1494,10 +1474,14 @@ class IgnoreCase(Bool):
"""Whether to ignore case when searching.""" """Whether to ignore case when searching."""
special = True special = True
valid_values = ValidValues(('true', "Search case-insensitively"),
('false', "Search case-sensitively"), def __init__(self, none_ok=False):
('smart', "Search case-sensitively if there " super().__init__(none_ok)
"are capital chars")) self.valid_values = ValidValues(
('true', "Search case-insensitively"),
('false', "Search case-sensitively"),
('smart', "Search case-sensitively if there "
"are capital chars"))
def transform(self, value): def transform(self, value):
if value.lower() == 'smart': if value.lower() == 'smart':
@ -1515,57 +1499,12 @@ class IgnoreCase(Bool):
super().validate(value) super().validate(value)
class NewInstanceOpenTarget(BaseType):
"""How to open links in an existing instance if a new one is launched."""
special = True
valid_values = ValidValues(('tab', "Open a new tab in the existing "
"window and activate the window."),
('tab-bg', "Open a new background tab in the "
"existing window and activate the "
"window."),
('tab-silent', "Open a new tab in the existing "
"window without activating "
"the window."),
('tab-bg-silent', "Open a new background tab "
"in the existing window "
"without activating the "
"window."),
('window', "Open in a new window."))
class DownloadPathSuggestion(BaseType):
"""How to format the question when downloading."""
special = True
valid_values = ValidValues(('path', "Show only the download path."),
('filename', "Show only download filename."),
('both', "Show download path and filename."))
class Referer(BaseType):
"""Send the Referer header."""
valid_values = ValidValues(('always', "Always send."),
('never', "Never send; this is not recommended,"
" as some sites may break."),
('same-domain', "Only send for the same domain."
" This will still protect your privacy, but"
" shouldn't break any sites."))
class UserAgent(BaseType): class UserAgent(BaseType):
"""The user agent to use.""" """The user agent to use."""
special = True special = True
def __init__(self, none_ok=False):
super().__init__(none_ok)
def validate(self, value): def validate(self, value):
self._basic_validation(value) self._basic_validation(value)
@ -1620,25 +1559,6 @@ class UserAgent(BaseType):
return out return out
class TabBarShow(BaseType):
"""When to show the tab bar."""
valid_values = ValidValues(('always', "Always show the tab bar."),
('never', "Always hide the tab bar."),
('multiple', "Hide the tab bar if only one tab "
"is open."),
('switching', "Show the tab bar when switching "
"tabs."))
class URLSegmentList(FlagList):
"""A list of URL segments."""
valid_values = ValidValues('host', 'path', 'query', 'anchor')
class TimestampTemplate(BaseType): class TimestampTemplate(BaseType):
"""A strftime-like template for timestamps. """A strftime-like template for timestamps.

View File

@ -225,27 +225,18 @@ class TestBaseType:
assert basetype.complete() == completions assert basetype.complete() == completions
class GoodMappingSubclass(configtypes.MappingType): class MappingSubclass(configtypes.MappingType):
"""A MappingType we use in TestMappingType which is valid/good.""" """A MappingType we use in TestMappingType which is valid/good."""
valid_values = configtypes.ValidValues('one', 'two')
MAPPING = { MAPPING = {
'one': 1, 'one': 1,
'two': 2, 'two': 2,
} }
def __init__(self, none_ok=False):
class BadMappingSubclass(configtypes.MappingType): super().__init__(none_ok)
self.valid_values = configtypes.ValidValues('one', 'two')
"""A MappingType which is missing a value in MAPPING."""
valid_values = configtypes.ValidValues('one', 'two')
MAPPING = {
'one': 1,
}
class TestMappingType: class TestMappingType:
@ -261,7 +252,7 @@ class TestMappingType:
@pytest.fixture @pytest.fixture
def klass(self): def klass(self):
return GoodMappingSubclass return MappingSubclass
@pytest.mark.parametrize('val', TESTS.keys()) @pytest.mark.parametrize('val', TESTS.keys())
def test_validate_valid(self, klass, val): def test_validate_valid(self, klass, val):
@ -276,9 +267,11 @@ class TestMappingType:
def test_transform(self, klass, val, expected): def test_transform(self, klass, val, expected):
assert klass().transform(val) == expected assert klass().transform(val) == expected
def test_bad_subclass_init(self): @pytest.mark.parametrize('typ', [configtypes.ColorSystem(),
with pytest.raises(ValueError): configtypes.Position(),
BadMappingSubclass() configtypes.SelectOnRemove()])
def test_mapping_type_matches_valid_values(self, typ):
assert list(sorted(typ.MAPPING)) == list(sorted(typ.valid_values))
class TestString: class TestString:
@ -383,9 +376,12 @@ class FlagListSubclass(configtypes.FlagList):
Valid values are 'foo', 'bar' and 'baz'. Valid values are 'foo', 'bar' and 'baz'.
""" """
valid_values = configtypes.ValidValues('foo', 'bar', 'baz')
combinable_values = ['foo', 'bar'] combinable_values = ['foo', 'bar']
def __init__(self, none_ok=False):
super().__init__(none_ok)
self.valid_values = configtypes.ValidValues('foo', 'bar', 'baz')
class TestFlagList: class TestFlagList: