Since we're not using those functions as argparse callbacks anymore, we
can write a normal function instead of factories, which simplifies
things a lot.
This means:
- An annotation like (int, str) is now typing.Union[int, str].
- utils.typing got expanded so it acts like the real typing.py, with
issubclass() working properly with typing.Union and __union_params__
being set.
- A literal string doesn't exist anymore as annotation, instead
@cmdutils.argument now has a 'choices' argument which can be used like
@cmdutils.argument('arg', choices=['val1', 'val2']).
- Argument validating/converting is now entirely handled by
argparser.type_conv instead of relying on python's argparse, i.e.
type/choices is now not passed to argparse anymore.
TestArgument didn't clear the globals as the fixture was inside
TestRegister.
This means test_run_vulture failed in funny ways because run_vulture.py
generated a whitelist containing "<locals>" for commands:
tests/unit/scripts/test_run_vulture.py:55: in run
return run_vulture.run([str(e.basename) for e in files])
scripts/dev/run_vulture.py:146: in run
vult.scavenge(files + [whitelist_file.name])
.tox/py35/lib/python3.5/site-packages/vulture.py:107: in scavenge
self.scan(module_string)
.tox/py35/lib/python3.5/site-packages/vulture.py:75: in scan
node = ast.parse(node_string, filename=self.file)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
source = 'qutebrowser.browser.commands.CommandDispatcher.buffer\nqutebrowser.misc.savemanager.SaveManager.save_command\nqutebro...iidoc.UsageFormatter._get_default_metavar_for_positional\nscripts.dev.src2asciidoc.UsageFormatter._metavar_formatter\n'
filename = '/tmp/tmp_ein2umn', mode = 'exec'
def parse(source, filename='<unknown>', mode='exec'):
"""
Parse the source into an AST node.
Equivalent to compile(source, filename, mode, PyCF_ONLY_AST).
"""
> return compile(source, filename, mode, PyCF_ONLY_AST)
E File "/tmp/tmp_ein2umn", line 16
E test_cmdutils.TestArgument.test_wrong_order.<locals>.fun
E ^
E SyntaxError: invalid syntax
Previously, negative bottom padding was used (probably to compensate
for a trailing <br>). With the table format, this is no longer
necessary and causes the last line to be drawn too low.
This allows webkit to color links that are clicked on but never rendered as
visited too. It also means if you get redirected from eg http://site.com to
http://site.com/ you have essentially duplicates in your history. This makes
the history completion a bit noisier. I suppose normalising paths before
checking for duplicates might help. Also note that otter has an isTypedIn flag
which might be used for dealing with this.
Now adds a url to browser history once we have connected and got enough data
to start rendering the page. The previous approach saved urls as soon as
navigation was initiated, so upon encountering a redirect the final url wasn't
saved.
Using layout started rather than load finished means that pages whose contents
manage to load minus one troublesome asset will still be saved.
Adds a title to the HistoryEntry class and includes it in the serialization
stuff. Not currently set from anywhere.
Not sure if anything more needs to be done to support non-ascii characters.
Everything works fine for me with unicode chars in url and title but
everything in my stack is utf-8.
Don't show special keys in the keyhint window as these currently cannot
be part of keychains.
Use a rounded border on the top-right corner and square on the rest.
This failed because dict.get('level') returned None with no level
parameter, and the subsequent [0] raised:
Traceback (most recent call last):
File ".../qutebrowser/utils/utils.py", line 624, in wrapper
return func(*args, **kwargs)
File ".../qutebrowser/browser/network/networkmanager.py", line 445, in createRequest
op, req, outgoing_data)
File ".../qutebrowser/browser/network/qutescheme.py", line 107, in createRequest
data = handler(self._win_id, request)
File ".../qutebrowser/browser/network/qutescheme.py", line 189, in qute_log
level = urllib.parse.parse_qs(request.url().query()).get('level')[0]
TypeError: 'NoneType' object is not subscriptable
With the changes to get rid of colorlog, we broke this, as e.g. {green}
was an undefined key for the vanilla logging.Formatter used for the
in-RAM log. Now we instead use a ColoredFormatter with colors turned
off.
From code review:
- escape all strings used in the keyhint html
- read the prefix color each time the hint is shown
- use show/hide instead of setVisible
- clean up pylint/flake8 errors
- use CssColor instead of QssColor for keyhint.fg.suffix
- add some padding to the keyhint popup
When the current keystring is a partial match for one or more bindings,
show the possible bindings in a small overlay.
The overlay is partially transparent by default, but the background
color is configurable as ui->keystring.bg.
- Add log.LOG_LEVELS to map names to levels (instead of using
logging._levelToName)
- Test that log pages do not contain messages below the requested level
- Use pythons urllib.parse.parse_qs instead of Qt's UrlQuery
- Document tab, bg, window args for :messages
- Clean up style
This adds a 'level' query parameter to qute://log and qute://plainlog.
For example, qute://log?level=warning will show an html page containing
log entries with severity warning or greater.
If the query is omitted, the original behavior of qute://log is
preserved.
:messages [level] is a command that opens qute://log?level=<level>.
By default, level defaults to 'error' as an easy way to see missed
error messages.
colorlog was problematic for various reasons:
- Not commonly packaged for Linux distributions
- Calling colorama.init() automatically on import
- Not supporting {foo} log formatting
- Not supporting an easy way to turn colors off
Instead we now do the log coloring by hand, which is simpler and means
everyone will have colored logs.
The output failed the tests as it was parsed as invalid. Indenting helps
with that.
This also simplifies things a bit by having a _log_stack function and
shows the type of stack we're printing.
Before we used a {'nargs': '*'} annotation for the respective argument
to tell qutebrowser it's optional for the commandline. Now we instead
use a star_args_optional argument for @cmdutils.register as a first step
towards freeing up argument annotations for PEP 484.
See #637.
The CompletionItemDelegate gets reused by Qt for various items in the
completion. Every time _get_textdoc() was called we created a new
QTextDocument, but since it has a long-living parent set (the delegate)
the old one was never actually garbage collected.
We now explicitly delete the old QTextDocument as it's not needed
anymore by either Qt or Python.
See #1476.
len(self.downloads) is already the index of the item in the download
list, this should be used for beginInsertRows(). The +1 is only for the
human readable part.
Issue #846
.rowCount() returns all downloads, even the finished ones that have not
yet been removed from the list. For confirming the quit event, we should
only consider downloads that are still running.
In on_config_changed, we now ignore FileNotFoundError as that's a common
occurence and not something worth logging.
In case of other OSError's we now also log the exact error message.
Issue 1413
This happens when the networkmanager is used by something that has no
tab_id, like the generic DownloadManager. In this case, we should just
skip the webview connection (as it makes no sense) instead of crashing
(which is the last thing we want to do).
All commands will be offered as completions for the <command> argument
of :bind.
Due to the way completers parse the command line, the following
bind --mode caret j
will throw off completions as 'caret' is treated as a positional arg in
terms of the argument count for completions.
In the above example, completion will be triggered for 'j' and no
completions will be given for the actual command.
bind --mode=caret j will complete correctly, though completions are not
filtered by the given mode.
I attempted an approach to filter the commands based on the mode but it
ended up being messy and flaky.
The <command> arg is now optional. If omitted, :bind prints the current
binding as a message. If --mode is given, the binding for that mode is
printed.
Allow a variable amount of whitespace for rgb, rgba, hsv, and hsva
strings in the config.
Previously only 'rgb(0, 0, 0)' was allowed. Now things like
'rgb(0,0,0)' are permitted.
The repeated 3-digit segments of the regexes were separated out to
reduce repetition and line length.
If the process emitted error() and then finished(), we already set
self._filepath to None and did other cleanup.
Instead we do the file reading inside _cleanup and call that from
on_process_error and on_process_finished.
Issue #1412
When passing --cachedir="" on the command line, standarddir.cache()
returns None, which stands for "deactivate cache" and has to be
properly handled in DiskCache.__init__() (i.e. don't pass it to
os.path.join)
This worked fine with Python 3.5 but causes a circular import which is
hard to break with Python 3.4.
The original solution was to do @pyqtSlot(object), but that doesn't work
with PyQt 5.6 anymore...
When using :tab-prev/:tab-next (or :tab-focus which uses :tab-next
internally) immediately after the last tab, those functions could be
called with 0 tabs open, which caused a ZeroDivisionError when trying to
do % 0.
Fixes#1448.
Allows to use ctrl+d to close tabs from the buffer completion widget
when they are selected. Respects current tab settings like whether you
can close the last tab in a window.
Had to change the `rebuild()` method to use `setData()` when possible
because the selection was being lost if the whole model was being rebuilt.
Current problems are:
1) When opening a new window while you already the tab completion open on
one window a category is added for the new window but new rows in
that category aren't picked up. Interesting if you open a third
window then close the second window the completion display is now
correct... I can see that the model is being updated correctly but I
am not sure why that isn't propagating to the view. Not sure whether
it is worth looking into (further) either.
2) Bit of duplication of code, it iterates over the window registry
twice. Could put everything in one loop but then that would be
dependant on the current behaviour of the `tab_closed` signal being
called with the relevant `tabbed_browser` still existing but with the
`shutting_down` flag set.
3) I'm still using just the one `rebuild()` method and removing items from
the end then calling `setData` on everything rather than having special
`on_tab/window_closed` methods (or partial functions) that delete the
actual corresponding item. Because if I did that I would also have to
special case tab moves etc.
Avoid a crash when undoing twice on the default page with last-close set to
default-page.
This was caused by logic to reuse the current tab if it is on the default page
and has no history. The fix is using openurl rather than removeTab/tabopen.
Mark two callbacks with pyqtSlot as appropriate.
Return False instead of raising NotImplementedException to avoid pylint
identifying MarkKeyParser as abstract.
Ensure MarkKeyParser implements on_keyconfig_changed, so it doesn't fail when
rebinding a key. It doesn't have keybindings, so the implementation is just
`pass`.
This also fixes a few flake8 style errors.
- Fix a docstring copy-paste
- Add own name/copyright date to new file
- Simplify a bdd expression (no need for regex)
- Scroll to a pixel position in a single operation
Rather than binding each set of local marks to a tab, bind them to a
url. Strip the fragment from the url, as two pages that differ only in
fragment are likely the same page.
Automatically set the special "'" mark when jumping.
jump-mark "'" will jump to the last position before the previous jump.
A jump could be navigating via a link, jumping to another mark, or
scrolling by percentage (e.g. gg or G).
set-mark <key> saves your current scroll position as mark <key>.
jump-mark <key> jumps to the position previously set for mark <key>.
If <key> is lowercase, it is local to the current tab. Each tab has its
own set of lowercase marks.
If <key> is uppercase, it is global across tabs, and stores a url and a
scroll position. Jumping to an uppercase mark navigates to that url,
then scrolls to the saved position.
Resolves#310.
* upstream/master: (327 commits)
Remove unused import
tox: Update Werkzeug to 0.11.8
Regenerate authors
Use __file__ instead of sys.argv[0]
Regenerate authors
Make update_3rdparty.py install correctly when run from any directory
Open command line urls explicitly.
tox: Update Werkzeug to 0.11.6
Move qutebrowser.rcc to misc/
Regenerate resources
Fix CHANGELOG/link in README
New qutebrowser logo!
www: Add releases link
Release v0.6.1
release checklist: Clarify how to build on Windows
Make sure the cheatsheet PNG is included in sdist
Fix cheatsheet link URL in quickstart
Mark segfault on exit in test_smoke as xfail
Add a xfail test for #797
Add missing file
...
Conflicts:
tests/integration/features/hints.feature
Under some circumstances I can't reproduce (switching/turning off
monitors?) it seems it's possible that SessionManager.save gets called
with last_window=True, without on_last_window_closed being called.
This might be to one of the Qt screen management bugs fixed in Qt 5.6,
which would explain why I can't reproduce it.
Instead of crashing, let's log the error and not save the session.
This makes it possible to jump to the very last tab, as opposed to the
last focused tab, by using -1 as the index. Generally negative indexes
are counted from the end.
Solves issue #1166
This was needed before there was editor.ExternalEditor as there were
various commands which needed to access the editor object.
Since this is encapsulated in ExternalEditor now, no need to keep a
reference to the object around.
The edit-url command opens a url (by default, the current url) in the
user's external editor and navigates to the result when the editor is
closed. This makes it easy to tweak the current url to navigate within
a site.
`edit-url` accepts the same flags as `open` (e.g. -t will open in a new
tab.
One may provide a url as an argument to create a shortcut to
pre-populate part of a url and allow filling in the rest.
There is no default keybinding.
Resolves#1261.
Searching for that error doesn't turn up many helpful results, but it
seems to be harmless and shown when downloading a file - it's also new
in Qt 5.6 it seems, so let's just ignore it.
The previous fix didn't work in situations where the web view was
actually focused, but had no focused element (like about:blank).
The new fix always works, and even is a lot simpler!
Fixes#504.
When a download is finished with `removed-finished-download` set to a
delay, it's removed via a singleshot QTimer.
However, when the window was closed in the meantime, the slot still was
executed by Qt, even though the DownloadManager was already deleted.
Fixes#1242
Those were added in #443, inspired by luakit.
However, all other bindings follow dwb's defaults, and dwb uses `gt` for
showing buffers. To be consistent, let's rebind gt to show :buffer.
`buffer` takes either a tab index or a string and focuses the specified
tab. The index can be of the form [0-9]+ which will switch to the
relevant tab in the current window or [0-9]+/[0-9]+ (that is
win_id/index) which will focus the specified window before switching
tabs. If a string is passed the list of open tabs across all windows is
sorted based on title and url (just like in the completion widget) and
the top result is selected.
Issue #1334
The problem was that there were too few slashes. On Linux, absolute
paths start with /, so
file:// + /home
gives file:///home, which is a valid path. On windows however, absolute
paths start with a drive letter, so
file:// + C:/Users
gives file://C:/Users, which is parsed as "host C, path Users", which is
why it could be written as file://c/Users (strip out the empty "port"),
giving us an invalid path.
The solution is to add the third slash in the template, and strip the
redundant slash on unix systems.
Additionally, this fixes a bug where navigating from '/home/' to the
parent directory would give '/home' instead of '/'
Fix for #676
It removes the target of the link, as to prevent the website to overrule
the user. I guess the following things should be done:
- add setting to enable/disable this behaviour
- and/or add "hint all current"
Only the first one would be easiest. The second one requires us to keep track
of the original target. I should open a pull request for discussion.
We can get UndefinedError when a new function got added to the jinja
env (and gets called from a template) and the user did update the
on-disk templates but not restart qutebrowser yet.
In this case, let's show a special error page to the user and tell them
to do :report in the unlikely case it's actually a bug.
Fixes#1362.
See #1360.
Before, in fonts -> _monospace we preferred Liberation Mono to Courier and
Courier New. Unfortunately, that font looks horrible on Windows if it's
installed, so let's avoid using it if possible.
On Linux, hopefully Courier New/Courier isn't available, and Liberation Mono
will get picked up instead (or one of the other alternatives).
* upstream/master: (22 commits)
Regenerate authors.
Only run geolocation tests on CI
Switch to flake8-docstrings with pydocstyle
Fix lint
Move pylint plugins to an installed package.
Include pytest-xvfb properly in frozen tests
tests: Handle trailing / in wait_for_load_finished.
Fix lint.
tox: Upgrade hypothesis to 3.0.2.
tests: Add first end-to-end test for hints.
hints: Log the used hint chars
bdd: use quteproc.wait_for_load_finished.
Remove xvfbwrapper from freeze_tests.py.
Regenerate authors.
Combine launch/crash time into one section.
Split long lines.
Switch to pytest-xvfb. Fixes#1309.
no ellipsis is inserted in big windows
Regenerate authors.
fixes#1308
...
Issues #1269, #866
qutebrowser would crash when XDG_DOWNLOAD_DIR was set to some
non-absolute value (which should not happen, but it can) and
"storage -> download-dir" was empty, since when the user didn't give an
absolute filename, even the joined path of download_dir() (i.e.
XDG_DOWNLOAD_DIR in this case) and the filename was not absolute either.
Since the path was not absolute, create_full_filename returned None,
which meant that os.path.basename(self._filename) raised an exception.
Now we display an error message and fall back to $HOME.
Issue #1214
Now uses a sensible filename for data: links instead of the whole base64
content. For PDF.js, it even uses the correct pdf filename.
TODO: Produces "QPainter:🔚 Painter ended with 2 saved states" while
running the tests here (Arch Linux):
CPython: 3.5.1
Qt: 5.5.1, runtime: 5.5.1
PyQt: 5.5.1
Otherwise the stacktrace might be confusing since it will show the
FileNotFoundException as the causing error, which is not true (it just
happens to be the last checked place).
The .path attribute was added so that we still have the requested path
in the error log.
See #1280.
For some reason, when comparing the repr in the two processes, we get different
results on OS X and Windows:
- expected: "fünf"
- "f\xfcnf" coming back from the subprocess on OS X
- "fnf" on Windows
Instead we're comparing the json dump now, which should be more predictable.
There are a lot of problems and flakiness with using a real clipboard.
Instead we now have a :debug-set-fake-clipboard command to set a text, and use
logging when getting the contents.
Fixes#1285.
Before we raised QtValueError (via qtutils.ensure_valid), but maybe there are
more callers out there which call fuzzy_url with an empty input - and it makes
more sense to raise InvalidUrlError which gets displayed to the user than
raising QtValueError which is more like an assertion.
I tried to set my editor to `termite -e "vim -f {}"`, termite being a
pretty cool and light terminal I use within my i3wm Arch linux box.
So when I open my editor I want it to launch a terminal with Vim inside
instead of GVim for various reasons.
The validation rejected this at first because it was looking for '{}'
inside ['foo', 'bar', 'baz {}'], essentially. So I need it to look
inside the sub-strings, not just the list.
Then after validation I need to perform the '{}' replacement inside the
sub-string too, not just replacing the whole string.
WebHistory now has a clear() method which is also a command
(history-clear) which clears the qutebrowser history using the new
lineparser clear() method and emits a cleared signal.
The completion model urlmodel connects to the WebHistory.cleared signal
and clears its history category completion list.
I am adding this as a temporary fix before #58 or #1051 get implemented.
It seems that unlike Gecko, WebKit does not support undo/redo operations
when the textarea's `value` attribute is changed directly. Fortunately
there is a WebKit-specific workaround using textInput event.
References:
* http://stackoverflow.com/a/7554295
* http://help.dottoro.com/ljuecqgv.php
The Shift+Ins key should arguably insert primary selection, not the
clipboard selection as every Qt program does. This commit makes it
possible via the hidden paste-primary command (enabled by default).
Unfortunately QtWebKit does not provide any straightforward way to
insert text at cursor position into editable fields, so we work around
this by executing a JavaScript snippet - inspired by this SO answer:
http://stackoverflow.com/a/11077016
This logged an error on Windows:
ERROR misc networkmanager:on_authentication_required:269 Unable to read the netrc file
Traceback (most recent call last):
File "c:\python34\Lib\netrc.py", line 27, in __init__
file = os.path.join(os.environ['HOME'], ".netrc")
File "C:\Users\florian\buildbot\slave\win8\build\.tox\py34\lib\os.py", line 633, in __getitem__
raise KeyError(key) from None
KeyError: 'HOME'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\florian\buildbot\slave\win8\build\qutebrowser\browser\network\networkmanager.py", line 262, in on_authentication_required
net = netrc.netrc()
File "c:\python34\Lib\netrc.py", line 29, in __init__
raise OSError("Could not find .netrc: $HOME is not set")
Since this case is pretty common, we don't want to log it - and checking the
variable beforehand is easier than parsing the exception message.
This should fix the failing tests on Windows.
Otherwise, on OS X we got the same SSL error logged twice as on_ssl_errors is
called twice. This means the tests only marked one as expected, and it failed
because of the other one.