Merge branch 'master' of git://github.com/Kingdread/qutebrowser into Kingdread-master

This commit is contained in:
Florian Bruhin 2015-08-08 15:14:08 +02:00
commit f76b741fb6
4 changed files with 128 additions and 23 deletions

View File

@ -60,6 +60,8 @@ Fixed
- Fixed entering of insert mode when certain disabled text fields were clicked.
- Fixed a crash when using `:set` with `-p` and `!` (invert value)
- Downloads with unknown size are now handled correctly.
- `:navigate increment/decrement` (`<Ctrl-A>`/`<Ctrl-X>`) now handles some
corner-cases better.
Removed
~~~~~~~

View File

@ -19,7 +19,6 @@
"""Command dispatcher for TabbedBrowser."""
import re
import os
import shlex
import posixpath
@ -472,29 +471,10 @@ class CommandDispatcher:
background: Open the link in a new background tab.
window: Open the link in a new window.
"""
encoded = bytes(url.toEncoded()).decode('ascii')
# Get the last number in a string
match = re.match(r'(.*\D|^)(\d+)(.*)', encoded)
if not match:
raise cmdexc.CommandError("No number found in URL!")
pre, number, post = match.groups()
if not number:
raise cmdexc.CommandError("No number found in URL!")
try:
val = int(number)
except ValueError:
raise cmdexc.CommandError("Could not parse number '{}'.".format(
number))
if incdec == 'decrement':
if val <= 0:
raise cmdexc.CommandError("Can't decrement {}!".format(val))
val -= 1
elif incdec == 'increment':
val += 1
else:
raise ValueError("Invalid value {} for indec!".format(incdec))
urlstr = ''.join([pre, str(val), post]).encode('ascii')
new_url = QUrl.fromEncoded(urlstr)
new_url = urlutils.incdec_number(url, incdec)
except urlutils.IncDecError as error:
raise cmdexc.CommandError(error.msg)
self._open(new_url, tab, background, window)
def _navigate_up(self, url, tab, background, window):

View File

@ -443,3 +443,59 @@ class FuzzyUrlError(Exception):
return self.msg
else:
return '{}: {}'.format(self.msg, self.url.errorString())
class IncDecError(Exception):
"""Exception raised by incdec_number on problems.
Attributes:
msg: The error message.
url: The QUrl which caused the error.
"""
def __init__(self, msg, url):
super().__init__(msg)
self.url = url
self.msg = msg
def __str__(self):
return '{}: {}'.format(self.msg, self.url.toString())
def incdec_number(url, incdec):
"""Find a number in the url and increment or decrement it.
Args:
url: The current url
incdec: Either 'increment' or 'decrement'
Return:
The new url with the number incremented/decremented.
Raises IncDecError if the url contains no number.
"""
if not url.isValid():
raise ValueError(get_errstring(url))
path = url.path()
# Get the last number in a string
match = re.match(r'(.*\D|^)(\d+)(.*)', path)
if not match:
raise IncDecError("No number found in URL!", url)
pre, number, post = match.groups()
# This should always succeed because we match \d+
val = int(number)
if incdec == 'decrement':
if val <= 0:
raise IncDecError("Can't decrement {}!".format(val), url)
val -= 1
elif incdec == 'increment':
val += 1
else:
raise ValueError("Invalid value {} for indec!".format(incdec))
new_path = ''.join([pre, str(val), post])
# Make a copy of the QUrl so we don't modify the original
new_url = QUrl(url)
new_url.setPath(new_path)
return new_url

View File

@ -524,3 +524,70 @@ def test_same_domain_invalid_url(url1, url2):
"""Test same_domain with invalid URLs."""
with pytest.raises(ValueError):
urlutils.same_domain(QUrl(url1), QUrl(url2))
class TestIncDecNumber:
"""Tests for urlutils.incdec_number()."""
@pytest.mark.parametrize('url, incdec, output', [
("http://example.com/index1.html", "increment", "http://example.com/index2.html"),
("http://foo.bar/folder_1/image_2", "increment", "http://foo.bar/folder_1/image_3"),
("http://bbc.c0.uk:80/story_1", "increment", "http://bbc.c0.uk:80/story_2"),
("http://mydomain.tld/1_%C3%A4", "increment", "http://mydomain.tld/2_%C3%A4"),
("http://example.com/site/5#5", "increment", "http://example.com/site/6#5"),
("http://example.com/index10.html", "decrement", "http://example.com/index9.html"),
("http://foo.bar/folder_1/image_3", "decrement", "http://foo.bar/folder_1/image_2"),
("http://bbc.c0.uk:80/story_1", "decrement", "http://bbc.c0.uk:80/story_0"),
("http://mydomain.tld/2_%C3%A4", "decrement", "http://mydomain.tld/1_%C3%A4"),
("http://example.com/site/5#5", "decrement", "http://example.com/site/4#5"),
])
def test_incdec_number(self, url, incdec, output):
"""Test incdec_number with valid URLs."""
new_url = urlutils.incdec_number(QUrl(url), incdec)
assert new_url == QUrl(output)
@pytest.mark.parametrize('url', [
"http://example.com/long/path/but/no/number",
"http://ex4mple.com/number/in/hostname",
"http://example.com:42/number/in/port",
"http://www2.example.com/number/in/subdomain",
"http://example.com/%C3%B6/urlencoded/data",
"http://example.com/number/in/anchor#5",
"http://www2.ex4mple.com:42/all/of/the/%C3%A4bove#5",
])
def test_no_number(self, url):
"""Test incdec_number with URLs that don't contain a number."""
with pytest.raises(urlutils.IncDecError):
urlutils.incdec_number(QUrl(url), "increment")
def test_number_below_0(self):
"""Test incdec_number with a number that would be below zero
after decrementing."""
with pytest.raises(urlutils.IncDecError):
urlutils.incdec_number(QUrl('http://example.com/page_0.html'),
'decrement')
def test_invalid_url(self):
"""Test if incdec_number rejects an invalid URL."""
with pytest.raises(ValueError):
urlutils.incdec_number(QUrl(""), "increment")
def test_wrong_mode(self):
"""Test if incdec_number rejects a wrong parameter for the incdec
argument."""
valid_url = QUrl("http://example.com/0")
with pytest.raises(ValueError):
urlutils.incdec_number(valid_url, "foobar")
@pytest.mark.parametrize("url, msg, expected_str", [
("http://example.com", "Invalid", "Invalid: http://example.com"),
])
def test_incdec_error(self, url, msg, expected_str):
"""Test IncDecError."""
url = QUrl(url)
with pytest.raises(urlutils.IncDecError) as excinfo:
raise urlutils.IncDecError(msg, url)
assert excinfo.value.url == url
assert str(excinfo.value) == expected_str