Compare commits

...

1243 Commits

Author SHA1 Message Date
Florian Bruhin
8bd4d3d24a Release v0.5.0 2016-01-05 19:30:50 +01:00
Florian Bruhin
8acbdda00e Don't hide stderr in link_pyqt.py.
We're just hiding useful debug information this way.
2016-01-05 19:17:56 +01:00
Florian Bruhin
2ccb4342a4 Merge branch 'Kingdread-pdfjs' 2016-01-05 19:12:57 +01:00
Florian Bruhin
0d6d722732 Update changelog. 2016-01-05 19:08:21 +01:00
Florian Bruhin
d75ee78845 Clean up pdfjs tests. 2016-01-05 18:47:50 +01:00
Florian Bruhin
88d28e690e Add pdf.js version to qute:version. 2016-01-05 18:47:50 +01:00
Florian Bruhin
06f1d00083 Regenerate docs. 2016-01-05 18:47:49 +01:00
Florian Bruhin
e0557ac29e Clarify license text. 2016-01-05 18:47:49 +01:00
Florian Bruhin
e603470260 Fix asciidoc2html on Windows.
Windows needs the SystemRoot environment variable set to initialize the crypto
API, what running Python in a subprocess does.

However, we did override the whole environment instead of extending it, which
means this broke on Windows when calling asciidoc:

    Traceback (most recent call last):
      File "C:\asciidoc-8.6.9\asciidoc.py", line 9, in <module>
        import sys, os, re, time, traceback, tempfile, subprocess, codecs, locale, unicodedata, copy
      File "C:\Python27\lib\tempfile.py", line 35, in <module>
        from random import Random as _Random
      File "C:\Python27\lib\random.py", line 885, in <module>
        _inst = Random()
      File "C:\Python27\lib\random.py", line 97, in __init__
        self.seed(x)
      File "C:\Python27\lib\random.py", line 113, in seed
        a = long(_hexlify(_urandom(2500)), 16)
    WindowsError: [Error -2146893795] Provider DLL failed to initialize correctly
2016-01-05 08:00:35 +01:00
Florian Bruhin
5b68092277 Download pdfjs in build_release.py.
freeze.py now optionally includes pdfjs if it's present. This means we don't
need to download it every time to run frozen tests, but we can include it in
build_release.py when building a windows package.
2016-01-05 07:27:58 +01:00
Florian Bruhin
e05bc20885 Revert "Call update_3rdparty before freezing"
This reverts commit 384a9ad923.
2016-01-05 07:22:26 +01:00
Florian Bruhin
a97ba9aa09 Merge branch 'pdfjs' of https://github.com/Kingdread/qutebrowser into Kingdread-pdfjs 2016-01-05 07:21:26 +01:00
Florian Bruhin
814e6f5959 Fix lint. 2016-01-05 07:16:39 +01:00
Florian Bruhin
eefc94fb4d Fix build_release.py with inexistent dist-dir. 2016-01-05 07:14:11 +01:00
Florian Bruhin
129990857a Point out crash reports are currently public.
See #481.
2016-01-05 07:07:45 +01:00
Florian Bruhin
5ff37c482f Update changelog. 2016-01-05 07:03:26 +01:00
Florian Bruhin
7001f068b3 Restart correctly after reporting crash.
Fixes #1128.
2016-01-05 07:02:20 +01:00
Florian Bruhin
8a3969e4ac Convert MANIFEST.in to unix lineendings. 2016-01-05 06:56:31 +01:00
Florian Bruhin
51a371ae7c Exclude *.pyc-files correctly from sdist.
Fixes #1091.
2016-01-05 06:54:47 +01:00
Florian Bruhin
8ab0b5b4ac Use build_release.py to build sdist on Linux.
See #1091.
2016-01-05 06:54:37 +01:00
Florian Bruhin
8d63f2bf93 www: symlink quickstart.html correctly.
Fixes #1203.
2016-01-04 22:51:01 +01:00
Florian Bruhin
705d77abfb Also handle the doc path not existing at all. 2016-01-04 20:36:15 +01:00
Florian Bruhin
20faecc7a0 Also handle inexistant doc path. 2016-01-04 20:35:16 +01:00
Florian Bruhin
ea182934f3 Update docs for :help tests. 2016-01-04 20:10:17 +01:00
Florian Bruhin
6eeb3fa32c pylint: Allow long lines for copyright. 2016-01-04 08:22:33 +01:00
Florian Bruhin
a5f2ac5f03 Adjust copyright years. 2016-01-04 07:12:39 +01:00
Florian Bruhin
c1d3a94936 Don't pass through shifted characters.
See #1207 - turns out that was a problem for *any* character.
2016-01-04 07:10:23 +01:00
Florian Bruhin
d8ac32fd0a Update changelog. 2016-01-03 17:24:26 +01:00
Florian Bruhin
8b76eb54a3 Regenerate authors. 2015-12-30 14:57:21 +01:00
Florian Bruhin
a7d699eeb4 Merge branch 'mschilli87-master' 2015-12-30 14:24:47 +01:00
Marcel Schilling
c2e77cbaa9 added python3-dev to dependencies (fixes #1200)
To build qutebrowser using tox (at least on Ubuntu 14.04.1) the python3-dev package is required (see issue #1200).
This commit adds this package to the list of dependencies for installation of qutebrowser on Debian/Ubuntu systems.
2015-12-30 14:24:28 +01:00
Florian Bruhin
abfe894027 Remove now useless pylint suppression. 2015-12-29 14:57:26 +01:00
Florian Bruhin
4bae668294 tox: Update xvfbwrapper to 0.2.7.
Do not pass open file descriptors to Xvfb
2015-12-29 14:50:42 +01:00
Florian Bruhin
5f248abd7d tox: Update requests to 2.9.1.
Bugfixes

- Resolve regression introduced in 2.9.0 that made it impossible to send binary
  strings as bodies in Python 3.
- Fixed errors when calculating cookie expiration dates in certain locales.

Miscellaneous

- Updated bundled urllib3 to 1.13.1.
2015-12-29 14:47:42 +01:00
Florian Bruhin
2f51dae2b3 tox: Update hypothesis to 1.18.1.
- Hypothesis will no longer write generated code to the file system. This will
  improve performance on some systems (e.g. if you're using PythonAnywhere
  which is running your code from NFS) and prevent some annoying interactions
  with auto-restarting systems.

- Hypothesis will cache the creation of some strategies. This can significantly
  improve performance for code that uses flatmap or composite and thus has to
  instantiate strategies a lot.
2015-12-29 14:45:49 +01:00
Florian Bruhin
b7998838d3 tox: Update astroid to 1.4.3.
* pkg_resources brain tips are a bit more specific, by specifiying proper
  returns.
* Standard library modules are properly detected by is_standard_module.
2015-12-29 14:44:00 +01:00
Florian Bruhin
e9bf5fc219 tox: Update hypothesis to 1.18.0.
Features:

- Tests and find are now explicitly seeded off the global random module. This
  means that if you nest one inside the other you will now get a health check
  error. It also means that you can control global randomization by seeding
  random.
- There is a new random_module() strategy which seeds the global random module
  for you and handles things so that you don't get a health check warning if
  you use it inside your tests.
- floats() now accepts two new arguments: allow_nan and allow_infinity. These
  default to the old behaviour, but when set to False will do what the names
  suggest.

Bug fixes:

- Fix a bug where tests that used text() on Python 3.4+ would not actually be
  deterministic even when explicitly seeded or using the derandomize mode,
  because generation depended on dictionary iteration order which was affected
  by hash randomization.
- Fix a bug where with complicated strategies the timing of the initial health
  check could affect the seeding of the subsequent test, which would also
  render supposedly deterministic tests non-deterministic in some scenarios.
- In some circumstances flatmap() could get confused by two structurally
  similar things it could generate and would produce a flaky test where the
  first time it produced an error but the second time it produced the other
  value, which was not an error. The same bug was presumably also possible in
  composite().
- flatmap() and composite() initial generation should now be moderately faster.
  This will be particularly noticeable when you have many values drawn from the
  same strategy in a single run, e.g. constructs like lists(s.flatmap(f)).
  Shrinking performance may have suffered, but this didn't actually produce an
  interestingly worse result in any of the standard scenarios tested.
2015-12-21 11:19:01 +01:00
Florian Bruhin
81e1c72588 pylint: unneeded-suppression -> useless-suppression 2015-12-21 10:02:43 +01:00
Florian Bruhin
168f65b1a4 tests: Use caplog.at_level, not atLevel. 2015-12-21 09:52:33 +01:00
Florian Bruhin
9101046fe5 tests: Adjust error message comparison for Windows. 2015-12-21 09:51:25 +01:00
Florian Bruhin
95e67bba7b Suppress pylint no-member for os.mkfifo. 2015-12-21 09:47:20 +01:00
Florian Bruhin
9f64dfb3b6 Skip all tests using py_proc when frozen. 2015-12-21 09:46:30 +01:00
Florian Bruhin
12f44d0a5e tox: Update astroid to 1.4.2 and pylint to 1.5.2. 2015-12-21 09:17:26 +01:00
Florian Bruhin
4b770f4f35 tests: Try to work around race condition. 2015-12-21 08:55:55 +01:00
Florian Bruhin
8fdbd94d71 userscripts: Remove on_proc_error.
When there was an error, the finished signal will be emitted too anyways, so if
we call cleanup here, we'll call it twice which means we'll get an exception.

Supersedes #1175.
2015-12-21 08:45:46 +01:00
Florian Bruhin
59c8e5c3d1 Add some tests for commands.userscripts. 2015-12-21 08:45:46 +01:00
Daniel Schadt
7944217da4 Adjust pdfjs unit tests for new logging level
The script generation output was changed because we changed the logging
level, this adjusts the unit tests to match the new output.
2015-12-20 20:14:17 +01:00
Florian Bruhin
2b1622b34d Update to pytest-bdd 2.16.0.
This avoids deprecation warnings emitted by python 3.5 and pytest 2.8.
2015-12-20 20:11:49 +01:00
Daniel Schadt
be0eb0b1cd Add pdfjs.is_available to vulture whitelist
vulture reports it as a false-positive, it's used in the tests but not
picked up by vulture.
2015-12-20 20:08:24 +01:00
Florian Bruhin
b8727d338f Fix DummyUserscriptRunner. 2015-12-20 20:04:00 +01:00
Daniel Schadt
6d02ef68ec Add BDD tests for pdfjs integration 2015-12-20 20:00:56 +01:00
Daniel Schadt
4fdf318fda pdfjs: Use "info" verbosity for pdf.js logging 2015-12-20 19:24:41 +01:00
Daniel Schadt
f2ed14a24a Add unit tests for browser.pdfjs 2015-12-20 19:24:41 +01:00
Daniel Schadt
1279e418ee pdfjs: Replace inline-removal with own function
Easier to unit-test and easier to understand for other programmers.
2015-12-20 19:24:41 +01:00
Daniel Schadt
c0b3160676 qutescheme: guess mimetype instead of 'text/html'
Since we're now using qute:// to serve files other than html
(see: pdfjs), it's a good idea to change the mimetype accordingly. This
also prevents warnings in the console, as QWebKit will complain e.g.
when stylesheets are served with 'text/html'.
2015-12-20 19:24:41 +01:00
Daniel Schadt
49ed04715e Remove unused tempfile import 2015-12-20 19:24:41 +01:00
Daniel Schadt
a072cf0175 Fix update_3rdparty on windows
You cannot open a file twice on windows, so the call to
urllib.request.urlretrieve was invalid, since we already opened the
temporary file. urlretrieve without a filename will automatically create
and return a temp-file, so we're fine.
2015-12-20 19:24:41 +01:00
Daniel Schadt
384a9ad923 Call update_3rdparty before freezing 2015-12-20 19:24:41 +01:00
Daniel Schadt
3a13e46c25 disable pdfjs by default 2015-12-20 19:24:41 +01:00
Daniel Schadt
cab1d3c666 fully encode URL before passing it to pdfjs 2015-12-20 19:24:41 +01:00
Daniel Schadt
2f34bdf9b9 Add link to pylint bug 2015-12-20 19:24:41 +01:00
Daniel Schadt
8e4ca1fc23 pdfjs: use PDFView.open instead of PDFView.load
Now we get a nice loading bar at the top of the page.
2015-12-20 19:24:41 +01:00
Daniel Schadt
c3f2cb02c8 pdfjs: adjust path in scripts/dev/misc_checks.py 2015-12-20 19:24:41 +01:00
Daniel Schadt
d7d577b1fa Fix pep8/pylint 2015-12-20 19:24:41 +01:00
Daniel Schadt
738fad50da Adjust .eslintignore 2015-12-20 19:24:41 +01:00
Daniel Schadt
1c13a3cd68 pdfjs: search in ~/.local/share/qutebrowser 2015-12-20 19:24:41 +01:00
Daniel Schadt
623b6fba7e pdfjs: open system file in binary read 2015-12-20 19:24:41 +01:00
Daniel Schadt
0095b72e03 Update pdfjs path in freeze.py 2015-12-20 19:24:41 +01:00
Daniel Schadt
b243acf172 Add a nice error page when pdfjs is not found 2015-12-20 19:24:41 +01:00
Daniel Schadt
9eb72bf08a pdfjs: use system-wide installation if available 2015-12-20 19:24:41 +01:00
Daniel Schadt
ef85d1af4c Move pdfjs and use original files
* No modified pdfjs installation needed
-> Groundwork for using a system-wide installation

* Script update_3rdparty.py to download and upack the latest pdfjs
  release
2015-12-20 19:24:41 +01:00
Daniel Schadt
ccb8e31e78 exclude .eslintignore from MANIFEST 2015-12-20 19:24:41 +01:00
Daniel Schadt
58cc1e9202 Add pdfjs to eslintignore 2015-12-20 19:24:41 +01:00
Daniel Schadt
60b9d7e6c3 Fix lints 2015-12-20 19:24:41 +01:00
Daniel Schadt
0811418746 pdfjs: don't embed data in html
We don't need more than one copy of the pdf.
2015-12-20 19:24:41 +01:00
Daniel Schadt
d89b1f4125 Update README 2015-12-20 19:24:41 +01:00
Daniel Schadt
dc9cd47afc pdfjs: add unittest for script generation 2015-12-20 19:24:41 +01:00
Daniel Schadt
e6548dd9e7 reorder pdfjs generation code 2015-12-20 19:24:41 +01:00
Daniel Schadt
3dfaab6194 pdfjs: actually wait until the file is loaded
Otherwise we get incomplete replies and thus no pdf to view.
2015-12-20 19:24:41 +01:00
Daniel Schadt
8b141037ef Add setting value to enable/disable pdf.js 2015-12-20 19:24:41 +01:00
Daniel Schadt
1882fb6006 Add pdf.js in frozen distribution 2015-12-20 19:24:41 +01:00
Daniel Schadt
2887250641 Add pdfjs to the distribution 2015-12-20 19:24:41 +01:00
Daniel Schadt
a4f808f56b Add pdf.js license to readme 2015-12-20 19:24:41 +01:00
Daniel Schadt
fcfc09f541 Revoke "LocalContentCanAccess*Urls"
Since we embed the content of the PDF directly, we no longer need the
permissions for pdf.js.
2015-12-20 19:24:41 +01:00
Daniel Schadt
ea4d9e884e pdfjs: Remove debug output file 2015-12-20 19:24:41 +01:00
Daniel Schadt
5e0090d5b8 pdfjs: Use abosolute URLs
That allows us to use the "original" page URL when displaying with
pdf.js, which means yanking the URL etc works as intended.
2015-12-20 19:24:41 +01:00
Daniel Schadt
0ee13392e1 Basic pdfjs support
Working, but not very well.

Todo:
- remove pdf_file.html debug file
- set URL correctly
2015-12-20 19:24:41 +01:00
Florian Bruhin
fc3a3ea8c6 Add missing not_frozen mark in test_guiprocess.
This should fix test failures when frozen.
2015-12-20 18:40:57 +01:00
Florian Bruhin
fcf94fd527 Remove various deprecated commands/arguments. 2015-12-20 18:38:29 +01:00
Florian Bruhin
ffc76b2a5c Fix spelling. 2015-12-20 17:39:36 +01:00
Florian Bruhin
84ed602b8d tox: Update Werkzeug to 0.11.3.
- Fixed an issue with copy operations not working against
  proxies.
- Changed the logging operations of the development server to
  correctly log where the server is running in all situations
  again.
- Fixed another regression with SSL wrapping similar to the
  fix in 0.11.2 but for a different code path.
2015-12-20 17:26:19 +01:00
Florian Bruhin
3687011e09 tox: Update CherryPy to 5.0.0.
-----
5.0.0
-----

* Removed deprecated support for ``ssl_certificate`` and
  ``ssl_private_key`` attributes and implicit construction
  of SSL adapter on Python 2 WSGI servers.
* Default SSL Adapter on Python 2 is the builtin SSL adapter,
  matching Python 3 behavior.

-----
4.0.0
-----

* Drop support for Python 2.5 and earlier.
* No longer build Windows installers by default.
2015-12-20 17:25:08 +01:00
Florian Bruhin
6b89eb43a2 Allow any non-space char in search engine names.
Closes #1189.
2015-12-20 17:22:54 +01:00
Florian Bruhin
5c769d8000 Report stdout/stderr of failed subprocesses. 2015-12-18 21:23:33 +01:00
Florian Bruhin
d3dc90cb2a Revert "tests: Use urllib to load redirect-later-continue."
This reverts commit 1e43b882ae.
Seems like this causes other trouble (the redirect-later request missing?!)
2015-12-18 20:24:03 +01:00
Florian Bruhin
f787f004af Fix _BaseUserscriptRunner when env is None. 2015-12-18 20:23:39 +01:00
Florian Bruhin
1e43b882ae tests: Use urllib to load redirect-later-continue.
This might avoid the EPROTOTYPE bug on OS X. See #1183.
2015-12-18 19:57:15 +01:00
Florian Bruhin
b3e4ac8043 tests: Fix AttributeError in _wait_for_clipboard. 2015-12-18 07:18:27 +01:00
Florian Bruhin
45d6dc6aa3 tests: Hopefully fix keyinput.feature flakiness.
While the original "no focused webview" bug (with the first test after spawning
qutebrowser) from #1183 was fixed, we still had a case where the next test
after ":fake-key sending key to the website with other window focused" failed,
presumably because the inspector was still focused, e.g. here:

http://qutebrowser.org:8010/builders/osx/builds/1175/steps/tests/logs/stdio

This hopefully fixes this by properly waiting until the inspector is gone.
2015-12-18 07:13:16 +01:00
Florian Bruhin
eed4a992ab tox: Update cherrypy to 3.8.2.
* Correct InternalServerError when null bytes in static file path. Now responds
  with 404 instead.
2015-12-18 05:19:33 +01:00
Florian Bruhin
172157ed0d Remove unused import, take two. 2015-12-17 23:09:11 +01:00
Florian Bruhin
a7dee6c053 Remove unused import. 2015-12-17 22:57:16 +01:00
Florian Bruhin
fc84e58043 tests: Ignore "SelectionRequest too old" globally.
If we use pytestmark, it won't be ignored inside subprocess output, so our fix
from https://github.com/The-Compiler/qutebrowser/issues/1124#issuecomment-158073581
never actually worked.

See #1124 and #1183.
2015-12-17 22:33:07 +01:00
Florian Bruhin
8786e979a6 tests: Wait for data in the clipboard.
This should hopefully stabilize the flaky clipboard tests.
See #1183.
2015-12-17 22:17:38 +01:00
Florian Bruhin
f19de5b908 tox: Update hypothesis to 1.17.1.
A small bug fix release, which fixes the fact that the 'note' function could
not be used on tests which used the @example decorator to provide explicit
examples.
2015-12-17 08:01:47 +01:00
Florian Bruhin
e78d2a8399 tests: Check args for loadFinished signals. 2015-12-17 07:49:28 +01:00
Florian Bruhin
c1951a8f15 tests: Get rid of QSignalSpy where we can. 2015-12-17 07:49:28 +01:00
Florian Bruhin
e9a0dffe3b tox: Update pytest-qt to 1.10.0.
- SignalBlocker now has a args attribute with the arguments of the signal that
  triggered it, or None on a time out.
- MultiSignalBlocker is now properly disconnects from signals upon exit.
2015-12-17 06:59:13 +01:00
Florian Bruhin
a1f4914271 tox: Update pytest-faulthandler to 1.3.0.
Now stops timeout when handling exceptions interactively.
2015-12-16 23:09:02 +01:00
Florian Bruhin
982e78249a tests: Clear captured output between tests. 2015-12-16 23:07:42 +01:00
Florian Bruhin
a157f822d6 tests: Handle report.longrepr being a tuple.
For some unknown reason, report.longrepr.addsection might not exist, which
caused failures on OS X and Windows. If that happens, we just don't add a
section at all.
2015-12-16 22:47:33 +01:00
Florian Bruhin
e6284ed5d4 tests: Improve some ugly test IDs. 2015-12-16 22:21:29 +01:00
Florian Bruhin
bba6589e19 Capture qutebrowser/httpbin output separately.
When using print and relying on pytest to capture it as stdout, we ran into
this pytest/pytest-qt issue:

https://github.com/pytest-dev/pytest-qt/issues/113

Now we use our own capturing mechanism instead, which also means we get nicer
output.

Fixes #1122.
2015-12-16 21:25:13 +01:00
Florian Bruhin
7f83c6c5c8 pylint: Disable no-member for hypothesis.Settings.
hypothesis.Settings.default is probably created dynamically.
2015-12-15 18:57:14 +01:00
Florian Bruhin
4a58e10e09 Enable hypothesis' strict mode. 2015-12-15 18:09:52 +01:00
Florian Bruhin
a387e9669c tox: Update requests to 2.9.0.
Minor Improvements (Backwards compatible)

- The verify keyword argument now supports being passed a path to a directory
  of CA certificates, not just a single-file bundle.
- Warnings are now emitted when sending files opened in text mode.
- Added the 511 Network Authentication Required status code to the status code
  registry.

Bugfixes

- For file-like objects that are not seeked to the very beginning, we now send
  the content length for the number of bytes we will actually read, rather than
  the total size of the file, allowing partial file uploads.
- When uploading file-like objects, if they are empty or have no obvious
  content length we set Transfer-Encoding: chunked rather than
  Content-Length: 0.
- We correctly receive the response in buffered mode when uploading chunked
  bodies.
- We now handle being passed a query string as a bytestring on Python 3, by
  decoding it as UTF-8.
- Sessions are now closed in all cases (exceptional and not) when using the
  functional API rather than leaking and waiting for the garbage collector to
  clean them up.
- Correctly handle digest auth headers with a malformed qop directive that
  contains no token, by treating it the same as if no qop directive was
  provided at all.
- Minor performance improvements when removing specific cookies by name.
2015-12-15 17:58:51 +01:00
Florian Bruhin
7b5f51b145 tests: Ignore empty $XDG_RUNTIME_DIR error.
For some reason it's unset for the buildbot on Ubuntu Trusty, and it shouldn't
matter.
2015-12-15 17:53:36 +01:00
Florian Bruhin
90c782a891 Revert "Avoid setenv substitution in tox.ini."
This reverts commit 7245e300e6.
This was fixed in tox 2.3.1.
2015-12-15 11:49:06 +01:00
Florian Bruhin
a2423b0b6c tox: Update hypothesis to 1.17.0.
This is actually the same release as 1.16.1, but 1.16.1 has been pulled because
it contains the following additional change that was not intended to be in a
patch release (it's perfectly stable, but is a larger change that should have
required a minor version bump):

Hypothesis will now perform a series of "health checks" as part of running your
tests. These detect and warn about some common error conditions that people
often run into which wouldn't necessarily have caued the test to fail but would
cause e.g. degraded performance or confusing results.
2015-12-15 11:48:07 +01:00
Florian Bruhin
fd96685b02 tests: Wait until the qutebrowser window has focus.
This should fix the second case in #1183 and other related flakiness in
keyinput.feature.
2015-12-15 07:43:14 +01:00
Florian Bruhin
c74bcf95aa tox: Update hypothesis to 1.16.1.
A small bugfix release that allows bdists for Hypothesis to be built under 2.7
- the compat3.py file which had Python 3 syntax wasn't intended to be loaded
under Python 2, but when building a bdist it was. In particular this would
break running setup.py test.
2015-12-15 06:59:06 +01:00
Florian Bruhin
ee845590b7 Limit colorama to <=0.3.3 for requirements.io. 2015-12-14 18:44:16 +01:00
Florian Bruhin
0f97fad87d Revert "requirements: Update colorama to 0.3.5."
This reverts commit 06298022a3.

We get this when the tests finished running:

Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/home/florian/proj/qutebrowser/git/.tox/py35/lib/python3.5/site-packages/colorama/initialise.py", line 19, in reset_all
    AnsiToWin32(orig_stdout).reset_all()
  File "/home/florian/proj/qutebrowser/git/.tox/py35/lib/python3.5/site-packages/colorama/ansitowin32.py", line 67, in __init__
    strip = conversion_supported or not is_a_tty(wrapped)
  File "/home/florian/proj/qutebrowser/git/.tox/py35/lib/python3.5/site-packages/colorama/ansitowin32.py", line 17, in is_a_tty
    return hasattr(stream, 'isatty') and stream.isatty()
ValueError: I/O operation on closed file
2015-12-14 07:14:39 +01:00
Florian Bruhin
879f99bddf tox: Update pytest to 2.8.5.
- fixed issue where class attributes injected during collection could break pytest.
- precompute junitxml chunks instead of storing the whole tree in objects
- fix ``pytest.deprecated_call()`` receiving multiple arguments
  (Regression introduced in 2.8.4).
2015-12-13 13:17:53 +01:00
Florian Bruhin
06298022a3 requirements: Update colorama to 0.3.5.
0.3.5
- Bumping version to re-upload a wheel distribution

0.3.4
- stream redirection now strips ANSI codes on Linux
- strip readline markers
- assign orig_stdout and orig_stderr when initialising
- Fore.RESET did not reset style of LIGHT_EX colors. Fixed by Andy Neff
- add context manager syntax. Thanks to Matt Olsen.
- colorama didn't work on Windows when environment variable 'TERM' was set.
- fix pylint errors in client code.
- Changes to readme and other improvements by Marc Abramowitz and Zearin
2015-12-13 13:11:50 +01:00
Florian Bruhin
430b133c41 userscripts: Add docs for _QtFIFOReader attributes. 2015-12-13 13:11:06 +01:00
Florian Bruhin
494d48aac1 userscripts: Make fifo private in _QtFIFOReader. 2015-12-12 00:33:50 +01:00
Florian Bruhin
3a2d031479 userscripts: Move closing of fifo to _QtFIFOReader. 2015-12-12 00:33:25 +01:00
Florian Bruhin
49be07eb18 Add config read in test_default_config.
For some reason this was failing on OS X/Travis otherwise?
2015-12-11 22:17:51 +01:00
Florian Bruhin
7245e300e6 Avoid setenv substitution in tox.ini.
This works around a bug with tox 2.3.0:
https://bitbucket.org/hpk42/tox/issues/294/
2015-12-11 21:39:41 +01:00
Florian Bruhin
d267cbd44f tests: Require qapp for test_old_config. 2015-12-11 18:16:46 +01:00
Florian Bruhin
24607fda8b Mark tabs -> auto-hide as removed as well.
tabs -> hide-auto was removed in d8017a04a8
because it was easier to do so compared to transforming it correctly when tabs
-> show was introduced. However, tabs -> auto-hide (the even older version)
wasn't removed, breaking config migration from earlier versions.

Fixes #1171.
2015-12-11 08:50:26 +01:00
Florian Bruhin
202bf59edc Add tests for renamed/deleted config options.
See #1171.
2015-12-11 08:50:26 +01:00
Florian Bruhin
ec06247327 Add tests to check upgrades from old configs.
See #1171.
2015-12-11 08:50:26 +01:00
Florian Bruhin
10dd1b50b9 Split ConfigManager.read from constructor. 2015-12-11 08:50:26 +01:00
Florian Bruhin
b3b2fb51fc tox: Update pytest-faulthandler to 1.2.0.
Now traceback dumping due to a timeout is cancelled when entering pdb.
2015-12-11 06:42:24 +01:00
Florian Bruhin
9b88167ae1 tox: Update decorator to 4.0.6.
Removed a file x.py accidentally entered in the tarball
2015-12-11 06:41:42 +01:00
Florian Bruhin
bed37defde tox: Update check-manifest to 0.30.
- Support git submodules
- Revert the zc.buildout support hack from 0.26 because it causes breakage
- Improve non-ASCII filename handling with Bazaar on Windows.
2015-12-11 06:40:49 +01:00
Florian Bruhin
dc4600008b tox: Update xvfbwrapper to 0.2.6.
Drops Python 2.6 support, no other notable changes it seems.
2015-12-10 06:10:51 +01:00
Florian Bruhin
fd63b21261 tox: Update pytest-catchlog to 1.2.1.
- Allow caplog.records() to be modified.
- Restore Python 2.6 compatibility.
2015-12-09 17:34:29 +01:00
Florian Bruhin
8d7e43e4c4 tox: Update hypothesis to 1.16.0.
There are no public API changes in this release but it includes a behaviour
change that I wasn't comfortable putting in a patch release.

- Functions from hypothesis.strategies will no longer raise InvalidArgument on
  bad arguments. Instead the same errors will be raised when a test using such
  a strategy is run. This may improve startup time in some cases, but the main
  reason for it is so that errors in strategies won't cause errors in loading,
  and it can interact correctly with things like pytest.mark.skipif.
- Errors caused by accidentally invoking the legacy API are now much less
  confusing, although still throw NotImplementedError.
- hypothesis.extra.django is 1.9 compatible.
- When tests are run with max_shrinks=0 this will now still rerun the test on
  failure and will no longer print "Trying example:" before each run.
  Additionally note() will now work correctly when used with max_shrinks=0.
2015-12-09 17:32:45 +01:00
Florian Bruhin
73b4704d6c tox: Update decorator to 4.0.5.
Documented a quirk signaled by David Goldstein when writing decorators for
functions with keyword arguments. Avoided copying the globals, as signaled by
Benjamin Peterson (2015/12/09)
2015-12-09 17:30:42 +01:00
Florian Bruhin
057cd70c9e Update changelog. 2015-12-07 22:50:41 +01:00
Florian Bruhin
14c083f915 Merge branch 'dylanaraps-master' 2015-12-07 21:13:37 +01:00
Florian Bruhin
6058c8aab2 Regenerate docs. 2015-12-07 21:13:30 +01:00
Florian Bruhin
3506947add Merge branch 'master' of https://github.com/dylanaraps/qutebrowser into dylanaraps-master 2015-12-07 21:12:37 +01:00
dylan araps
1bc8d10ac7 Added config option to change tab title alignment 2015-12-07 19:43:43 +11:00
Florian Bruhin
dddd1e87a5 tox: Update pytest to 2.8.4.
- ``deprecated_call()`` now works when the deprecated function has been already
  called by another test in the same module.
- ``--pastebin`` option now works on Python 3.
- ``--pastebin`` now works correctly when captured output contains non-ascii
  characters.
- Fix another error when collecting with a nasty __getattr__().
- fix the summary printed when no tests did run.
- a number of documentation modernizations wrt good practices.
2015-12-06 22:22:33 +01:00
Florian Bruhin
9814c24d9e Merge branch 'jcorentin-master' 2015-12-04 18:33:13 +01:00
Florian Bruhin
491a02e4a5 Regenerate authors. 2015-12-04 18:33:05 +01:00
Florian Bruhin
c319b524bf Merge branch 'master' of https://github.com/jcorentin/qutebrowser into jcorentin-master 2015-12-04 18:32:46 +01:00
Florian Bruhin
2a030107b9 tox: Upgrade CherryPy to 3.8.0.
Pass ``exc_info`` to logger as keyword rather than formatting the error and
injecting into the message.
2015-12-04 07:16:34 +01:00
Florian Bruhin
0a6c82d071 Merge branch 'Kingdread-download-page' 2015-12-04 07:11:16 +01:00
Corentin Jule
d8d873f044 Fix typo for Pep257 2015-12-04 00:28:58 +01:00
Daniel Schadt
5acc982b44 Clean up mhtml doc and use email.message.Message
MIMEMultipart is not needed for the attachements, a simple Message is
enough.

Also fix the README markup and the _start_download docstring.
2015-12-03 22:51:46 +01:00
Corentin Jule
1941af8add Fix TypeError on ConfigManager.remove_option 2015-12-03 20:48:50 +01:00
Florian Bruhin
e68965fea2 bdd: Wait for help pages to be loaded in tests.
This hopefully fixes #1150.
2015-12-02 22:22:31 +01:00
Florian Bruhin
4170e3c9af bdd: Simplify qute:settings test. 2015-12-02 22:19:43 +01:00
Florian Bruhin
4e888e8e19 pylint: Re-enable wrong-import-position.
This now works due to a fix in pylint 1.5.1.
2015-12-02 18:14:44 +01:00
Florian Bruhin
f342f129c6 Refactor how use_color is set in scripts/utils. 2015-12-02 18:14:34 +01:00
Florian Bruhin
7df01440a3 pylint: Remove unsubscriptable-object workaround.
https://bitbucket.org/logilab/pylint/issues/685/ was fixed in pylint 1.5.1.
2015-12-02 17:55:46 +01:00
Florian Bruhin
cab6bf87b4 tox: Update to pylint 1.5.1.
* Don't emit unsubscriptable-object if the node is found
  inside an abstract class.

* Add wrong-import-position to check_messages's decorator arguments
  for ImportChecker.leave_module

  This fixes an esoteric bug which occurs when ungrouped-imports and
  wrong-import-order are disabled and pylint is executed on multiple files.
  What happens is that without wrong-import-position in check_messages,
  leave_module will never be called, which means that the first non-import node
  from other files might leak into the current file,
  leading to wrong-import-position being emitted by pylint.

* Fix a crash which occurred when old visit methods are encountered
  in plugin modules.

* Don't emit import-self and cyclic-import for relative imports
  of modules with the same name as the package itself.
2015-12-02 17:53:59 +01:00
Florian Bruhin
4e73aa9f0f Update changelog. 2015-12-02 07:38:03 +01:00
Florian Bruhin
e64f64e456 Merge branch 'artur-shaik-caret_mode_windows_osx' 2015-12-02 06:24:42 +01:00
Florian Bruhin
f23af85161 Regenerate authors. 2015-12-02 06:24:34 +01:00
Florian Bruhin
d418f7f9fa Merge branch 'caret_mode_windows_osx' of https://github.com/artur-shaik/qutebrowser into artur-shaik-caret_mode_windows_osx 2015-12-02 06:22:27 +01:00
Florian Bruhin
71d1aed041 Merge branch 'forkbong-tab-move-wrap' 2015-12-02 06:21:02 +01:00
Florian Bruhin
91fcc91092 Regenerate authors. 2015-12-02 06:20:53 +01:00
Florian Bruhin
eeadeb400c Style fix. 2015-12-02 06:20:41 +01:00
Panagiotis Ktistakis
6e8ac374dd Add tests for :tab-move wrapping. 2015-12-02 03:35:25 +02:00
Panagiotis Ktistakis
de3460da3e Wrap tabs on :tab-move +/- if tabs->wrap is true. 2015-12-02 03:17:54 +02:00
Florian Bruhin
eff0e4c7cc pylint: Enable useless-suppression globally.
We deactivate it locally where needed, i.e. where we are sure it's some
platform-specific thing.
2015-12-01 23:01:09 +01:00
Florian Bruhin
cf54fa1ef1 pylint: Remove some now useless suppressions. 2015-12-01 23:00:48 +01:00
Florian Bruhin
e1f53302be Revert "tox: Add {posargs} for pylint."
This breaks on Travis/AppVeyor were different environments all get the same
args.
This reverts commit b59951cc98.
2015-12-01 22:51:03 +01:00
Florian Bruhin
b3515f5e82 pylint: Remove import-error disabling from tests. 2015-12-01 22:47:10 +01:00
Florian Bruhin
5817b47f75 Revert "Use fully qualified imports in tests."
Seems like this also breaks frozen tests...
This reverts commit c7fdcc92b8.
2015-12-01 22:45:59 +01:00
Florian Bruhin
109984c96e pylint: Check attr-defined-outside-init for tests. 2015-12-01 22:41:16 +01:00
Florian Bruhin
803398c49b Use some more fixtures for older tests. 2015-12-01 22:40:58 +01:00
Florian Bruhin
ad72b26b1a Add comment why abstract-method is ignored. 2015-12-01 22:16:23 +01:00
Florian Bruhin
c7fdcc92b8 Use fully qualified imports in tests.
This is cleaner even if pylint can't handle it.
2015-12-01 22:03:59 +01:00
Florian Bruhin
788a096150 pylint: Ignore import-error globally for tests. 2015-12-01 22:03:59 +01:00
Florian Bruhin
150a83d8f4 pylint: Remove unneeded supressions. 2015-12-01 22:03:58 +01:00
Florian Bruhin
a156d51844 Don't use for-else when returning. 2015-12-01 21:56:38 +01:00
Florian Bruhin
31265b80b6 pylint: Add WORKAROUND to some comments. 2015-12-01 21:56:38 +01:00
Florian Bruhin
b59951cc98 tox: Add {posargs} for pylint. 2015-12-01 20:05:19 +01:00
Artur Shaik
c9d47ae92a More win32 workarounds 2015-12-01 16:53:07 +06:00
Artur Shaik
25545617a0 Try workaround for win32 platform. 2015-12-01 16:19:13 +06:00
Artur Shaik
3a5ce22eac Remove unnecessary actions in block jumps. 2015-12-01 13:17:28 +06:00
Florian Bruhin
d53c4f2702 tests: Increase test_late_message timeout.
This was failing on Travis on OS X, and waiting 1s for process start and 0.5s
sleep seems a bit tight.
2015-12-01 08:10:44 +01:00
Florian Bruhin
81f522336f Do PYTHONPATH shenanigans in run_pylint_on_tests.
If we do it in tox.ini, there are two drawbacks:

- We have more stuff in PYTHONPATH even if we don't when actually using
  qutebrowser.
- The separator is platform specific, so we can't easily do this in a portable
  way in tox.ini.
2015-12-01 08:07:42 +01:00
Florian Bruhin
8be04e4f6c pylint: Disable non-callable in SslError.
This wasn't hashable (and thus __hash__ wasn't callable) with Qt < 5.4.
2015-12-01 07:50:08 +01:00
Florian Bruhin
9cce8fe825 Adjust vulture whitelist for pylint changes. 2015-12-01 07:48:33 +01:00
Florian Bruhin
7e8f16dd22 pylint: Disable deprecated-method in test_conftest. 2015-12-01 07:16:53 +01:00
Florian Bruhin
6f9b02741a Switch from map() to list comprehensions. 2015-12-01 07:16:32 +01:00
Florian Bruhin
251e657bd1 pylint: Disable some messages again.
See https://bitbucket.org/logilab/pylint/issues/713/
This partially reverts a42d99a8b7.
2015-12-01 07:10:39 +01:00
Florian Bruhin
009e29789a tox: Add {toxinidir} to PYTHONPATH for pylint.
Seems like it doesn't like to import qutebrowser from the tests anymore
otherwise...
2015-12-01 07:10:39 +01:00
Florian Bruhin
101f81844c pylint: Adjust custom checkers for astroid 1.4.
Otherwise we'd run into https://bitbucket.org/logilab/pylint/issues/711
2015-12-01 07:10:39 +01:00
Florian Bruhin
a42d99a8b7 pylint: Get rid of some customizations in pylintrc 2015-11-30 21:08:17 +01:00
Florian Bruhin
9755a9b00f pylint: Improve ignored-classes list. 2015-11-30 21:08:17 +01:00
Florian Bruhin
5b5003d599 pylint: Use qualified names for ignored-classes. 2015-11-30 21:08:17 +01:00
Florian Bruhin
99258dac46 pylint: Remove defining-attr-methods from pylintrc. 2015-11-30 21:08:17 +01:00
Florian Bruhin
5dc891f207 pylint: Move expected-line-ending-format to config. 2015-11-30 21:08:17 +01:00
Florian Bruhin
41b9fd7853 tox: Remove --rcfile for pylint.
We don't need this anymore as pylint now reads .pylintrc automatically.
2015-11-30 21:08:17 +01:00
Artur Shaik
d00f999dcf move_to_end_of_prev_block without unnecessary command. 2015-11-30 22:27:24 +06:00
Florian Bruhin
455e5f6523 Merge branch 'flv0-log-javascript-console' 2015-11-30 08:08:58 +01:00
Florian Bruhin
6ad1d37eb5 Regenerate docs. 2015-11-30 08:08:52 +01:00
Florian Bruhin
5f13fd2ece Merge branch 'log-javascript-console' of https://github.com/flv0/qutebrowser into flv0-log-javascript-console 2015-11-30 08:08:31 +01:00
Florian Bruhin
7d9ef320d2 Merge branch 'flv0-conf-remove-special' 2015-11-30 07:42:56 +01:00
Florian Bruhin
f93785a0be Merge branch 'conf-remove-special' of https://github.com/flv0/qutebrowser into flv0-conf-remove-special 2015-11-30 07:42:04 +01:00
Florian Bruhin
a987c08b69 tox: Set basepython = python3 for pylint. 2015-11-30 07:38:49 +01:00
Florian Bruhin
2f955470db travis: Add buildtimetrend. 2015-11-30 07:37:04 +01:00
Florian Bruhin
48252258dd Disable some new pylint checks. 2015-11-30 07:16:24 +01:00
Florian Bruhin
6e392f0f09 Add workarounds for pylint/astroid update. 2015-11-30 07:16:12 +01:00
Florian Bruhin
0004bebc09 tox: Update astroid/pylint to 1.4.1/1.5.0.
This means logilab-common isn't needed anymore and it runs with python 3.5 now.
2015-11-30 07:15:40 +01:00
Florian Bruhin
a9de97968d Make pylint shut up about ua_fetch.py. 2015-11-30 07:12:18 +01:00
Florian Bruhin
f7a13fa1f9 Rename LineParserWrapper to LineParserMixin.
This makes pylint shut up as it realizes it is, in fact, a mixin.
2015-11-30 07:11:35 +01:00
Florian Bruhin
2ba55a0e77 Split generate_settings in src2asciidoc. 2015-11-30 07:11:03 +01:00
Florian Bruhin
27d0c004e2 Don't reuse variable in compact_text. 2015-11-30 07:10:39 +01:00
Florian Bruhin
288bf1524e Fix some unidiomatic comparisons. 2015-11-30 07:10:21 +01:00
Florian Bruhin
e227712e21 Don't reuse DocstringParser attribute. 2015-11-30 07:09:40 +01:00
Florian Bruhin
7e6be517e3 Simplify indicator_width code. 2015-11-30 07:09:02 +01:00
Florian Bruhin
307fe6b109 Avoid shadowing 'model'. 2015-11-30 07:03:49 +01:00
Florian Bruhin
a4f47150b4 Simplify unneeded if. 2015-11-30 07:00:51 +01:00
Florian Bruhin
a008b488b1 tox: Set ignore_errors for some environments.
We want to run pylint on tests as well if the first pylint invocation failed.
2015-11-30 07:00:20 +01:00
Patric Schmitz
a8b808819a update log-javascript-console option documentation 2015-11-29 19:24:09 +01:00
Patric Schmitz
b9aa40ea74 remove config types special variable 2015-11-29 18:53:37 +01:00
Patric Schmitz
98a454a428 log-javascript-console -> [none, debug, info] 2015-11-29 18:37:11 +01:00
Florian Bruhin
d286f637d6 tests: Set basedir to None, not ''.
Turns out setting basedir='' creates cache/ in cwd.
2015-11-29 01:23:28 +01:00
Florian Bruhin
f7a3a9e015 Split testprocess.wait_for into two methods. 2015-11-29 01:23:19 +01:00
Florian Bruhin
736fd7d45e Use os.path.join for bookmarks/urls path.
This should fix the tests on Windows which failed because they matched against
a message containing \.
2015-11-29 00:59:18 +01:00
Florian Bruhin
6a46aea934 Fix tests for basedir logging.
f5febc4 broke various tests which called standarddir.init() without a valid
basedir.
2015-11-29 00:35:18 +01:00
Florian Bruhin
a67644589e bdd: Add first test for :bookmark-add. 2015-11-28 23:37:27 +01:00
Florian Bruhin
f9d7f20aac tests: Raise if wait_for is used without kwargs.
Otherwise wait_for would return immediately because matches is empty so
any(matches) is True.
2015-11-28 23:36:26 +01:00
Florian Bruhin
f5febc4807 Log basedir and save it in QuteProcess for tests. 2015-11-28 23:35:32 +01:00
Florian Bruhin
e26c499bd6 lineparser: Log after saving is done.
This will make end to end tests easier as we can easily wait until saving is
done.
2015-11-28 23:35:04 +01:00
Florian Bruhin
8d5b6b2dad bdd: Add tests for :home. 2015-11-28 22:44:05 +01:00
Florian Bruhin
052e758f38 bdd: Add tests for :help. 2015-11-28 22:34:19 +01:00
Florian Bruhin
429f520997 Merge branch 'flv0-log-javascript-console' 2015-11-28 21:12:41 +01:00
Florian Bruhin
1d4c51b78a Regenerate authors. 2015-11-28 21:12:31 +01:00
Florian Bruhin
c236e70920 Merge branch 'log-javascript-console' of https://github.com/flv0/qutebrowser into flv0-log-javascript-console 2015-11-28 21:12:25 +01:00
Florian Bruhin
83b94a8be5 Fix session tests.
FakeMainWindow needs to be a QObject now as we use sip.isdeleted since
8cf6ace0e7 and that raises a TypeError on
non-QObject's.
2015-11-28 20:41:42 +01:00
Florian Bruhin
03b6459d2f tox: Update py to 1.4.31. 2015-11-28 20:38:20 +01:00
Florian Bruhin
8cf6ace0e7 Ignore deleted windows when saving session.
This hopefully helps with a crash on Windows which happens from time to time
during some multi-window tabs.feature tests:

Traceback (most recent call last):
  File "...\mainwindow\mainwindow.py", line 446, in closeEvent
    self._do_close()
  File "...\mainwindow\mainwindow.py", line 405, in _do_close
    objreg.get('session-manager').save_last_window_session()
  File "...\misc\sessions.py", line 247, in save_last_window_session
    self._last_window_session = self._save_all()
  File "...\misc\sessions.py", line 183, in _save_all
    win_data['geometry'] = bytes(main_window.saveGeometry())
RuntimeError: wrapped C/C++ object of type MainWindow has been deleted
2015-11-28 20:30:41 +01:00
Patric Schmitz
913aa209c6 remove BadMappingSubclass and rename MappingSubclass 2015-11-28 20:17:31 +01:00
Patric Schmitz
dbc6f63fc0 remove whitespace 2015-11-28 18:57:41 +01:00
Patric Schmitz
03ba38578e set valid_values after __init__ consistently, move type validation out of class into pytest 2015-11-28 18:29:51 +01:00
Patric Schmitz
fdde05569c remove redundant __init__ and rely on base class 2015-11-28 18:29:51 +01:00
Patric Schmitz
c14b52f916 initialize valid_values separately, not using base class __init__ parameter 2015-11-28 18:29:51 +01:00
Patric Schmitz
c322130dc0 style changes 2015-11-28 18:29:51 +01:00
Patric Schmitz
6f65397dfe always set valid_values in __init__ instead of class scope variable 2015-11-28 18:29:51 +01:00
Patric Schmitz
9b453aaad5 revert config transformation 2015-11-28 18:29:51 +01:00
Patric Schmitz
9aaf5c18c1 set valid_values in __init__ methods, except for BaseType s.t. variable is shared across derived class scopes 2015-11-28 18:29:51 +01:00
Patric Schmitz
55edd9cda7 add valid_values = None to config basetype 2015-11-28 18:29:51 +01:00
Patric Schmitz
2867df4c21 revert log-javascript-console changes 2015-11-28 18:29:51 +01:00
Patric Schmitz
6431542eba fixes to config types, remove unneeded derived __init__ and call base __init__ 2015-11-28 18:29:51 +01:00
Patric Schmitz
2a705e2eb6 Make non-specialized config types String. Closes #1103 2015-11-28 18:29:51 +01:00
Patric Schmitz
75f9f2af8d get rid of redundant option description 2015-11-28 18:29:51 +01:00
Patric Schmitz
ff6d3e05a6 log-javascript-console now String option: none, debug, info
Make BaseType.valid_values per-instance variable
2015-11-28 18:29:51 +01:00
Artur Shaik
73f999da31 Revert a43c206 and b344f92. 2015-11-28 21:29:54 +06:00
Florian Bruhin
f847ddf3cb bdd: Remove :rl-backward-delete-char test.
It's flaky and tested enough via unittests.
2015-11-27 20:29:49 +01:00
Florian Bruhin
9d92baa996 Stop uploading test results to AppVeyor.
Seems like we get a HTTP 500 now...
2015-11-27 20:12:25 +01:00
Florian Bruhin
bf3bd3bb9d Wait for favicon to be loaded for mhtml tests.
This hopefully helps with the flaky MHTML tests on Windows where the favicon
was loaded *after* clearing the requests:

http://qutebrowser.org:8010/builders/win8/builds/1370/steps/unittests-frozen/logs/stdio
2015-11-27 19:30:06 +01:00
Florian Bruhin
962ba36cda Skip qtutils.savefile_open tests without DISPLAY.
I don't get why, but for some reason they cause a segfault from time to time...
So let's just skip them.
2015-11-27 19:11:37 +01:00
Florian Bruhin
d6acb3c3f4 bdd: Hopefully make caret tests more stable.
We now wait until the clipboard actually changed, which should make things run
better.

This should fix the cases where the expected value is empty in #1142.
2015-11-27 18:44:59 +01:00
Florian Bruhin
b79049261e Delay :yank notification until message was yanked.
This should make yankpaste tests more reliable.
2015-11-27 18:32:17 +01:00
Florian Bruhin
d5b634301f Make :rl-backward-delete-char test more stable.
The text could be inserted *after* :rl-backward-delete-char was run.
2015-11-27 18:15:17 +01:00
Florian Bruhin
f577da9a6b Disable App Nap on OS X on Travis. Fixes #1143. 2015-11-27 17:50:19 +01:00
Florian Bruhin
e9ca1ba5c1 bdd: Add a test for :rl-backward-delete-char. 2015-11-27 16:28:06 +01:00
Florian Bruhin
be4cf19bb1 tests: Improve some parametrized test IDs. 2015-11-27 16:25:25 +01:00
Florian Bruhin
f3c378858b tests: Remove duplicate test_split testcases. 2015-11-27 16:22:48 +01:00
Florian Bruhin
edf5463007 tests: Fix cmdline_test generation.
We accidentally provided valid values twice and invalid values not at all.
2015-11-27 16:17:07 +01:00
Florian Bruhin
84d6359990 bdd: Wait until page is loaded for tab-detach test
This should make this test more stable hopefully.
2015-11-27 15:18:53 +01:00
Florian Bruhin
b344f92a90 Add two missing xfail markers. 2015-11-27 15:10:08 +01:00
Florian Bruhin
a43c206893 Mark some caret tests as xfail on Windows/OS X.
See #1142.
2015-11-27 14:39:33 +01:00
Florian Bruhin
e4947b03be Fix lint. 2015-11-27 11:50:23 +01:00
Florian Bruhin
b4a630563f bdd: Add tests for caret mode. 2015-11-26 23:42:43 +01:00
Florian Bruhin
dbdedf74c0 bdd: Handle \n when checking clipboard contents. 2015-11-26 22:32:01 +01:00
Florian Bruhin
23068e9679 Don't log yanked test with :yank-selected.
It makes our tests fail (invalid log line) and is probably not needed.
2015-11-26 21:23:11 +01:00
Florian Bruhin
3d291482a3 bdd: Move clipboard functions to conftest.py.
Those are needed for caret.feature and yankpaste.feature.
2015-11-26 21:22:50 +01:00
Florian Bruhin
bf8a82db12 bdd: Add a test for :tab-detach. 2015-11-26 20:56:36 +01:00
Florian Bruhin
8d1a60528d bdd: Add some tests for :tab-clone. 2015-11-26 20:44:32 +01:00
Florian Bruhin
8e7a76280b Use cmdutils.check_exclusive for :tab-clone. 2015-11-26 20:11:53 +01:00
Florian Bruhin
26bbf11ed2 Fix coverage.xml path in .gitignore. 2015-11-26 19:02:22 +01:00
Florian Bruhin
7f5e07d7cc bdd: Add some tests for :tab-move. 2015-11-26 18:37:47 +01:00
Florian Bruhin
3bcc80048d bdd: Move yankpaste.html to title.html. 2015-11-26 18:37:33 +01:00
Florian Bruhin
6f1474be71 bdd: Remove trailing dots. 2015-11-26 17:50:39 +01:00
Florian Bruhin
f56e7b1220 Simplify :tab-move code. 2015-11-26 17:44:34 +01:00
Florian Bruhin
987ee59f58 :tab-move: Fix tab index shown in error message. 2015-11-26 16:37:54 +01:00
Florian Bruhin
5a95cfdc7a Change CommandError to ValueError for :tab-move.
This should never happen.
2015-11-26 16:37:29 +01:00
Florian Bruhin
bc28a168cc bdd: Add tests for :tab-prev/:tab-next/tabs->wrap. 2015-11-26 16:19:03 +01:00
Florian Bruhin
102db181c5 Remove unused imports. 2015-11-26 15:55:40 +01:00
Florian Bruhin
7eb6f658eb tests: Use JSON for webserver_sub logging.
This simplifies logging output and parsing.
2015-11-26 14:40:20 +01:00
Florian Bruhin
b8467b8fef tests: Various cleanups. 2015-11-26 14:25:33 +01:00
Florian Bruhin
7baed5f80f tests: Don't start qutebrowser process if unneeded. 2015-11-26 13:56:42 +01:00
Florian Bruhin
fac76576d7 bdd: Add "the following tabs should be open" step.
This simplifies a lot of .feature files because we don't actually need to check
the full session.
2015-11-26 01:33:56 +01:00
Florian Bruhin
c861cf54e6 tests: Make QuteProcess.path_to_url public. 2015-11-26 01:33:27 +01:00
Florian Bruhin
fc328b275a bdd: Add some tests for :tab-focus. 2015-11-26 00:48:39 +01:00
Florian Bruhin
9328e1703c Merge branch 'Kingdread-incdec-setting' 2015-11-25 23:06:43 +01:00
Daniel Schadt
d082c248a8 Disallow empty values in url-incdec-segments 2015-11-25 19:35:37 +01:00
Florian Bruhin
951c2e8eb6 Fix qflags_key comparison. 2015-11-25 18:54:03 +01:00
Florian Bruhin
c755a78518 bdd: Add tests for :tab-close/:tab-only. 2015-11-25 18:48:10 +01:00
Florian Bruhin
a6045ab551 Handle invalid select-on-remove case. 2015-11-25 18:47:36 +01:00
Florian Bruhin
67f726c9d4 tests: Add another BOM test for javascript_escape. 2015-11-25 18:47:16 +01:00
Florian Bruhin
73e9fd1118 Handle BOM (\ufeff) for webelem.javascript_escape. 2015-11-25 18:14:52 +01:00
Florian Bruhin
816d62bca5 bdd: Reorganize numbered test files. 2015-11-25 18:02:14 +01:00
Florian Bruhin
eed2584e3f Fixup for last commit. 2015-11-25 17:55:33 +01:00
Florian Bruhin
0a7b552111 bdd: Use 'q' key for forward-unbound-keys test.
It seems ' gives us a 222 keycode with newer Qt versions, but 0 with older
ones. 'q' which is a much lower code should hopefully work better.
2015-11-25 17:52:00 +01:00
Florian Bruhin
21a1f9ca65 bdd: Add various key input tests. 2015-11-25 17:20:53 +01:00
Florian Bruhin
9670ffb78e bdd: Add "the JS message ... should not be logged". 2015-11-25 17:20:05 +01:00
Florian Bruhin
388cc7ae29 bdd: Add "Then ... should be logged" step. 2015-11-25 17:19:49 +01:00
Florian Bruhin
9fe02d55c9 bdd: Add "I press the keys ..." step. 2015-11-25 17:19:16 +01:00
Florian Bruhin
7cfea665ff tests: Strip trailing slash for webserver paths. 2015-11-25 10:40:24 +01:00
Florian Bruhin
24a71e5c2e Fix webelem.javascript_escape with U+2028/U+2029. 2015-11-25 10:32:22 +01:00
Florian Bruhin
ba4471bb2f doc: Replace issue badge by codecov in readme. 2015-11-24 21:39:07 +01:00
Florian Bruhin
eaec930605 tox: Update coverage to 4.0.3.
- Fixed a mysterious problem that manifested in different ways: sometimes
  hanging the process, sometimes making database connections fail.
- The XML report now has correct <source> elements when using a --source=
  option somewhere besides the current directory.
- Fixed an unusual edge case of detecting source encodings
- Help messages that mention the command to use now properly use the actual
  command name, which might be different than “coverage”.
2015-11-24 21:35:29 +01:00
Florian Bruhin
f48bebb7ff tox: Update hypothesis to 1.15.0.
A release with two new features.

- A 'characters' strategy for more flexible generation of text with particular
  character ranges and types.
- Add support for preconditions to the rule based stateful testing.
2015-11-24 21:34:43 +01:00
Florian Bruhin
027a10c04b bdd: Add some tests for :navigate. 2015-11-24 21:32:45 +01:00
Florian Bruhin
8f2b29a1f9 tests: Make it possible to load httpbin root. 2015-11-24 21:27:20 +01:00
Florian Bruhin
93ef85ff16 tests: Serve index.html files in webserver_sub.py. 2015-11-24 20:43:20 +01:00
Florian Bruhin
f8668ff710 bdd: Add a test for :open with -t and -b. 2015-11-24 20:31:08 +01:00
Florian Bruhin
c22e1df400 Add whitespace. 2015-11-24 19:24:39 +01:00
Florian Bruhin
28b739b9b5 bdd: Add tests for :open. 2015-11-24 19:19:23 +01:00
Florian Bruhin
287b2ba258 bdd: Replace (port) when setting a setting. 2015-11-24 19:19:03 +01:00
Florian Bruhin
925a5ba809 bdd: Add test for :debug-console. 2015-11-24 18:37:34 +01:00
Florian Bruhin
8faf4717e5 Make :debug-console toggle the console. 2015-11-24 18:32:18 +01:00
Florian Bruhin
2ef2e3088f bdd: Add tests for :view-source. 2015-11-24 18:24:33 +01:00
Florian Bruhin
d58a5d4d15 bdd: Add "the page source should look like" step. 2015-11-24 18:22:43 +01:00
Florian Bruhin
b7323914b8 tests: Add plain arg to quteprocess.get_contents. 2015-11-24 18:22:20 +01:00
Florian Bruhin
35de87f973 Expand ~ with :dump-page. 2015-11-24 18:04:10 +01:00
Florian Bruhin
b37dac7bfa Handle errors in :dump-page. 2015-11-24 18:03:39 +01:00
Florian Bruhin
e405492667 Ignore errors when removing temp basedir. 2015-11-24 17:50:39 +01:00
Florian Bruhin
7b1e2ab471 Skip some inspector tests on windows.
Those cause trouble because it can't clean up the local storage directory...
2015-11-24 17:48:09 +01:00
Florian Bruhin
3905884a84 Disable all QWebSettings storage when quitting.
This hopefully helps with issues on the Windows buildbot:

    Error in atexit._run_exitfuncs:
    Traceback (most recent call last):
      File "C:\Users\florian\buildbot\slave\win8\build\.tox\py34\lib\shutil.py", line 371, in _rmtree_unsafe
	os.unlink(fullname)
    PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'C:\\Users\\florian\\AppData\\Local\\Temp\\qutebrowser-basedir-ixuexfeu\\data\\local-storage\\qrc__0.localstorage'
2015-11-24 17:24:14 +01:00
Florian Bruhin
43d7b139e8 Ignore another libpng warning.
This happened here:
https://ci.appveyor.com/project/The-Compiler/qutebrowser/build/master-1536/job/k8es4nh719cc27hf
2015-11-24 16:59:35 +01:00
Florian Bruhin
d13ae4c666 tests: Make checks for focus window more forgiving.
It seems on OS X we get this instead of focusing the webview:
"Focus object changed: <qutebrowser.browser.inspector.WebInspector object at ...>"
2015-11-24 16:54:35 +01:00
Florian Bruhin
922fdc0526 Fix :fake-key with no focused webview. 2015-11-24 16:28:56 +01:00
Florian Bruhin
4c1eff625f tests: Make inspector smoke test more reliable.
Before we didn't wait until the inspector window was hidden, which caused the
following tests to fail on our OS X buildbot:

    ==================================== ERRORS ====================================
    _________ ERROR at teardown of test_fakekey_sending_key_to_the_website _________

    [...]

    tests/integration/testprocess.py:186: InvalidLine
    ----------------------------- Captured stdout call -----------------------------
    [...]
    INVALID: Traceback (most recent call last):
    IGNORED:   File "/Users/buildbot/buildbot/slave/osx/build/qutebrowser/app.py", line 109, in <lambda>
    IGNORED:     target_arg=target_arg))
    IGNORED:   File "/Users/buildbot/buildbot/slave/osx/build/qutebrowser/app.py", line 263, in process_pos_args
    IGNORED:     commandrunner.run_safely_init(cmd[1:])
    IGNORED:   File "/Users/buildbot/buildbot/slave/osx/build/qutebrowser/commands/runners.py", line 266, in run_safely_init
    IGNORED:     self.run(text, count)
    IGNORED:   File "/Users/buildbot/buildbot/slave/osx/build/qutebrowser/commands/runners.py", line 249, in run
    IGNORED:     result.cmd.run(self._win_id, args)
    IGNORED:   File "/Users/buildbot/buildbot/slave/osx/build/qutebrowser/commands/command.py", line 505, in run
    IGNORED:     self.handler(*posargs, **kwargs)
    IGNORED:   File "/Users/buildbot/buildbot/slave/osx/build/qutebrowser/browser/commands.py", line 1781, in fake_key
    IGNORED:     tab='current')
    IGNORED:   File "/Users/buildbot/buildbot/slave/osx/build/qutebrowser/utils/objreg.py", line 215, in get
    IGNORED:     reg = _get_registry(scope, window, tab)
    IGNORED:   File "/Users/buildbot/buildbot/slave/osx/build/qutebrowser/utils/objreg.py", line 202, in _get_registry
    IGNORED:     return _get_tab_registry(window, tab)
    IGNORED:   File "/Users/buildbot/buildbot/slave/osx/build/qutebrowser/utils/objreg.py", line 152, in _get_tab_registry
    IGNORED:     raise RegistryUnavailableError('tab')
    INVALID: qutebrowser.utils.objreg.RegistryUnavailableError: tab
    [...]

While this is a real issue, this test shouldn't affect the next one.

Since we have to wait for windows getting focused but Xvfb doesn't do that, we
skip this tests when running via Xvfb.
2015-11-24 16:17:26 +01:00
Florian Bruhin
542d13b70d tests: Add a not_xvfb marker. 2015-11-24 16:17:07 +01:00
Florian Bruhin
75178b0cdc Log when the focus object changed.
This is mainly needed for tests to synchronize things properly.
2015-11-24 15:24:45 +01:00
Florian Bruhin
14f4689998 tests: Fix TestInitLog.
This worked before b0d4ebe because --debug was given and the
"args.loglevel.upper()" part was never executed.

However, loglevel is expected as a string, not as an int.
2015-11-23 21:50:48 +01:00
Florian Bruhin
0becee05e1 Update changelog. 2015-11-23 21:49:34 +01:00
Florian Bruhin
c73de6ea4d Change "Added binding ..." logs to vdebug. 2015-11-23 21:41:31 +01:00
Florian Bruhin
b0d4ebe844 Don't log VDEBUG messages with --debug.
This reduces the log spam quite a bit, which also makes things easier when
dealing with CI output.
2015-11-23 21:40:11 +01:00
Florian Bruhin
9479a50784 bdd: Add a timeout to redirect-later with -1 delay. 2015-11-23 21:37:22 +01:00
Florian Bruhin
196d1e95be tests: Skip test_normal_connection IPC test on OS X.
Seems like it hangs there sometimes.
2015-11-23 20:33:11 +01:00
Florian Bruhin
607ca0f478 tests: Wait until page is dumped for header check.
If we don't do this, it's possible for the test process to delete the temporary
directory before qutebrowser actually writes the file.
2015-11-23 20:12:52 +01:00
Florian Bruhin
d4c24c935c bdd: Compare unordered req's for :reload --force. 2015-11-23 20:00:25 +01:00
Florian Bruhin
79680f505e Fix docstring. 2015-11-23 19:46:50 +01:00
Florian Bruhin
f3b89dba9b tests: Make test_reload/..._with_force more stable.
This waits until the pages have actually been reloaded.
2015-11-23 19:44:53 +01:00
Florian Bruhin
e2da9aa3f8 tests: Make test_stop more stable.
It's now based by the browser opening a second page after :stop is run rather
than timing-based, which hopefully should make it run more stable on Travis.
2015-11-23 19:43:11 +01:00
Florian Bruhin
d324dd5f70 bdd: Add "I open ... in a new tab" step. 2015-11-23 19:42:01 +01:00
Florian Bruhin
39f29e2531 tests: Wait until clipboard actually changed.
Hopefully fixes #1124.
2015-11-23 16:29:37 +01:00
Florian Bruhin
17b5ccde0e tests: Ignore "SelectionRequest too old" message.
See #1124.
2015-11-23 16:25:03 +01:00
Florian Bruhin
162c8b30e6 Remove unused import. 2015-11-23 14:49:37 +01:00
Florian Bruhin
7a82bb55e4 bdd: Add tests for :reload. 2015-11-23 14:37:54 +01:00
Florian Bruhin
1e79aae231 bdd: Add check_header step. 2015-11-23 14:37:40 +01:00
Florian Bruhin
76143574ef tests: Add quteproc.get_content. 2015-11-23 14:37:29 +01:00
Florian Bruhin
31892b437e Add :debug-dump-page command.
This can probably be merged into :download later, when the mess is cleaned up.
2015-11-23 14:35:46 +01:00
Florian Bruhin
52aca30342 tests: Add quteproc.temp_setting. 2015-11-23 13:31:17 +01:00
Florian Bruhin
e6eaa5f140 tests: Add quteproc.get_setting. 2015-11-23 13:30:49 +01:00
Florian Bruhin
b7b4ee1b27 Merge branch 'Kingdread-download-page' 2015-11-23 13:27:59 +01:00
Florian Bruhin
ae00dac0be Update changelog. 2015-11-23 13:27:52 +01:00
Florian Bruhin
0d60ec43ed Regenerate docs. 2015-11-23 13:26:32 +01:00
Florian Bruhin
16e1a65448 Merge branch 'download-page' of https://github.com/Kingdread/qutebrowser into Kingdread-download-page 2015-11-23 13:16:16 +01:00
Daniel Schadt
89c9b5959e Don't ask the user twice for a filename
Fixes a bug where the user would be asked twice for a filename when
using :download without a dest-argument.

The problem was that we unconditionally overwrote filename, even if one
was given, thus discarding any "filename-finding-process" that we had
and asking the user again.
2015-11-23 12:32:58 +01:00
Florian Bruhin
d68798a15b Merge branch 'larryhynes-patch-1' 2015-11-23 11:26:24 +01:00
Florian Bruhin
efa745b53f Fix indent. 2015-11-23 11:26:01 +01:00
Florian Bruhin
049102c644 Regenerate authors. 2015-11-23 11:24:40 +01:00
Florian Bruhin
f4cccdf13f Merge branch 'patch-1' of https://github.com/larryhynes/qutebrowser into larryhynes-patch-1 2015-11-23 11:23:10 +01:00
Florian Bruhin
b45b8d57bb Merge branch 'forkbong-argparse-usage' 2015-11-23 11:21:11 +01:00
Florian Bruhin
135dc64de7 Regenerate authors. 2015-11-23 11:20:56 +01:00
Florian Bruhin
ee0627128a Merge branch 'argparse-usage' of https://github.com/forkbong/qutebrowser into forkbong-argparse-usage 2015-11-23 11:20:49 +01:00
Florian Bruhin
ea06c64ed4 Fix typos. 2015-11-23 11:17:26 +01:00
Panagiotis Ktistakis
f3f0ef9841 Remove unnecessary 'usage:' from argument parser. 2015-11-23 01:10:35 +02:00
Florian Bruhin
4fa32bd0cd bdd: Use a fresh instance for :stop test.
This hopefully makes it more stable on Travis on OS X.
2015-11-22 17:07:54 +01:00
larryhynes
706a4e3d39 Change error to warning for text not found on page 2015-11-21 23:47:00 +00:00
Daniel Schadt
86eda2843d Normalize application/x-javascript
Should be just application/javascript
2015-11-21 16:19:01 +01:00
Florian Bruhin
39def173ca bdd: Fix request list for :stop test.
We changed the URL in the last commit but forgot to adjust that.
2015-11-21 15:31:19 +01:00
Florian Bruhin
eb232734b4 bdd: Increase timeouts for :stop test.
The old ones weren't enough for Travis it seems.
2015-11-21 15:14:32 +01:00
Florian Bruhin
4f165a7669 bdd: Add a test for :stop. 2015-11-21 14:23:44 +01:00
Daniel Schadt
7d6327873a Pass test only when mhtml file is written
Otherwise we might spill data to tests that come after the mhtml ones.
2015-11-21 12:45:57 +01:00
Daniel Schadt
59c9c6ccb0 Actually test :download --mhtml, not :download 2015-11-21 12:37:26 +01:00
Florian Bruhin
8607d527bf tox: Update check-manifest to 0.29.
Fix --python with just a command name, to be found in path.
2015-11-21 10:44:58 +01:00
Florian Bruhin
11c9155961 Merge branch 'meles5-website' 2015-11-21 09:29:24 +01:00
Florian Bruhin
8b8ce6d9f0 Merge branch 'titles' of https://github.com/meles5/qutebrowser into meles5-website 2015-11-21 09:26:28 +01:00
Florian Bruhin
8c88b8168f Merge branch 'metatags' of https://github.com/meles5/qutebrowser into meles5-website 2015-11-21 09:26:06 +01:00
meles5
c54df5f142 Improved meta tags on the website 2015-11-21 08:45:13 +01:00
Daniel Schadt
c7294781f5 Don't make ExpectedRequest orderable
Instead, make it hashable and use collections.Counter instead of sorted
lists. This actually produces a nicer output for differences between
the counters.
2015-11-21 00:20:09 +01:00
Daniel Schadt
c12011c84d Style fixes 2015-11-21 00:10:49 +01:00
Florian Bruhin
2727f3c2a8 Hide QObject::connect stateChanged warning. 2015-11-20 22:01:21 +01:00
meles5
401f71236d pylint: disable too-many-statements 2015-11-20 21:53:28 +01:00
meles5
b9240924d2 Seperated into two lines 2015-11-20 21:39:17 +01:00
meles5
d9f1699a3b Improved website titles 2015-11-20 21:12:06 +01:00
Daniel Schadt
b776aeac84 Use same representation in webview and quteprocess
Otherwise the "page loaded" message will not be recognized.

Also use percent-encoding to avoid unicode-related bugs on different
systems.
2015-11-20 19:11:20 +01:00
Florian Bruhin
af875f4b8f Add a :fake-key command.
Closes #556.
See #551.
2015-11-20 19:06:06 +01:00
Daniel Schadt
0a9a75c337 Add more tests for the :download command 2015-11-20 18:31:39 +01:00
Daniel Schadt
0c2a285fef Convert to QUrl before waiting for the logline
webview uses QUrl to output the url and thus might convert some escape
sequences to their unicode characters. If we don't do the same
conversions here, we will "miss" the log message and fail the test.
2015-11-20 18:30:08 +01:00
Daniel Schadt
d5bc962046 mhtml: Current index != Current tab_id 2015-11-20 18:15:03 +01:00
Daniel Schadt
7f8c118991 Fix pylint 2015-11-20 16:57:27 +01:00
Daniel Schadt
b38a3caa4c Hide dest-old in the documentation of download 2015-11-20 16:34:27 +01:00
Daniel Schadt
cd78086d10 Fix pep257 2015-11-20 16:23:46 +01:00
Daniel Schadt
729d29b8a7 webserver: listen on 127.0.0.1 instead of 0.0.0.0 2015-11-20 16:17:34 +01:00
Daniel Schadt
09e310277d Remove server global, use lambda instead 2015-11-20 16:13:30 +01:00
Daniel Schadt
fb8f200291 Remove polling in webserver, use property instead 2015-11-20 16:11:13 +01:00
Daniel Schadt
613faf84ef Move pylint comment 2015-11-20 15:30:27 +01:00
Daniel Schadt
fe1c8ee4e8 Also add cherrypy.wsgiserver.wsgiserver3 to freeze 2015-11-20 15:27:17 +01:00
Daniel Schadt
097a14d5f3 Disable pylint no-member for cherrypy.wsgiserver 2015-11-20 14:03:51 +01:00
Daniel Schadt
cb40b1020c Add cherrypy.wsgiserver to frozen tests 2015-11-20 14:00:17 +01:00
Daniel Schadt
a991a8c43c Don't compare requests triggered by loading a page 2015-11-20 13:42:32 +01:00
Daniel Schadt
3466ee03f6 Change development server to cherrypy.wsgiserver
The Flask/Werkzeug development servers had some issues which lead to
failing tests (together with some Qt bugs).
2015-11-20 13:35:24 +01:00
Daniel Schadt
452c6f5310 Add __str__ method to ExpectedRequest
Better for reading test logs.
2015-11-20 13:35:24 +01:00
Florian Bruhin
1ec03462c8 Add a utils.parse_keystring. 2015-11-20 07:06:16 +01:00
Florian Bruhin
9a310dd1fb bdd: Add step to check for JS console.log. 2015-11-20 07:06:16 +01:00
Florian Bruhin
22a8f8def6 tox: Update pytest to 2.8.3.
- add __name__ attribute to testcases in TestCaseFunction to support the
  @unittest.skip decorator on functions and methods.
- collecting tests if test module level obj has __getattr__().
- don't collect tests if their failure cannot be reported correctly e.g. they
  are a callable instance of a class.
- fixed internal error when filtering tracebacks where one entry belongs to a
  file which is no longer available.
- enhancement made to highlight in red the name of the failing tests so
  they stand out in the output.
- minor fixes for interaction with OS X El Capitan system integrity
  protection
2015-11-19 23:00:04 +01:00
Florian Bruhin
1e37e09e29 Merge branch 'vyp-#1117' 2015-11-19 15:20:34 +01:00
Florian Bruhin
2dc7fc3b5a Regenerate authors. 2015-11-19 15:20:25 +01:00
xd1le
b9163c5079 doc: Document <unbound> in keys.conf.
Closes #1117.
2015-11-20 00:55:33 +11:00
Florian Bruhin
bb807cfa07 tox: Update pytest-mock to 0.9.0.
New mocker.resetall function, which calls reset_mock() in all mocked objects up
to that point.
2015-11-18 21:15:36 +01:00
Florian Bruhin
d2baced354 Update changelog. 2015-11-18 20:48:26 +01:00
Florian Bruhin
cdb6c6b3a3 Merge branch 'Konubinix-netrc' 2015-11-18 20:48:17 +01:00
Florian Bruhin
a164cd4da2 Regenerate authors. 2015-11-18 20:43:41 +01:00
Florian Bruhin
271cb47f87 Merge branch 'netrc' of https://github.com/Konubinix/qutebrowser into Konubinix-netrc 2015-11-18 20:38:57 +01:00
Florian Bruhin
c7f386cec0 Avoid logging in signal handlers.
If we don't do that, we can get this:

--- Logging error ---
Traceback (most recent call last):
  File ".../python3.5/logging/__init__.py", line 984, in emit
    self.flush()
  File ".../python3.5/logging/__init__.py", line 964, in flush
    self.stream.flush()
RuntimeError: reentrant call inside <_io.BufferedWriter name='<stderr>'>
Call stack:
  [...]
  File ".../qutebrowser/app.py", line 122, in qt_mainloop
    return qApp.exec_()
  File ".../qutebrowser/utils/objreg.py", line 118, in on_destroyed
    log.destroy.debug("schedule removal: {}".format(name))
  File ".../python3.5/logging/__init__.py", line 1267, in debug
    self._log(DEBUG, msg, args, **kwargs)
  File ".../python3.5/logging/__init__.py", line 1415, in _log
    self.handle(record)
  File ".../python3.5/logging/__init__.py", line 1425, in handle
    self.callHandlers(record)
  File ".../python3.5/logging/__init__.py", line 1487, in callHandlers
    hdlr.handle(record)
  File ".../python3.5/logging/__init__.py", line 855, in handle
    self.emit(record)
  File ".../python3.5/logging/__init__.py", line 984, in emit
    self.flush()
  File ".../python3.5/logging/__init__.py", line 964, in flush
    self.stream.flush()
  File ".../qutebrowser/misc/crashsignal.py", line 365, in interrupt
    log.destroy.info("Do the same again to forcefully quit.")
Message: 'Do the same again to forcefully quit.'
Arguments: ()
2015-11-18 20:21:23 +01:00
Florian Bruhin
4d1f37f296 bdd: Add tests for :inspector. 2015-11-18 20:08:25 +01:00
Florian Bruhin
55992337b8 bdd: Add a --qute-delay argument. 2015-11-18 20:01:40 +01:00
Daniel Schadt
4060fd5e90 Fix mhtml tests 2015-11-18 19:56:49 +01:00
Daniel Schadt
3438a45b19 Merge branch 'master' into download-page 2015-11-18 19:27:26 +01:00
Daniel Schadt
0d6d276592 mhtml: remove non-existing ftp asset
This could be the cause of failing tests, depending on the OS.
2015-11-18 19:15:18 +01:00
Florian Bruhin
90c1240ad4 tests: Remove unnecessary override. 2015-11-18 18:29:27 +01:00
Florian Bruhin
dd2ec30b97 Revert "Use parametrization for TestKeyToString:test_all."
This reverts commit aa1ea9b063.

I changed my mind on this, generating >400 tests for this is stupid.
2015-11-18 18:15:21 +01:00
Florian Bruhin
9f89033b8e Whoops. 2015-11-18 18:09:59 +01:00
Florian Bruhin
202fc8a5bd Only run codecov once.
Otherwise coverage diffs make no sense...

This reverts commit daaa15396c.
2015-11-18 17:47:26 +01:00
Samuel Loury
0298fcc841 Use credentials from netrc when available 2015-11-18 16:44:45 +01:00
Florian Bruhin
a845bf22ff ci_install: Clean up PyQt URL. 2015-11-18 08:28:35 +01:00
Florian Bruhin
3251bd8419 doc: Merge "error800"/"Error 800" in author list. 2015-11-18 08:12:02 +01:00
Florian Bruhin
dcfa73cf91 AppVeyor: Use PyQt 5.5.1. 2015-11-18 08:08:40 +01:00
Florian Bruhin
c46015b906 Add checklist for new PyQt release to CONTRIBUTING. 2015-11-18 08:08:40 +01:00
Florian Bruhin
89e3c2a703 Fix lint. 2015-11-18 07:43:10 +01:00
Florian Bruhin
3ec38539c5 Adjust version numbers in README. 2015-11-18 07:16:59 +01:00
Florian Bruhin
6f2407ac26 Regenerate authors. 2015-11-18 07:07:56 +01:00
Florian Bruhin
b735d079d5 Merge branch 'www' 2015-11-18 07:02:40 +01:00
Florian Bruhin
7239f7bb68 www: Don't build unneeded files. 2015-11-18 06:54:59 +01:00
Florian Bruhin
98fbdde846 www: Remove author line/asciidoc vars from output. 2015-11-18 06:51:46 +01:00
Florian Bruhin
244d86c85a www: Make script work if output path exists. 2015-11-18 06:41:40 +01:00
Florian Bruhin
cb624ea6ee www: Add some more links to the header. 2015-11-18 06:41:28 +01:00
Florian Bruhin
ad5988513b Fix lint. 2015-11-17 20:28:27 +01:00
Florian Bruhin
0ccd19f980 Fix lint. 2015-11-17 20:10:53 +01:00
Florian Bruhin
fbe5eb4671 Merge pull request #1114 from meles5/www
Add a license to the website files
2015-11-17 19:50:01 +01:00
Florian Bruhin
be19c76369 Merge branch 'lamarpavel-issue923' 2015-11-17 19:48:24 +01:00
Florian Bruhin
d37b311dcb Regenerate authors. 2015-11-17 19:46:31 +01:00
Florian Bruhin
ea5484c3a2 Fix nitpicks. 2015-11-17 19:46:24 +01:00
Florian Bruhin
f20ffca540 Merge branch 'issue923' of https://github.com/lamarpavel/qutebrowser into lamarpavel-issue923 2015-11-17 19:43:35 +01:00
Florian Bruhin
5a10ca96c5 Merge branch 'halfwit-master' 2015-11-17 19:31:00 +01:00
Florian Bruhin
4b531d142b Regenerate authors. 2015-11-17 19:30:51 +01:00
Florian Bruhin
e010602791 Remove outdated comment. 2015-11-17 19:30:08 +01:00
Florian Bruhin
54fe9407c4 Merge branch 'master' of https://github.com/halfwit/qutebrowser into halfwit-master 2015-11-17 19:29:54 +01:00
Halfwit
7822a33975 Finalizing comments and arguments passed in 2015-11-17 08:41:20 -07:00
Halfwit
09999654e2 Adding back second usage comment 2015-11-17 07:56:40 -07:00
Halfwit
773982ad23 The-Compiler's changes 2015-11-17 07:52:02 -07:00
Florian Bruhin
516a81c3cc tests: Don't parse httpbin date.
We don't need the parsed date, and the parsing is locale dependent, which can
cause trouble.
2015-11-17 07:36:21 +01:00
Florian Bruhin
726525b26a bdd: Add some more tests for scrolling with floats. 2015-11-17 06:57:33 +01:00
Florian Bruhin
40e2258ef3 Don't accept floats for :scroll-px. 2015-11-17 06:57:13 +01:00
Florian Bruhin
71134f97e3 bdd: Wait for request with "... should be loaded".
Hopefully makes things less prone to race conditions.
2015-11-17 06:42:13 +01:00
Florian Bruhin
779df4c08e bdd: Use separate files for scroll navigate tests.
hello.txt was already cached from some other tests, so let's make sure a fresh
file gets loaded.
2015-11-17 06:40:23 +01:00
Florian Bruhin
7fe9be432a tests: Make httpbin.Request a proper class. 2015-11-16 23:24:11 +01:00
Florian Bruhin
bc96da47ef bdd: Tests for scrolling with non-scrollable page. 2015-11-16 20:35:44 +01:00
Florian Bruhin
bbaab24ce8 Fix lint. 2015-11-16 20:24:27 +01:00
Florian Bruhin
b68adf1245 Merge _scroll_percent into scroll_perc. 2015-11-16 19:05:05 +01:00
Florian Bruhin
a4d15b550e Abort :back/:forward at beginning/end of history. 2015-11-16 19:03:07 +01:00
Florian Bruhin
eef760359c Add missing 3.txt. 2015-11-16 07:17:53 +01:00
Florian Bruhin
6a4ea944cf bdd: Add tests with very big counts. 2015-11-16 07:17:43 +01:00
Florian Bruhin
fe08cb24f8 bdd: Test some commands with count. 2015-11-15 20:48:07 +01:00
Florian Bruhin
eeab4d41ba Make it possible to pass a count via command name.
This is only used for tests so far and not intended for general usage (and thus
undocumented).
2015-11-15 19:55:01 +01:00
Florian Bruhin
29a1620e81 bdd: Add tests for :scroll-page with --*-navigate. 2015-11-15 17:50:26 +01:00
Florian Bruhin
7de206e350 Fix :scroll-perc 0/100 0. 2015-11-15 16:38:56 +01:00
Florian Bruhin
3d44d619fc bdd: Add some tests for :scroll-{perc,page}. 2015-11-15 16:38:56 +01:00
Florian Bruhin
1af30772b1 bdd: Add some comments to scroll.feature. 2015-11-15 16:38:56 +01:00
Florian Bruhin
4c75422c05 bdd: Add some :debug-webaction tests. 2015-11-15 16:38:56 +01:00
Florian Bruhin
145772476b bdd: Add some tests for :jseval. 2015-11-15 16:38:56 +01:00
Florian Bruhin
cfea69494a tests: Ignore stateChanged Qt warning. 2015-11-15 16:38:56 +01:00
Florian Bruhin
9f1c6e0139 bdd: Add some comments to misc.feature. 2015-11-15 16:38:56 +01:00
Florian Bruhin
384c753094 tests: Add ensure_not_logged to TestProcess. 2015-11-15 16:38:56 +01:00
Lamar Pavel
46d335cdee Update list of user agents with new script. 2015-11-14 16:06:45 +01:00
Lamar Pavel
d745819715 Improve script to print entries grouped by browser
The ua_fetch.py has been re-written entirely to find specific entries for
each browser based on diversity rather than sole popularity. The output
is now formatted to print the entries for each browser grouped together.
2015-11-14 15:57:24 +01:00
Florian Bruhin
e9ece3d114 tests: Validate **kwargs for TestProcess.wait_for. 2015-11-13 23:26:14 +01:00
meles5
cd912b7582 Restore to old fonts 2015-11-13 23:09:24 +01:00
Florian Bruhin
9607fae935 Skip check_coverage.py with --lf. 2015-11-13 22:43:12 +01:00
Florian Bruhin
b61462ccb8 Fix the style fixes. 2015-11-13 22:41:37 +01:00
Florian Bruhin
1da7996c3b Style fixes. 2015-11-13 22:27:41 +01:00
Florian Bruhin
04c2e45bee bdd: Add a first test for :jseval. 2015-11-13 07:56:59 +01:00
Florian Bruhin
3290048458 tests: Do custom fnmatch-like matching.
fnmatch treats [, ] and ? as shell metacharacters too, and has no way to escape
them. We need a literal [] and really only need * for filtering.
2015-11-13 07:56:59 +01:00
Florian Bruhin
205af3737f bdd: Skip yankpaste tests if clipboard is broken.
This seems to be the case on OS X Yosemite (on my Mac Mini).
2015-11-13 06:54:45 +01:00
Florian Bruhin
0085421ec6 tests: Use __tracebackhide__ in wait_for methods. 2015-11-13 06:45:55 +01:00
Florian Bruhin
ce66d731f2 tests: Add missing file. 2015-11-13 06:24:53 +01:00
Florian Bruhin
c29643b98d Add .coverage.* to .gitignore. 2015-11-13 06:24:03 +01:00
Florian Bruhin
3695e05691 Use pytest-faulthandler on all platforms. 2015-11-13 06:23:31 +01:00
Florian Bruhin
55b83409d9 tox: Update pytest-faulthandler to 1.1.0.
--faulthandler-timeout option is now properly supported in Python 3+; also a
warning is issued instead of an error on platforms without a
faulthandler.dump_traceback_later function.
2015-11-13 06:22:29 +01:00
Florian Bruhin
40c7990d3a tests: Skip ipc TestSendToRunningInstance on OS X.
This did hang often on OS X, and I don't have the time to properly debug this.

See #1045.
2015-11-12 22:17:37 +01:00
Florian Bruhin
85c82b32fb tests: Only print ignored lines with invalid ones. 2015-11-12 22:13:56 +01:00
Florian Bruhin
a740ace115 AppVeyor: Run tests with -v. 2015-11-12 22:13:10 +01:00
Florian Bruhin
1dd5bb1596 bdd: Add more tests for :zoom 2015-11-12 22:10:13 +01:00
Daniel Schadt
4210d7e15d mhtml: use png instead of ico for test
Seems like httpbin sends a different MIME-type on travis than on my
laptop, something 'clear' like image/png should fix this.
2015-11-12 21:58:33 +01:00
Florian Bruhin
00ccc236bb bdd: Add more :paste tests. 2015-11-12 21:52:39 +01:00
Florian Bruhin
25921792ef tests: Allow to open about:…/qute:… in QuteProc. 2015-11-12 21:52:06 +01:00
Daniel Schadt
354259777a mhtml: don't test with dynamically modified page 2015-11-12 21:07:14 +01:00
Daniel Schadt
69a92af097 mhtml: add "complex" test case
The html page is very ugly, but tests the downloader pretty throughout
2015-11-12 20:57:38 +01:00
Florian Bruhin
200467c7f3 doc: Add entry about mutt to FAQ. 2015-11-12 20:35:48 +01:00
Florian Bruhin
ef79b87597 tox: Update Werkzeug to 0.11.2.
- Fix inheritable sockets on Windows on Python 3.
- Fixed an issue with the forking server not starting any longer.
- Fixed SSL wrapping on platforms that supported opening sockets
  by file descriptor.
- No longer log from the watchdog reloader.
- Unicode errors in hosts are now better catched or converted into
  bad request errors.
2015-11-12 20:30:26 +01:00
Florian Bruhin
ba902f1d92 tests: Fix test_testprocess flakyness.
When we don't include the start time in the measurement, the subprocess will
already start sleeping before we start measuring, which can lead to times
measured which are around 260-300ms.
2015-11-12 20:29:06 +01:00
Daniel Schadt
aef26e7779 mhtml: Recognize more files as css 2015-11-12 20:11:36 +01:00
Florian Bruhin
9c5ce8a688 tests: Improve partial_compare output. 2015-11-12 19:04:37 +01:00
Daniel Schadt
30e2afb59d mhtml: reduce test flakiness
Waiting for "All assets downloaded" may lead to race conditions when
the output file is read before qute wrote it, so the test fails.
2015-11-12 13:17:10 +01:00
Michael
2a9d56790f Create Openpage
Wrapper script to pass options in to qutedmenu
2015-11-11 23:22:31 -07:00
Michael
f22ccae6fd Create qutedmenu
Bemenu integration for Qutebrowser
2015-11-11 23:21:33 -07:00
Daniel Schadt
c759bf7a2f Move common filename-ask-code to a function
This should reduce code/logic-duplication regarding asking for download
filenames.
2015-11-12 00:12:51 +01:00
Florian Bruhin
256352024b Fix lint. 2015-11-11 22:39:17 +01:00
Florian Bruhin
1f3df64fe4 bdd: Add some first tests for :paste. 2015-11-11 22:38:43 +01:00
Florian Bruhin
ad8c9988f0 Fix lint. 2015-11-11 22:23:43 +01:00
Daniel Schadt
18da73227b Don't shadow built-in "dir" 2015-11-11 21:20:04 +01:00
Florian Bruhin
f0083adfb5 Remove unused import. 2015-11-11 21:14:26 +01:00
Florian Bruhin
15b77bf2e9 Fix catchlog move in run_frozen_tests.py. 2015-11-11 21:13:48 +01:00
Florian Bruhin
e25ae49c0e Use os.path.commonprefix to get common path.
os.path.commonpath is only available on Python 3.5.
2015-11-11 21:11:14 +01:00
Daniel Schadt
62b0c4d178 Merge branch 'download-page-tests' of https://github.com/The-Compiler/qutebrowser into download-page 2015-11-11 21:03:36 +01:00
Florian Bruhin
3680f01576 Switch to pytest 2.8.
Closes #1077.

There were two issues:

- Paths for coverage.py suddenly were absolute instead of relative, so we strip
  the common base part if that happens.

  /home/florian/proj/qutebrowser/git/qutebrowser/browser/cookies.py has 100%
  coverage but is not in perfect_files!
  /home/florian/proj/qutebrowser/git/qutebrowser/browser/http.py has 100%
  coverage but is not in perfect_files!
  [...]

- There was an io.UnsupportedOperationError in test_check_coverage.py because
  of pytest-faulthandler, so we just don't load that in the subprocess.
2015-11-11 20:57:47 +01:00
Daniel Schadt
4e3cd8b9e8 Don't prompt if not storage->prompt-download-dir 2015-11-11 20:39:35 +01:00
Daniel Schadt
0f8ec73c55 mhtml: also check dir before starting the download
Otherwise the downloads will be useless anyway.
2015-11-11 20:05:42 +01:00
Daniel Schadt
43c3a38938 mhtml: Don't crash if output dir doesn't exist 2015-11-11 20:00:20 +01:00
Florian Bruhin
416cfaf002 tests: Switch from pytest-capturelog to catchlog. 2015-11-11 19:57:03 +01:00
Florian Bruhin
a5efbe7412 tox: Update check-manifest to 0.28.
- Fix detection of git submodules.
- Apply ignore patterns in subdirectories too.
2015-11-11 14:57:45 +01:00
Florian Bruhin
6bd45bbf24 tests: Add some code for MHTML integration tests. 2015-11-11 09:01:05 +01:00
Florian Bruhin
7cddd52b2d Merge branch 'download-page' of https://github.com/Kingdread/qutebrowser into Kingdread-download-page 2015-11-10 22:39:07 +01:00
Florian Bruhin
d99f9a3a20 Improve :set error messages. 2015-11-10 22:09:36 +01:00
Florian Bruhin
54e2cea460 Fix some corner cases with :set. 2015-11-10 21:27:42 +01:00
Florian Bruhin
a26e99f004 bdd: Add some tests for :set. 2015-11-10 21:07:49 +01:00
Florian Bruhin
128465f12b Add some more tests for :set-cmd-text. 2015-11-10 19:22:13 +01:00
Florian Bruhin
7701bf602a Add --append argument to :set-cmd-text. 2015-11-10 19:21:54 +01:00
Florian Bruhin
cd25a25c96 tox: Update werkzeug to 0.11.1
- Fixed a regression on Python 3 in the debugger.
2015-11-10 19:14:55 +01:00
Florian Bruhin
788ea2720b Merge branch 'lamarpavel-test-browser-cache-more' 2015-11-10 18:57:44 +01:00
Florian Bruhin
2ca23d8037 Regenerate authors. 2015-11-10 18:57:36 +01:00
Florian Bruhin
250f0e7410 Merge branch 'test-browser-cache-more' of https://github.com/lamarpavel/qutebrowser into lamarpavel-test-browser-cache-more 2015-11-10 18:57:28 +01:00
Florian Bruhin
374b448e51 Get rid of unnecessary file.readline() calls. 2015-11-10 18:44:42 +01:00
Daniel
a5ee39c35e Fix PEP 8 2015-11-10 09:45:01 +01:00
Florian Bruhin
d71618031d bdd: Decrease timeouts if not on CI. 2015-11-10 09:24:47 +01:00
Florian Bruhin
ada4b669bc tests: Strip [2s ago] markers from log messages. 2015-11-10 09:23:37 +01:00
Florian Bruhin
e1c6cd6c6d tests: Skip test_file for PyQIODevice on OS X.
Those seem to cause a hang on Travis on OS X sometimes.
2015-11-10 08:55:31 +01:00
Florian Bruhin
dc3bfb5eb4 bdd: Print ignored lines in testprocess. 2015-11-10 08:47:29 +01:00
Florian Bruhin
6b4dbad15b bdd: Wait until request is done for hints.feature. 2015-11-10 08:22:06 +01:00
Florian Bruhin
596ed5f545 bdd: Add some more back/forward tests. 2015-11-10 07:51:09 +01:00
Florian Bruhin
f440953ada bdd: Add step to start a fresh instance. 2015-11-10 07:51:09 +01:00
Florian Bruhin
6e7d6fb00e tests: Use fnmatch for strings in partial_match. 2015-11-10 06:50:31 +01:00
Florian Bruhin
3fac74656e bdd: Add some misc. tests. 2015-11-10 06:33:47 +01:00
Lamar Pavel
aaf62fc6d0 Add cache tests to perfectly covered files. 2015-11-10 03:49:18 +01:00
Lamar Pavel
a2a1b77857 Undo unnecessary change 2015-11-10 03:45:38 +01:00
Lamar Pavel
fe8ddd79c0 Use config_stub.set instead of emitting sginal manually 2015-11-10 03:43:02 +01:00
Daniel
c0535727ef Only download elements with rel={stylesheet,icon}
Websites may set the rel attribute to whatever they want, so we just
care about stylesheets and icons and not the other stuff like wss
links (looking at you, GitHub), RSS-feeds, ...
2015-11-09 22:57:31 +01:00
Florian Bruhin
2fc1612bd4 Fix removing of automatic downloads w/ -1 timeout.
With ui -> remove-finished-downloads set to -1, when a download was started
with auto_remove=True (like with :adblock-update), there was a QTimer set up
with timeout -1, which causes this instead of doing something sane:

WARNING: QTimer::singleShot: Timers cannot have negative timeouts
2015-11-09 22:45:51 +01:00
Florian Bruhin
566f94111c Don't warn if element vanished on mouse release.
This happens somewhat reliably on Ubuntu Trusty with the hint test, and more
reliably on Travis.
2015-11-09 22:12:24 +01:00
Florian Bruhin
5e38861649 Fix warning regex in pytest.ini. 2015-11-09 22:12:10 +01:00
Florian Bruhin
0162583444 Fix check_coverage.py return value. 2015-11-09 20:07:08 +01:00
Florian Bruhin
41f7c11ab5 tests: Ignore XSETTINGS_S atom warning. 2015-11-09 19:55:32 +01:00
Florian Bruhin
6579866abe Quote weird Qt functions for logging. 2015-11-09 19:55:05 +01:00
Florian Bruhin
d288c9598d tests: Add some quteprocess.LogLine tests. 2015-11-09 19:34:34 +01:00
Florian Bruhin
4f6415631f tests: Parse function/line being unset for LogLine. 2015-11-09 19:34:13 +01:00
Florian Bruhin
9a2125fc18 Update changelog. 2015-11-09 18:24:23 +01:00
Florian Bruhin
65648da1ad Fix #889 during a webpage shutdown.
If we're in the middle of closing a WebPage, the webview will still be
registered, but already deleted by Qt - so we get a RuntimeError/TypeError
there.
2015-11-09 18:22:35 +01:00
Florian Bruhin
dce44f2dc5 bdd: Add some first tests for hints. 2015-11-09 18:20:23 +01:00
Florian Bruhin
f3d76b5af6 Fix :follow-hint with an invalid keystring. 2015-11-09 18:20:23 +01:00
Florian Bruhin
1aebefca18 bdd: Make "I run ..." work with PrerequisitesError. 2015-11-09 18:20:23 +01:00
Florian Bruhin
35c36725f2 Disallow :follow-hint outside of hint mode.
Fixes #1105.
2015-11-09 18:20:23 +01:00
Daniel
f79722975f Fix _download_dir reference 2015-11-09 17:14:04 +01:00
Daniel
a1bc020fec mhtml: Sanitize default filename suggestion 2015-11-09 17:01:08 +01:00
Daniel
4f01382c64 mhtml: Ignore non-http(s) assets 2015-11-09 17:01:08 +01:00
Daniel
71533b3456 mhtml: Add comments describing the hostblock check 2015-11-09 17:01:08 +01:00
Daniel
5601c8e7c1 mhtml: Skip test if cssutils is unavailable
Instead of failing the test (assert cssutils is not None)
2015-11-09 17:01:08 +01:00
Daniel
9694b3b548 downloads: Remove safety check in on_reply_error
Probably not needed after the last commit.
2015-11-09 17:01:08 +01:00
Daniel
252dc9a8bd mhtml: Don't attempt to download hostblocked urls 2015-11-09 17:01:08 +01:00
Daniel
c2218f51cd Add mhtml.last_used_directory to vulture whitelist 2015-11-09 17:01:08 +01:00
Daniel
f34161423c Fix "line too long" 2015-11-09 17:01:08 +01:00
Daniel
a780325a3a Allow directories to be entered as destination
The filename will then default to 'page title.mht'
2015-11-09 17:01:08 +01:00
Daniel
ae8a9b8798 Handle non-ASCII in headers/url better 2015-11-09 17:01:08 +01:00
Daniel
8bb887ddab Specify window and tab instead of 'current' 2015-11-09 17:01:08 +01:00
Daniel
a1e0ccb787 Fix spelling/style. 2015-11-09 17:01:08 +01:00
Daniel
f2f9529af7 Remove sys import in test_mhtml 2015-11-09 17:01:08 +01:00
Daniel
ed8a6a4c7b Update to cssutils 1.0.1
This fixes cssutils on Python 3.5 (yay!).
2015-11-09 17:01:08 +01:00
Daniel
3a2bb2d348 Add cssutils to README and utils/version.py 2015-11-09 17:01:08 +01:00
Daniel
12a9deb9bc Fix lints 2015-11-09 17:01:08 +01:00
Daniel
d1f8d29c20 Add --mhtml flag to :download
And remove :download-whole command.
2015-11-09 17:01:08 +01:00
Daniel
8cf0af004f Deprecate :download [url] [dest], add --dest param
:download --dest [dest] [url] is the new syntax.
2015-11-09 17:00:46 +01:00
Daniel
a898fd21d1 Update docs 2015-11-09 17:00:46 +01:00
Daniel
b17d74452f Expand $HOME before checking if file exists
Otherwise we might accidentally overwrite a file.
2015-11-09 16:59:16 +01:00
Daniel
dd8ff860f4 Fix lint 2015-11-09 16:59:16 +01:00
Daniel
b027e6af1b Mark cssutils tests as xfail on Python >= 3.5 2015-11-09 16:59:16 +01:00
Daniel
dab0db30a5 Remove tests for remove_file from test_mhtml.py 2015-11-09 16:59:16 +01:00
Daniel
919365dfa1 Remove dead code mhtml.py:MHTMLWriter:remove_file 2015-11-09 16:59:16 +01:00
Daniel
1902e4858f Also catch re.error on cssutils import
cssutils 1.0 and earlier are broken on Python 3.5 due to a bad regex
escape.
2015-11-09 16:59:16 +01:00
Daniel
957d68c477 Revert "Remove cssutils from mhtml.py"
This reverts commit 22a0f0952704d284846ab2572790d99a85515c57.
2015-11-09 16:59:16 +01:00
Daniel
ce1a99cc7c Remove cssutils from mhtml.py 2015-11-09 16:59:16 +01:00
Daniel
706b8c6600 Shorten line 2015-11-09 16:59:16 +01:00
Daniel
6601df14a3 mhtml: ask before overwriting dest 2015-11-09 16:59:16 +01:00
Daniel
420c087373 use cssutils 2015-11-09 16:59:16 +01:00
Daniel
749b1c02cc Style changes for mhtml and test_mhtml 2015-11-09 16:59:16 +01:00
Daniel
b05a0d191d Fix module path in test_mhtml
Also fix docstring for _get_css_imports
2015-11-09 16:59:16 +01:00
Daniel
2eeace1c2c Move misc.mhtml to browser.mhtml 2015-11-09 16:59:16 +01:00
Daniel
a092ef1fe6 String quote style changes
"" for user facing strings
'' for internal strings
except when quotes appear inside a string, to avoid escaping them
2015-11-09 16:59:16 +01:00
Daniel
9bf9124324 Fix mhtml tests, add test for _NoCloseBytesIO 2015-11-09 16:59:16 +01:00
Daniel
366916a8bf Use more specific selectors to filter webelements 2015-11-09 16:59:16 +01:00
Daniel
bf90c8c06b Add tests for mhtml
This also makes the output of MHTMLWriter deterministic, by

1) Setting the boundary at object creation, allowing uuid.uuid4 to be
   monkey patched

2) Outputting the files in sorted order (sorted by location), as python
   dicts are unordered by default.
2015-11-09 16:59:16 +01:00
Daniel
5fcbc839bb Allow many spaces and tabs after @import in CSS 2015-11-09 16:59:16 +01:00
Daniel
afa2f339e6 mhtm: use downloads logger instead of misc 2015-11-09 16:59:16 +01:00
Daniel
cb477a2623 Decode headers with ISO-8859-1 instead of ASCII 2015-11-09 16:59:16 +01:00
Daniel
a63aed5965 Use email.encoders instead of own encoder function 2015-11-09 16:59:16 +01:00
Daniel
ba81332d45 _get_css_imports now works on strings only
This also means that it returns strings, making the calls to .decode
unneeded.
2015-11-09 16:59:16 +01:00
Daniel
d3a21927f2 Remove default values in MHTMLWriter.__init__ 2015-11-09 16:59:16 +01:00
Daniel
e5bfb9884b Use WebElementWrapper instead of QWebElement
* also don't derive from object
* also set the _used flag on _Downloader
2015-11-09 16:59:16 +01:00
Daniel
a3cc71e317 Don't from-import functions/classes 2015-11-09 16:59:16 +01:00
Daniel
83aee4fad5 Rename on_meta_data_change to on_meta_data_changed 2015-11-09 16:59:16 +01:00
Daniel
8593144fa7 Make _path_suggestion public 2015-11-09 16:59:16 +01:00
Daniel
f58f6f24ee Use email.mime instead of manually writing the msg 2015-11-09 16:59:16 +01:00
Daniel
64c74bde90 Fix pylint for _NoCloseBytesIO 2015-11-09 16:59:16 +01:00
Daniel
05cc4b9650 Change boundary
This version contains a sequence that is illegal in quoted-printable
and thus safe from accidentally appearing in a website.
2015-11-09 16:59:16 +01:00
Daniel
8eafa1a105 Also scan CSS in <style> tags and inline CSS
As both may contain external links too (@import, url(...))
2015-11-09 16:59:16 +01:00
Daniel
02c1fa1232 Save mhtml if no assets need to be downloaded 2015-11-09 16:59:16 +01:00
Daniel
991b6d4fc9 Remove urljoin import 2015-11-09 16:59:16 +01:00
Daniel
5c6b715720 Use QUrl.resolved instead of urlparse.urljoin 2015-11-09 16:59:16 +01:00
Daniel
11ed60620a Also load assets referenced in css files
Things like "@import stylesheet.css" and "url(...)".
2015-11-09 16:59:16 +01:00
Daniel
6b086d159d Ask for filename when none is given 2015-11-09 16:59:16 +01:00
Daniel
679ab65b5f Message on finished download 2015-11-09 16:59:16 +01:00
Daniel
fd7820ea16 occurs -> occurred 2015-11-09 16:59:16 +01:00
Daniel
111feebf89 Refactor start_download to a class 2015-11-09 16:59:16 +01:00
Daniel
49a32f0041 First round of lint fixes 2015-11-09 16:59:16 +01:00
Daniel
024ae52366 Replaced quote-printable with own function
The original one had some inconsistencies that lead to bugs.

The content-type of the root document now also contains the charset.
2015-11-09 16:59:16 +01:00
Daniel
930871be01 First working version
The files can be opened with qutebrowser

Problems still with Umlauts in the encoded file.
2015-11-09 16:59:16 +01:00
Daniel
fbe5386e56 Initial version of website downloader
Saving websites as MHTML via :download-whole

Still needs some cleanup and a "ask for save path".
2015-11-09 16:59:16 +01:00
Florian Bruhin
99e090db78 tox: Update werkzeug to 0.11.
Version 0.11
------------

Released on November 8th 2015, codename Gleisbaumaschine.

- Added ``reloader_paths`` option to ``run_simple`` and other functions in
  ``werkzeug.serving``. This allows the user to completely override the Python
  module watching of Werkzeug with custom paths.
- Many custom cached properties of Werkzeug's classes are now subclasses of
  Python's ``property`` type.
- ``bind_to_environ`` now doesn't differentiate between implicit and explicit
  default port numbers in ``HTTP_HOST``.
- ``BuildErrors`` are now more informative. They come with a complete sentence
  as error message, and also provide suggestions.
- Fix a bug in the user agent parser where Safari's build number instead of
  version would be extracted.
- Fixed issue where RedisCache set_many was broken for twemproxy, which doesn't
  support the default MULTI command.
- ``mimetype`` parameters on request and response classes are now always
  converted to lowercase.
- Changed cache so that cache never expires if timeout is 0. This also fixes
  an issue with redis setex
- Werkzeug now assumes ``UTF-8`` as filesystem encoding on Unix if Python
  detected it as ASCII.
- New optional `has` method on caches.
- Fixed various bugs in `parse_options_header`.
- If the reloader is enabled the server will now open the socket in the parent
  process if this is possible.  This means that when the reloader kicks in
  the connection from client will wait instead of tearing down.  This does
  not work on all Python versions.
- Implemented PIN based authentication for the debugger.  This can optionally
  be disabled but is discouraged.  This change was necessary as it has been
  discovered that too many people run the debugger in production.
- Devserver no longer requires SSL module to be installed.

Version 0.10.5
--------------

(bugfix release, release date yet to be decided)

- Reloader: Correctly detect file changes made by moving temporary files over
  the original, which is e.g. the case with PyCharm.
- Fix bool behavior of ``werkzeug.datastructures.ETags`` under Python 3
2015-11-09 09:46:36 +01:00
Florian Bruhin
30db09bbda tox: Update pyroma to 1.8.3.
- Checking a PyPI package could fail under Python 3.
2015-11-09 09:46:02 +01:00
Florian Bruhin
0daf5885be Add some BDD tests for downloads. 2015-11-09 07:49:11 +01:00
Florian Bruhin
b59a56921e Fix crashes with downloads in a closed tab.
When a download was redirected or failed after a tab was closed, there was a
KeyError in the object registry.

Fixes #889. This is a regression introduced in
976f758da1 / #731.
2015-11-09 07:46:22 +01:00
Florian Bruhin
89c0ff0d9b bdd: Add a redirect-later page in webserver_sub.
This is needed for download tests.
2015-11-09 07:46:03 +01:00
Florian Bruhin
021ea444a1 bdd: Fix separations between tests.
With this change, no test should affect another one anymore. Changes in detail:

- Before each test, invalid lines are cleaned so the invalid output from the
  previous test doesn't affect the next one.
- Before each test, qutebrowser is restarted if it was quit.
- After each test, the data is cleared properly in every case.
- If there was an invalid output, the test waits for 1s for more output, and
  then terminates qutebrowser so it's restarted with a clean state.
2015-11-09 07:43:48 +01:00
Florian Bruhin
8b016df023 bdd: Make InvalidLine show some more informations. 2015-11-09 07:41:57 +01:00
Florian Bruhin
62f11273c5 tests: Fix quteproc.after_test() fixture.
It accidentally was named wrong, which caused it to never be executed. That
means the teardown log wasn't actually checked for errors.
2015-11-09 07:40:25 +01:00
Florian Bruhin
64730f566f tests: Make wait for loading work with downloads. 2015-11-09 07:39:24 +01:00
Florian Bruhin
8aa29a2ba2 bdd: Fix assert in "The requests should be" step.
When we call get_requests() inside the assertion, it won't act the same when
reinterpreting it.
2015-11-09 07:38:34 +01:00
Florian Bruhin
a05da2a956 bdd: Add a "then no crash should happen" step.
This is actually just a NOP, but helps in writing nice sentences ;)
2015-11-09 07:37:52 +01:00
Florian Bruhin
ae0e391c04 bdd: Add a "When I wait for the message ..." step. 2015-11-09 07:37:23 +01:00
Florian Bruhin
56bdb74ed9 bdd: Allow (port) replacement in "When I run ...". 2015-11-09 07:37:04 +01:00
Florian Bruhin
9dfe84c197 Accept longer URL in WebView repr before eliding.
This broke bdd tests because … was inserted in the log.
2015-11-09 07:36:10 +01:00
Florian Bruhin
9cfd96fcef Make :follow-hint take a keystring. 2015-11-09 07:35:56 +01:00
Florian Bruhin
c1c5b0f2b4 Fix prompt for download directory when turned off. 2015-11-09 07:35:03 +01:00
Florian Bruhin
95483f73d8 Add some assertions to DownloadItem.retry. 2015-11-09 07:34:49 +01:00
Florian Bruhin
612174ada0 Add a :download-retry command.
Closes #1097.
2015-11-09 07:17:54 +01:00
Florian Bruhin
19a9985f0d Update changelog. 2015-11-09 07:16:55 +01:00
meles5
44e60ccc3e Rename 2015-11-06 20:37:37 +01:00
meles5
4c4515cba9 Changed to .tff files and add a license notice 2015-11-06 20:34:59 +01:00
Florian Bruhin
4c2e92c998 Make testprocess test more stable. 2015-11-06 07:17:15 +01:00
Florian Bruhin
25ecd9068c tests: Don't wait for the same line twice.
We need to search for lines in the history because we could miss something
otherwise, but for subsequent wait_for calls, we really don't want to wait for
the same thing again.

This should make test_backforward.py more stable as it *actually* waits when
going back now. Before, it did produce failures such as this one on OS X:

____________________________ test_going_backforward ____________________________
[..]
    @bdd.then(bdd.parsers.parse("The requests should be:\n{pages}"))
    def list_of_loaded_pages(httpbin, pages):
        requests = [httpbin.Request('GET', '/' + path.strip())
                    for path in pages.split('\n')]
>       assert httpbin.get_requests() == requests
E       assert [Request(verb...rward/1.txt')] == [Request(verb=...rward/2.txt')]
E         At index 3 diff: Request(verb='GET', path='/data/backforward/1.txt') != Request(verb='GET', path='/data/backforward/2.txt')
E         Full diff:
E         [Request(verb='GET', path='/data/backforward/1.txt'),
E         Request(verb='GET', path='/data/backforward/2.txt'),
E         Request(verb='GET', path='/data/backforward/1.txt'),
E         -  Request(verb='GET', path='/data/backforward/1.txt')]
E         ?                                              ^
E         +  Request(verb='GET', path='/data/backforward/2.txt')]
E         ?                                              ^
tests/integration/features/conftest.py:85: AssertionError
2015-11-06 07:02:17 +01:00
Florian Bruhin
f5f74b7ddc tests: Use a base class for testprocess lines. 2015-11-06 07:02:17 +01:00
Florian Bruhin
da88908815 Fix deprecation warning when clearing downloads. 2015-11-06 07:02:17 +01:00
Florian Bruhin
3fcc27636a Improve documentation for general -> editor. 2015-11-06 07:02:17 +01:00
Lamar Pavel
cbb9fd203a Fix test of existing metadata files
In test_cache_existing_metadata_file() we are now getting the correct
path to the metadata files, thus making the test useful. This was the
last missing test, the cache is now 100% covered (issue#999).
2015-11-05 23:08:38 +01:00
Florian Bruhin
5541e3ed32 bdd: Wait until title is loaded in yankpaste. 2015-11-05 08:03:03 +01:00
Florian Bruhin
b0430ca3e7 bdd: Make it possible to wait for messages. 2015-11-05 08:02:55 +01:00
Florian Bruhin
547fc9f40e Simplify testprocess tests. 2015-11-05 07:40:10 +01:00
Florian Bruhin
10e52c6e9f Make testprocess test more robust. 2015-11-05 07:39:31 +01:00
Florian Bruhin
bf74fda5b2 Fix lint. 2015-11-05 07:33:32 +01:00
Florian Bruhin
76f5f4fefb bdd: Remove now unnecessary sleep. 2015-11-05 07:07:43 +01:00
Florian Bruhin
beab639d7a bdd: Wait for finished loads in backforward. 2015-11-05 07:07:43 +01:00
Florian Bruhin
924b0052c6 bdd: Match historic messages in wait_for.
Fixes #1083.
2015-11-05 07:07:43 +01:00
Florian Bruhin
6c718bc839 travis: Show (folded) coverage report. 2015-11-04 23:22:56 +01:00
Florian Bruhin
8ccadda0e9 tox: Update pytest-travis-fold to 1.2.0.
- Recognize 'pytest-cov' and fold coverage report
2015-11-04 23:15:51 +01:00
Florian Bruhin
5fc26bc477 tox: Update coverage to 4.0.2.
- More work on supporting unusually encoded source.
- Files or directories with non-ASCII characters are now handled properly.
- Setting a trace function with sys.settrace was broken by a change in 4.0.1.
- Officially support PyPy 4.0, which required no changes, just updates to the
  docs.
2015-11-04 17:59:46 +01:00
Florian Bruhin
59bc72cfbb Merge branch 'NoctuaNivalis-master' 2015-11-04 17:46:03 +01:00
Florian Bruhin
58c5b52ff3 Update docs. 2015-11-04 17:45:33 +01:00
Florian Bruhin
ac10fbc095 Handle qute:... handlers in run_vulture. 2015-11-04 17:45:16 +01:00
Florian Bruhin
939e95b344 Add missing decorator for qute:version. 2015-11-04 17:45:12 +01:00
Florian Bruhin
3525659b90 Fix pep8 issues. 2015-11-04 17:41:33 +01:00
Florian Bruhin
4e8cf70c10 Merge branch 'master' of https://github.com/NoctuaNivalis/qutebrowser into NoctuaNivalis-master 2015-11-04 17:19:00 +01:00
Felix Van der Jeugt
8354894838 rename the add_handler function everywhere 2015-11-04 09:49:46 +01:00
Florian Bruhin
af3318e72a doc: Clarify where to run tox.
Fixes #1087.
2015-11-04 09:45:48 +01:00
Florian Bruhin
c383b42af3 Merge branch 'forkbong-master' 2015-11-04 07:14:09 +01:00
Florian Bruhin
38756fc466 Update docs. 2015-11-04 07:12:44 +01:00
Florian Bruhin
6c20190473 Merge branch 'master' of https://github.com/forkbong/qutebrowser into forkbong-master 2015-11-04 07:12:32 +01:00
Florian Bruhin
702842c977 configtypes: Handle max. recursion depth for Regex. 2015-11-04 07:02:23 +01:00
Panagiotis Ktistakis
782f09488a Deprecate :download-remove --all.
:download-clear should be used instead.
2015-11-04 01:06:39 +02:00
Panagiotis Ktistakis
dc06787f83 Make key config migration for clearing downloads. 2015-11-04 01:01:27 +02:00
Felix Van der Jeugt
896ac0a7e9 fix the comments on style/typos 2015-11-03 23:15:07 +01:00
Felix Van der Jeugt
84c498b638 use global variable in place of class variable 2015-11-03 23:12:38 +01:00
Felix Van der Jeugt
0233423d9a using a class method is cleaner 2015-11-03 22:54:59 +01:00
Felix Van der Jeugt
a923572341 replace global constant with class variable and decorators 2015-11-03 22:54:59 +01:00
Florian Bruhin
2c7b0d2fb4 Add some bdd tests for scrolling. 2015-11-03 22:42:25 +01:00
Florian Bruhin
49137150ad tests: Print raw yaml in get_session() in QuteProc. 2015-11-03 22:41:56 +01:00
Florian Bruhin
2427bf5cb6 bdd: Make expect_error handle warnings. 2015-11-03 22:40:19 +01:00
Florian Bruhin
85608a8b8d Make :scroll error message deterministic. 2015-11-03 22:36:08 +01:00
Panagiotis Ktistakis
7dadd97f01 Implement :download-clear command.
Fixes #1013.
2015-11-03 20:27:02 +02:00
Florian Bruhin
17396e1030 bdd tests: Add QuteProc.get_session(). 2015-11-03 14:55:46 +01:00
Florian Bruhin
d992390cbe bdd: Move yankpaste/test.html to yankpaste.html. 2015-11-03 14:40:30 +01:00
Florian Bruhin
e31240e6c9 tests: Increase wait_for default timeout again. 2015-11-03 07:54:24 +01:00
Florian Bruhin
c78bbd9fd0 tests: Show some information for WaitForTimeout. 2015-11-03 07:53:51 +01:00
Florian Bruhin
535bcab310 bdd tests: Restart qutebrowser once per module.
This should be a good compromise between reproducibility and speed.
2015-11-03 07:00:46 +01:00
Florian Bruhin
f5eb755ef3 tests: Ignore some Qt warnings during teardown. 2015-11-03 06:38:48 +01:00
Florian Bruhin
7e0e770d53 bdd: Increase timeouts. 2015-11-03 06:35:52 +01:00
Florian Bruhin
e13de98790 Fix lint. 2015-11-02 23:49:44 +01:00
Florian Bruhin
7da0d2b6d5 Add some bdd tests for zooming. 2015-11-02 23:41:48 +01:00
Florian Bruhin
3155e20999 tests: Add helpers to compare sessions. 2015-11-02 23:41:48 +01:00
Florian Bruhin
ce6ba605e4 Reorganize bdd tests. 2015-11-02 20:32:15 +01:00
Florian Bruhin
bb4152d705 Add xfail test for vulture bug. 2015-11-02 18:25:16 +01:00
Florian Bruhin
144acc9f91 Merge branch 'skinnay-master' 2015-11-02 17:59:49 +01:00
Florian Bruhin
4da2bdfaa7 Update docs. 2015-11-02 17:59:43 +01:00
Florian Bruhin
d9af27670b Transform remove-finished-downloads=true to 1s.
2s seems rather long.
2015-11-02 17:58:08 +01:00
Florian Bruhin
0fb2778e4b Merge branch 'master' of https://github.com/skinnay/qutebrowser into skinnay-master 2015-11-02 17:55:40 +01:00
Florian Bruhin
16ba597173 tox: Update check-manifest to 0.27.
Fix utter breakage on Windows, introduced in 0.26. (The bug -- clearing the
environment unnecessarily -- could probably also cause locale-related problems
on other OSes.)
2015-11-02 17:53:20 +01:00
Florian Bruhin
1906a8c66e travis: Increase faulthandler timeout, take two. 2015-11-02 08:33:14 +01:00
Florian Bruhin
066c7959e8 travis: Increase faulthandler timeout. 2015-11-02 08:20:14 +01:00
Florian Bruhin
1563693037 tests: Ignore "QIODevice::write: device not open". 2015-11-02 08:15:22 +01:00
Florian Bruhin
a1b394d373 tests: Ignore "QNetworkReplyImplPrivate::error". 2015-11-02 08:09:07 +01:00
Florian Bruhin
7431d7cf89 tests: Increase quteproc start timeout. 2015-11-02 08:08:36 +01:00
Florian Bruhin
8884de71d8 Fix checking for primary selection. 2015-11-02 08:07:25 +01:00
Florian Bruhin
362ef3f74e tox: Fix pylint deps. 2015-11-02 08:01:54 +01:00
Florian Bruhin
611cf7eba7 tox: Re-freeze test dependencies. 2015-11-02 07:47:48 +01:00
Florian Bruhin
672d11e25a Add bdd test for :yank/:paste. 2015-11-02 07:43:37 +01:00
Florian Bruhin
0d67cff5cb Merge branch 'bdd'
Conflicts:
      tests/test_conftest.py
      tox.ini
2015-11-02 06:36:30 +01:00
Florian Bruhin
56758c8cea Ignore messages which are in qt_log_ignore. 2015-11-02 06:19:19 +01:00
Florian Bruhin
6dc3b5de36 Add some margin to wait_for stopwatch. 2015-11-02 06:11:35 +01:00
Florian Bruhin
8e09fd929b Ignore QWaitCondition error. 2015-11-02 06:10:31 +01:00
Florian Bruhin
4451165a27 Change IPC warnings to debug.
This seems to show up on Ubuntu Trusty (with older Qt) as well...
2015-11-01 23:11:42 +01:00
Florian Bruhin
b79ccb5e79 bdd: Make message matching work. 2015-11-01 22:49:39 +01:00
Florian Bruhin
dac2898585 Parse log messages in LogLine. 2015-11-01 22:49:29 +01:00
Florian Bruhin
6431997a5a Add some testprocess tests. 2015-11-01 22:48:44 +01:00
Florian Bruhin
239bc3bdea Connect read_log before starting process. 2015-11-01 22:48:44 +01:00
Florian Bruhin
dfc1782bbf Add testprocess.wait_for to react to messages. 2015-11-01 22:48:44 +01:00
Florian Bruhin
70decdc2c8 Fix lint. 2015-11-01 22:47:58 +01:00
Florian Bruhin
e88e9a66da Fix deleting of --temp-basedir on Windows.
Before it couldn't get deleted because Qt still kept the icon database open in
some way.

By clearing it when shutting down, this works correctly.

Fixes #1017.
2015-11-01 22:47:58 +01:00
Florian Bruhin
4b683cdd8f Check invalid logs after exiting process. 2015-11-01 22:47:58 +01:00
Florian Bruhin
1c7fd7d80e Rename testprocess cleanup to terminate. 2015-11-01 22:47:58 +01:00
Florian Bruhin
18ead66f04 Fix odd QuteProc crash. 2015-11-01 22:47:58 +01:00
Florian Bruhin
5ed419c7f5 Make reloading more reliable.
Before, we didn't wait until the reload is done, which could lead to a race
condition.
2015-11-01 22:47:58 +01:00
Florian Bruhin
2be5c4cd27 Fix lint. 2015-11-01 22:47:58 +01:00
Florian Bruhin
86d32f6e19 Set basepython = python3.4 for unittests-frozen. 2015-11-01 22:47:58 +01:00
Florian Bruhin
1a562594fa Broken error message matching. 2015-11-01 22:40:11 +01:00
Florian Bruhin
3a948be490 Add test for unexpected error logging. 2015-11-01 22:40:11 +01:00
Florian Bruhin
ac148c11ec Skip bdd tests when frozen for now.
See:

https://github.com/pytest-dev/pytest-bdd/issues/158
https://github.com/pytest-dev/pytest-bdd/issues/159
2015-11-01 22:40:11 +01:00
Florian Bruhin
b878b139dd Ignore errors when decoding subprocess output.
This would otherwise fail on Windows because … get translated to an UTF-8 NEL
(U+0085)...
2015-11-01 22:40:11 +01:00
Florian Bruhin
be20001594 Adjust log regex to parse "Unknown module". 2015-11-01 22:40:11 +01:00
Florian Bruhin
ee8d538964 Run new qutebrowser instance for each test.
The possibilities how a test can affect another are just too high.
2015-11-01 22:40:11 +01:00
Florian Bruhin
8664e45558 Use httpbin.Request namedtuple for comparisons.
This makes it easier to look at the pytest diff when things go wrong.
2015-11-01 22:40:11 +01:00
Florian Bruhin
6e786ff9b7 Open in a new tab. 2015-11-01 22:40:11 +01:00
Florian Bruhin
4bf6359205 Rename Request.url to Request.path. 2015-11-01 22:40:11 +01:00
Florian Bruhin
c052c8a107 Don't show full debug log without --verbose. 2015-11-01 22:40:11 +01:00
Florian Bruhin
af000a8ac6 Wait longer for process to start. 2015-11-01 22:40:11 +01:00
Florian Bruhin
ffc465e863 First work-in-progress feature test. 2015-11-01 22:40:11 +01:00
Florian Bruhin
7d17957e90 Ignore inspect.getargspec() warning during tests.
https://github.com/pytest-dev/pytest-bdd/issues/153
2015-11-01 22:40:11 +01:00
Florian Bruhin
670a4d274b Add pytest-bdd to tox.ini. 2015-11-01 22:40:11 +01:00
Florian Bruhin
76fcec4e4c tests: First steps towards end-to-end tests. 2015-11-01 22:40:11 +01:00
Lamar Pavel
baa3bd18a0 Fix indentation 2015-11-01 20:12:57 +01:00
Lamar Pavel
37d37148b7 Add pragma comment 2015-11-01 19:49:20 +01:00
Florian Bruhin
867f509bcc tests: Ignore QDisabledNetworkReply warning.
I guess they are displayed now during teardown with the changes in pytest-qt.
2015-11-01 18:04:09 +01:00
Florian Bruhin
3a522fb551 tests: Remove .close() workaround.
This is not needed anymore with pytest-qt 1.9.0.
2015-11-01 17:41:40 +01:00
Florian Bruhin
79e80afac8 tox: Update pytest-qt to 1.9.0.
- Exception capturing now happens as early/late as possible in order to catch
  all possible exceptions (including fixtures).
- Widgets registered by qtbot.addWidget are now closed before all other
  fixtures are tear down.
- qtbot now has a new wait method which does a blocking wait while the event
  loop continues to run, similar to QTest::qWait.
- raise RuntimeError instead of ImportError when failing to import any Qt
  binding: raising the latter causes pluggy in pytest-2.8 to generate a subtle
  warning instead of a full blown error.
2015-11-01 17:39:42 +01:00
Florian Bruhin
998d78c5b9 tox: Update hypothesis to 1.14.0.
New features:

* Add 'note' function which lets you include additional information in the
  final test run's output.
* Add 'choices' strategy which gives you a choice function that emulates
  random.choice.
* Add 'uuid' strategy that generates UUIDs'
* Add 'shared' strategy that lets you create a strategy that just generates a
  single shared value for each test run

Bugs:

* Using strategies of the form streaming(x.flatmap(f)) with find or in stateful
  testing would have caused InvalidArgument errors when the resulting values
  were used (because code that expected to only be called within a test context
  would be invoked).
2015-11-01 17:38:05 +01:00
Lamar Pavel
e86795f644 Add another test for pyqtslot on_config_changed
There are now two tests changing the config for private-browsing, covering
both True->False and False->True.
2015-11-01 14:55:03 +01:00
Lamar Pavel
70a6fe1561 Add tests triggering pyqtslot on_config_changed
Both settings relevant to the cache (cache-size and private-browsing) are
changed, a signal is emitted and the effect on the cache is verified.
2015-11-01 14:39:43 +01:00
Lamar Pavel
d127469d78 Add tests for fileMetaData()
One of those three tests is not complete as I couldn't yet find a way
to predict the path and name of cached files when using tmpdir.
2015-10-31 21:56:15 +01:00
Lamar Pavel
b94f7c7681 Add test for metaData() with cache deactivated 2015-10-31 18:49:58 +01:00
Lamar Pavel
404da750c6 Fix insertion into wrong cache 2015-10-31 18:32:14 +01:00
Lamar Pavel
571d7a680b Fix all other tests that weren't using DiskCache
So yeah, this explains a lot of the missing paths reported by the
coverage analysis.
2015-10-31 17:09:00 +01:00
Lamar Pavel
35762955cf Fix test_cache_remove_data
The test was not using qutebrowsers DiskCache class at all but Qts
QNetworkDiskCache. As a result the code paths of DiskCache.remove()
were never visited.
2015-10-31 16:57:00 +01:00
Lamar Pavel
3c2bc670ff Add test for alternate path of DiskCache.clear() 2015-10-31 16:33:01 +01:00
Lamar Pavel
e1446c3448 Add another test for deactivated cache
This one is testing the missing path in updateMetaData for a not activated
cache.
2015-10-31 16:28:17 +01:00
Lamar Pavel
39e37b043e Add more tests for deactivated cache
Getting closer to 100% completion, add tests for missing paths of
DiskCache.insert and DiskCache.cacheSize().
2015-10-31 16:13:29 +01:00
skinnay
11e5774f46 Changed _get_value_transformer function to take a dictionary mapping old
values to new values as input.
Added entry for changing remove-finished-downloads setting to new int
value.
2015-10-30 19:37:43 -04:00
Florian Bruhin
b2dceb078f Merge branch 'lamarpavel-test-browser-cache' 2015-10-30 18:54:37 +01:00
Florian Bruhin
367e501e56 Regenerate authors. 2015-10-30 18:54:30 +01:00
Florian Bruhin
468b2c4ade Merge branch 'test-browser-cache' of https://github.com/lamarpavel/qutebrowser into lamarpavel-test-browser-cache 2015-10-30 18:54:24 +01:00
Florian Bruhin
d5fe1d3635 Merge pull request #1075 from meles5/www
Improved asciidoc2html script
2015-10-30 18:52:14 +01:00
Florian Bruhin
c09ae4675c Merge branch 'MazeChaZer-feature/remove-unused-tab' 2015-10-30 18:51:08 +01:00
Florian Bruhin
4c03197984 Regenerate authors. 2015-10-30 18:50:15 +01:00
Florian Bruhin
5bd07d23a3 Merge branch 'feature/remove-unused-tab' of https://github.com/MazeChaZer/qutebrowser into MazeChaZer-feature/remove-unused-tab 2015-10-30 18:49:07 +01:00
Florian Bruhin
e5b98a9762 tox: Update check-manifest to 0.26.
* Do not complain about missing .gitattributes file.
* Normalize unicode representation and case of filenames.
* Drop Python 2.6 support.
* Support installation via zc.buildout better.
2015-10-30 18:46:50 +01:00
meles5
6d6ef1e386 tox fixes 2015-10-30 14:52:09 +01:00
Florian Bruhin
d2672bce86 tox: Update hypothesis to 1.13.0
This is quite a small release, but deprecates some public API functions and
removes some internal API functionality so gets a minor version bump.

- All calls to the 'strategy' function are now deprecated, even ones which pass
  just a SearchStrategy instance (which is still a no-op).
- Never documented hypothesis.extra entry_points mechanism has now been removed
  (it was previously how hypothesis.extra packages were loaded and has been
  deprecated and unused for some time)
- Some corner cases that could previously have produced an OverflowError when
  simplifying failing cases using hypothesis.extra.datetimes (or dates or
  times) have now been fixed.
- Hypothesis load time for first import has been significantly reduced - it
  used to be around 250ms (on my SSD laptop) and now is around 100-150ms. This
  almost never matters but was slightly annoying when using it in the console.
- hypothesis.strategies.randoms was previously missing from __all__.
2015-10-30 07:42:09 +01:00
Lamar Pavel
27ec9e1c43 Fix typo 2015-10-30 02:46:43 +01:00
Lamar Pavel
b5af1c8730 Add three tests querying and removing data
Two of these are testing return values of a deactivated cache and the
third is trying to query data that was never inserted into an active
cache.
2015-10-30 02:41:17 +01:00
Lamar Pavel
b3fa19eb96 Add sanity test involving almost everything 2015-10-30 02:03:34 +01:00
Lamar Pavel
05994ad90e Add theshold to cache-size test
The strict test condition before was violated by Qt internals which
seem to violate documented guarantees but are not part of qutebrowsers
code and thus can only be tested to a certain extent.
2015-10-30 01:22:16 +01:00
skinnay
88ba4831a8 Merge branch 'finished-downloads' 2015-10-29 17:40:22 -04:00
skinnay
6125e51de3 removed whitespace 2015-10-29 14:54:54 -04:00
skinnay
af70e783b6 removed extra whitespace 2015-10-29 14:49:16 -04:00
skinnay
5a34fdfd0c Changed the functionality of "remove-finished-downloads" setting.
Instead of being a boolean value indicating whether or not to instantly remove
downloads when they finish, it's now an integer value representing the
number of milliseconds to wait before removing downloads when they
finish. The default value, -1, means that the downloads will not be
removed when they finished. This is the same behavior as the previous
default value of false.
2015-10-29 13:44:28 -04:00
meles5
7cb462ff82 Improved the folder-copy function 2015-10-29 16:52:38 +01:00
meles5
1488f59d8f Close file 2015-10-29 16:33:20 +01:00
meles5
f807842a52 Improved code style 2015-10-29 16:30:25 +01:00
meles5
8600acddb1 Moved everything into one block and used with to open files 2015-10-29 15:41:57 +01:00
Jonas Schürmann
a4aacde88f Undo: Fix issues with url comparison 2015-10-29 09:36:42 +01:00
Lamar Pavel
9a8032fa91 Fix pylint errors (upper case variable names) 2015-10-29 03:13:25 +01:00
Lamar Pavel
a6526a1be2 Add tests to update and verify meta data of cache entries 2015-10-29 02:57:16 +01:00
Lamar Pavel
2cab750a54 Add test for DiskCache.remove() 2015-10-29 02:37:32 +01:00
Lamar Pavel
e4c79a68d1 re-write tests to fill the cache
Previously the tests were not adding any data to the cache, making the
tests for a cache size other than 0 meaningless.
The new tests create cache entries and fill them with some data that
can be tested against.
2015-10-29 02:28:57 +01:00
Jonas Schürmann
618d9ceabf Fix PEP 257 violation 2015-10-29 00:52:44 +01:00
Jonas Schürmann
ebe9835e5a Remove unused tab on undo 2015-10-29 00:22:54 +01:00
Florian Bruhin
6f07eb562f Revert "Don't use faulthandler plugin for check_coverage."
This reverts commit 497fba5667.
2015-10-28 08:22:41 +01:00
Florian Bruhin
497fba5667 Don't use faulthandler plugin for check_coverage. 2015-10-28 07:45:34 +01:00
meles5
8de3f8d487 Improved script 2015-10-27 22:24:28 +01:00
Florian Bruhin
11098b8b82 Merge branch 'MazeChaZer-feature/duckduckgo.com' 2015-10-27 20:53:42 +01:00
Florian Bruhin
776a89820f Regenerate authors. 2015-10-27 20:53:34 +01:00
Jonas Schürmann
fe32b349a5 Use duckduckgo.com instead of www.duckduckgo.com 2015-10-27 20:31:10 +01:00
Florian Bruhin
8004508b3c wip 2015-10-27 17:57:06 +01:00
Florian Bruhin
9b104b0af7 ci_install: Update installed packages. 2015-10-27 17:54:23 +01:00
Florian Bruhin
a0c2c37a40 travis: Don't pass --required to codecov.
The latest release doesn't support that yet.
2015-10-27 17:54:05 +01:00
Florian Bruhin
02dda23be6 AppVeyor: Really fix codecov. 2015-10-27 17:53:50 +01:00
Florian Bruhin
daaa15396c AppVeyor: Don't use shallow clones.
Otherwise codecov.io won't work.
2015-10-27 17:53:14 +01:00
Florian Bruhin
381d857f2c Revert "Add workarounds for issues with pylint tip."
This reverts commit 1d2683993e.
This causes a bad-option-value issue with the current pylint.
2015-10-26 22:05:21 +01:00
Florian Bruhin
1d2683993e Add workarounds for issues with pylint tip. 2015-10-26 21:20:11 +01:00
Florian Bruhin
66b337c2b1 Add missing superclass init calls. 2015-10-26 21:07:08 +01:00
Florian Bruhin
021a379dd2 Add xfailed test for #1070. 2015-10-26 21:02:34 +01:00
Florian Bruhin
fa671a7b5e Fix codecov on AppVeyor. 2015-10-26 19:38:59 +01:00
Florian Bruhin
7656d1320a tox: Update pytest-travis-fold to 1.1.1. 2015-10-26 18:55:44 +01:00
Florian Bruhin
4fcb2feced tox: Add a pylint-tip testenv. 2015-10-26 18:51:41 +01:00
Florian Bruhin
c85aa40073 Skip connected_socket IPC tests on OS X.
Fixes #1045 - I don't have the time to look into this :-/
2015-10-26 09:04:41 +01:00
Florian Bruhin
c335aff900 Revert "Add pytest-timeout."
This reverts commit 8919a152fe.

Seems to cause more trouble than it's worth... bogus timeouts on OS X and
Windows, with Windows then hanging...
2015-10-26 08:53:55 +01:00
Florian Bruhin
0cdc744afd Try running codecov on AppVeyor. 2015-10-26 08:51:06 +01:00
Florian Bruhin
6f646a9da5 travis: Pass -X gcov --required to codecov. 2015-10-26 08:47:00 +01:00
Florian Bruhin
fc573963f4 Fix lint. 2015-10-26 08:43:55 +01:00
Florian Bruhin
4e48e3d725 ci_install: Only install codecov when needed. 2015-10-26 07:37:20 +01:00
Florian Bruhin
66afdbaf16 travis: Don't run codecov if it's unneeded. 2015-10-26 07:35:29 +01:00
Florian Bruhin
cf623f0d8d ci_install: Also install codecov on OS X. 2015-10-26 07:34:56 +01:00
Florian Bruhin
8919a152fe Add pytest-timeout. 2015-10-26 07:33:32 +01:00
Florian Bruhin
8dc5c95cef tox: Pass TRAVIS to testenvs.
This hopefully makes pytest-travis-fold work correctly.
2015-10-26 07:31:12 +01:00
Florian Bruhin
8fee25491b Merge branch 'jcpetkovich-flexible-hint-filtering' 2015-10-26 07:00:52 +01:00
Florian Bruhin
a1ade58557 Update docs. 2015-10-26 07:00:45 +01:00
Florian Bruhin
68024ba6bd Merge branch 'flexible-hint-filtering' of https://github.com/jcpetkovich/qutebrowser into jcpetkovich-flexible-hint-filtering 2015-10-26 06:59:56 +01:00
Florian Bruhin
883febe243 Return a QColor for qtutils.interpolate_color.
This broke the tests for older PyQt versions because the test had a
test_utils.Color(test_utils.Color(...)) object (double-wrapped), and the
comparisons failed there for some reason.
2015-10-26 06:45:36 +01:00
Florian Bruhin
34cc2870f4 Fix indents in configdata.py. 2015-10-26 06:23:07 +01:00
Jean-Christophe Petkovich
589e8e9d05 Flexible Link Hint Filtering
I think it makes more sense to filter for any text within a link rather
than just the text at the beginning. I've been playing around with this
a little and I like it a lot better.

When using numbers as link hints, It would be awesome if the link hint
strings themselves could also be updated based on how many links are
left, but I'm still figuring out how to do this.

What do you think?
2015-10-25 21:17:48 -04:00
Florian Bruhin
9b3987febb Add some completions for hints -> chars. 2015-10-25 21:22:19 +01:00
Florian Bruhin
bb5e5137cd configtypes: Allow completions for String. 2015-10-25 21:18:06 +01:00
Florian Bruhin
2d4adf4476 doc/userscripts: Clarify how to call userscripts via hints. 2015-10-25 20:12:10 +01:00
Florian Bruhin
eb1a1bbdd8 Use pacman -Suy in doc/stacktrace 2015-10-24 23:04:20 +02:00
Florian Bruhin
08c4bfefe0 Update docs. 2015-10-24 16:04:53 +02:00
Florian Bruhin
f614e5b98a Add none value for colors -> tabs.indicator.system. 2015-10-24 16:01:32 +02:00
Florian Bruhin
857a70ded7 Merge branch 'Kingdread-issue-1015' 2015-10-24 08:08:03 +02:00
Florian Bruhin
343e0b89c0 Regenerate authors. 2015-10-24 08:07:52 +02:00
Florian Bruhin
cdb9c0998f Add a comment for close() call. 2015-10-24 08:07:43 +02:00
Daniel
9722d4ba03 test_tabwidget: Make config_stub explicit
... also call TabWidget.close() at the end of the test.
2015-10-24 01:32:01 +02:00
Daniel
279d0926ee Remove unused import, make pylint happy 2015-10-23 19:52:56 +02:00
Daniel
0851999b89 Add unit/regression test 2015-10-23 19:52:56 +02:00
Daniel
7a413ad6d5 Remove unneeded functions from TabBar.
addTab() and insertTab() are not called and if they were called would
raise an exception (self.set_page_title not defined).
2015-10-23 19:52:56 +02:00
Daniel
8d88dd9d75 Fix crash with small icons
Fixes #1015
2015-10-23 19:52:56 +02:00
Florian Bruhin
bb75cb23b9 Revert "Disable some codecov features."
This reverts commit 3d93413022.
2015-10-23 19:39:17 +02:00
Florian Bruhin
3d93413022 Disable some codecov features. 2015-10-23 19:14:46 +02:00
Florian Bruhin
14334dce21 Don't remove coverage.xml on CI. 2015-10-23 19:14:46 +02:00
Florian Bruhin
023d80fe40 Set source in .coveragerc.
This should make codecov.io pick the right source files up too.
2015-10-23 19:14:46 +02:00
Florian Bruhin
67a0a6b944 Try codecov. 2015-10-23 19:14:46 +02:00
Florian Bruhin
87e94930b5 Run tests verbose on Travis.
Hopefully helps with figuring out what test hangs in #1045.
2015-10-23 07:08:35 +02:00
Lamar Pavel
24887a6564 Adjust coding style based on pylint warnings 2015-10-23 01:49:00 +02:00
Florian Bruhin
de0542929a tox: Update httpbin to 0.4.0.
- New /image/svg endpoint
- add deploy to heroku button
- add 406 response to /image
- don't always emit the transfer-encoding header for stream endpoint.
2015-10-22 22:24:40 +02:00
Florian Bruhin
9482662d7e travis: Pass --faulthandler-timeout. 2015-10-22 06:44:46 +02:00
Lamar Pavel
4a8dec5eb8 Code style; complete first batch of tests. 2015-10-21 22:31:46 +02:00
Lamar Pavel
82c608038d Coding style 2015-10-21 22:31:46 +02:00
Lamar Pavel
0b78fb65c9 Test if cleared cache is actually empty 2015-10-21 22:31:46 +02:00
Lamar Pavel
aa62a547d5 Use tmpdir fixture instead of "/foo/bar" 2015-10-21 22:31:46 +02:00
Lamar Pavel
da800e3fa7 Don't setMaximumCacheSize if there is no cache 2015-10-21 22:31:46 +02:00
Lamar Pavel
a99d3f6525 Add first 3 tests for browser.cache
Note: test_cache_deactivated_private_browsing is currently failing
2015-10-21 22:31:46 +02:00
Florian Bruhin
d9d2366f27 Merge pull request #1042 from meles5/www
Style changes
2015-10-21 20:13:16 +02:00
meles5
81556430c9 Style changes 2015-10-21 19:57:20 +02:00
Florian Bruhin
fabe53564f Add www folder. 2015-10-21 19:48:00 +02:00
Florian Bruhin
aef4f4ed00 Merge branch 'Kingdread-config-timestamp' 2015-10-21 18:27:44 +02:00
Daniel
ef8a681fcc Add TimestampTemplate config type
No more crash when 'completion->timestamp-format' is set to '%'.

Fixes #1039.
2015-10-21 17:23:39 +02:00
Florian Bruhin
daf81f5fcd www: Working website generation. 2015-10-21 07:31:47 +02:00
Florian Bruhin
f6fffee9d3 www: Keep modified sources if building failed. 2015-10-21 07:19:04 +02:00
Florian Bruhin
406b7a7034 Fix wrong image width in README.asciidoc. 2015-10-21 07:18:42 +02:00
Florian Bruhin
4fb374e764 Fix test_run_vulture when frozen. 2015-10-21 06:11:07 +02:00
Florian Bruhin
aba31babca Add some tests for run_vulture.py. 2015-10-20 23:42:01 +02:00
Florian Bruhin
b12cfa9d05 Fix filters in run_vulture.py. 2015-10-20 23:31:46 +02:00
Florian Bruhin
db350719d5 Make run_vulture.py more modular. 2015-10-20 23:25:50 +02:00
Florian Bruhin
4dd3483aca Remove unused import. 2015-10-20 22:49:00 +02:00
Florian Bruhin
4f4dfb1e31 Add arguments to run_vulture.py. 2015-10-20 22:48:01 +02:00
Florian Bruhin
764914a8b2 Clean up cache.DiskCache. 2015-10-20 22:40:43 +02:00
Florian Bruhin
0187dd6ac6 Add get_coredumpct_traces script. 2015-10-20 21:26:53 +02:00
Lamar Pavel
45f9e61815 Fix pylint error (line too long) 2015-10-20 18:17:12 +02:00
Florian Bruhin
2f36789ff4 Revert "travis: Mark OS X as allowed failure for now."
This reverts commit 5499e686e2.
2015-10-20 18:14:27 +02:00
Florian Bruhin
7d026efbfb Revert "travis: Patch PyQt on OS X."
This reverts commit 5fce514168.
2015-10-20 18:14:25 +02:00
Florian Bruhin
e03068ed84 Start adding website features to asciidoc2html. 2015-10-20 18:13:31 +02:00
Lamar Pavel
08bbb6b7c7 Consider new UA script in tox tests
To avoid failing tests tox now includes one of the modules required by
the script and the latter informs pylint to ignore one of the imports.
2015-10-20 17:30:39 +02:00
Lamar Pavel
7703fa217b Add some UAs manually for diversity
The automatically fetched list includes popular user-agents but does not
guarantee any kind of diversity, so there are now a few statically
printed UAs from mobile browsers.
2015-10-20 17:28:22 +02:00
Florian Bruhin
71a150af22 Refactor asciidoc2html.py. 2015-10-20 06:54:43 +02:00
Lamar Pavel
332df99a77 Add docstring to new script 2015-10-20 03:28:27 +02:00
Lamar Pavel
6ebb37aa17 Update UA list and add script to fetch UAs
The script is based on a gist posted by @averrin and has been modified
to print the output according to the format expected by qutebrowser,
ready to be pasted into configtypes.py.
2015-10-20 02:52:11 +02:00
Florian Bruhin
0a40dfced6 tox: Update to pytest-travis-fold to 1.1.0.
- Move auxiliary logic from TravisContext into module-level functions
- Add 'travis' fixture and functions for folding given string/lines
2015-10-19 22:06:50 +02:00
Florian Bruhin
8e0389fd37 tox: Update pytest-html to 1.7.
- Add report sections including stdout and stderr to log.
- Fix INTERNALERROR when an xdist slave crashes.
2015-10-19 19:41:35 +02:00
Florian Bruhin
bd189392a8 tests: Upload junit.xml to AppVeyor. 2015-10-19 17:29:54 +02:00
Florian Bruhin
5fce514168 travis: Patch PyQt on OS X.
This is to circumvent https://github.com/Homebrew/homebrew/issues/45114
The build takes a lot longer now, but at least it works.
2015-10-19 17:29:01 +02:00
Florian Bruhin
7519694e22 tox: Update hypothesis to 1.12.0.
- Significantly improved performance of creating strategies using the functions
  from the hypothesis.strategies module by deferring the calculation of their
  repr until it was needed. This is unlikely to have been an performance issue
  for you unless you were using flatmap, composite or stateful testing, but for
  some cases it could be quite a significant impact.
- A number of cases where the repr of strategies build from lambdas is improved
- Add dates() and times() strategies to hypothesis.extra.datetimes
- Add new 'profiles' mechanism to the settings system
- Deprecates mutability of Settings, both the Settings.default top level
  property and individual settings.
- A Settings object may now be directly initialized from a parent Settings.
- @given should now give a better error message if you attempt to use it with a
  function that uses destructuring arguments (it still won't work, but it will
  error more clearly),
- A number of spelling corrections in error messages
- py.test should no longer display the intermediate modules Hypothesis
  generates when running in verbose mode
- Hypothesis should now correctly handle printing objects with non-ascii reprs
  on python 3 when running in a locale that cannot handle ascii printing to
  stdout.
- Add a unique=True argument to lists(). This is equivalent to unique_by=lambda
  x: x, but offers a more convenient syntax.
2015-10-19 07:35:27 +02:00
Florian Bruhin
5499e686e2 travis: Mark OS X as allowed failure for now.
See https://github.com/Homebrew/homebrew/issues/45114
2015-10-19 06:33:42 +02:00
Florian Bruhin
66e0812ab6 Merge branch 'neeasade-master' 2015-10-19 05:18:43 +02:00
Florian Bruhin
de4ee92b56 Update docs. 2015-10-19 05:18:30 +02:00
Florian Bruhin
9f11990efc Rename scrollbar.padding/scrollbar.width. 2015-10-19 05:15:52 +02:00
Florian Bruhin
4f10e553a8 Merge branch 'master' of https://github.com/neeasade/qutebrowser into neeasade-master 2015-10-18 23:08:05 +02:00
Florian Bruhin
a88962fa98 tox: Update pytest-travis-fold to 1.0.1. 2015-10-18 22:26:25 +02:00
Nathan Isom
d326cc050e correct style string, file modeline. 2015-10-18 14:11:22 -05:00
Nathan Isom
ec3cafc293 resolve merge conflicts and merge branch scrollbar. 2015-10-18 11:42:56 -05:00
Florian Bruhin
9c68a928ea Merge branch 'neeasade-templatemagic' 2015-10-18 18:22:16 +02:00
Florian Bruhin
86ee53a7e6 Regenerate authors. 2015-10-18 18:22:09 +02:00
Florian Bruhin
82dfec6a18 Merge branch 'templatemagic' of https://github.com/neeasade/qutebrowser into neeasade-templatemagic 2015-10-18 18:20:41 +02:00
Nathan Isom
e92a7495c4 keep bg/fg test. 2015-10-18 10:41:15 -05:00
Nathan Isom
9b5c0075b9 Move min-height to correctly fix bug, edit colors to match https://github.com/The-Compiler/qutebrowser/pull/1021. 2015-10-17 19:31:47 -05:00
Nathan Isom
f1b9a3408f Remove fontdict test, edit register stylesheet test to match new font result. 2015-10-17 19:23:48 -05:00
Florian Bruhin
d862821552 Merge branch 'meles5-jinja' 2015-10-17 19:05:26 +02:00
Florian Bruhin
c29562d769 Regenerate authors. 2015-10-17 19:05:15 +02:00
Florian Bruhin
b22fbe3993 Update changelog. 2015-10-17 19:05:03 +02:00
Florian Bruhin
c8346a11fc Merge branch 'jinja' of https://github.com/meles5/qutebrowser into meles5-jinja 2015-10-17 19:04:36 +02:00
meles5
78c57ad416 Fixed AppVeyor test 2015-10-17 18:43:14 +02:00
meles5
2398762e85 Fix tests 2015-10-17 18:29:13 +02:00
meles5
ff4c002096 A few changes 2015-10-17 17:33:05 +02:00
Nathan Isom
6391da4f6f Forgot font changes. 2015-10-16 12:02:57 -05:00
Nathan Isom
b18549bbed Remove fontdict wrapper 2015-10-16 11:42:46 -05:00
Florian Bruhin
0400945ac4 Raise exception when a stylesheet is unparsable. 2015-10-16 18:26:34 +02:00
Nathan Isom
869e2d9127 missed one. 2015-10-16 11:18:25 -05:00
Nathan Isom
9b8b2130ef remove deprecated test. 2015-10-16 10:59:02 -05:00
Nathan Isom
09b18fbc68 edit colordict to match. 2015-10-16 10:55:17 -05:00
Nathan Isom
2a11adc8ac initial replace pass. 2015-10-16 10:52:02 -05:00
Nathan Isom
27db1ad891 fix scrollbar not showing up error, change test_get_stylesheet a bit. 2015-10-16 09:56:31 -05:00
Florian Bruhin
743c3b1e26 Fix broken UrlType member. 2015-10-16 06:53:07 +02:00
Florian Bruhin
24dc166e1f tests: Use extend=True for qt_log_ignore marks.
This should finally resolve the warning flakiness on OS X.
2015-10-16 06:24:29 +02:00
Florian Bruhin
71e6c38065 tox: Update to pytest-qt 1.8.0.
- pytest.mark.qt_log_ignore now supports an extend parameter that will extend
  the list of regexes used to ignore Qt messages (defaults to False).

- Fixed internal error when interacting with other plugins that raise an error,
  hiding the original exception.
2015-10-16 06:20:07 +02:00
Florian Bruhin
4bb1a37cf1 Rename travis fold name. 2015-10-15 22:22:28 +02:00
Florian Bruhin
309be9b057 Use travis_fold on ci_install.py. 2015-10-15 21:46:24 +02:00
Florian Bruhin
619f47ee1d tox: Add pytest-travis-fold 2015-10-15 21:40:17 +02:00
Nathan Isom
57d8ebfb83 not hardcode width/padding values. 2015-10-15 14:06:16 -05:00
Nathan Isom
19c27a04e5 Add completion scrollbar settings. 2015-10-15 13:18:32 -05:00
Nathan Isom
0e186487f5 Revert "Don't pass config to stylesheets."
This reverts commit dc0e8b4626.
2015-10-15 12:36:24 -05:00
Florian Bruhin
ebd576d98f Merge branch 'neeasade-url-color' 2015-10-15 18:35:56 +02:00
Florian Bruhin
5c85dd22b4 Update docs and changelog. 2015-10-15 18:34:56 +02:00
Florian Bruhin
91ce3ed672 Merge branch 'url-color' of https://github.com/neeasade/qutebrowser into neeasade-url-color 2015-10-15 18:32:47 +02:00
meles5
326757917c Fixed windows support (Windows test couldn't work) 2015-10-15 17:39:31 +02:00
Florian Bruhin
5f8ea6dc16 Use the official way to get Trusty on Travis.
See http://blog.travis-ci.com/2015-10-14-opening-up-ubuntu-trusty-beta/
2015-10-15 08:22:21 +02:00
Florian Bruhin
e6ee0c08cf testprocess: Restart process when it quits. 2015-10-14 21:52:11 +02:00
Florian Bruhin
f858af666f testprocess: Get executable/args from subclasses. 2015-10-14 21:52:11 +02:00
Nathan Isom
6843e9c413 typo in configdata.py. 2015-10-14 13:37:24 -05:00
Nathan Isom
4876bdf7ce style. 2015-10-14 13:34:41 -05:00
Nathan Isom
e78b00cce2 Fix configdata.py typos, use scheme from url. 2015-10-14 13:22:28 -05:00
Nathan Isom
d7d4c232d0 Initial shot at issue #691 2015-10-14 13:10:24 -05:00
Florian Bruhin
26596316c6 Pin some more dependencies in tox.ini.
This hard-pins everything except for the main [testenv].
2015-10-14 18:28:39 +02:00
Florian Bruhin
ab099ea6ea Fix another spelling mistake. 2015-10-14 07:02:50 +02:00
Florian Bruhin
36b7db0672 Regenerate authors. 2015-10-14 07:02:14 +02:00
Florian Bruhin
62fa2811e3 Merge branch 'master' of https://github.com/shaggytwodope/qutebrowser 2015-10-14 07:02:04 +02:00
Florian Bruhin
d3925e91a3 tox: Update coverage to 4.0.1.
- When combining data files, unreadable files will now generate a warning
  instead of failing the command.  This is more in line with the older
  coverage.py v3.7.1 behavior, which silently ignored unreadable files.

- The --skip-covered option would skip reporting on 100% covered files, but
  also skipped them when calculating total coverage.  This was wrong, it should
  only remove lines from the report, not change the final answer.  This is now
  fixed.

- In 4.0, the data file recorded a summary of the system on which it was run.
  Combined data files would keep all of those summaries.  This could lead to
  enormous data files consisting of mostly repetitive useless information. That
  summary is now gone.  If you want summary information,
  get in touch, and we'll figure out a better way to do it.

- Test suites that mocked os.path.exists would experience strange failures, due
  to coverage.py using their mock inadvertently.  This is now fixed.

- Importing a ``__init__`` module explicitly would lead to an error:
  ``AttributeError: 'module' object has no attribute '__path__'``.  This is now
  fixed.

- Code that uses ``sys.settrace(sys.gettrace())`` used to incur a more than 2x
  speed penalty.  Now there's no penalty at all.

- Pyexpat C code will no longer be recorded as a source file.

- The source kit now contains all of the files needed to have a complete source
  tree.
2015-10-14 07:00:40 +02:00
Florian Bruhin
67ecd93326 Spell-check committing and existent. 2015-10-14 06:56:13 +02:00
John ShaggyTwoDope Jenkins
65418307fd typos 2015-10-13 16:09:49 -07:00
Florian Bruhin
28a28763c7 tox: Update logilab-common to 1.1.0.
* configuration: have a stable order for sections
* testlib: clean out deprecated TestCase methods, move pytest specifics to pytest.py
* fix a few python3 bugs in umessage, configuration and optik_ext modules
* testlib: report failures and skips in generative tests properly
* optik_ext: return bytes as ints and not floats
2015-10-12 19:06:49 +02:00
Florian Bruhin
f8ad011a32 tox: Update pytest-sugar to 0.5.1.
- Colour progressbar correctly for low number of tests
- Fix error case when deactivating pytest-sugar using --lf together with
  --nosugar
- --nosugar deprecated, use -p no:sugar
2015-10-12 19:05:59 +02:00
Florian Bruhin
294eb19e61 Fix tests/integration/webserver.py when frozen. 2015-10-10 17:41:27 +02:00
Florian Bruhin
3e9088083f Raise correct InvalidLine exception. 2015-10-10 17:29:23 +02:00
Florian Bruhin
904b7b202e Merge branch 'antoyo-bug/bookmark-click-delete' 2015-10-10 17:23:05 +02:00
Florian Bruhin
18e52922c1 Update changelog. 2015-10-10 17:22:52 +02:00
Florian Bruhin
893df967df Merge branch 'bug/bookmark-click-delete' of https://github.com/antoyo/qutebrowser into antoyo-bug/bookmark-click-delete 2015-10-10 17:21:27 +02:00
Florian Bruhin
2f075c382b Move out test process handling to its own file. 2015-10-10 17:20:20 +02:00
Antoni Boucher
1acd32f697 Fixed issue #1008. 2015-10-10 11:16:06 -04:00
Florian Bruhin
9c0ef87a62 tox: Update pep257 to 0.7.0.
Upstream changelog:

New Features

- Added the D104 error code - "Missing docstring in public package". This new
  error is turned on by default. Missing docstring in __init__.py files which
  previously resulted in D100 errors ("Missing docstring in public module")
  will now result in D104.

- Added the D105 error code - "Missing docstring in magic method'. This new
  error is turned on by default. Missing docstrings in magic method which
  previously resulted in D102 error ("Missing docstring in public method") will
  now result in D105. Note that exceptions to this rule are variadic magic
  methods - specifically __init__, __call__ and __new__, which will be
  considered non-magic and missing docstrings in them will result in D102.

- Support the option to exclude all error codes. Running pep257 with --select=
  (or select= in the configuration file) will exclude all errors which could
  then be added one by one using add-select. Useful for projects new to pep257.

- Added check D211: No blank lines allowed before class docstring. This change
  is a result of a change to the official PEP257 convention. Therefore, D211
  will now be checked by default instead of D203, which required a single blank
  line before a class docstring.

- Configuration files are now handled correctly. The closer a configuration
  file is to a checked file the more it matters. Configuration files no longer
  support explain, source, debug, verbose or count.

Bug Fixes

- On Python 2.x, D302 ("Use u""" for Unicode docstrings") is not reported if
  unicode_literals is imported from __future__.

- Fixed a bug where there was no executable for pep257 on Windows.
2015-10-10 13:10:13 +02:00
Florian Bruhin
4f2dbb3a72 Don't show icons when cloning tabs if turned off.
Fixes #1007.
2015-10-10 12:48:45 +02:00
Florian Bruhin
d0be9256b5 Update changelog. 2015-10-08 10:49:12 +02:00
Florian Bruhin
b5dc9d485d Regenerate docs. 2015-10-08 10:47:52 +02:00
Florian Bruhin
749d7bfc3c Add backticks to docs. 2015-10-08 10:47:36 +02:00
Florian Bruhin
2c8aa26c93 Merge branch 'master' of https://github.com/pemic/qutebrowser into pemic-master 2015-10-08 10:39:33 +02:00
Florian Bruhin
93a64a4ae5 Don't pass tests/ argument on AppVeyor.
This breaks unittests-frozen as the tests aren't actually in that dir anymore.
2015-10-08 10:19:24 +02:00
Peter Michely
bfccb91e42 Changed code and docs according to comments 2015-10-08 10:13:47 +02:00
Florian Bruhin
20bd1cc5fd Fix tests with 'DISPLAY='. 2015-10-08 06:36:38 +02:00
Florian Bruhin
ffab11c871 Install tox for eslint on Travis. 2015-10-08 06:24:31 +02:00
Florian Bruhin
661f7cde92 Run eslint via tox.
This makes the .travis.yml simpler again and fixes the fact that the exit
status of a command was ignored because of the "|| true".
2015-10-08 06:12:46 +02:00
Peter Michely
10f4798559 Fixed whitespace errors 2015-10-08 01:10:44 +02:00
Peter Michely
6be5c65c36 Fixed issue #943 and changed the docs accordingly 2015-10-07 23:53:21 +02:00
Florian Bruhin
224ab3237d Fix .travis.yml syntax. 2015-10-07 23:14:03 +02:00
Florian Bruhin
0960f229f0 Get rid of ci_run.py again. 2015-10-07 23:12:33 +02:00
Florian Bruhin
fb9e3639d0 Disable pytest-sugar properly for AppVeyor. 2015-10-07 23:09:30 +02:00
Florian Bruhin
0845671165 Start Xvfb for CI from tests. 2015-10-07 23:05:39 +02:00
Florian Bruhin
94d88e280b tox: Add pytest-sugar.
Nicer test output FTW!
2015-10-07 22:13:22 +02:00
Florian Bruhin
c2ea2aa6d7 Remove unused import. 2015-10-07 22:05:22 +02:00
Florian Bruhin
129df05932 ipc: Skip socketOptions test on Qt < 5.4. 2015-10-07 22:04:30 +02:00
Florian Bruhin
a5df7675eb requirements.txt: Update pyPEG2 to 2.15.2. 2015-10-07 21:53:13 +02:00
Florian Bruhin
7db1f65425 ipc: Avoid using QLocalServer.setSocketOptions.
This causes problems with AddressInUseError being swallowed.

Fixes #997.
2015-10-07 21:52:09 +02:00
Florian Bruhin
2e46efccdc tox: Update pytest to 2.8.2. 2015-10-07 18:14:56 +02:00
Florian Bruhin
2918f33569 Include xvfbwrapper when freezing tests. 2015-10-07 17:06:19 +02:00
Florian Bruhin
52ced6c652 Start Xvfb for tests.
Fixes #851.
2015-10-07 16:54:46 +02:00
Florian Bruhin
b0671ef530 tox: Don't add --faulthandler-timeout to pytest.
This breaks the tests on Windows currently:

https://github.com/pytest-dev/pytest-faulthandler/issues/8
2015-10-07 07:01:03 +02:00
Florian Bruhin
3153f69945 tox: Add pytest-faulthandler for main testenv. 2015-10-07 06:43:50 +02:00
Florian Bruhin
5ecd935ee3 tox: Update six to 1.10.0.
Upstream changelog:

- Improve the performance of `six.int2byte` on Python 3.
- Don't add the `winreg` module to `six.moves` on non-Windows platforms.
- Add `six.moves.getcwd` and `six.moves.getcwdu`.
- Add `create_unbound_method` to create unbound methods.
2015-10-07 06:39:08 +02:00
Florian Bruhin
6d117eac6a Update changelog. 2015-10-07 06:37:36 +02:00
Florian Bruhin
2f6d0083d6 Merge branch 'MazeChaZer-feature/target-flag' 2015-10-07 06:24:01 +02:00
Florian Bruhin
7e25d30814 Regenerate docs. 2015-10-07 06:23:49 +02:00
Florian Bruhin
424809b120 Merge branch 'feature/target-flag' of https://github.com/MazeChaZer/qutebrowser into MazeChaZer-feature/target-flag 2015-10-07 06:22:29 +02:00
Jonas Schürmann
1e8170d98b Fixed lines which were too long 2015-10-06 23:18:04 +02:00
Jonas Schürmann
afc166a13e Coding style fixes #1002 2015-10-06 22:59:49 +02:00
Florian Bruhin
7e2ae9f39f Also install nodejs-legacy on Travis.
This is needed to get /usr/bin/node which npm/eslint seem to use.
2015-10-06 07:32:22 +02:00
Florian Bruhin
bdff26a024 tox: Run py35 testenv by default. 2015-10-06 07:10:32 +02:00
Florian Bruhin
439c00f32a Run eslint on Travis.
See #773.
2015-10-06 07:10:32 +02:00
Florian Bruhin
d094a495cc Avoid apt-get on Travis if possible.
This should speed up builds as no apt-get update is needed.
2015-10-06 07:10:32 +02:00
Florian Bruhin
98e451c90e Install vulture for pylint testenv. 2015-10-06 07:10:32 +02:00
Florian Bruhin
d9018fed14 Don't install python-dev packages on Travis.
Those don't seem to be needed anymore.
2015-10-06 07:10:32 +02:00
Florian Bruhin
f79db832e4 Parallelize tests on AppVeyor. 2015-10-06 07:10:32 +02:00
Florian Bruhin
aa9498bb41 Add separate testenv for vulture. 2015-10-06 07:10:32 +02:00
Florian Bruhin
d7ca469d08 tox: Don't link pyqt for pyroma/check-manifest. 2015-10-06 07:10:32 +02:00
Florian Bruhin
4b2e0470c8 Parallelize test runs on Travis. 2015-10-06 07:10:32 +02:00
Florian Bruhin
5e958faf29 Add --noconftest flags for some testenvs. 2015-10-06 07:10:32 +02:00
Florian Bruhin
bc26592bb7 tox: Update some environments to pytest 2.8.1.
This works for everything except the main environment which is blocked on the
pytest-catchlog fix.
2015-10-06 07:10:32 +02:00
Florian Bruhin
04619e0f81 Run Python 3.5 on OS X and get rid of Xvfb wrapper. 2015-10-06 07:10:32 +02:00
Florian Bruhin
0a3844a3be tox: Don't set basepython for [testenv].
Otherwise this'd override basepython for any testenv (py34/py35) to use the
installed /usr/bin/python3.

Closes #1001.
2015-10-06 07:10:32 +02:00
Florian Bruhin
fda477397e Get rid of py34-integration testenv.
Fixes #1000.
2015-10-06 07:10:32 +02:00
Jonas Schürmann
45c9768c16 Added --target command line argument #922
This argument is used to override the new-instance-open-target config
option.
2015-10-05 21:15:52 +02:00
Florian Bruhin
228b4104b0 tests: Ignore type conversion messages. 2015-10-05 08:22:53 +02:00
Florian Bruhin
cabbe406e3 tests: Fix ignoring of "load glyph failed" message.
The mark seems to be swallowed somehow when it's after @hypothesis.given.

See https://github.com/DRMacIver/hypothesis/issues/189
2015-10-05 08:11:26 +02:00
Florian Bruhin
54557fee20 Fix lint. 2015-10-05 06:53:56 +02:00
Florian Bruhin
17778f1457 Prevent :restart when there's a SyntaxError.
Closes #910.
2015-10-04 23:24:35 +02:00
Florian Bruhin
6293842c18 Run vulture in misc testenv.
Closes #973.
2015-10-04 23:04:09 +02:00
Florian Bruhin
b6f3b1951e Remove more dead code. 2015-10-04 22:21:49 +02:00
Florian Bruhin
bff93ff00a Adjust release docs. 2015-10-04 21:15:23 +02:00
Florian Bruhin
03754b360a Release v0.4.1. 2015-10-04 21:14:45 +02:00
Florian Bruhin
005753e83e Remove some dead code.
See #973.
2015-10-04 20:43:29 +02:00
Florian Bruhin
f4fdcbdd71 Add a --check-all to check_coverage.py. 2015-10-04 20:35:24 +02:00
Florian Bruhin
54ae1582af Make check_coverage work when called with a file. 2015-10-04 19:36:26 +02:00
Florian Bruhin
55efd1358b Work around coverage.py bug in test_check_coverage.
Fixes #981.
See https://bitbucket.org/ned/coveragepy/issues/422/
2015-10-04 18:33:37 +02:00
Florian Bruhin
12a11a5931 Revert "Remove colors -> tabs.bg.bar setting."
This reverts commit 801d2ae8e6.

This is still useful/needed for vertical tab bars.
2015-10-04 17:49:52 +02:00
Florian Bruhin
f607659ece Revert "Update changelog."
This reverts commit a2c94e448e.
2015-10-04 17:49:36 +02:00
Florian Bruhin
252abc8954 Update changelog. 2015-10-04 17:13:39 +02:00
Florian Bruhin
83a75bd263 Merge branch 'Kingdread-incdec-setting' 2015-10-04 17:12:46 +02:00
Florian Bruhin
4600832eb6 Regenerate authors. 2015-10-04 17:12:36 +02:00
Florian Bruhin
de49e5f0a5 Use 'is None' to compare to None. 2015-10-04 17:05:24 +02:00
Florian Bruhin
7ff881c3e3 Merge branch 'incdec-setting' of https://github.com/Kingdread/qutebrowser into Kingdread-incdec-setting 2015-10-04 17:04:40 +02:00
Florian Bruhin
6a4785ec3a Merge branch 'daniel-lawrence-lu-master' 2015-10-04 16:56:37 +02:00
Florian Bruhin
a2c94e448e Update changelog. 2015-10-04 16:35:40 +02:00
Florian Bruhin
c6c34c4ac5 Regenerate authors. 2015-10-04 16:34:44 +02:00
Florian Bruhin
801d2ae8e6 Remove colors -> tabs.bg.bar setting.
This isn't needed anymore after the recent tab width fix, as the tabbar color
is invisible now.
2015-10-04 16:32:45 +02:00
Florian Bruhin
fbf6696e2a Merge branch 'master' of https://github.com/daniel-lawrence-lu/qutebrowser into daniel-lawrence-lu-master 2015-10-04 16:30:17 +02:00
Florian Bruhin
89e0b96bb6 tox: Update pytest-cov to 2.2.0.
Upstream changelog:

* Added support for changing working directory in tests. Previously changing
  working directory would disable coverage measurements in suprocesses.
* Fixed broken handling for ``--cov-report=annotate``.
2015-10-04 15:50:34 +02:00
Florian Bruhin
d229e90724 Fix some splelling mistakes. 2015-10-04 15:41:42 +02:00
Florian Bruhin
0b4dc12869 Use basepython = python3.4 for pylint.
This means users will need PyQt5/sip compiled for Python 3.4, but that's
certainly better than pylint not working at all.
2015-10-04 14:31:54 +02:00
Daniel Lu
de5308cbbf removes leftover space in tab bar when the window width is not divisible by the number of tabs 2015-10-02 23:24:44 -04:00
Florian Bruhin
739d2cfffd Fix displaying of web history if limited to -1.
This is a regression introduced in 2aa7e5bb35.
Fixes #991.
2015-10-02 22:56:18 +02:00
Daniel
73ba3ddaee Add all possible combinations to FlagList.complete 2015-10-02 18:53:03 +02:00
Daniel
f12fbe875e Use a two-digit number for incdec tests 2015-10-02 11:44:54 +02:00
Florian Bruhin
7761dd5af4 configtypes: Disallow ValidValues without values. 2015-10-02 11:37:41 +02:00
Daniel
c78f83e692 Add port numbers to incdec_number tests 2015-10-02 11:27:56 +02:00
Florian Bruhin
b863c9807b Fix warning pattern, take two. 2015-10-02 10:59:11 +02:00
Florian Bruhin
8cdbd2a15f Fix pattern for QSslSocketBackendPrivate warning. 2015-10-02 10:47:44 +02:00
Florian Bruhin
2c719006cf tests: Fix skipping with multiple platform markers. 2015-10-02 10:39:21 +02:00
Florian Bruhin
240e271b0d tests: Translate platform markers to skipif marks.
This means pytest shows the correct location and the marks work correctly when
marking individual items in a parametrize marker.
2015-10-02 09:26:33 +02:00
Florian Bruhin
18bd20e109 Skip test_ipc:test_timeout on OS X.
It almost always causes issues and I have no idea why... Let's skip it for now.

Fixes #975.
2015-10-02 08:52:51 +02:00
Florian Bruhin
b88a22b139 tests: Add a not_osx platform marker. 2015-10-02 08:51:40 +02:00
Florian Bruhin
9f7836131d tests: Add a reason argument to platform markers. 2015-10-02 08:51:22 +02:00
Florian Bruhin
b42b12b7a5 Fix ipc.py coverage. 2015-10-02 08:17:50 +02:00
Florian Bruhin
454b2348a8 ipc: Actually use CONNECT_TIMEOUT. 2015-10-02 08:11:37 +02:00
Florian Bruhin
ea663f9975 IPC: Handle socket timeout correctly.
Hopefully fixes #975.
2015-10-02 08:11:26 +02:00
Florian Bruhin
264f9c4919 Mention Linux Mint version needed. 2015-10-02 08:03:10 +02:00
Florian Bruhin
afa7a1a9a0 Remove broken margin-left for progress bar.
Closes #125 (by obsoleting it).
2015-10-02 08:03:10 +02:00
Florian Bruhin
5c52d4d04e Fix TestGitStrSubprocess.test_real_git on Windows.
Fixes #939.
2015-10-02 07:36:06 +02:00
Florian Bruhin
93ed853c36 Fix tests on Xvfb.
Fixes #984.
2015-10-02 07:07:38 +02:00
Florian Bruhin
d6301beb2a Improve configtypes.Regex tests and docs. 2015-10-01 23:24:27 +02:00
Florian Bruhin
16ac3baf2e configtypes: Handle invalid escapes in regexes. 2015-10-01 23:11:48 +02:00
Florian Bruhin
e4a216e7cf configtypes: Refactor regex validation. 2015-10-01 22:29:24 +02:00
Florian Bruhin
8e52e5f2fc Don't use deprecated logging calls. 2015-10-01 21:39:42 +02:00
Florian Bruhin
65891c6f0d Fail tests on Python warnings.
Fixes #982.
2015-10-01 21:34:00 +02:00
Daniel
c9a959043b Smarter tests for incdec_number
Now we generate possible combinations automatically instead of listing
several example values by hand.
2015-10-01 21:27:05 +02:00
Daniel
8228a96180 Stylistic changes, more testing for incdec 2015-10-01 20:57:08 +02:00
Florian Bruhin
f552f433f8 Rename stupidly named test. 2015-10-01 18:58:45 +02:00
Florian Bruhin
0b4cee420f Merge same authors and regenerate authors. 2015-10-01 18:25:46 +02:00
Florian Bruhin
f16cc5986c Merge branch 'averrin-crash_report' 2015-10-01 18:23:41 +02:00
Florian Bruhin
37e5a46808 Merge branch 'crash_report' of https://github.com/averrin/qutebrowser into averrin-crash_report 2015-10-01 18:23:04 +02:00
Florian Bruhin
d849cd42e5 Merge branch 'andybalaam-note-source-highlight-dependency' 2015-10-01 18:21:45 +02:00
Florian Bruhin
f7d49f29b7 Update authors. 2015-10-01 18:21:37 +02:00
Andy Balaam
c989351b14 Document the need for source-highlight to be installed for asciidoc2html to work fully. 2015-10-01 15:44:18 +01:00
Alexey Nabrodov
293c9f1022 trying to fix tests 2 2015-10-01 16:34:34 +03:00
Alexey Nabrodov
044c0a0c4f trying to fix tests 2015-10-01 16:26:56 +03:00
Alexey Nabrodov
54d4f4f48b refactor and test 2015-10-01 15:57:11 +03:00
Alexey Nabrodov
ce9aafdc1b why???? 2015-10-01 14:15:32 +03:00
Alexey Nabrodov
be332fe723 init env vars in crash report 2015-10-01 14:11:35 +03:00
Daniel
4881d81444 Add new configtype: FlagList
This class contains validation code shared by ConfirmQuit and
URLSegmentList, that is it checks for duplicate values and compares
each value to valid_values.
2015-10-01 00:40:21 +02:00
Florian Bruhin
ab6390b44e Fix changelog for v0.4.1. 2015-09-30 22:18:45 +02:00
Florian Bruhin
7c72929af4 Update changelog. 2015-09-30 22:16:25 +02:00
Florian Bruhin
57abd53e56 Regenerate docs. 2015-09-30 21:32:48 +02:00
Florian Bruhin
ae3497a3a1 Remove unnecessary str(). 2015-09-30 21:26:41 +02:00
Daniel
bc631d7d8b Fix configtypes test coverage 2015-09-30 21:17:27 +02:00
Florian Bruhin
7fcbbc98f6 Merge branch 'scroll_in_title' of https://github.com/averrin/qutebrowser into averrin-scroll_in_title 2015-09-30 21:16:36 +02:00
Daniel
bed90d1319 Regenerate settings.asciidoc 2015-09-30 19:49:17 +02:00
Daniel
1bdb012b2c Add a config option for navigate_incdec
Also known as Ctrl-A/Ctrl-X. You can now specify which parts of the URL
should be searched for numbers.

The setting is general->url-incdec-segments and it's a set with valid
values of 'host', 'path', 'query' and 'anchor'.
2015-09-30 19:18:00 +02:00
Florian Bruhin
eb662a2468 Update changelog. 2015-09-30 07:34:15 +02:00
Florian Bruhin
f972d043c5 Fix StopIteration handling in _init_late_modules.
This caused a PendingDeprecationWarning with Python 3.5:

Traceback (most recent call last):
  File "/home/florian/proj/qutebrowser/git/qutebrowser/utils/debug.py", line 237, in log_time
    yield
  File "/home/florian/proj/qutebrowser/git/qutebrowser/app.py", line 433, in _init_late_modules
    next(reader)
StopIteration

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/florian/proj/qutebrowser/git/qutebrowser/app.py", line 433, in _init_late_modules
    next(reader)
  File "/usr/lib64/python3.5/contextlib.py", line 77, in __exit__
    self.gen.throw(type, value, traceback)
PendingDeprecationWarning: generator 'log_time' raised StopIteration
2015-09-30 07:32:36 +02:00
Florian Bruhin
07c02041fc Update changelog. 2015-09-30 06:46:09 +02:00
Florian Bruhin
edc74657ad Revert accidental basepython change in tox.ini. 2015-09-30 06:37:00 +02:00
Florian Bruhin
985c067f90 tests: Ignore another SSL Qt warning on OS X. 2015-09-29 21:31:00 +02:00
Florian Bruhin
b82772ca4c Merge branch 'neeasade-issue-#977' 2015-09-29 21:24:45 +02:00
Florian Bruhin
14ca66f20e Update authors. 2015-09-29 21:24:38 +02:00
Florian Bruhin
637133f39f Merge branch 'issue-#977' of https://github.com/neeasade/qutebrowser into neeasade-issue-#977 2015-09-29 21:24:28 +02:00
Florian Bruhin
a164eee1ba Hide skip output for unittests-nodisp env. 2015-09-29 21:07:00 +02:00
neeasade
2e62d24062 Empty osver for linux, adjust test to match this. 2015-09-29 13:59:22 -05:00
neeasade
ddeabc6643 Change dist() call in unit test. 2015-09-29 13:15:48 -05:00
neeasade
b5ec476ca6 Fixes #977 with none deprecated call. 2015-09-29 12:56:49 -05:00
Alexey Nabrodov
75d53e2879 and again 2015-09-29 12:19:47 +03:00
Alexey Nabrodov
a98878dd8a fix unused coords 2015-09-29 12:07:35 +03:00
Florian Bruhin
11961db72c Add maxlen argument to ErrorNetworkReply.readData.
This was missing before, causing a (hidden) exception with Python < 3.5, and
this with 3.5:

    TypeError: readData() takes 1 positional argument but 2 were given

    During handling of the above exception, another exception occurred:

    SystemError: PyEval_EvalFrameEx returned a result with an error set

Fixes #969.
2015-09-29 08:41:20 +02:00
Florian Bruhin
5db4ed0ed1 Add fallback argument to ConfigManager.get.
This is needed for interpolation since this change in Python 3.4:

https://hg.python.org/cpython/rev/267422f7c927

This broke qutebrowser in Debian experimental when updating python from
3.4.3-8 to 3.4.3-9 as they pulled from hg.

Fixes #968.
2015-09-29 08:22:33 +02:00
Florian Bruhin
bb9bd40f6b tox: Update pytest-mock to 0.8.1.
- mock.ANY is also accessible from the mocker fixture
- pytest-mock is now also available as a wheel.
2015-09-29 07:00:18 +02:00
Florian Bruhin
9846011ca7 tox: Update beautifulsoup to 4.4.1.
Upstream changelog:

* Fixed a bug that deranged the tree when part of it was
  removed. Thanks to Eric Weiser for the patch and John Wiseman for a
  test.

* Fixed a parse bug with the html5lib tree-builder. Thanks to Roel
  Kramer for the patch.

* Improved the implementation of CSS selector grouping. Thanks to
  Orangain for the patch.

* Fixed the test_detect_utf8 test so that it works when chardet is
  installed.

* Corrected the output of Declaration objects.
2015-09-29 06:58:37 +02:00
Florian Bruhin
866017f9c1 Pass --verbose to Homebrew.
The homebrew progress bars cause Travis to bail out because the 4MB maximum log
size was reached. Ironically, that does not happen with --verbose.
2015-09-29 06:54:14 +02:00
Florian Bruhin
590caa53f5 Skip some tox environments on OS X. 2015-09-29 06:54:11 +02:00
Florian Bruhin
2cfc1361b5 Merge branch 'travis-docker' 2015-09-28 22:23:58 +02:00
Florian Bruhin
1e5028a7f3 Allow unittests-nodisp to run w/o DISPLAY on CI. 2015-09-28 22:19:33 +02:00
Florian Bruhin
2500b1f759 Add a unittests-nodisp environment. 2015-09-28 21:55:35 +02:00
Florian Bruhin
4854ca42fd Fix tests without DISPLAY. 2015-09-28 21:50:55 +02:00
Florian Bruhin
1861b0a5e4 Don't skip all tests without DISPLAY set.
We used qapp in a session scoped fixture, which means testing without DISPLAY
skipped all tests.
2015-09-28 21:50:44 +02:00
Alexey Nabrodov
7cd7b43e7a fix docs 2015-09-28 19:53:55 +03:00
Alexey Nabrodov
1b6860b748 add scroll_pos to window title && fix signals 2015-09-28 19:43:50 +03:00
Florian Bruhin
88caa1a8c8 Merge branch 'Kingdread-configtypes-tests' 2015-09-28 15:18:04 +02:00
Florian Bruhin
3789a37f5b Regenerate authors. 2015-09-28 15:15:53 +02:00
Daniel
3e2985d776 Add tests for RegexEq
...also fix a small typo in RegexEq's comment.
2015-09-28 14:58:00 +02:00
Daniel
05bcddb6f9 Use RegexEq in configtypes tests
This prevents the tests from failing if the regex cache overflows,
since re.compile objects compare by identitiy instead of patterns.
2015-09-28 14:24:36 +02:00
Florian Bruhin
43a42def2b tox: Update hypothesis to 1.11.4.
- Hide modifications Hypothesis needs to make to sys.path by undoing them after
  we've imported the relevant modules. This is a workaround for issues
  cryptography experienced on windows.
- Slightly improved performance of drawing from sampled_from on large lists of
  alternatives.
- Significantly improved performance of drawing from one_of or strategies using
  | (note this includes a lot of strategies internally - floats() and
  integers() both fall into this category). There turned out to be a massive
  performance regression introduced in 1.10.0 affecting these which probably
  would have made tests using Hypothesis significantly slower than they should
  have been.
2015-09-27 20:51:36 +02:00
meles5
4fa2f34af4 Test for AppVeyor updated 2015-09-25 18:51:07 +02:00
meles5
d7dd1b3507 Windows support useless 2015-09-25 18:39:15 +02:00
meles5
fc7488645f The resource_url() function should now support Windows 2015-09-25 18:21:04 +02:00
Alexey Nabrodov
717298e423 add scroll_pos to title-format 2015-09-25 19:14:52 +03:00
meles5
8bcc0e4b92 filescheme.py & dirbrowser.html updated 2015-09-25 14:49:03 +02:00
meles5
70597d574f Added resource_url() function and used this function in the error page 2015-09-25 14:31:04 +02:00
Florian Bruhin
a6ceab5dbc Fix pip executable name for OS X. 2015-09-24 08:53:20 +02:00
Florian Bruhin
2940a4267b Work around Travis issue with OS X. 2015-09-24 08:47:54 +02:00
Florian Bruhin
0de1e40f20 Add filescheme test for names with special chars.
Inspired by https://github.com/QupZilla/qupzilla/pull/1711
2015-09-24 06:45:33 +02:00
Florian Bruhin
a9144cdd21 tox: Update hypothesis to 1.11.3
- Better argument validation for datetimes() strategy - previously setting
  max_year < datetime.MIN_YEAR or min_year > datetime.MAX_YEAR would not have
  raised an InvalidArgument error and instead would have behaved confusingly.
- Compatibility with being run on pytest < 2.7 (achieved by disabling the
  plugin).
2015-09-23 19:08:30 +02:00
Florian Bruhin
a76d9a5914 tox: Update hypothesis to 1.11.2.
Bug fixes:

- Settings(database=my_db) would not be correctly inherited when used as a
  default setting, so that newly created settings would use the database_file
  setting and create an SQLite example database.
- Settings.default.database = my_db would previously have raised an error and
  now works.
- Timeout could sometimes be significantly exceeded if during simplification
  there were a lot of examples tried that didn't trigger the bug.
- When loading a heavily simplified example using a basic() strategy from the
  database this could cause Python to trigger a recursion error.
- Remove use of deprecated API in pytest plugin so as to not emit warning

Misc:

- hypothesis-pytest is now part of hypothesis core. This should have no
  externally visible consequences, but you should update your dependencies to
  remove hypothesis-pytest and depend on only Hypothesis.
- Better repr for hypothesis.extra.datetimes() strategies.
- Add .close() method to abstract base class for Backend (it was already
  present in the main implemnetation).
2015-09-23 18:27:33 +02:00
Florian Bruhin
311ae78bc3 Adjust check_coverage.py for coverage 4.0. 2015-09-21 07:42:10 +02:00
Florian Bruhin
cbc0721906 tox: Update coverage.py to 4.0.0.
Changelog:

Backward incompatibilities:

- Python versions supported are now:
  - CPython 2.6, 2.7, 3.3, 3.4 and 3.5
  - PyPy2 2.4, 2.6
  - PyPy3 2.4
- The original command line switches (-x to run a program, etc) are no longer
  supported.
- The COVERAGE_OPTIONS environment variable is no longer supported. It was a
  hack for --timid before configuration files were available.
- The original module-level function interface to coverage.py is no longer
  supported. You must now create a coverage.Coverage object, and use methods on
  it.
- The Coverage.use_cache method is no longer supported.
- The private method Coverage._harvest_data is now called Coverage.get_data(),
  and returns the CoverageData containing the collected data.
- Coverage.py is now licensed under the Apache 2.0 license. See NOTICE.txt for
  details.
- Coverage.py kits no longer include tests and docs. If you were using them,
  get in touch and let me know how.

Major new features:

- Plugins: third parties can write plugins to add file support for non-Python
  files, such as web application templating engines, or languages that compile
  down to Python. See Plugins for how to use plugins, and Plugin classes for
  details of how to write them. A plugin for measuring Django template coverage
  is available: django_coverage_plugin
- Gevent, eventlet, and greenlet are now supported. The [run] concurrency
  setting, or the --concurrency command line switch, specifies the concurrency
  library in use. Huge thanks to Peter Portante for initial implementation, and
  to Joe Jevnik for the final insight that completed the work.
- The data storage has been re-written, using JSON instead of pickle. The
  CoverageData class is a new supported API to the contents of the data file.
  Data files from older versions of coverage.py can be converted to the new
  format with python -m coverage.pickle2json.
- Wildly experimental: support for measuring processes started by the
  multiprocessing module. To use, set --concurrency=multiprocessing, either on
  the command line or in the .coveragerc file. Thanks, Eduardo Schettino.
  Currently, this does not work on Windows.

New features:

- Options are now also read from a setup.cfg file, if any. Sections are
  prefixed with “coverage:”, so the [run] options will be read from the
  [coverage:run] section of setup.cfg.
- The HTML report now has filtering. Type text into the Filter box on the index
  page, and only modules with that text in the name will be shown. Thanks,
  Danny Allen.
- A new option: coverage report --skip-covered (or [report] skip_covered) will
  reduce the number of files reported by skipping files with 100% coverage.
  Thanks, Krystian Kichewko. This means that empty __init__.py files will be
  skipped, since they are 100% covered.
- You can now specify the --fail-under option in the .coveragerc file as the
  [report] fail_under option.
- The report -m command now shows missing branches when reporting on branch
  coverage. Thanks, Steve Leonard.
- The coverage combine command now accepts any number of directories or files
  as arguments, and will combine all the data from them. This means you don’t
  have to copy the files to one directory before combining. Thanks, Christine
  Lytwynec.
- A new configuration option for the XML report: [xml] package_depth controls
  which directories are identified as packages in the report. Directories
  deeper than this depth are not reported as packages. The default is that all
  directories are reported as packages. Thanks, Lex Berezhny.
- A new configuration option, [run] note, lets you set a note that will be
  stored in the runs section of the data file. You can use this to annotate the
  data file with any information you like.
- The COVERAGE_DEBUG environment variable can be used to set the [run] debug
  configuration option to control what internal operations are logged.
- A new version identifier is available, coverage.version_info, a plain tuple
  of values similar to sys.version_info.

Improvements:

- Coverage.py now always adds the current directory to sys.path, so that
  plugins can import files in the current directory.
- Coverage.py now accepts a directory name for coverage run and will run a
  __main__.py found there, just like Python will. Thanks, Dmitry Trofimov.
- The --debug switch can now be used on any command.
- Reports now use file names with extensions. Previously, a report would
  describe a/b/c.py as “a/b/c”. Now it is shown as “a/b/c.py”. This allows for
  better support of non-Python files.
- Missing branches in the HTML report now have a bit more information in the
  right-hand annotations. Hopefully this will make their meaning clearer.
- The XML report now contains a <source> element. Thanks Stan Hu.
- The XML report now includes a missing-branches attribute. Thanks, Steve Peak.
  This is not a part of the Cobertura DTD, so the XML report no longer
  references the DTD.
- The XML report now reports each directory as a package again. This was a bad
  regression, I apologize.
- In parallel mode, coverage erase will now delete all of the data files.
- A new warning is possible, if a desired file isn’t measured because it was
  imported before coverage.py was started.
- The coverage.process_startup() function now will start coverage measurement
  only once, no matter how many times it is called. This fixes problems due to
  unusual virtualenv configurations.
- Unrecognized configuration options will now print an error message and stop
  coverage.py. This should help prevent configuration mistakes from passing
  silently.

API changes:

- The class defined in the coverage module is now called Coverage instead of
  coverage, though the old name still works, for backward compatibility.
- You can now programmatically adjust the configuration of coverage.py by
  calling Coverage.set_option() after construction. Coverage.get_option() reads
  the configuration values.
- If the config_file argument to the Coverage constructor is specified as
  ”.coveragerc”, it is treated as if it were True. This means setup.cfg is also
  examined, and a missing file is not considered an error.

Bug fixes:

- The textual report and the HTML report used to report partial branches
  differently for no good reason. Now the text report’s “missing branches”
  column is a “partial branches” column so that both reports show the same
  numbers. This closes issue 342.
- The fail-under value is now rounded the same as reported results, preventing
  paradoxical results, fixing issue 284.
- Branch coverage couldn’t properly handle certain extremely long files. This
  is now fixed, closing issue 359.
- Branch coverage didn’t understand yield statements properly. Mickie Betz
  persisted in pursuing this despite Ned’s pessimism. Fixes issue 308 and issue
  324.
- Files with incorrect encoding declaration comments are no longer ignored by
  the reporting commands.
- Empty files are now reported as 100% covered in the XML report, not 0%
  covered.
- The XML report will now create the output directory if need be. Thanks, Chris
  Rose.
- HTML reports no longer raise UnicodeDecodeError if a Python file has
  undecodable characters.
- The annotate command will now annotate all files, not just ones relative to
  the current directory.
2015-09-21 07:16:37 +02:00
Florian Bruhin
6a8c1e62b7 tox: Update pyflakes to 1.0.0.
Changes:

- Don't mark shadowing variable as 'used'.
- Test that used variable in loop is considered used
- Don't report UnusedImport when binding global name
- Support Python 3.5 async/await statements for Pyflakes.
- Use os.linesep for Windows compatibility
- os.chmod() supports only read-only flag operations on Windows
2015-09-21 07:15:48 +02:00
Florian Bruhin
977bfb4c73 tox: Filter pytest to <2.8.0 for requires.io.
We'll have to wait for hypothesis-pytest and pytest-capturelog/catchlog to be
fixed first.
2015-09-21 07:14:37 +02:00
Florian Bruhin
5ba7b5cf0f Fix lint. 2015-09-19 22:03:56 +02:00
Florian Bruhin
64a6b518dc Regenerate docs. 2015-09-19 21:50:06 +02:00
Florian Bruhin
f96de5a598 Add config for tab colors for odd/even sel. tabs. 2015-09-19 21:45:57 +02:00
Florian Bruhin
957116658d Clean up freeze.py. 2015-09-18 22:33:50 +02:00
Florian Bruhin
7d6c39d64b Run frozen smoke test via pytest. 2015-09-18 22:23:18 +02:00
Florian Bruhin
ae07e00038 Move httpbin stuff out of integration/conftest.py. 2015-09-18 20:20:06 +02:00
Florian Bruhin
a8a2fd2e7d Rename webserver.py to webserver_sub.py. 2015-09-18 20:08:31 +02:00
Florian Bruhin
34f8e9ef18 Merge branch 't-wissmann-open_download' 2015-09-18 07:40:09 +02:00
Florian Bruhin
fd2855f800 Update authors. 2015-09-18 07:40:02 +02:00
Florian Bruhin
8dbc1cd1ed Merge branch 'open_download' of https://github.com/t-wissmann/qutebrowser into t-wissmann-open_download 2015-09-18 07:39:37 +02:00
Florian Bruhin
54ff8d2c0e Merge branch 'Carpetsmoker-issue-940' 2015-09-18 07:02:10 +02:00
Florian Bruhin
841e8fbbd1 Save search parameters in tabbed_browser. 2015-09-18 07:01:51 +02:00
Florian Bruhin
f62bf099a0 Also re-highlight text when restarting search. 2015-09-18 06:58:05 +02:00
Florian Bruhin
72cddb290b Cleanups 2015-09-18 06:55:17 +02:00
Martin Tournoij
a80c61e78a Use a single search term per-window
Previously, every tab had its own search term. This sets single search term per
window. using `/hello`, `gt`, and `n` will search for `hello` in the 2nd tab.

This fixes issue #940
2015-09-18 02:18:54 +02:00
Florian Bruhin
a4569b11ad tests: Skip test_stale_legacy_server when frozen. 2015-09-17 22:02:12 +02:00
Florian Bruhin
2cb1f9226a Make httpbin tests run when frozen. 2015-09-17 21:51:09 +02:00
Florian Bruhin
fbf9c74752 tests: Increase some timeouts for OS X. 2015-09-17 21:22:35 +02:00
Florian Bruhin
20e5c4cbe9 Update changelog. 2015-09-17 21:01:30 +02:00
Florian Bruhin
d9bad853e7 Merge branch 'wayland-deco' of ssh://tonks/qutebrowser 2015-09-17 21:00:17 +02:00
Florian Bruhin
4adce826b0 tox: Fix substitution. 2015-09-17 20:03:47 +02:00
Florian Bruhin
7e84a1a5b8 Fix lint. 2015-09-17 20:02:39 +02:00
Florian Bruhin
7eeabb2467 Fix integration tests with CRLF. 2015-09-17 19:52:56 +02:00
Florian Bruhin
0f69487f22 Adjust pylint ignores for py.path.
Since db513aa pylint can now import py, but fails because it can't infer that
there's a py.path.
2015-09-17 19:12:28 +02:00
Florian Bruhin
a6f113375c Add missing integration test data dir. 2015-09-17 19:10:16 +02:00
Florian Bruhin
01f424fdb0 tox: Update pytest-flakes to 1.0.1.
Changelog:

- make the data json clean so we can support modern pytest
2015-09-17 19:03:43 +02:00
Florian Bruhin
c195ee225d Add missing docs and fix lint. 2015-09-17 19:02:03 +02:00
Florian Bruhin
929957c4fb tox: Update dependencies for httpbin tests. 2015-09-17 19:02:03 +02:00
Florian Bruhin
c530312aca httpbin: Improve request parsing/logging. 2015-09-17 19:02:03 +02:00
Florian Bruhin
fd264631c4 Move httpbin data to data/ instead of html/. 2015-09-17 19:02:03 +02:00
Florian Bruhin
2bfb7609ac Show data in test_httpbin. 2015-09-17 19:02:03 +02:00
Florian Bruhin
48b599a774 Start work on httpbin integration tests. 2015-09-17 19:02:03 +02:00
Florian Bruhin
db513aa956 tox: Require all testenv deps for pylint. 2015-09-17 19:00:49 +02:00
Thorsten Wißmann
855f8402c6 open_download: Warn if download dir is empty 2015-09-17 10:32:26 +02:00
Thorsten Wißmann
9e25e3b96b open_download: Allow download dir to be a symlink 2015-09-17 10:32:26 +02:00
Thorsten Wißmann
b8f200b370 Add open_download userscript 2015-09-17 10:32:17 +02:00
Florian Bruhin
bb224a9d39 Regenerate docs. 2015-09-17 06:53:28 +02:00
Florian Bruhin
ee2b9adce4 Move checking if an URL is blocked to adblock.py. 2015-09-17 06:46:27 +02:00
Florian Bruhin
accbf157e0 Merge branch 'Kingdread-whitelist-hosts' 2015-09-17 06:39:17 +02:00
Florian Bruhin
ac27f46170 Add piwik.org to default whitelist. 2015-09-17 06:38:24 +02:00
Florian Bruhin
f9645d608b Update authors. 2015-09-17 06:37:53 +02:00
Florian Bruhin
a589ddab4a Merge branch 'whitelist-hosts' of https://github.com/Kingdread/qutebrowser into Kingdread-whitelist-hosts 2015-09-17 06:37:44 +02:00
Florian Bruhin
731a86ce33 Merge branch 'acogneau-cookies_tests' 2015-09-16 23:01:26 +02:00
Florian Bruhin
7f573616c8 Remove unused import. 2015-09-16 23:01:14 +02:00
Florian Bruhin
57242e925c Fix names of constants. 2015-09-16 23:00:02 +02:00
Florian Bruhin
375b7c8ab2 Update authors. 2015-09-16 22:58:46 +02:00
Florian Bruhin
d5baed5e83 Merge branch 'cookies_tests' of https://github.com/acogneau/qutebrowser into acogneau-cookies_tests 2015-09-16 22:58:28 +02:00
Florian Bruhin
0745de647b Allow debug.log_time to be used as decorator. 2015-09-16 22:50:19 +02:00
Florian Bruhin
545d82a04d utils.debug: Allow passing logger to log_time. 2015-09-16 22:38:31 +02:00
Florian Bruhin
80d3bb712d Merge branch 'averrin-patch-2' 2015-09-16 22:32:52 +02:00
Florian Bruhin
ef17f50298 Update authors. 2015-09-16 22:32:30 +02:00
Florian Bruhin
503e3ce48d Merge branch 'patch-2' of https://github.com/averrin/qutebrowser into averrin-patch-2 2015-09-16 22:32:21 +02:00
Florian Bruhin
8a01dc9194 Merge branch 'antoyo-bug/web-history-max-items' 2015-09-16 22:30:47 +02:00
Florian Bruhin
c451fc3883 Merge branch 'bug/web-history-max-items' of https://github.com/antoyo/qutebrowser into antoyo-bug/web-history-max-items 2015-09-16 22:25:45 +02:00
Florian Bruhin
28f34b76af tox: Update hypothesis to 1.11.1.
Bug fixes:

- When running Hypothesis tests in parallel (e.g. using pytest-xdist) there was
  a race condition caused by code generation.
- Example databases are now cached per thread so as to not use sqlite
  connections from multiple threads. This should make Hypothesis now entirely
  thread safe.
- floats() with only min_value or max_value set would have had a very bad
  distribution.
- Running on 3.5, Hypothesis would have emitted deprecation warnings because of
  use of inspect.getargspec
2015-09-16 22:14:24 +02:00
Florian Bruhin
8c66f3c45a Merge branch 't-wissmann-view_in_mpv' 2015-09-16 21:29:21 +02:00
Florian Bruhin
98e470cc22 Update authors. 2015-09-16 21:29:13 +02:00
Florian Bruhin
fe16b95f00 Fix typo. 2015-09-16 21:29:03 +02:00
Florian Bruhin
a01c172bc4 Merge branch 'view_in_mpv' of https://github.com/t-wissmann/qutebrowser into t-wissmann-view_in_mpv 2015-09-16 21:26:16 +02:00
Florian Bruhin
1a1862a10d Increase timeout. 2015-09-16 20:26:31 +02:00
Florian Bruhin
88167ce4ce Shorten test IDs. 2015-09-16 20:25:02 +02:00
Florian Bruhin
7eca4acb6a Ignore first QWheelEvent for webview.
Hopefully fixes #395.
2015-09-16 20:07:18 +02:00
Florian Bruhin
55cf8516e5 tox: Update pytest-qt to 1.7.0.
Upstream changelog:

- PYTEST_QT_API can now be set to pyqt4v2 in order to use version 2 of the
  PyQt4 API.
2015-09-16 17:46:32 +02:00
Florian Bruhin
b47fd21b5a Update changelog. 2015-09-16 17:45:14 +02:00
Daniel
dd679c6c14 Fix is_whitelisted_domain docstring 2015-09-16 17:16:35 +02:00
Daniel
fc806525a2 Move whitelist host code to networkmanager
This means no :adblock-update after modifying the whitelist.
2015-09-16 17:10:03 +02:00
Daniel
523e071a97 Stylistic changes to is_whitelisted_domain 2015-09-16 17:04:19 +02:00
Daniel
ccdb59cce1 Add adblock host whitelisting
The config option "content host-blocking-whitelist" may contain comma
separated domains that are exempt from host blocking.

The listed domains may contain the wildcards "*" and "?" to match many
and one character, respectively.

You need to run :adblock-update after modifying the list.
2015-09-16 16:31:17 +02:00
Averrin
3904b7de58 Leave passthrough mode when change tab 2015-09-16 16:44:31 +03:00
Florian Bruhin
9561b7b02c Reset QT_WAYLAND_DISABLE_WINDOWDECORATION. 2015-09-16 10:23:21 +02:00
Florian Bruhin
f83f4a6a1a Add setting. 2015-09-16 08:52:51 +02:00
Florian Bruhin
08e1d9a304 hardcoded 2015-09-16 08:42:59 +02:00
Florian Bruhin
0fa9da56bf Revert "ipc tests: Speed up TestListen::test_atime_update."
This reverts commit 443a2e1657.

We actually need to wait a bit to make sure the atime is updated.
2015-09-16 07:16:14 +02:00
Florian Bruhin
9ab14c0384 Fix IPC coverage. 2015-09-16 07:16:07 +02:00
Florian Bruhin
443a2e1657 ipc tests: Speed up TestListen::test_atime_update. 2015-09-16 07:13:31 +02:00
Florian Bruhin
7ffff72368 ipc: Make sure server is always shut down in tests.
Hopefully fixes #947.
2015-09-16 07:11:30 +02:00
Florian Bruhin
dd2a70e01f Fix IPC tests.
This was broken when adding some more logging.
2015-09-16 07:10:54 +02:00
Florian Bruhin
73cb981ebb Add some more IPC logging. 2015-09-15 23:05:50 +02:00
Florian Bruhin
ff24ba5437 ipc: Fix atime timer interval. 2015-09-15 22:59:53 +02:00
Florian Bruhin
47b75e1cdc tox: Update pytest to 2.7.3.
Changelog:

- Allow 'dev', 'rc', or other non-integer version strings in `importorskip`.
  Thanks to Eric Hunsberger for the PR.

- fix issue856: consider --color parameter in all outputs (for example
  --fixtures). Thanks Barney Gale for the report and Bruno Oliveira for the PR.

- fix issue855: passing str objects as `plugins` argument to pytest.main
  is now interpreted as a module name to be imported and registered as a
  plugin, instead of silently having no effect.
  Thanks xmo-odoo for the report and Bruno Oliveira for the PR.

- fix issue744: fix for ast.Call changes in Python 3.5+.  Thanks
  Guido van Rossum, Matthias Bussonnier, Stefan Zimmermann and
  Thomas Kluyver.

- fix issue842: applying markers in classes no longer propagate this markers
  to superclasses which also have markers.
  Thanks xmo-odoo for the report and Bruno Oliveira for the PR.

- preserve warning functions after call to pytest.deprecated_call. Thanks
  Pieter Mulder for PR.

- fix issue854: autouse yield_fixtures defined as class members of
  unittest.TestCase subclasses now work as expected.
  Thannks xmo-odoo for the report and Bruno Oliveira for the PR.

- fix issue833: --fixtures now shows all fixtures of collected test files, instead of just the
  fixtures declared on the first one.
  Thanks Florian Bruhin for reporting and Bruno Oliveira for the PR.

- fix issue863: skipped tests now report the correct reason when a skip/xfail
  condition is met when using multiple markers.
  Thanks Raphael Pierzina for reporting and Bruno Oliveira for the PR.

- optimized tmpdir fixture initialization, which should make test sessions
  faster (specially when using pytest-xdist). The only visible effect
  is that now pytest uses a subdirectory in the $TEMP directory for all
  directories created by this fixture (defaults to $TEMP/pytest-$USER).
  Thanks Bruno Oliveira for the PR.
2015-09-15 22:34:47 +02:00
Florian Bruhin
91b4ba2a48 Only run runtime test on Linux. 2015-09-15 22:31:37 +02:00
Florian Bruhin
d887bbeb24 Revert "standarddir: Fix runtime basedir test on OS X."
This reverts commit 46ac1e2bf90f1c74a1cc502e08b717715b90eb39.
2015-09-15 22:31:37 +02:00
Florian Bruhin
89b4adf158 standarddir: Fix runtime basedir test on OS X. 2015-09-15 22:31:37 +02:00
Florian Bruhin
0bbd410016 standarddir: Fix coverage. 2015-09-15 22:31:37 +02:00
Florian Bruhin
00d6970c66 standarddir: Add some OS X tests. 2015-09-15 22:31:37 +02:00
Florian Bruhin
cc052a539f Add standarddir.download() tests. 2015-09-15 22:31:37 +02:00
Florian Bruhin
df095daf24 Simplify standarddir tests. 2015-09-15 22:31:37 +02:00
Florian Bruhin
04ec9c2624 Get rid of standarddir.temp() again. 2015-09-15 22:31:37 +02:00
Florian Bruhin
3bdfa3001c ipc: Always use standarddir.runtime(). 2015-09-15 22:31:37 +02:00
Florian Bruhin
748496e88d Refactor standarddir.
See #941.
2015-09-15 22:31:37 +02:00
Florian Bruhin
f5221ceb4b travis: Set a fixed path.
This should fix build errors on Travis, as it was picking up some Python from
/opt...
2015-09-15 13:19:51 +02:00
Florian Bruhin
f1ce6d0ed6 tox: Remove unittests-watch env. 2015-09-15 13:19:22 +02:00
Florian Bruhin
8e925cc5a2 Merge branch 'claudehohl-master' 2015-09-15 10:24:44 +02:00
Claude
d054fda4ac making userid wildcardish 2015-09-15 10:11:06 +02:00
Claude
5130be4495 workaround for debian, need additional permissions 2015-09-15 10:03:54 +02:00
Alexander Cogneau
ec11a61ed8 Fix failing tests 2015-09-13 23:08:31 +02:00
Antoni Boucher
f0a2128499 Fixed style. 2015-09-12 18:01:04 -04:00
Antoni Boucher
2aa7e5bb35 Fixed issue #934. 2015-09-12 17:48:36 -04:00
Alexander Cogneau
c08beda1aa Code cleanup 2015-09-12 22:11:14 +02:00
Florian Bruhin
e075e6c9df Clean up correctly after standarddir tests. 2015-09-11 21:20:45 +02:00
Florian Bruhin
09b0877eab Revert "Refactor standarddir."
This reverts commit 330f3f8f13.
2015-09-11 21:20:31 +02:00
Florian Bruhin
330f3f8f13 Refactor standarddir.
See #941.
2015-09-11 20:05:13 +02:00
Florian Bruhin
b16a482b4c Improve releasing documentation. 2015-09-11 19:43:55 +02:00
Florian Bruhin
7a32bbd955 tox: Reduce dependencies for cxfreeze-windows. 2015-09-11 19:43:29 +02:00
Alexander Cogneau
851bf4cd31 Fix pylint 2015-09-06 16:13:41 +02:00
Alexander Cogneau
6541a360b1 Final cooikies tests 2015-09-06 00:24:38 +02:00
Alexander Cogneau
d36c701b07 Fixed comments 2015-09-04 11:44:59 +02:00
Alexander Cogneau
418328e61b Cookie tests done 2015-09-03 18:17:39 +02:00
Thorsten Wißmann
bbdec1779a Add check that view_in_mpv is run as a userscript
Also fix another typo.
2015-09-03 18:02:22 +02:00
Alexander Cogneau
96e3a0b1f1 first cookie tests 2015-09-03 17:24:01 +02:00
Thorsten Wißmann
de5cdf6f0f Also hide <embed> tags
But only hide those tags that aren't children (or descendants) of other
tags that get replaced anyway. That is needed because sometimes, flash
videos are in <embed> tags, sometimgs in <object> tags and sometimes in
<embed> tags within <object> tags.

Furthermore enforce our "click here" link to have transparent background
(and in future: remove as many properties from website specific CSS
stylesheets).
2015-09-03 16:34:30 +02:00
Thorsten Wißmann
e5b7fdb565 Fix typos spotted by The-Compiler 2015-09-02 17:20:51 +02:00
Thorsten Wißmann
197feade32 Also replace flash videos
This means: also replace <object> tags and put the replacement message
even higher in the z-order. (Latter had to be done to make it the
replacement visible on espn _dot_ com)
2015-09-02 17:18:44 +02:00
Thorsten Wißmann
fe6a6c33ae Add view_in_mpv userscript 2015-09-02 15:59:52 +02:00
346 changed files with 16192 additions and 2494 deletions

View File

@@ -4,15 +4,14 @@ cache:
- C:\projects\qutebrowser\.cache
build: off
environment:
PYTHON: 'C:\Python34'
PYTHONUNBUFFERED: 1
matrix:
- TESTENV: py34
- TESTENV: unittests-frozen
- TESTENV: pylint
install:
- C:\Python27\python -u scripts\dev\ci_install.py
test_script:
- C:\Python34\Scripts\tox -e py34
- C:\Python34\Scripts\tox -e py34-integration
- C:\Python34\Scripts\tox -e unittests-frozen
- C:\Python34\Scripts\tox -e smoke-frozen
- C:\Python34\Scripts\tox -e pylint
- C:\Python34\Scripts\tox -e %TESTENV% -- -p "no:sugar" -v --junitxml=junit.xml

View File

@@ -1,4 +1,5 @@
[run]
source = qutebrowser
branch = true
omit =
qutebrowser/__main__.py

1
.eslintignore Normal file
View File

@@ -0,0 +1 @@
qutebrowser/3rdparty/pdfjs/*

3
.gitignore vendored
View File

@@ -21,7 +21,8 @@ __pycache__
/.venv
/.coverage
/htmlcov
/.coverage.xml
/coverage.xml
/.coverage.*
/.tox
/testresults.html
/.cache

View File

@@ -9,8 +9,8 @@ load-plugins=pylint_checkers.config,
pylint_checkers.settrace
[MESSAGES CONTROL]
enable=all
disable=no-self-use,
bad-builtin,
fixme,
global-statement,
locally-disabled,
@@ -23,28 +23,29 @@ disable=no-self-use,
blacklisted-name,
too-many-lines,
logging-format-interpolation,
interface-not-implemented,
broad-except,
bare-except,
eval-used,
exec-used,
file-ignored
file-ignored,
wrong-import-order,
ungrouped-imports,
redefined-variable-type,
suppressed-message
[BASIC]
module-rgx=(__)?[a-z][a-z0-9_]*(__)?$
function-rgx=([a-z_][a-z0-9_]{2,50}|setUpModule|tearDownModule)$
function-rgx=[a-z_][a-z0-9_]{2,50}$
const-rgx=[A-Za-z_][A-Za-z0-9_]{0,30}$
method-rgx=[a-z_][A-Za-z0-9_]{2,50}$
attr-rgx=[a-z_][a-z0-9_]{0,30}$
argument-rgx=[a-z_][a-z0-9_]{0,30}$
variable-rgx=[a-z_][a-z0-9_]{0,30}$
class-attribute-rgx=[A-Za-z_][A-Za-z0-9_]{1,30}$
inlinevar-rgx=[a-z_][a-z0-9_]*$
docstring-min-length=3
[FORMAT]
max-line-length=79
ignore-long-lines=<?https?://
ignore-long-lines=(<?https?://|^# Copyright 201\d)
expected-line-ending-format=LF
[SIMILARITIES]
min-similarity-lines=8
@@ -52,11 +53,13 @@ min-similarity-lines=8
[VARIABLES]
dummy-variables-rgx=_.*
[CLASSES]
defining-attr-methods=__init__,__new__,setUp
[DESIGN]
max-args=10
[TYPECHECK]
ignored-classes=WebElementWrapper,AnsiCodes,UnsetObject
# MsgType added as WORKAROUND for
# https://bitbucket.org/logilab/pylint/issues/690/
# UnsetObject because pylint infers any objreg.get(...) as UnsetObject.
ignored-classes=qutebrowser.utils.objreg.UnsetObject,
qutebrowser.browser.webelem.WebElementWrapper,
scripts.dev.check_coverage.MsgType

View File

@@ -1,9 +1,30 @@
# So we get Ubuntu Trusty - using "dist: trusty" breaks OS X.
sudo: required
dist: trusty
os:
- linux
- osx
env:
global:
- PATH=/home/travis/bin:/home/travis/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
matrix:
- TESTENV=py35
- TESTENV=py34
- TESTENV=unittests-nodisp
- TESTENV=misc
- TESTENV=vulture
- TESTENV=pep257
- TESTENV=pyflakes
- TESTENV=pep8
- TESTENV=mccabe
- TESTENV=pyroma
- TESTENV=check-manifest
- TESTENV=pylint
- TESTENV=eslint
# Not really, but this is here so we can do stuff by hand.
language: c
@@ -16,18 +37,40 @@ install:
- python scripts/dev/ci_install.py
script:
- xvfb-run -s "-screen 0 640x480x16" tox -e py34,py34-integration
- tox -e misc
- tox -e pep257
- tox -e pyflakes
- tox -e pep8
- tox -e mccabe
- tox -e pylint
- tox -e pyroma
- tox -e check-manifest
- tox -e $TESTENV -- -p no:sugar -v --cov-report term tests
after_success:
- '[[ ($TESTENV == py34 || $TESTENV == py35) && $TRAVIS_OX == linux ]] && codecov -e TESTENV -X gcov'
# Travis bug - OS X builds get routed to Ubuntu Trusty if "dist: trusty" is
# given.
matrix:
allow_failures:
exclude:
- os: linux
env: TESTENV=py35
- os: osx
env: TESTENV=py34
- os: osx
env: TESTENV=unittests-nodisp
- os: osx
env: TESTENV=misc
- os: osx
env: TESTENV=vulture
- os: osx
env: TESTENV=pep257
- os: osx
env: TESTENV=pyflakes
- os: osx
env: TESTENV=pep8
- os: osx
env: TESTENV=mccabe
- os: osx
env: TESTENV=pyroma
- os: osx
env: TESTENV=check-manifest
- os: osx
env: TESTENV=pylint
- os: osx
env: TESTENV=eslint
notifications:
webhooks:
- https://buildtimetrend.herokuapp.com/travis

View File

@@ -14,6 +14,144 @@ This project adheres to http://semver.org/[Semantic Versioning].
// `Fixed` for any bug fixes.
// `Security` to invite users to upgrade in case of vulnerabilities.
v0.5.0
------
Added
~~~~~
- Ability to preview PDFs using pdf.js in the browser if it's installed. This
is disabled by default and can be enabled using the
`content -> pdfjs-enabled` setting.
- New setting `ui -> hide-wayland-decoration` to hide the window decoration
when using wayland.
- New userscripts in `misc/userscripts`:
- `open_download` to easily open a file in your downloads folder.
- `view_in_mpv` to open a video in mpv and remove it from the page.
- `qutedmenu` and `dmenu_qutebrowser` to select URLs via dmenu
- New setting `content -> host-blocking-whitelist` to whitelist certain domains
from the adblocker.
- `{scroll_pos}` can now be used in `ui -> window-title-format` and
`tabs -> title-format`.
- New setting `general -> url-incdec-segments` to configure which segments of
the URL should be affected by `:navigate increment/decrement`.
- New `--target` argument to specify how URLs should be opened in an existing
instance.
- New setting `statusbar.url.fg.success.https` to set the foreground color for
the URL when a page was loaded via HTTPS.
- The scrollbar in the completion is now styled, and the following new options
got added:
* `completion -> scrollbar-width`
* `completion -> scrollbar-padding`
* `colors -> completion.scrollbar.fg`
* `colors -> completion.scrollbar.bg`
- New value `none` for options taking a color system so they don't display a
gradient:
* `colors -> tabs.indicator.system`
* `colors -> downloads.fg.system`
* `colors -> downloads.bg.system`
- New command `:download-retry` to retry a failed download.
- New command `:download-clear` which replaces `:download-remove --all`.
- `:set-cmd-text` has a new `--append` argument to append to the current
statusbar text.
- qutebrowser now uses `~/.netrc` if available to authenticate via HTTP.
- New `:fake-key` command to send a fake keypress to a website or to
qutebrowser.
- New `--mhtml` argument for `:download` to download a page including all
ressources as MHTML file.
- New option `tabs -> title-alignment` to change the alignment of tab titles.
Changed
~~~~~~~
- The `colors -> tabs.bg/fg.selected` option got split into
`tabs.bg/fg.selected.odd/even`.
- `:spawn --userscript` and `:hint` with the `userscript` target now look up
relative paths in `~/.local/share/qutebrowser/userscripts` or
`$XDG_DATA_DIR`. Using a binary in `$PATH` won't work anymore with
`--userscript`.
- New design for error pages
- Link filtering for hints now checks if the text is contained anywhere in
the link, and matches case-insensitively.
- The `ui -> remove-finished-downloads` option got changed to an integer and
now takes a time (in milliseconds) to keep the download around after it's
finished. When set to `-1`, downloads are never removed.
- The `:follow-hint` command now optionally takes the keystring of a hint to
follow.
- `:scroll-px` now doesn't take floats anymore, which made little sense.
- Updated the user agent list for the `:set network user-agent` completion.
- Starting with `--debug` doesn't log `VDEBUG` messages anymore (add
`--loglevel VDEBUG` to get them).
- `:debug-console` now hides the console if it's already shown.
- `:yank-selected` now doesn't log the selected text anymore.
- `general -> log-javascript-console` got changed from a boolean to an option
taking a loglevel (`none`, `info`, `debug`).
- `:tab-move +/-` now wraps around if `tabs -> wrap` is `true`.
- When a subprocess (like launched by `:spawn`) fails, its stdout/stderr is now
logged to the console.
- A search engine name can now contain any non-space character, like dashes.
Deprecated
~~~~~~~~~~
- `:download-remove --all` is now deprecated and `:download-clear` should be
used instead.
- `:download <url> <destination>` is now deprecated and
`:download --dest <destination> <url>` should be used instead.
Removed
~~~~~~~
- `:scroll` with two pixel-arguments (deprecated in v0.3.0)
- The `:run-userscript` command (deprecated in v0.2.0)
- The `rapid` and `rapid-win` targets for `:hint` (deprecated in v0.2.0)
- The `:cancel-download` command (deprecated in v0.2.0)
- The `:download-page` command (deprecated in v0.2.0)
Fixed
~~~~~
- Fixed retrying of downloads which were started in a now closed tab.
- Fixed displaying of web history if `web-history-max-items` is set to -1.
- Cloned tabs now don't display favicons anymore if show-favicons is False.
- Fixed a crash when clicking a bookmark name and pressing `Ctrl-D`.
- Fixed a crash when a website presents a very small favicon.
- Fixed prompting for download directory when
`storage -> prompt-download-directory` was unset.
- Fixed crash when using `:follow-hint` outside of hint mode.
- Fixed crash when using `:set foo bar?` with invalid section/option.
- Fixed scrolling to the very left/right with `:scroll-perc`.
- Using an external editor should now work correctly with some funny chars
(U+2028/U+2029/BOM).
- Movements in caret mode now should work correctly on OS X and Windows.
- Fixed upgrade from earlier config versions.
- Fixed crash when killing a running userscript.
- Fixed characters being passed through when shifted with
`forward-unbound-keys` set to `auto`.
- Fixed restarting after a crash is reported.
- Removed `.pyc` files accidentally contained in source releases.
v0.4.1
------
Fixed
~~~~~
- Adjusted AppArmor config for the IPC changes in v0.4.0.
- Fixed atime update frequency for IPC file.
- Worked around a Qt issue where middle-clicking caused scrolling with a
touchpad to restart at the beginning of the page.
- The `completion -> web-history-max-items` setting is now also respected for
items added after starting qutebrowser.
- Search terms are now shared between different tabs again
- Tests (a reduced subset of them) now run correctly again when DISPLAY is not
set.
- Fixed an issue causing qutebrowser to crash with Python 3.5 as soon as an ad
was blocked.
- Fixed an issue causing qutebrowser to not start with more recent Python 3.4
versions (e.g. on Debian experimental).
- Fixed various `PendingDeprecationWarnings` shown with Python 3.5.
v0.4.0
------
@@ -423,7 +561,7 @@ Removed
Fixed
~~~~~
* Fix rare exception when a key is pressed shorly after opening a window
* Fix rare exception when a key is pressed shortly after opening a window
* Fix exception with certain invalid URLs like `http:foo:0`
* Work around Qt bug which renders checkboxes on OS X unusable
* Fix exception when a local files can't be read in `:adblock-update`

View File

@@ -227,7 +227,7 @@ Hints
Python and Qt objects
~~~~~~~~~~~~~~~~~~~~~
For many tasks, there are solutions in both Qt and the Python standard libary
For many tasks, there are solutions in both Qt and the Python standard library
available.
In qutebrowser, the policy is usually using the Python libraries, as they
@@ -548,27 +548,40 @@ workaround.
https://github.com/The-Compiler/qutebrowser/issues?q=is%3Aopen+is%3Aissue+label%3Aqt[qutebrowser
bugs] and check if they're fixed.
New PyQt release
~~~~~~~~~~~~~~~~
* See above
* Install new PyQt in Windows VM (32- and 64-bit)
* Download new installer and update PyQt installer path in `ci_install.py`.
qutebrowser release
~~~~~~~~~~~~~~~~~~~
* Make sure there are no unstaged changes.
* Run `src2asciidoc.py` and commit changes if necessary.
* Run `asciidoc2html.py`.
* Adjust `__version_info__` in `qutebrowser/__init__.py`.
* Make sure there are no unstaged changes and the tests are green.
* Run all tests on all supported systems.
* Test an upgrade from the previous version (no manual intervention).
* Test an upgrade from the first version (no manual intervention).
* Adjust `__version_info__` in `qutebrowser/__init__.py`.
* Remove *(unreleased)* from changelog.
* Run tests again
* Run `asciidoc2html.py`.
* Commit
* Create annotated git tag (`git tag -s "v0.X.Y" -m "Release v0.X.Y"`)
* If it's a new minor, create git branch `v0.X.x`
* `git push`; `git push "v0.X.Y"`
* If committing on minor branch, cherry-pick release commit to master.
* `git push origin`; `git push origin v0.X.Y`
* Create release on github
* Mark the milestone at https://github.com/The-Compiler/qutebrowser/milestones
as closed.
* Create standalone Windows package (32/64bit) in Windows VM
* Upload to PyPI: `python setup.py register sdist upload --sign`
* Upload to qutebrowser.org with checksum/GPG
* Run `scripts/dev/build_release.py` on Linux to build an sdist
* Upload to PyPI: `twine upload dist/foo{,.asc}`
* Create Windows packages via `scripts/dev/build_release.py` and upload.
* Upload to qutebrowser.org with checksum/GPG
- On server: `sudo mkdir -p /srv/http/qutebrowser/releases/v0.X.Y/windows`
- `rsync -avPh dist/ tonks:`
- On server: `sudo mv qutebrowser-0.X.Y.tar.gz* /srv/http/qutebrowser/releases/v0.X.Y`
* Update AUR package
* Announce to qutebrowser mailinglist

View File

@@ -1,5 +1,6 @@
Frequently asked questions
==========================
:title: Frequently asked questions
The Compiler <mail@qutebrowser.org>
[qanda]
@@ -60,7 +61,7 @@ Why Python?::
But isn't Python too slow for a browser?::
http://www.infoworld.com/d/application-development/van-rossum-python-not-too-slow-188715[No.]
I believe efficency while coding is a lot more important than efficency
I believe efficiency while coding is a lot more important than efficiency
while running. Also, most of the heavy lifting of qutebrowser is done by Qt
and WebKit in C++, with the
https://wiki.python.org/moin/GlobalInterpreterLock[GIL] released.
@@ -87,6 +88,16 @@ Note that you might need an additional package (e.g.
https://www.archlinux.org/packages/community/any/youtube-dl/[youtube-dl] on
Archlinux) to play web videos with mpv.
How do I use qutebrowser with mutt?::
Due to a Qt limitation, local files without `.html` extensions are
"downloaded" instead of displayed, see
https://github.com/The-Compiler/qutebrowser/issues/566[#566]. You can work
around this by using this in your `mailcap`:
+
----
text/html; mv %s %s.html && qutebrowser %s.html >/dev/null 2>/dev/null; needsterminal;
----
== Troubleshooting
Configuration not saved after modifying config.::
@@ -103,7 +114,7 @@ Unable to view flash content.::
Experiencing freezing on sites like duckduckgo and youtube.::
This issue could be caused by stale plugin files installed by `mozplugger`
if mozplugger was subsequently removed.
Try exiting qutebroser and removing `~/.mozilla/plugins/mozplugger*.so`.
Try exiting qutebrowser and removing `~/.mozilla/plugins/mozplugger*.so`.
See https://github.com/The-Compiler/qutebrowser/issues/357[Issue #357]
for more details.
@@ -115,7 +126,7 @@ Experiencing segfaults (crashes) on Debian systems.::
Segfaults on Facebook, Medium, Amazon, ...::
If you are on a Debian or Ubuntu based system, you might experience some crashes
visting these sites. This is caused by various bugs in Qt which have been
visiting these sites. This is caused by various bugs in Qt which have been
fixed in Qt 5.4. However Debian and Ubuntu are slow to adopt or upgrade
some packages. On Debian Jessie, it's recommended to use the experimental
repos as described in https://github.com/The-Compiler/qutebrowser/blob/master/INSTALL.asciidoc#on-debian--ubuntu[INSTALL].

View File

@@ -8,7 +8,7 @@ qutebrowser should run on these systems:
* Debian jessie or newer
* Ubuntu Trusty (14.04 LTS) or newer
* Any other distribution based on these (e.g. Linux Mint)
* Any other distribution based on these (e.g. Linux Mint 17+)
Unfortunately there is no Debian package yet, but installing qutebrowser is
still relatively easy! If you want to help packaging it for Debian, please
@@ -32,7 +32,7 @@ Then install the packages like this:
----
# apt-get update
# apt-get install -t experimental python3-pyqt5 python3-pyqt5.qtwebkit python3-sip
# apt-get install -t experimental python3-pyqt5 python3-pyqt5.qtwebkit python3-sip python3-dev
# apt-get install python-tox
----
@@ -50,14 +50,14 @@ For distributions other than Debian or if you prefer to not use the
experimental repo:
----
# apt-get install python3-pyqt5 python3-pyqt5.qtwebkit python-tox python3-sip
# apt-get install python3-pyqt5 python3-pyqt5.qtwebkit python-tox python3-sip python3-dev
----
To generate the documentation for the `:help` command, when using the git
repository (rather than a release):
----
# apt-get install asciidoc
# apt-get install asciidoc source-highlight
$ python3 scripts/asciidoc2html.py
----
@@ -83,7 +83,7 @@ To generate the documentation for the `:help` command, when using the git
repository (rather than a release):
----
# dnf install asciidoc
# dnf install asciidoc source-highlight
$ python3 scripts/asciidoc2html.py
----
@@ -208,7 +208,7 @@ it as part of the packaging process.
Installing qutebrowser with tox
-------------------------------
Run tox like this to set up a
Run tox inside the qutebrowser repository to set up a
https://docs.python.org/3/library/venv.html[virtual environment]:
----

View File

@@ -1,34 +1,37 @@
global-exclude __pycache__ *.pyc *.pyo
recursive-include qutebrowser *.py
recursive-include qutebrowser/html *.html
recursive-include qutebrowser/img *.svg
recursive-include qutebrowser/test *.py
recursive-include qutebrowser/javascript *.js
graft icons
graft doc/img
graft misc
graft scripts
include qutebrowser/utils/testfile
include qutebrowser/git-commit-id
include COPYING doc/* README.asciidoc CONTRIBUTING.asciidoc FAQ.asciidoc INSTALL.asciidoc CHANGELOG.asciidoc
include qutebrowser.desktop
include requirements.txt
include tox.ini
include qutebrowser.py
prune scripts/dev
exclude scripts/asciidoc2html.py
exclude doc/notes
recursive-exclude doc *.asciidoc
include doc/qutebrowser.1.asciidoc
prune tests
exclude pytest.ini
exclude qutebrowser.rcc
exclude .coveragerc
exclude .pylintrc
exclude .eslintrc
exclude doc/help
exclude .appveyor.yml
exclude .travis.yml
exclude misc/appveyor_install.py
recursive-include qutebrowser *.py
recursive-include qutebrowser/html *.html
recursive-include qutebrowser/img *.svg *.png
recursive-include qutebrowser/test *.py
recursive-include qutebrowser/javascript *.js
graft qutebrowser/3rdparty
graft icons
graft doc/img
graft misc
recursive-include scripts *.py
include qutebrowser/utils/testfile
include qutebrowser/git-commit-id
include COPYING doc/* README.asciidoc CONTRIBUTING.asciidoc FAQ.asciidoc INSTALL.asciidoc CHANGELOG.asciidoc
include qutebrowser.desktop
include requirements.txt
include tox.ini
include qutebrowser.py
prune www
prune scripts/dev
exclude scripts/asciidoc2html.py
exclude doc/notes
recursive-exclude doc *.asciidoc
include doc/qutebrowser.1.asciidoc
prune tests
exclude pytest.ini
exclude qutebrowser.rcc
exclude .coveragerc
exclude .pylintrc
exclude .eslintrc
exclude .eslintignore
exclude doc/help
exclude .appveyor.yml
exclude .travis.yml
exclude misc/appveyor_install.py
global-exclude __pycache__ *.pyc *.pyo

View File

@@ -6,14 +6,16 @@
qutebrowser
===========
// QUTE_WEB_HIDE
image:icons/qutebrowser-64x64.png[qutebrowser logo] *A keyboard-driven, vim-like browser based on PyQt5 and QtWebKit.*
image:https://img.shields.io/pypi/l/qutebrowser.svg?style=flat["license badge",link="https://github.com/The-Compiler/qutebrowser/blob/master/COPYING"]
image:https://img.shields.io/pypi/v/qutebrowser.svg?style=flat["version badge",link="https://pypi.python.org/pypi/qutebrowser/"]
image:https://img.shields.io/github/issues/The-Compiler/qutebrowser.svg?style=flat["issues badge",link="https://github.com/The-Compiler/qutebrowser/issues"]
image:https://requires.io/github/The-Compiler/qutebrowser/requirements.svg?branch=master["requirements badge",link="https://requires.io/github/The-Compiler/qutebrowser/requirements/?branch=master"]
image:https://travis-ci.org/The-Compiler/qutebrowser.svg?branch=master["Build Status", link="https://travis-ci.org/The-Compiler/qutebrowser"]
image:https://ci.appveyor.com/api/projects/status/9gmnuip6i1oq7046?svg=true["AppVeyor build status", link="https://ci.appveyor.com/project/The-Compiler/qutebrowser"]
image:https://codecov.io/github/The-Compiler/qutebrowser/coverage.svg?branch=master["coverage badge",link="https://codecov.io/github/The-Compiler/qutebrowser?branch=master"]
// QUTE_WEB_HIDE_END
qutebrowser is a keyboard-focused browser with a minimal GUI. It's based
on Python, PyQt5 and QtWebKit and free software, licensed under the GPL.
@@ -24,7 +26,7 @@ Screenshots
-----------
image:doc/img/main.png["screenshot 1",width=300,link="doc/img/main.png"]
image:doc/img/downloads.png["screenshot 2",width=300j,link="doc/img/downloads.png"]
image:doc/img/downloads.png["screenshot 2",width=300,link="doc/img/downloads.png"]
image:doc/img/completion.png["screenshot 3",width=300,link="doc/img/completion.png"]
image:doc/img/hints.png["screenshot 4",width=300,link="doc/img/hints.png"]
@@ -89,17 +91,21 @@ Requirements
The following software and libraries are required to run qutebrowser:
* http://www.python.org/[Python] 3.4
* http://qt.io/[Qt] 5.2.0 or newer (5.5.0 recommended)
* http://www.python.org/[Python] 3.4 or newer
* http://qt.io/[Qt] 5.2.0 or newer (5.5.1 recommended)
* QtWebKit
* http://www.riverbankcomputing.com/software/pyqt/intro[PyQt] 5.2.0 or newer
(5.5.0 recommended) for Python 3
(5.5.1 recommended) for Python 3
* https://pypi.python.org/pypi/setuptools/[pkg_resources/setuptools]
* http://fdik.org/pyPEG/[pyPEG2]
* http://jinja.pocoo.org/[jinja2]
* http://pygments.org/[pygments]
* http://pyyaml.org/wiki/PyYAML[PyYAML]
The following libraries are optional and provide a better user experience:
* http://cthedot.de/cssutils/[cssutils]
To generate the documentation for the `:help` command, when using the git
repository (rather than a release), http://asciidoc.org/[asciidoc] is needed.
@@ -135,49 +141,65 @@ Contributors, sorted by the number of commits in descending order:
// QUTE_AUTHORS_START
* Florian Bruhin
* Daniel Schadt
* Antoni Boucher
* Lamar Pavel
* Bruno Oliveira
* Martin Tournoij
* Alexander Cogneau
* Martin Tournoij
* Raphael Pierzina
* Joel Torstensson
* Claude
* Lamar Pavel
* Austin Anderson
* Artur Shaik
* ZDarian
* Peter Vilim
* John ShaggyTwoDope Jenkins
* Daniel
* Jimmy
* Zach-Button
* rikn00
* Thorsten Wißmann
* meles5
* Patric Schmitz
* Artur Shaik
* Nathan Isom
* Austin Anderson
* Thorsten Wißmann
* Alexey "Averrin" Nabrodov
* ZDarian
* John ShaggyTwoDope Jenkins
* Peter Vilim
* Jonas Schürmann
* Panagiotis Ktistakis
* Jimmy
* skinnay
* error800
* Zach-Button
* Halfwit
* Felix Van der Jeugt
* rikn00
* Martin Zimmermann
* Error 800
* Brian Jackson
* sbinix
* neeasade
* jnphilipp
* Tobias Patzl
* Peter Michely
* Larry Hynes
* Johannes Altmanninger
* Samir Benmendil
* Regina Hug
* Mathias Fussenegger
* Larry Hynes
* Fritz V155 Reichwald
* Franz Fellner
* Corentin Jule
* zwarag
* meles5
* error800
* xd1le
* dylan araps
* Tim Harder
* Thiago Barroso Perrotta
* Samuel Loury
* Matthias Lisin
* Marcel Schilling
* Jean-Christophe Petkovich
* Helen Sherwood-Taylor
* HalosGhost
* Gregor Pohl
* Eivind Uggedal
* Daniel Lu
* Arseniy Seroka
* Andy Balaam
* Andreas Fischer
// QUTE_AUTHORS_END
@@ -250,3 +272,14 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
pdf.js
------
qutebrowser optionally uses https://github.com/mozilla/pdf.js/[pdf.js] to
display PDF files in the browser. Windows releases come with a bundled pdf.js.
pdf.js is distributed under the terms of the Apache License. You can
find a copy of the license in `qutebrowser/3rdparty/pdfjs/LICENSE` (in the
Windows release or after running `scripts/dev/update_3rdparty.py`), or online
http://www.apache.org/licenses/LICENSE-2.0.html[here].

View File

@@ -14,9 +14,12 @@
|<<close,close>>|Close the current window.
|<<download,download>>|Download a given URL, or current page if no URL given.
|<<download-cancel,download-cancel>>|Cancel the last/[count]th download.
|<<download-clear,download-clear>>|Remove all finished downloads from the list.
|<<download-delete,download-delete>>|Delete the last/[count]th download from disk.
|<<download-open,download-open>>|Open the last/[count]th download.
|<<download-remove,download-remove>>|Remove the last/[count]th download from the list.
|<<download-retry,download-retry>>|Retry the first failed/[count]th download.
|<<fake-key,fake-key>>|Send a fake keypress or key string to the website or qutebrowser.
|<<forward,forward>>|Go forward in the history of the current tab.
|<<fullscreen,fullscreen>>|Toggle fullscreen mode.
|<<help,help>>|Show help about a command or setting.
@@ -143,13 +146,18 @@ Close the current window.
[[download]]
=== download
Syntax: +:download ['url'] ['dest']+
Syntax: +:download [*--mhtml*] [*--dest* 'DEST'] ['url'] ['dest-old']+
Download a given URL, or current page if no URL given.
The form `:download [url] [dest]` is deprecated, use `:download --dest [dest] [url]` instead.
==== positional arguments
* +'url'+: The URL to download. If not given, download the current page.
* +'dest'+: The file path to write the download to, or not given to ask.
==== optional arguments
* +*-m*+, +*--mhtml*+: Download the current page and all assets as mhtml file.
* +*-d*+, +*--dest*+: The file path to write the download to, or not given to ask.
[[download-cancel]]
=== download-cancel
@@ -158,6 +166,10 @@ Cancel the last/[count]th download.
==== count
The index of the download to cancel.
[[download-clear]]
=== download-clear
Remove all finished downloads from the list.
[[download-delete]]
=== download-delete
Delete the last/[count]th download from disk.
@@ -179,11 +191,32 @@ Syntax: +:download-remove [*--all*]+
Remove the last/[count]th download from the list.
==== optional arguments
* +*-a*+, +*--all*+: If given removes all finished downloads.
* +*-a*+, +*--all*+: Deprecated argument for removing all finished downloads.
==== count
The index of the download to cancel.
[[download-retry]]
=== download-retry
Retry the first failed/[count]th download.
==== count
The index of the download to cancel.
[[fake-key]]
=== fake-key
Syntax: +:fake-key [*--global*] 'keystring'+
Send a fake keypress or key string to the website or qutebrowser.
:fake-key xy - sends the keychain 'xy' :fake-key <Ctrl-x> - sends Ctrl-x :fake-key <Escape> - sends the escape key
==== positional arguments
* +'keystring'+: The keystring to send.
==== optional arguments
* +*-g*+, +*--global*+: If given, the keys are sent to the qutebrowser UI.
[[forward]]
=== forward
Syntax: +:forward [*--tab*] [*--bg*] [*--window*]+
@@ -261,7 +294,11 @@ Start hinting.
- With `spawn`: The executable and arguments to spawn.
`{hint-url}` will get replaced by the selected
URL.
- With `userscript`: The userscript to execute.
- With `userscript`: The userscript to execute. Either store
the userscript in
`~/.local/share/qutebrowser/userscripts`
(or `$XDG_DATA_DIR`), or use an absolute
path.
- With `fill`: The command to fill the statusbar with.
`{hint-url}` will get replaced by the selected
URL.
@@ -554,7 +591,7 @@ If the option name ends with '?', the value of the option is shown instead. If t
[[set-cmd-text]]
=== set-cmd-text
Syntax: +:set-cmd-text [*--space*] 'text'+
Syntax: +:set-cmd-text [*--space*] [*--append*] 'text'+
Preset the statusbar to some text.
@@ -563,6 +600,7 @@ Preset the statusbar to some text.
==== optional arguments
* +*-s*+, +*--space*+: If given, a space is added to the end.
* +*-a*+, +*--append*+: If given, the text is appended to the current text.
==== note
* This command does not split arguments after the last argument and handles quotes literally.
@@ -580,7 +618,9 @@ Note the {url} variable which gets replaced by the current URL might be useful h
* +'cmdline'+: The commandline to execute.
==== optional arguments
* +*-u*+, +*--userscript*+: Run the command as a userscript.
* +*-u*+, +*--userscript*+: Run the command as a userscript. Either store the userscript in `~/.local/share/qutebrowser/userscripts`
(or `$XDG_DATA_DIR`), or use an absolute path.
* +*-v*+, +*--verbose*+: Show notifications when the command started/exited.
* +*-d*+, +*--detach*+: Whether the command should be detached from qutebrowser.
@@ -769,7 +809,7 @@ How many steps to zoom out.
|<<completion-item-prev,completion-item-prev>>|Select the previous completion item.
|<<drop-selection,drop-selection>>|Drop selection and keep selection mode enabled.
|<<enter-mode,enter-mode>>|Enter a key mode.
|<<follow-hint,follow-hint>>|Follow the currently selected hint.
|<<follow-hint,follow-hint>>|Follow a hint.
|<<follow-selected,follow-selected>>|Follow the selected text.
|<<leave-mode,leave-mode>>|Leave the mode we're currently in.
|<<message-error,message-error>>|Show an error message in the statusbar.
@@ -858,7 +898,12 @@ Enter a key mode.
[[follow-hint]]
=== follow-hint
Follow the currently selected hint.
Syntax: +:follow-hint ['keystring']+
Follow a hint.
==== positional arguments
* +'keystring'+: The hint to follow.
[[follow-selected]]
=== follow-selected
@@ -1091,7 +1136,7 @@ This acts like readline's yank.
[[scroll]]
=== scroll
Syntax: +:scroll 'direction' ['dy']+
Syntax: +:scroll 'direction'+
Scroll the current tab in the given direction.
@@ -1181,6 +1226,7 @@ These commands are mainly intended for debugging. They are hidden if qutebrowser
|<<debug-cache-stats,debug-cache-stats>>|Print LRU cache stats.
|<<debug-console,debug-console>>|Show the debugging console.
|<<debug-crash,debug-crash>>|Crash for debugging purposes.
|<<debug-dump-page,debug-dump-page>>|Dump the current page's content to a file.
|<<debug-pyeval,debug-pyeval>>|Evaluate a python string and display the results as a web page.
|<<debug-trace,debug-trace>>|Trace executed code via hunter.
|<<debug-webaction,debug-webaction>>|Execute a webaction.
@@ -1206,6 +1252,18 @@ Crash for debugging purposes.
==== positional arguments
* +'typ'+: either 'exception' or 'segfault'.
[[debug-dump-page]]
=== debug-dump-page
Syntax: +:debug-dump-page [*--plain*] 'dest'+
Dump the current page's content to a file.
==== positional arguments
* +'dest'+: Where to write the file to.
==== optional arguments
* +*-p*+, +*--plain*+: Write plain text instead of HTML.
[[debug-pyeval]]
=== debug-pyeval
Syntax: +:debug-pyeval 's'+

View File

@@ -20,9 +20,10 @@
|<<general-site-specific-quirks,site-specific-quirks>>|Enable workarounds for broken sites.
|<<general-default-encoding,default-encoding>>|Default encoding to use for websites.
|<<general-new-instance-open-target,new-instance-open-target>>|How to open links in an existing instance if a new one is launched.
|<<general-log-javascript-console,log-javascript-console>>|Whether to log javascript console messages.
|<<general-log-javascript-console,log-javascript-console>>|How to log javascript console messages.
|<<general-save-session,save-session>>|Whether to always save the open pages.
|<<general-session-default-name,session-default-name>>|The name of the session to save by default, or empty for the last loaded session.
|<<general-url-incdec-segments,url-incdec-segments>>|The URL segments where `:navigate increment/decrement` will search for a number.
|==============
.Quick reference for section ``ui''
@@ -41,12 +42,13 @@
|<<ui-user-stylesheet,user-stylesheet>>|User stylesheet to use (absolute filename, filename relative to the config directory or CSS string). Will expand environment variables.
|<<ui-css-media-type,css-media-type>>|Set the CSS media type.
|<<ui-smooth-scrolling,smooth-scrolling>>|Whether to enable smooth scrolling for webpages.
|<<ui-remove-finished-downloads,remove-finished-downloads>>|Whether to remove finished downloads automatically.
|<<ui-remove-finished-downloads,remove-finished-downloads>>|Number of milliseconds to wait before removing finished downloads. Will not be removed if value is -1.
|<<ui-hide-statusbar,hide-statusbar>>|Whether to hide the statusbar unless a message is shown.
|<<ui-statusbar-padding,statusbar-padding>>|Padding for statusbar (top, bottom, left, right).
|<<ui-window-title-format,window-title-format>>|The format to use for the window title. The following placeholders are defined:
|<<ui-hide-mouse-cursor,hide-mouse-cursor>>|Whether to hide the mouse cursor.
|<<ui-modal-js-dialog,modal-js-dialog>>|Use standard JavaScript modal dialog for alert() and confirm()
|<<ui-hide-wayland-decoration,hide-wayland-decoration>>|Hide the window decoration when using wayland (requires restart)
|==============
.Quick reference for section ``network''
@@ -76,6 +78,8 @@
|<<completion-web-history-max-items,web-history-max-items>>|How many URLs to show in the web history.
|<<completion-quick-complete,quick-complete>>|Whether to move on to the next part when there's only one possible completion left.
|<<completion-shrink,shrink>>|Whether to shrink the completion to be smaller than the configured size if there are no scrollbars.
|<<completion-scrollbar-width,scrollbar-width>>|Width of the scrollbar in the completion window (in px).
|<<completion-scrollbar-padding,scrollbar-padding>>|Padding of scrollbar handle in completion window (in px).
|==============
.Quick reference for section ``input''
@@ -114,6 +118,7 @@
|<<tabs-indicator-width,indicator-width>>|Width of the progress indicator (0 to disable).
|<<tabs-tabs-are-windows,tabs-are-windows>>|Whether to open windows instead of tabs.
|<<tabs-title-format,title-format>>|The format to use for the tab title. The following placeholders are defined:
|<<tabs-title-alignment,title-alignment>>|Alignment of the text inside of tabs
|<<tabs-mousewheel-tab-switching,mousewheel-tab-switching>>|Switch between tabs using the mouse wheel.
|<<tabs-padding,padding>>|Padding for tabs (top, bottom, left, right).
|<<tabs-indicator-padding,indicator-padding>>|Padding for indicators (top, bottom, left, right).
@@ -159,6 +164,8 @@
|<<content-cookies-store,cookies-store>>|Whether to store cookies.
|<<content-host-block-lists,host-block-lists>>|List of URLs of lists which contain hosts to block.
|<<content-host-blocking-enabled,host-blocking-enabled>>|Whether host blocking is enabled.
|<<content-host-blocking-whitelist,host-blocking-whitelist>>|List of domains that should always be loaded, despite being ad-blocked.
|<<content-enable-pdfjs,enable-pdfjs>>|Enable pdf.js to view PDF files in the browser.
|==============
.Quick reference for section ``hints''
@@ -169,7 +176,7 @@
|<<hints-opacity,opacity>>|Opacity for hints.
|<<hints-mode,mode>>|Mode to use for hints.
|<<hints-chars,chars>>|Chars used for hint strings.
|<<hints-min-chars,min-chars>>|Mininum number of chars used for hint strings.
|<<hints-min-chars,min-chars>>|Minimum number of chars used for hint strings.
|<<hints-scatter,scatter>>|Whether to scatter hint key chains (like Vimium) or not (like dwb).
|<<hints-uppercase,uppercase>>|Make chars in hint strings uppercase.
|<<hints-auto-follow,auto-follow>>|Whether to auto-follow a hint if there's only one left.
@@ -193,8 +200,10 @@
|<<colors-completion.item.selected.border.top,completion.item.selected.border.top>>|Top border color of the completion widget category headers.
|<<colors-completion.item.selected.border.bottom,completion.item.selected.border.bottom>>|Bottom border color of the selected completion item.
|<<colors-completion.match.fg,completion.match.fg>>|Foreground color of the matched text in the completion.
|<<colors-completion.scrollbar.fg,completion.scrollbar.fg>>|Color of the scrollbar handle in completion view.
|<<colors-completion.scrollbar.bg,completion.scrollbar.bg>>|Color of the scrollbar in completion view
|<<colors-statusbar.fg,statusbar.fg>>|Foreground color of the statusbar.
|<<colors-statusbar.bg,statusbar.bg>>|Foreground color of the statusbar.
|<<colors-statusbar.bg,statusbar.bg>>|Background color of the statusbar.
|<<colors-statusbar.fg.error,statusbar.fg.error>>|Foreground color of the statusbar if there was an error.
|<<colors-statusbar.bg.error,statusbar.bg.error>>|Background color of the statusbar if there was an error.
|<<colors-statusbar.fg.warning,statusbar.fg.warning>>|Foreground color of the statusbar if there is a warning.
@@ -211,7 +220,8 @@
|<<colors-statusbar.bg.caret-selection,statusbar.bg.caret-selection>>|Background color of the statusbar in caret mode with a selection
|<<colors-statusbar.progress.bg,statusbar.progress.bg>>|Background color of the progress bar.
|<<colors-statusbar.url.fg,statusbar.url.fg>>|Default foreground color of the URL in the statusbar.
|<<colors-statusbar.url.fg.success,statusbar.url.fg.success>>|Foreground color of the URL in the statusbar on successful load.
|<<colors-statusbar.url.fg.success,statusbar.url.fg.success>>|Foreground color of the URL in the statusbar on successful load (http).
|<<colors-statusbar.url.fg.success.https,statusbar.url.fg.success.https>>|Foreground color of the URL in the statusbar on successful load (https).
|<<colors-statusbar.url.fg.error,statusbar.url.fg.error>>|Foreground color of the URL in the statusbar on error.
|<<colors-statusbar.url.fg.warn,statusbar.url.fg.warn>>|Foreground color of the URL in the statusbar when there's a warning.
|<<colors-statusbar.url.fg.hover,statusbar.url.fg.hover>>|Foreground color of the URL in the statusbar for hovered links.
@@ -219,8 +229,10 @@
|<<colors-tabs.bg.odd,tabs.bg.odd>>|Background color of unselected odd tabs.
|<<colors-tabs.fg.even,tabs.fg.even>>|Foreground color of unselected even tabs.
|<<colors-tabs.bg.even,tabs.bg.even>>|Background color of unselected even tabs.
|<<colors-tabs.fg.selected,tabs.fg.selected>>|Foreground color of selected tabs.
|<<colors-tabs.bg.selected,tabs.bg.selected>>|Background color of selected tabs.
|<<colors-tabs.fg.selected.odd,tabs.fg.selected.odd>>|Foreground color of selected odd tabs.
|<<colors-tabs.bg.selected.odd,tabs.bg.selected.odd>>|Background color of selected odd tabs.
|<<colors-tabs.fg.selected.even,tabs.fg.selected.even>>|Foreground color of selected even tabs.
|<<colors-tabs.bg.selected.even,tabs.bg.selected.even>>|Background color of selected even tabs.
|<<colors-tabs.bg.bar,tabs.bg.bar>>|Background color of the tab bar.
|<<colors-tabs.indicator.start,tabs.indicator.start>>|Color gradient start for the tab indicator.
|<<colors-tabs.indicator.stop,tabs.indicator.stop>>|Color gradient end for the tab indicator.
@@ -294,7 +306,7 @@ Default: +pass:[true]+
=== startpage
The default page(s) to open at the start, separated by commas.
Default: +pass:[https://www.duckduckgo.com]+
Default: +pass:[https://duckduckgo.com]+
[[general-default-page]]
=== default-page
@@ -335,7 +347,8 @@ Default: +pass:[15000]+
=== editor
The editor (and arguments) to use for the `open-editor` command.
Use `{}` for the filename. The value gets split like in a shell, so you can use `"` or `'` to quote arguments.
The arguments get split like in a shell, so you can use `"` or `'` to quote them.
`{}` gets replaced by the filename of the file to be edited.
Default: +pass:[gvim -f &quot;{}&quot;]+
@@ -428,14 +441,15 @@ Default: +pass:[tab]+
[[general-log-javascript-console]]
=== log-javascript-console
Whether to log javascript console messages.
How to log javascript console messages.
Valid values:
* +true+
* +false+
* +none+: Don't log messages.
* +debug+: Log messages with debug level.
* +info+: Log messages with info level.
Default: +pass:[false]+
Default: +pass:[debug]+
[[general-save-session]]
=== save-session
@@ -454,6 +468,19 @@ The name of the session to save by default, or empty for the last loaded session
Default: empty
[[general-url-incdec-segments]]
=== url-incdec-segments
The URL segments where `:navigate increment/decrement` will search for a number.
Valid values:
* +host+
* +path+
* +query+
* +anchor+
Default: +pass:[path,query]+
== ui
General options related to the user interface.
@@ -570,14 +597,9 @@ Default: +pass:[false]+
[[ui-remove-finished-downloads]]
=== remove-finished-downloads
Whether to remove finished downloads automatically.
Number of milliseconds to wait before removing finished downloads. Will not be removed if value is -1.
Valid values:
* +true+
* +false+
Default: +pass:[false]+
Default: +pass:[-1]+
[[ui-hide-statusbar]]
=== hide-statusbar
@@ -605,6 +627,7 @@ The format to use for the window title. The following placeholders are defined:
* `{title}`: The title of the current web page
* `{title_sep}`: The string ` - ` if a title is set, empty otherwise.
* `{id}`: The internal window ID of this window.
* `{scroll_pos}`: The page scroll position.
Default: +pass:[{perc}{title}{title_sep}qutebrowser]+
@@ -630,6 +653,17 @@ Valid values:
Default: +pass:[false]+
[[ui-hide-wayland-decoration]]
=== hide-wayland-decoration
Hide the window decoration when using wayland (requires restart)
Valid values:
* +true+
* +false+
Default: +pass:[false]+
== network
Settings related to the network.
@@ -802,6 +836,18 @@ Valid values:
Default: +pass:[false]+
[[completion-scrollbar-width]]
=== scrollbar-width
Width of the scrollbar in the completion window (in px).
Default: +pass:[12]+
[[completion-scrollbar-padding]]
=== scrollbar-padding
Padding of scrollbar handle in completion window (in px).
Default: +pass:[2]+
== input
Options related to input modes.
@@ -1079,9 +1125,22 @@ The format to use for the tab title. The following placeholders are defined:
* `{title_sep}`: The string ` - ` if a title is set, empty otherwise.
* `{index}`: The index of this tab.
* `{id}`: The internal tab ID of this tab.
* `{scroll_pos}`: The page scroll position.
Default: +pass:[{index}: {title}]+
[[tabs-title-alignment]]
=== title-alignment
Alignment of the text inside of tabs
Valid values:
* +left+
* +right+
* +center+
Default: +pass:[left]+
[[tabs-mousewheel-tab-switching]]
=== mousewheel-tab-switching
Switch between tabs using the mouse wheel.
@@ -1433,6 +1492,29 @@ Valid values:
Default: +pass:[true]+
[[content-host-blocking-whitelist]]
=== host-blocking-whitelist
List of domains that should always be loaded, despite being ad-blocked.
Domains may contain * and ? wildcards and are otherwise required to exactly match the requested domain.
Local domains are always exempt from hostblocking.
Default: +pass:[piwik.org]+
[[content-enable-pdfjs]]
=== enable-pdfjs
Enable pdf.js to view PDF files in the browser.
Note that the files can still be downloaded by clicking the download button in the pdf.js viewer.
Valid values:
* +true+
* +false+
Default: +pass:[false]+
== hints
Hinting settings.
@@ -1467,7 +1549,7 @@ Default: +pass:[asdfghjkl]+
[[hints-min-chars]]
=== min-chars
Mininum number of chars used for hint strings.
Minimum number of chars used for hint strings.
Default: +pass:[1]+
@@ -1613,6 +1695,18 @@ Foreground color of the matched text in the completion.
Default: +pass:[#ff4444]+
[[colors-completion.scrollbar.fg]]
=== completion.scrollbar.fg
Color of the scrollbar handle in completion view.
Default: +pass:[${completion.fg}]+
[[colors-completion.scrollbar.bg]]
=== completion.scrollbar.bg
Color of the scrollbar in completion view
Default: +pass:[${completion.bg}]+
[[colors-statusbar.fg]]
=== statusbar.fg
Foreground color of the statusbar.
@@ -1621,7 +1715,7 @@ Default: +pass:[white]+
[[colors-statusbar.bg]]
=== statusbar.bg
Foreground color of the statusbar.
Background color of the statusbar.
Default: +pass:[black]+
@@ -1723,7 +1817,13 @@ Default: +pass:[${statusbar.fg}]+
[[colors-statusbar.url.fg.success]]
=== statusbar.url.fg.success
Foreground color of the URL in the statusbar on successful load.
Foreground color of the URL in the statusbar on successful load (http).
Default: +pass:[white]+
[[colors-statusbar.url.fg.success.https]]
=== statusbar.url.fg.success.https
Foreground color of the URL in the statusbar on successful load (https).
Default: +pass:[lime]+
@@ -1769,18 +1869,30 @@ Background color of unselected even tabs.
Default: +pass:[darkgrey]+
[[colors-tabs.fg.selected]]
=== tabs.fg.selected
Foreground color of selected tabs.
[[colors-tabs.fg.selected.odd]]
=== tabs.fg.selected.odd
Foreground color of selected odd tabs.
Default: +pass:[white]+
[[colors-tabs.bg.selected]]
=== tabs.bg.selected
Background color of selected tabs.
[[colors-tabs.bg.selected.odd]]
=== tabs.bg.selected.odd
Background color of selected odd tabs.
Default: +pass:[black]+
[[colors-tabs.fg.selected.even]]
=== tabs.fg.selected.even
Foreground color of selected even tabs.
Default: +pass:[${tabs.fg.selected.odd}]+
[[colors-tabs.bg.selected.even]]
=== tabs.bg.selected.even
Background color of selected even tabs.
Default: +pass:[${tabs.bg.selected.odd}]+
[[colors-tabs.bg.bar]]
=== tabs.bg.bar
Background color of the tab bar.
@@ -1814,6 +1926,7 @@ Valid values:
* +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.
Default: +pass:[rgb]+
@@ -1874,6 +1987,7 @@ Valid values:
* +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.
Default: +pass:[rgb]+
@@ -1886,6 +2000,7 @@ Valid values:
* +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.
Default: +pass:[rgb]+

View File

@@ -62,6 +62,9 @@ show it.
*-R*, *--override-restore*::
Don't restore a session even if one would be restored.
*--target* '{auto,tab,tab-bg,tab-silent,tab-bg-silent,window}'::
How URLs should be opened if there is already a qutebrowser instance running.
=== debug arguments
*-l* 'LOGLEVEL', *--loglevel* 'LOGLEVEL'::
Set loglevel

View File

@@ -76,7 +76,7 @@ Server = http://qutebrowser.org/qt-debug/$arch
Then install the packages:
----
# pacman -Sy pyqt5-common-debug python-pyqt5-debug qt5-base-debug qt5-webkit-debug
# pacman -Suy pyqt5-common-debug python-pyqt5-debug qt5-base-debug qt5-webkit-debug
----
The `-debug` packages conflict with the non-debug variants - it's safe to

View File

@@ -5,6 +5,9 @@ The Compiler <mail@qutebrowser.org>
qutebrowser is extensible by writing userscripts which can be called via the
`:spawn --userscript` command, or via a key binding.
You can also call a userscript via hints so they get the selected hint URL by
calling `:hint links userscript ...`.
These userscripts are similar to the (non-javascript) dwb userscripts. They can
be written in any language which can read environment variables and write to a
FIFO. Note they are *not* related to Greasemonkey userscripts.
@@ -15,6 +18,10 @@ mpv, a simple key binding to something like `:spawn mpv {url}` should suffice.
Also note userscripts need to have the executable bit set (`chmod +x`) for
qutebrowser to run them.
To call a userscript, it needs to be stored in your data directory under
`userscripts` (for example: `~/.local/share/qutebrowser/userscripts/myscript`),
or just use an absolute path.
Getting information
-------------------

View File

@@ -29,6 +29,8 @@ profile qutebrowser /usr/{local/,}bin/qutebrowser {
/proc/*/mounts r,
owner /tmp/** rwkl,
owner /run/user/*/ rw,
owner /run/user/*/** krw,
@{HOME}/.config/qutebrowser/** krw,
@{HOME}/.local/share/qutebrowser/** krw,

113
misc/userscripts/open_download Executable file
View File

@@ -0,0 +1,113 @@
#!/bin/bash -e
# Both standalone script and qutebrowser userscript that opens a rofi menu with
# all files from the download director and opens the selected file. It works
# both as a userscript and a standalone script that is called from outside of
# qutebrowser.
#
# Suggested keybinding (for "show downloads"):
# spawn --userscript ~/.config/qutebrowser/open_download
# sd
#
# Requirements:
# - rofi (in a recent version)
# - xdg-open and xdg-mime
# - You should configure qutebrowser to download files to a single directory
# - It comes in handy if you enable remove-finished-downloads. If you want to
# see the recent downloads, just press "sd".
#
# Thorsten Wißmann, 2015 (thorsten` on freenode)
# Any feedback is welcome!
# open a file from the download directory using rofi
DOWNLOAD_DIR=${DOWNLOAD_DIR:-$HOME/Downloads}
# the name of the rofi command
ROFI_CMD=${ROFI_CMD:-rofi}
ROFI_ARGS=${ROFI_ARGS:-}
msg() {
local cmd="$1"
shift
local msg="$*"
if [ -z "$QUTE_FIFO" ] ; then
echo "$cmd: $msg" >&2
else
echo "message-$cmd '${msg//\'/\\\'}'" >> "$QUTE_FIFO"
fi
}
die() {
msg error "$*"
if [ -n "$QUTE_FIFO" ] ; then
# when run as a userscript, the above error message already informs the
# user about the failure, and no additional "userscript exited with status
# 1" is needed.
exit 0;
else
exit 1;
fi
}
if ! [ -d "$DOWNLOAD_DIR" ] ; then
die "Download directory »$DOWNLOAD_DIR« not found!"
fi
if ! $(which "${ROFI_CMD}" > /dev/null ) ; then
die "Rofi command »${ROFI_CMD}« not found in PATH!"
fi
rofi_default_args=(
-monitor -2 # place above window
-location 6 # aligned at the bottom
-width 100 # use full window width
-i
-no-custom
-format i # make rofi return the index
-l 10
-p 'Open download:' -dmenu
)
crop-first-column() {
local maxlength=${1:-40}
local expression='s|^\([^\t]\{0,'"$maxlength"'\}\)[^\t]*\t|\1\t|'
sed "$expression"
}
ls-files() {
# add the slash at the end of the download dir enforces to follow the
# symlink, if the DOWNLOAD_DIR itself is a symlink
ls -Q --quoting-style escape -h -o -1 -A -t "${DOWNLOAD_DIR}/" \
| grep '^[-]' \
| cut -d' ' -f3- \
| sed 's,^\(.*[^\]\) \(.*\)$,\2\t\1,' \
| sed 's,\\\(.\),\1,g'
}
mapfile -t entries < <(ls-files)
# we need to manually check that there are items, because rofi doesn't show up
# if there are no items and -no-custom is passed to rofi.
if [ "${#entries[@]}" -eq 0 ] ; then
die "Download directory »${DOWNLOAD_DIR}« empty"
fi
line=$(printf "%s\n" "${entries[@]}" \
| crop-first-column 55 \
| column -s $'\t' -t \
| $ROFI_CMD "${rofi_default_args[@]}" $ROFI_ARGS) || true
if [ -z "$line" ]; then
exit 0
fi
file="${entries[$line]}"
file="${file%%$'\t'*}"
path="$DOWNLOAD_DIR/$file"
filetype=$(xdg-mime query filetype "$path")
application=$(xdg-mime query default "$filetype")
if [ -z "$application" ] ; then
die "Do not know how to open »$file« of type $filetype"
fi
msg info "Opening »$file« (of type $filetype) with ${application%.desktop}"
xdg-open "$path" &

60
misc/userscripts/qutedmenu Executable file
View File

@@ -0,0 +1,60 @@
#!/usr/bin/env bash
# Handle open -s && open -t with bemenu
#:bind o spawn --userscript /path/to/userscripts/qutedmenu open
#:bind O spawn --userscript /path/to/userscripts/qutedmenu tab
# If you would like to set a custom colorscheme/font use these dirs.
# https://github.com/halfwit/dotfiles/blob/master/.config/dmenu/bemenucolors
readonly confdir=${XDG_CONFIG_HOME:-$HOME/.config}
readonly datadir=${XDG_DATA_HOME:-$HOME/.local/share}
readonly optsfile=$confdir/dmenu/bemenucolors
create_menu() {
# Check quickmarks
while read -r url; do
printf -- '%s\n' "$url"
done < "$confdir"/qutebrowser/quickmarks
# Next bookmarks
while read -r url _; do
printf -- '%s\n' "$url"
done < "$confdir"/qutebrowser/bookmarks/urls
# Finally history
while read -r _ url; do
printf -- '%s\n' "$url"
done < "$datadir"/qutebrowser/history
}
get_selection() {
opts+=(-p qutebrowser)
#create_menu | dmenu -l 10 "${opts[@]}"
create_menu | bemenu -l 10 "${opts[@]}"
}
# Main
# https://github.com/halfwit/dotfiles/blob/master/.config/dmenu/font
if [[ -s $confdir/dmenu/font ]]; then
read -r font < "$confdir"/dmenu/font
fi
if [[ $font ]]; then
opts+=(-fn "$font")
fi
if [[ -s $optsfile ]]; then
source "$optsfile"
fi
url=$(get_selection)
url=${url/*http/http}
# If no selection is made, exit (escape pressed, e.g.)
[[ ! $url ]] && exit 0
case $1 in
open) printf '%s' "open $url" >> "$QUTE_FIFO" || qutebrowser "$url" ;;
tab) printf '%s' "open -t $url" >> "$QUTE_FIFO" || qutebrowser "$url" ;;
esac

141
misc/userscripts/view_in_mpv Executable file
View File

@@ -0,0 +1,141 @@
#!/bin/bash -e
#
# Behaviour:
# Userscript for qutebrowser which views the current web page in mpv using
# sensible mpv-flags. While viewing the page in MPV, all <video>, <embed>,
# and <object> tags in the original page are temporarily removed. Clicking on
# such a removed video restores the respective video.
#
# In order to use this script, just start it using `spawn --userscript` from
# qutebrowser. I recommend using an alias, e.g. put this in the
# [alias]-section of qutebrowser.conf:
#
# mpv = spawn --userscript /path/to/view_in_mpv
#
# Background:
# Most of my machines are too slow to play youtube videos using html5, but
# they work fine in mpv (and mpv has further advantages like video scaling,
# etc). Of course, I don't want the video to be played (or even to be
# downloaded) twice — in MPV and in qwebkit. So I often close the tab after
# opening it in mpv. However, I actually want to keep the rest of the page
# (comments and video suggestions), i.e. only the videos should disappear
# when mpv is started. And that's precisely what the present script does.
#
# Thorsten Wißmann, 2015 (thorsten` on freenode)
# Any feedback is welcome!
if [ -z "$QUTE_FIFO" ] ; then
cat 1>&2 <<EOF
Error: $0 can not be run as a standalone script.
It is a qutebrowser userscript. In order to use it, call it using
'spawn --userscript' as described in qute://help/userscripts.html
EOF
exit 1
fi
msg() {
local cmd="$1"
shift
local msg="$*"
if [ -z "$QUTE_FIFO" ] ; then
echo "$cmd: $msg" >&2
else
echo "message-$cmd '${msg//\'/\\\'}'" >> "$QUTE_FIFO"
fi
}
MPV_COMMAND=${MPV_COMMAND:-mpv}
# Warning: spaces in single flags are not supported
MPV_FLAGS=${MPV_FLAGS:- --force-window --no-terminal --keep-open=yes --ytdl }
video_command=( "$MPV_COMMAND" $MPV_FLAGS )
js() {
cat <<EOF
function descendantOfTagName(child, ancestorTagName) {
// tells whether child has some (proper) ancestor
// with the tag name ancestorTagName
while (child.parentNode != null) {
child = child.parentNode;
if (typeof child.tagName === 'undefined') break;
if (child.tagName.toUpperCase() == ancestorTagName.toUpperCase()) {
return true;
}
}
return false;
}
var App = {};
var all_videos = [];
all_videos.push.apply(all_videos, document.getElementsByTagName("video"));
all_videos.push.apply(all_videos, document.getElementsByTagName("object"));
all_videos.push.apply(all_videos, document.getElementsByTagName("embed"));
App.backup_videos = Array();
App.all_replacements = Array();
for (i = 0; i < all_videos.length; i++) {
var video = all_videos[i];
if (descendantOfTagName(video, "object")) {
// skip tags that are contained in an object, because we hide
// the object anyway.
continue;
}
var replacement = document.createElement("div");
replacement.innerHTML = "
<p style=\\"margin-bottom: 0.5em\\">
Opening page with:
<span style=\\"font-family: monospace;\\">${video_command[*]}</span>
</p>
<p>
In order to restore this particular video
<a style=\\"font-weight: bold;
color: white;
background: transparent;
\\"
onClick=\\"restore_video(this, " + i + ");\\"
href=\\"javascript: restore_video(this, " + i + ")\\"
>click here</a>.
</p>
";
replacement.style.position = "relative";
replacement.style.zIndex = "100003000000";
replacement.style.fontSize = "1rem";
replacement.style.textAlign = "center";
replacement.style.verticalAlign = "middle";
replacement.style.height = "100%";
replacement.style.background = "#101010";
replacement.style.color = "white";
replacement.style.border = "4px dashed #545454";
replacement.style.padding = "2em";
replacement.style.margin = "auto";
App.all_replacements[i] = replacement;
App.backup_videos[i] = video;
video.parentNode.replaceChild(replacement, video);
}
function restore_video(obj, index) {
obj = App.all_replacements[index];
video = App.backup_videos[index];
console.log(video);
obj.parentNode.replaceChild(video, obj);
}
/** force repainting the video, thanks to:
* http://martinwolf.org/2014/06/10/force-repaint-of-an-element-with-javascript/
*/
var siteHeader = document.getElementById('header');
siteHeader.style.display='none';
siteHeader.offsetHeight; // no need to store this anywhere, the reference is enough
siteHeader.style.display='block';
EOF
}
printjs() {
js | sed 's,//.*$,,' | tr '\n' ' '
}
echo "jseval -q $(printjs)" >> "$QUTE_FIFO"
msg info "Opening $QUTE_URL with mpv"
"${video_command[@]}" "$QUTE_URL"

View File

@@ -6,7 +6,9 @@ markers =
windows: Tests which only can run on Windows.
linux: Tests which only can run on Linux.
osx: Tests which only can run on OS X.
not_osx: Tests which can not run on OS X.
not_frozen: Tests which can't be run if sys.frozen is True.
not_xvfb: Tests which can't be run with Xvfb.
frozen: Tests which can only be run if sys.frozen is True.
integration: Tests which test a bigger portion of code, run without coverage.
flakes-ignore =
@@ -29,4 +31,11 @@ qt_log_ignore =
^QWindowsWindow::setGeometryDp: Unable to set geometry .*
^QProcess: Destroyed while process .* is still running\.
^"Method "GetAll" with signature "s" on interface "org\.freedesktop\.DBus\.Properties" doesn't exist
^virtual void QSslSocketBackendPrivate::transmit\(\) SSL write failed with error: -9805
^virtual void QSslSocketBackendPrivate::transmit\(\) SSLRead failed with: -9805
^Type conversion already registered from type .*
^QNetworkReplyImplPrivate::error: Internal problem, this method must only be called once\.
^QWaitCondition: Destroyed while threads are still waiting
^QXcbXSettings::QXcbXSettings\(QXcbScreen\*\) Failed to get selection owner for XSETTINGS_S atom
^QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to .*
^QXcbClipboard: SelectionRequest too old

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -24,12 +24,12 @@
import os.path
__author__ = "Florian Bruhin"
__copyright__ = "Copyright 2014-2015 Florian Bruhin (The Compiler)"
__copyright__ = "Copyright 2014-2016 Florian Bruhin (The Compiler)"
__license__ = "GPL"
__maintainer__ = __author__
__email__ = "mail@qutebrowser.org"
__version_info__ = (0, 4, 0)
__version__ = '.'.join(map(str, __version_info__))
__version_info__ = (0, 5, 0)
__version__ = '.'.join(str(e) for e in __version_info__)
__description__ = "A keyboard-driven, vim-like browser based on PyQt5 and QtWebKit."
basedir = os.path.dirname(os.path.realpath(__file__))

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env python3
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -29,8 +29,10 @@ import shutil
import tempfile
import atexit
import datetime
import tokenize
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebKit import QWebSettings
from PyQt5.QtGui import QDesktopServices, QPixmap, QIcon, QCursor, QWindow
from PyQt5.QtCore import (pyqtSlot, qInstallMessageHandler, QTimer, QUrl,
QObject, Qt, QEvent)
@@ -40,7 +42,7 @@ except ImportError:
hunter = None
import qutebrowser
import qutebrowser.resources # pylint: disable=unused-import
import qutebrowser.resources
from qutebrowser.completion.models import instances as completionmodels
from qutebrowser.commands import cmdutils, runners, cmdexc
from qutebrowser.config import style, config, websettings, configexc
@@ -58,8 +60,7 @@ qApp = None
def run(args):
"""Initialize everthing and run the application."""
# pylint: disable=too-many-statements
"""Initialize everything and run the application."""
if args.version:
print(version.version(short=True))
print()
@@ -102,8 +103,9 @@ def run(args):
if server is None:
sys.exit(usertypes.Exit.ok)
else:
server.got_args.connect(lambda args, cwd:
process_pos_args(args, cwd=cwd, via_ipc=True))
server.got_args.connect(lambda args, target_arg, cwd:
process_pos_args(args, cwd=cwd, via_ipc=True,
target_arg=target_arg))
init(args, crash_handler)
ret = qt_mainloop()
@@ -228,7 +230,7 @@ def _load_session(name):
session_manager.delete('_restart')
def process_pos_args(args, via_ipc=False, cwd=None):
def process_pos_args(args, via_ipc=False, cwd=None, target_arg=None):
"""Process positional commandline args.
URLs to open have no prefix, commands to execute begin with a colon.
@@ -237,6 +239,14 @@ def process_pos_args(args, via_ipc=False, cwd=None):
args: A list of arguments to process.
via_ipc: Whether the arguments were transmitted over IPC.
cwd: The cwd to use for fuzzy_url.
target_arg: Command line argument received by a running instance via
ipc. If the --target argument was not specified, target_arg
will be an empty string instead of None. This behavior is
caused by the PyQt signal
``got_args = pyqtSignal(list, str, str)``
used in the misc.ipc.IPCServer class. PyQt converts the
None value into a null QString and then back to an empty
python string
"""
if via_ipc and not args:
win_id = mainwindow.get_window(via_ipc, force_window=True)
@@ -254,7 +264,11 @@ def process_pos_args(args, via_ipc=False, cwd=None):
log.init.debug("Empty argument")
win_id = mainwindow.get_window(via_ipc, force_window=True)
else:
win_id = mainwindow.get_window(via_ipc)
if via_ipc and target_arg and target_arg != 'auto':
open_target = target_arg
else:
open_target = config.get('general', 'new-instance-open-target')
win_id = mainwindow.get_window(via_ipc, force_target=open_target)
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=win_id)
log.init.debug("Startup URL {}".format(cmd))
@@ -264,7 +278,6 @@ def process_pos_args(args, via_ipc=False, cwd=None):
message.error('current', "Error in startup argument '{}': "
"{}".format(cmd, e))
else:
open_target = config.get('general', 'new-instance-open-target')
background = open_target in ('tab-bg', 'tab-bg-silent')
tabbed_browser.tabopen(url, background=background)
@@ -413,30 +426,34 @@ def _init_modules(args, crash_handler):
cookie_jar = cookies.CookieJar(qApp)
objreg.register('cookie-jar', cookie_jar)
log.init.debug("Initializing cache...")
diskcache = cache.DiskCache(qApp)
diskcache = cache.DiskCache(standarddir.cache(), parent=qApp)
objreg.register('cache', diskcache)
log.init.debug("Initializing completions...")
completionmodels.init()
log.init.debug("Misc initialization...")
if config.get('ui', 'hide-wayland-decoration'):
os.environ['QT_WAYLAND_DISABLE_WINDOWDECORATION'] = '1'
else:
os.environ.pop('QT_WAYLAND_DISABLE_WINDOWDECORATION', None)
_maybe_hide_mouse_cursor()
objreg.get('config').changed.connect(_maybe_hide_mouse_cursor)
def _init_late_modules(args):
"""Initialize modules which can be inited after the window is shown."""
try:
log.init.debug("Reading web history...")
reader = objreg.get('web-history').async_read()
with debug.log_time(log.init, 'Reading history'):
while True:
QApplication.processEvents()
log.init.debug("Reading web history...")
reader = objreg.get('web-history').async_read()
with debug.log_time(log.init, 'Reading history'):
while True:
QApplication.processEvents()
try:
next(reader)
except StopIteration:
pass
except (OSError, UnicodeDecodeError) as e:
error.handle_fatal_exc(e, args, "Error while initializing!",
pre_text="Error while initializing")
sys.exit(usertypes.Exit.err_init)
except StopIteration:
break
except (OSError, UnicodeDecodeError) as e:
error.handle_fatal_exc(e, args, "Error while initializing!",
pre_text="Error while initializing")
sys.exit(usertypes.Exit.err_init)
class Quitter:
@@ -463,6 +480,25 @@ class Quitter:
"""Slot which gets invoked when the last window was closed."""
self.shutdown(last_window=True)
def _compile_modules(self):
"""Compile all modules to catch SyntaxErrors."""
if os.path.basename(sys.argv[0]) == 'qutebrowser':
# Launched via launcher script
return
elif hasattr(sys, 'frozen'):
return
else:
path = os.path.abspath(os.path.dirname(qutebrowser.__file__))
if not os.path.isdir(path):
# Probably running from an python egg.
return
for dirpath, _dirnames, filenames in os.walk(path):
for fn in filenames:
if os.path.splitext(fn)[1] == '.py':
with tokenize.open(os.path.join(dirpath, fn)) as f:
compile(f.read(), fn, 'exec')
def _get_restart_args(self, pages=(), session=None):
"""Get the current working directory and args to relaunch qutebrowser.
@@ -531,6 +567,10 @@ class Quitter:
except sessions.SessionError as e:
log.destroy.exception("Failed to save session!")
raise cmdexc.CommandError("Failed to save session: {}!".format(e))
except SyntaxError as e:
log.destroy.exception("Got SyntaxError")
raise cmdexc.CommandError("SyntaxError in {}:{}: {}".format(
e.filename, e.lineno, e))
if ok:
self.shutdown()
@@ -551,6 +591,7 @@ class Quitter:
Return:
True if the restart succeeded, False otherwise.
"""
self._compile_modules()
log.destroy.debug("sys.executable: {}".format(sys.executable))
log.destroy.debug("sys.path: {}".format(sys.path))
log.destroy.debug("sys.argv: {}".format(sys.argv))
@@ -650,14 +691,19 @@ class Quitter:
error.handle_fatal_exc(
e, self._args, "Error while saving!",
pre_text="Error while saving {}".format(key))
# Disable storage so removing tempdir will work
QWebSettings.setIconDatabasePath('')
QWebSettings.setOfflineWebApplicationCachePath('')
QWebSettings.globalSettings().setLocalStoragePath('')
# Re-enable faulthandler to stdout, then remove crash log
log.destroy.debug("Deactivating crash log...")
objreg.get('crash-handler').destroy_crashlogfile()
# Delete temp basedir
if self._args.temp_basedir:
atexit.register(shutil.rmtree, self._args.basedir)
atexit.register(shutil.rmtree, self._args.basedir,
ignore_errors=True)
# If we don't kill our custom handler here we might get segfaults
log.destroy.debug("Deactiving message handler...")
log.destroy.debug("Deactivating message handler...")
qInstallMessageHandler(None)
# Now we can hopefully quit without segfaults
log.destroy.debug("Deferring QApplication::exit...")
@@ -702,6 +748,12 @@ class Application(QApplication):
objreg.register('app', self)
self.launch_time = datetime.datetime.now()
self.focusObjectChanged.connect(self.on_focus_object_changed)
@pyqtSlot(QObject)
def on_focus_object_changed(self, obj):
"""Log when the focus object changed."""
log.misc.debug("Focus object changed: {!r}".format(obj))
def __repr__(self):
return utils.get_repr(self)
@@ -770,12 +822,9 @@ class EventFilter(QObject):
Return:
True if the event should be filtered, False if it's passed through.
"""
if qApp.overrideCursor() is None:
# Mouse cursor shown -> don't filter event
return False
else:
# Mouse cursor hidden -> filter event
return True
# Mouse cursor shown (overrideCursor None) -> don't filter event
# Mouse cursor hidden (overrideCursor not None) -> filter event
return qApp.overrideCursor() is not None
def eventFilter(self, obj, event):
"""Handle an event.

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -24,6 +24,7 @@ import os.path
import functools
import posixpath
import zipfile
import fnmatch
from qutebrowser.config import config
from qutebrowser.utils import objreg, standarddir, log, message
@@ -59,6 +60,22 @@ def get_fileobj(byte_io):
return io.TextIOWrapper(byte_io, encoding='utf-8')
def is_whitelisted_host(host):
"""Check if the given host is on the adblock whitelist.
Args:
host: The host of the request as string.
"""
whitelist = config.get('content', 'host-blocking-whitelist')
if whitelist is None:
return False
for pattern in whitelist:
if fnmatch.fnmatch(host, pattern.lower()):
return True
return False
class FakeDownload:
"""A download stub to use on_download_finished with local files."""
@@ -74,7 +91,7 @@ class HostBlocker:
"""Manage blocked hosts based from /etc/hosts-like files.
Attributes:
blocked_hosts: A set of blocked hosts.
_blocked_hosts: A set of blocked hosts.
_in_progress: The DownloadItems which are currently downloading.
_done_count: How many files have been read successfully.
_hosts_file: The path to the blocked-hosts file.
@@ -87,7 +104,7 @@ class HostBlocker:
'local')
def __init__(self):
self.blocked_hosts = set()
self._blocked_hosts = set()
self._in_progress = []
self._done_count = 0
data_dir = standarddir.data()
@@ -97,16 +114,23 @@ class HostBlocker:
self._hosts_file = os.path.join(data_dir, 'blocked-hosts')
objreg.get('config').changed.connect(self.on_config_changed)
def is_blocked(self, url):
"""Check if the given URL (as QUrl) is blocked."""
if not config.get('content', 'host-blocking-enabled'):
return False
host = url.host()
return host in self._blocked_hosts and not is_whitelisted_host(host)
def read_hosts(self):
"""Read hosts from the existing blocked-hosts file."""
self.blocked_hosts = set()
self._blocked_hosts = set()
if self._hosts_file is None:
return
if os.path.exists(self._hosts_file):
try:
with open(self._hosts_file, 'r', encoding='utf-8') as f:
for line in f:
self.blocked_hosts.add(line.strip())
self._blocked_hosts.add(line.strip())
except OSError:
log.misc.exception("Failed to read host blocklist!")
else:
@@ -121,7 +145,7 @@ class HostBlocker:
"""Update the adblock block lists."""
if self._hosts_file is None:
raise cmdexc.CommandError("No data storage is configured!")
self.blocked_hosts = set()
self._blocked_hosts = set()
self._done_count = 0
urls = config.get('content', 'host-block-lists')
download_manager = objreg.get('download-manager', scope='window',
@@ -189,7 +213,7 @@ class HostBlocker:
error_count += 1
continue
if host not in self.WHITELISTED:
self.blocked_hosts.add(host)
self._blocked_hosts.add(host)
log.misc.debug("{}: read {} lines".format(byte_io.name, line_count))
if error_count > 0:
message.error('current', "adblock: {} read errors for {}".format(
@@ -198,10 +222,10 @@ class HostBlocker:
def on_lists_downloaded(self):
"""Install block lists after files have been downloaded."""
with open(self._hosts_file, 'w', encoding='utf-8') as f:
for host in sorted(self.blocked_hosts):
for host in sorted(self._blocked_hosts):
f.write(host + '\n')
message.info('current', "adblock: Read {} hosts from {} sources."
.format(len(self.blocked_hosts), self._done_count))
.format(len(self._blocked_hosts), self._done_count))
@config.change_filter('content', 'host-block-lists')
def on_config_changed(self):

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -25,7 +25,7 @@ from PyQt5.QtCore import pyqtSlot
from PyQt5.QtNetwork import QNetworkDiskCache, QNetworkCacheMetaData
from qutebrowser.config import config
from qutebrowser.utils import utils, standarddir, objreg
from qutebrowser.utils import utils, objreg
class DiskCache(QNetworkDiskCache):
@@ -34,17 +34,15 @@ class DiskCache(QNetworkDiskCache):
Attributes:
_activated: Whether the cache should be used.
_cache_dir: The base directory for cache files (standarddir.cache())
_http_cache_dir: the HTTP subfolder in _cache_dir.
"""
def __init__(self, parent=None):
def __init__(self, cache_dir, parent=None):
super().__init__(parent)
cache_dir = standarddir.cache()
if config.get('general', 'private-browsing') or cache_dir is None:
self._activated = False
else:
self._activated = True
self.setCacheDirectory(os.path.join(standarddir.cache(), 'http'))
self.setMaximumCacheSize(config.get('storage', 'cache-size'))
self._cache_dir = cache_dir
self._http_cache_dir = os.path.join(cache_dir, 'http')
self._maybe_activate()
objreg.get('config').changed.connect(self.on_config_changed)
def __repr__(self):
@@ -52,19 +50,24 @@ class DiskCache(QNetworkDiskCache):
maxsize=self.maximumCacheSize(),
path=self.cacheDirectory())
def _maybe_activate(self):
"""Activate/deactivate the cache based on the config."""
if (config.get('general', 'private-browsing') or
self._cache_dir is None):
self._activated = False
else:
self._activated = True
self.setCacheDirectory(self._http_cache_dir)
self.setMaximumCacheSize(config.get('storage', 'cache-size'))
@pyqtSlot(str, str)
def on_config_changed(self, section, option):
"""Update cache size/activated if the config was changed."""
if (section, option) == ('storage', 'cache-size'):
self.setMaximumCacheSize(config.get('storage', 'cache-size'))
elif (section, option) == ('general', 'private-browsing'):
if (config.get('general', 'private-browsing') or
standarddir.cache() is None):
self._activated = False
else:
self._activated = True
self.setCacheDirectory(
os.path.join(standarddir.cache(), 'http'))
elif (section, option) == ('general', # pragma: no branch
'private-browsing'):
self._maybe_activate()
def cacheSize(self):
"""Return the current size taken up by the cache.

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -20,6 +20,8 @@
"""Command dispatcher for TabbedBrowser."""
import os
import os.path
import sys
import shlex
import posixpath
import functools
@@ -37,7 +39,7 @@ import pygments.formatters
from qutebrowser.commands import userscripts, cmdexc, cmdutils, runners
from qutebrowser.config import config, configexc
from qutebrowser.browser import webelem, inspector, urlmarks
from qutebrowser.browser import webelem, inspector, urlmarks, downloads, mhtml
from qutebrowser.keyinput import modeman
from qutebrowser.utils import (message, usertypes, log, qtutils, urlutils,
objreg, utils)
@@ -152,59 +154,6 @@ class CommandDispatcher:
else:
return None
def _scroll_percent(self, perc=None, count=None, orientation=None):
"""Inner logic for scroll_percent_(x|y).
Args:
perc: How many percent to scroll, or None
count: How many percent to scroll, or None
orientation: Qt.Horizontal or Qt.Vertical
"""
if perc is None and count is None:
perc = 100
elif perc is None:
perc = count
if perc == 0:
self.scroll('top')
elif perc == 100:
self.scroll('bottom')
else:
perc = qtutils.check_overflow(perc, 'int', fatal=False)
frame = self._current_widget().page().currentFrame()
m = frame.scrollBarMaximum(orientation)
if m == 0:
return
frame.setScrollBarValue(orientation, int(m * perc / 100))
def _tab_move_absolute(self, idx):
"""Get an index for moving a tab absolutely.
Args:
idx: The index to get, as passed as count.
"""
if idx is None:
return 0
elif idx == 0:
return self._count() - 1
else:
return idx - 1
def _tab_move_relative(self, direction, delta):
"""Get an index for moving a tab relatively.
Args:
direction: + or - for relative moving, None for absolute.
delta: Delta to the current tab.
"""
if delta is None:
# We don't set delta to 1 in the function arguments because this
# gets called from tab_move which has delta set to None by default.
delta = 1
if direction == '-':
return self._current_index() - delta
elif direction == '+':
return self._current_index() + delta
def _tab_focus_last(self):
"""Select the tab which was last focused."""
try:
@@ -217,14 +166,6 @@ class CommandDispatcher:
raise cmdexc.CommandError("Last focused tab vanished!")
self._set_current_index(idx)
def _editor_cleanup(self, oshandle, filename):
"""Clean up temporary file when the editor was closed."""
try:
os.close(oshandle)
os.remove(filename)
except OSError:
raise cmdexc.CommandError("Failed to delete tempfile...")
def _get_selection_override(self, left, right, opposite):
"""Helper function for tab_close to get the tab to select.
@@ -253,6 +194,9 @@ class CommandDispatcher:
raise cmdexc.CommandError(
"-o is not supported with 'tabs->select-on-remove' set to "
"'previous'!")
else: # pragma: no cover
raise ValueError("Invalid select-on-remove value "
"{!r}!".format(conf_selection))
return None
@cmdutils.register(instance='command-dispatcher', scope='window',
@@ -387,8 +331,7 @@ class CommandDispatcher:
Return:
The new QWebView.
"""
if bg and window:
raise cmdexc.CommandError("Only one of -b/-w can be given!")
cmdutils.check_exclusive((bg, window), 'bw')
curtab = self._current_widget()
cur_title = self._tabbed_browser.page_title(self._current_index())
# The new tab could be in a new tabbed_browser (e.g. because of
@@ -402,7 +345,8 @@ class CommandDispatcher:
window=newtab.win_id)
idx = new_tabbed_browser.indexOf(newtab)
new_tabbed_browser.set_page_title(idx, cur_title)
new_tabbed_browser.setTabIcon(idx, curtab.icon())
if config.get('tabs', 'show-favicons'):
new_tabbed_browser.setTabIcon(idx, curtab.icon())
newtab.keep_icon = True
newtab.setZoomFactor(curtab.zoomFactor())
history = qtutils.serialize(curtab.history())
@@ -419,20 +363,27 @@ class CommandDispatcher:
def _back_forward(self, tab, bg, window, count, forward):
"""Helper function for :back/:forward."""
if (not forward and not
self._current_widget().page().history().canGoBack()):
# Catch common cases before e.g. cloning tab
history = self._current_widget().page().history()
if not forward and not history.canGoBack():
raise cmdexc.CommandError("At beginning of history.")
if (forward and not
self._current_widget().page().history().canGoForward()):
elif forward and not history.canGoForward():
raise cmdexc.CommandError("At end of history.")
if tab or bg or window:
widget = self.tab_clone(bg, window)
else:
widget = self._current_widget()
history = widget.page().history()
for _ in range(count):
if forward:
if not history.canGoForward():
raise cmdexc.CommandError("At end of history.")
widget.forward()
else:
if not history.canGoBack():
raise cmdexc.CommandError("At beginning of history.")
widget.back()
@cmdutils.register(instance='command-dispatcher', scope='window',
@@ -471,8 +422,9 @@ class CommandDispatcher:
background: Open the link in a new background tab.
window: Open the link in a new window.
"""
segments = set(config.get('general', 'url-incdec-segments'))
try:
new_url = urlutils.incdec_number(url, incdec)
new_url = urlutils.incdec_number(url, incdec, segments=segments)
except urlutils.IncDecError as error:
raise cmdexc.CommandError(error.msg)
self._open(new_url, tab, background, window)
@@ -534,13 +486,13 @@ class CommandDispatcher:
self._navigate_up(url, tab, bg, window)
elif where in ('decrement', 'increment'):
self._navigate_incdec(url, where, tab, bg, window)
else:
else: # pragma: no cover
raise ValueError("Got called with invalid value {} for "
"`where'.".format(where))
@cmdutils.register(instance='command-dispatcher', hide=True,
scope='window', count='count')
def scroll_px(self, dx: {'type': float}, dy: {'type': float}, count=1):
def scroll_px(self, dx: {'type': int}, dy: {'type': int}, count=1):
"""Scroll the current tab by 'count * dx/dy' pixels.
Args:
@@ -556,31 +508,14 @@ class CommandDispatcher:
@cmdutils.register(instance='command-dispatcher', hide=True,
scope='window', count='count')
def scroll(self,
direction: {'type': (str, float)},
dy: {'type': float, 'hide': True}=None,
count=1):
def scroll(self, direction: {'type': (str, int)}, count=1):
"""Scroll the current tab in the given direction.
Args:
direction: In which direction to scroll
(up/down/left/right/top/bottom).
dy: Deprecated argument to support the old dx/dy form.
count: multiplier
"""
try:
# Check for deprecated dx/dy form (like with scroll-px).
dx = float(direction)
dy = float(dy)
except (ValueError, TypeError):
# Invalid values will get handled later.
pass
else:
message.warning(self._win_id, ":scroll with dx/dy arguments is "
"deprecated - use :scroll-px instead!")
self.scroll_px(dx, dy, count=count)
return
fake_keys = {
'up': Qt.Key_Up,
'down': Qt.Key_Down,
@@ -594,9 +529,10 @@ class CommandDispatcher:
try:
key = fake_keys[direction]
except KeyError:
expected_values = ', '.join(sorted(fake_keys))
raise cmdexc.CommandError("Invalid value {!r} for direction - "
"expected one of: {}".format(
direction, ', '.join(fake_keys)))
direction, expected_values))
widget = self._current_widget()
frame = widget.page().currentFrame()
@@ -643,8 +579,24 @@ class CommandDispatcher:
horizontal: Scroll horizontally instead of vertically.
count: Percentage to scroll.
"""
self._scroll_percent(perc, count,
Qt.Horizontal if horizontal else Qt.Vertical)
if perc is None and count is None:
perc = 100
elif perc is None:
perc = count
orientation = Qt.Horizontal if horizontal else Qt.Vertical
if perc == 0 and orientation == Qt.Vertical:
self.scroll('top')
elif perc == 100 and orientation == Qt.Vertical:
self.scroll('bottom')
else:
perc = qtutils.check_overflow(perc, 'int', fatal=False)
frame = self._current_widget().page().currentFrame()
m = frame.scrollBarMaximum(orientation)
if m == 0:
return
frame.setScrollBarValue(orientation, int(m * perc / 100))
@cmdutils.register(instance='command-dispatcher', hide=True,
scope='window', count='count')
@@ -686,7 +638,7 @@ class CommandDispatcher:
pass
elif mult_y < 0:
self.scroll('page-up', count=-int(mult_y))
elif mult_y > 0:
elif mult_y > 0: # pragma: no branch
self.scroll('page-down', count=int(mult_y))
mult_y = 0
if mult_x == 0 and mult_y == 0:
@@ -728,9 +680,16 @@ class CommandDispatcher:
mode = QClipboard.Clipboard
target = "clipboard"
log.misc.debug("Yanking to {}: '{}'".format(target, s))
msg = "Yanked {} to {}: {}".format(what, target, s)
clipboard.changed.connect(functools.partial(
self._display_yank_msg, clipboard, msg))
clipboard.setText(s, mode)
message.info(self._win_id, "Yanked {} to {}: {}".format(
what, target, s))
def _display_yank_msg(self, clipboard, msg):
"""Display a message when something was yanked."""
message.info(self._win_id, msg)
clipboard.changed.disconnect()
@cmdutils.register(instance='command-dispatcher', scope='window',
count='count')
@@ -915,19 +874,25 @@ class CommandDispatcher:
If moving relatively: Offset.
"""
if direction is None:
new_idx = self._tab_move_absolute(count)
# absolute moving
new_idx = 0 if count is None else count - 1
elif direction in '+-':
try:
new_idx = self._tab_move_relative(direction, count)
except ValueError:
raise cmdexc.CommandError("Count must be given for relative "
"moving!")
else:
raise cmdexc.CommandError("Invalid direction '{}'!".format(
direction))
# relative moving
delta = 1 if count is None else count
if direction == '-':
new_idx = self._current_index() - delta
elif direction == '+': # pragma: no branch
new_idx = self._current_index() + delta
if config.get('tabs', 'wrap'):
new_idx %= self._count()
else: # pragma: no cover
raise ValueError("Invalid direction '{}'!".format(direction))
if not 0 <= new_idx < self._count():
raise cmdexc.CommandError("Can't move tab to position {}!".format(
new_idx))
new_idx + 1))
tab = self._current_widget()
cur_idx = self._current_index()
icon = self._tabbed_browser.tabIcon(cur_idx)
@@ -951,7 +916,9 @@ class CommandDispatcher:
useful here.
Args:
userscript: Run the command as a userscript.
userscript: Run the command as a userscript. Either store the
userscript in `~/.local/share/qutebrowser/userscripts`
(or `$XDG_DATA_DIR`), or use an absolute path.
verbose: Show notifications when the command started/exited.
detach: Whether the command should be detached from qutebrowser.
cmdline: The commandline to execute.
@@ -968,7 +935,7 @@ class CommandDispatcher:
cmd, args, userscript))
if userscript:
# ~ expansion is handled by the userscript module.
self.run_userscript(cmd, *args, verbose=verbose)
self._run_userscript(cmd, *args, verbose=verbose)
else:
cmd = os.path.expanduser(cmd)
proc = guiprocess.GUIProcess(self._win_id, what='command',
@@ -984,9 +951,7 @@ class CommandDispatcher:
"""Open main startpage in current tab."""
self.openurl(config.get('general', 'startpage')[0])
@cmdutils.register(instance='command-dispatcher', scope='window',
deprecated='Use :spawn --userscript instead!')
def run_userscript(self, cmd, *args: {'nargs': '*'}, verbose=False):
def _run_userscript(self, cmd, *args, verbose=False):
"""Run a userscript given as argument.
Args:
@@ -1138,34 +1103,72 @@ class CommandDispatcher:
cur.inspector.show()
@cmdutils.register(instance='command-dispatcher', scope='window')
def download(self, url=None, dest=None):
def download(self, url=None, dest_old: {'hide': True}=None, *,
mhtml_=False, dest=None):
"""Download a given URL, or current page if no URL given.
The form `:download [url] [dest]` is deprecated, use `:download --dest
[dest] [url]` instead.
Args:
url: The URL to download. If not given, download the current page.
dest_old: (deprecated) Same as dest.
dest: The file path to write the download to, or None to ask.
mhtml_: Download the current page and all assets as mhtml file.
"""
if dest_old is not None:
message.warning(
self._win_id, ":download [url] [dest] is deprecated - use"
" download --dest [dest] [url]")
if dest is not None:
raise cmdexc.CommandError("Can't give two destinations for the"
" download.")
dest = dest_old
download_manager = objreg.get('download-manager', scope='window',
window=self._win_id)
if url:
if mhtml_:
raise cmdexc.CommandError("Can only download the current page"
" as mhtml.")
url = urlutils.qurl_from_user_input(url)
urlutils.raise_cmdexc_if_invalid(url)
download_manager.get(url, filename=dest)
else:
page = self._current_widget().page()
download_manager.get(self._current_url(), page=page)
if mhtml_:
self._download_mhtml(dest)
else:
page = self._current_widget().page()
download_manager.get(self._current_url(), page=page,
filename=dest)
@cmdutils.register(instance='command-dispatcher', scope='window',
deprecated="Use :download instead.")
def download_page(self):
"""Download the current page."""
self.download()
def _download_mhtml(self, dest=None):
"""Download the current page as a MHTML file, including all assets.
Args:
dest: The file path to write the download to.
"""
web_view = self._current_widget()
if dest is None:
suggested_fn = self._current_title() + ".mht"
suggested_fn = utils.sanitize_filename(suggested_fn)
filename, q = downloads.ask_for_filename(
suggested_fn, self._win_id, parent=web_view,
)
if filename is not None:
mhtml.start_download_checked(filename, web_view=web_view)
else:
q.answered.connect(functools.partial(
mhtml.start_download_checked, web_view=web_view))
q.ask()
else:
mhtml.start_download_checked(dest, web_view=web_view)
@cmdutils.register(instance='command-dispatcher', scope='window')
def view_source(self):
"""Show the source of the current page."""
# pylint: disable=no-member
# https://bitbucket.org/logilab/pylint/issue/491/
# WORKAROUND for https://bitbucket.org/logilab/pylint/issue/491/
widget = self._current_widget()
if widget.viewing_source:
raise cmdexc.CommandError("Already viewing source!")
@@ -1180,6 +1183,32 @@ class CommandDispatcher:
tab.setHtml(highlighted, current_url)
tab.viewing_source = True
@cmdutils.register(instance='command-dispatcher', scope='window',
debug=True)
def debug_dump_page(self, dest, plain=False):
"""Dump the current page's content to a file.
Args:
dest: Where to write the file to.
plain: Write plain text instead of HTML.
"""
web_view = self._current_widget()
mainframe = web_view.page().mainFrame()
if plain:
data = mainframe.toPlainText()
else:
data = mainframe.toHtml()
dest = os.path.expanduser(dest)
try:
with open(dest, 'w', encoding='utf-8') as f:
f.write(data)
except OSError as e:
raise cmdexc.CommandError('Could not write page: {}'.format(e))
else:
message.info(self._win_id, "Dumped page to {}.".format(dest))
@cmdutils.register(instance='command-dispatcher', name='help',
completion=[usertypes.Completion.helptopic],
scope='window')
@@ -1269,6 +1298,17 @@ class CommandDispatcher:
except webelem.IsNullError:
raise cmdexc.CommandError("Element vanished while editing!")
def _clear_search(self, view, text):
"""Clear search string/highlights for the given view.
This does nothing if the view's search text is the same as the given
text.
"""
if view.search_text is not None and view.search_text != text:
# We first clear the marked text, then the highlights
view.search('', 0)
view.search('', QWebPage.HighlightAllOccurrences)
@cmdutils.register(instance='command-dispatcher', scope='window',
maxsplit=0)
def search(self, text="", reverse=False):
@@ -1279,11 +1319,7 @@ class CommandDispatcher:
reverse: Reverse search direction.
"""
view = self._current_widget()
if view.search_text is not None and view.search_text != text:
# We first clear the marked text, then the highlights
view.search('', 0)
view.search('', QWebPage.HighlightAllOccurrences)
self._clear_search(view, text)
flags = 0
ignore_case = config.get('general', 'ignore-case')
if ignore_case == 'smart':
@@ -1301,6 +1337,8 @@ class CommandDispatcher:
view.search(text, flags | QWebPage.HighlightAllOccurrences)
view.search_text = text
view.search_flags = flags
self._tabbed_browser.search_text = text
self._tabbed_browser.search_flags = flags
@cmdutils.register(instance='command-dispatcher', hide=True,
scope='window', count='count')
@@ -1311,7 +1349,14 @@ class CommandDispatcher:
count: How many elements to ignore.
"""
view = self._current_widget()
if view.search_text is not None:
self._clear_search(view, self._tabbed_browser.search_text)
if self._tabbed_browser.search_text is not None:
view.search_text = self._tabbed_browser.search_text
view.search_flags = self._tabbed_browser.search_flags
view.search(view.search_text,
view.search_flags | QWebPage.HighlightAllOccurrences)
for _ in range(count):
view.search(view.search_text, view.search_flags)
@@ -1324,8 +1369,13 @@ class CommandDispatcher:
count: How many elements to ignore.
"""
view = self._current_widget()
if view.search_text is None:
return
self._clear_search(view, self._tabbed_browser.search_text)
if self._tabbed_browser.search_text is not None:
view.search_text = self._tabbed_browser.search_text
view.search_flags = self._tabbed_browser.search_flags
view.search(view.search_text,
view.search_flags | QWebPage.HighlightAllOccurrences)
# The int() here serves as a QFlags constructor to create a copy of the
# QFlags instance rather as a reference. I don't know why it works this
# way, but it does.
@@ -1411,11 +1461,16 @@ class CommandDispatcher:
"""
webview = self._current_widget()
if not webview.selection_enabled:
act = QWebPage.MoveToNextWord
act = [QWebPage.MoveToNextWord]
if sys.platform == 'win32':
act.append(QWebPage.MoveToPreviousChar)
else:
act = QWebPage.SelectNextWord
act = [QWebPage.SelectNextWord]
if sys.platform == 'win32':
act.append(QWebPage.SelectPreviousChar)
for _ in range(count):
webview.triggerPageAction(act)
for a in act:
webview.triggerPageAction(a)
@cmdutils.register(instance='command-dispatcher', hide=True,
modes=[KeyMode.caret], scope='window', count='count')
@@ -1427,9 +1482,13 @@ class CommandDispatcher:
"""
webview = self._current_widget()
if not webview.selection_enabled:
act = [QWebPage.MoveToNextWord, QWebPage.MoveToNextChar]
act = [QWebPage.MoveToNextWord]
if sys.platform != 'win32':
act.append(QWebPage.MoveToNextChar)
else:
act = [QWebPage.SelectNextWord, QWebPage.SelectNextChar]
act = [QWebPage.SelectNextWord]
if sys.platform != 'win32':
act.append(QWebPage.SelectNextChar)
for _ in range(count):
for a in act:
webview.triggerPageAction(a)
@@ -1482,10 +1541,10 @@ class CommandDispatcher:
"""
webview = self._current_widget()
if not webview.selection_enabled:
act = [QWebPage.MoveToEndOfBlock, QWebPage.MoveToNextLine,
act = [QWebPage.MoveToNextLine,
QWebPage.MoveToStartOfBlock]
else:
act = [QWebPage.SelectEndOfBlock, QWebPage.SelectNextLine,
act = [QWebPage.SelectNextLine,
QWebPage.SelectStartOfBlock]
for _ in range(count):
for a in act:
@@ -1501,10 +1560,10 @@ class CommandDispatcher:
"""
webview = self._current_widget()
if not webview.selection_enabled:
act = [QWebPage.MoveToStartOfBlock, QWebPage.MoveToPreviousLine,
act = [QWebPage.MoveToPreviousLine,
QWebPage.MoveToStartOfBlock]
else:
act = [QWebPage.SelectStartOfBlock, QWebPage.SelectPreviousLine,
act = [QWebPage.SelectPreviousLine,
QWebPage.SelectStartOfBlock]
for _ in range(count):
for a in act:
@@ -1520,10 +1579,10 @@ class CommandDispatcher:
"""
webview = self._current_widget()
if not webview.selection_enabled:
act = [QWebPage.MoveToEndOfBlock, QWebPage.MoveToNextLine,
act = [QWebPage.MoveToNextLine,
QWebPage.MoveToEndOfBlock]
else:
act = [QWebPage.SelectEndOfBlock, QWebPage.SelectNextLine,
act = [QWebPage.SelectNextLine,
QWebPage.SelectEndOfBlock]
for _ in range(count):
for a in act:
@@ -1539,11 +1598,9 @@ class CommandDispatcher:
"""
webview = self._current_widget()
if not webview.selection_enabled:
act = [QWebPage.MoveToStartOfBlock, QWebPage.MoveToPreviousLine,
QWebPage.MoveToEndOfBlock]
act = [QWebPage.MoveToPreviousLine, QWebPage.MoveToEndOfBlock]
else:
act = [QWebPage.SelectStartOfBlock, QWebPage.SelectPreviousLine,
QWebPage.SelectEndOfBlock]
act = [QWebPage.SelectPreviousLine, QWebPage.SelectEndOfBlock]
for _ in range(count):
for a in act:
webview.triggerPageAction(a)
@@ -1590,7 +1647,6 @@ class CommandDispatcher:
else:
mode = QClipboard.Clipboard
target = "clipboard"
log.misc.debug("Yanking to {}: '{}'".format(target, s))
clipboard.setText(s, mode)
message.info(self._win_id, "{} {} yanked to {}".format(
len(s), "char" if len(s) == 1 else "chars", target))
@@ -1662,3 +1718,40 @@ class CommandDispatcher:
message.info(self._win_id, out[:5000] + ' [...trimmed...]')
else:
message.info(self._win_id, out)
@cmdutils.register(instance='command-dispatcher', scope='window')
def fake_key(self, keystring, global_=False):
"""Send a fake keypress or key string to the website or qutebrowser.
:fake-key xy - sends the keychain 'xy'
:fake-key <Ctrl-x> - sends Ctrl-x
:fake-key <Escape> - sends the escape key
Args:
keystring: The keystring to send.
global_: If given, the keys are sent to the qutebrowser UI.
"""
try:
keyinfos = utils.parse_keystring(keystring)
except utils.KeyParseError as e:
raise cmdexc.CommandError(str(e))
for keyinfo in keyinfos:
press_event = QKeyEvent(QEvent.KeyPress, keyinfo.key,
keyinfo.modifiers, keyinfo.text)
release_event = QKeyEvent(QEvent.KeyRelease, keyinfo.key,
keyinfo.modifiers, keyinfo.text)
if global_:
receiver = QApplication.focusWindow()
if receiver is None:
raise cmdexc.CommandError("No focused window!")
else:
try:
receiver = objreg.get('webview', scope='tab',
tab='current')
except objreg.RegistryUnavailableError:
raise cmdexc.CommandError("No focused webview!")
QApplication.postEvent(receiver, press_event)
QApplication.postEvent(receiver, release_event)

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -68,19 +68,27 @@ class CookieJar(RAMCookieJar):
_lineparser: The LineParser managing the cookies file.
"""
def __init__(self, parent=None):
def __init__(self, parent=None, *, line_parser=None):
super().__init__(parent)
self._lineparser = lineparser.LineParser(
standarddir.data(), 'cookies', binary=True, parent=self)
cookies = []
for line in self._lineparser:
cookies += QNetworkCookie.parseCookies(line)
self.setAllCookies(cookies)
if line_parser:
self._lineparser = line_parser
else:
self._lineparser = lineparser.LineParser(
standarddir.data(), 'cookies', binary=True, parent=self)
self.parse_cookies()
objreg.get('config').changed.connect(self.cookies_store_changed)
objreg.get('save-manager').add_saveable(
'cookies', self.save, self.changed,
config_opt=('content', 'cookies-store'))
def parse_cookies(self):
"""Parse cookies from lineparser and store them."""
cookies = []
for line in self._lineparser:
cookies += QNetworkCookie.parseCookies(line)
self.setAllCookies(cookies)
def purge_old_cookies(self):
"""Purge expired cookies from the cookie jar."""
# Based on:

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -48,8 +48,13 @@ ModelRole = usertypes.enum('ModelRole', ['item'], start=Qt.UserRole,
RetryInfo = collections.namedtuple('RetryInfo', ['request', 'manager'])
DownloadPath = collections.namedtuple('DownloadPath', ['filename',
'question'])
# Remember the last used directory
_last_used_directory = None
last_used_directory = None
# All REFRESH_INTERVAL milliseconds, speeds will be recalculated and downloads
@@ -57,20 +62,20 @@ _last_used_directory = None
REFRESH_INTERVAL = 500
def _download_dir():
def download_dir():
"""Get the download directory to use."""
directory = config.get('storage', 'download-directory')
remember_dir = config.get('storage', 'remember-download-directory')
if remember_dir and _last_used_directory is not None:
return _last_used_directory
if remember_dir and last_used_directory is not None:
return last_used_directory
elif directory is None:
return standarddir.download()
else:
return directory
def _path_suggestion(filename):
def path_suggestion(filename):
"""Get the suggested file path.
Args:
@@ -79,15 +84,79 @@ def _path_suggestion(filename):
suggestion = config.get('completion', 'download-path-suggestion')
if suggestion == 'path':
# add trailing '/' if not present
return os.path.join(_download_dir(), '')
return os.path.join(download_dir(), '')
elif suggestion == 'filename':
return filename
elif suggestion == 'both':
return os.path.join(_download_dir(), filename)
return os.path.join(download_dir(), filename)
else:
raise ValueError("Invalid suggestion value {}!".format(suggestion))
def create_full_filename(basename, filename):
"""Create a full filename based on the given basename and filename.
Args:
basename: The basename to use if filename is a directory.
filename: The path to a folder or file where you want to save.
Return:
The full absolute path, or None if filename creation was not possible.
"""
if os.path.isabs(filename) and os.path.isdir(filename):
# We got an absolute directory from the user, so we save it under
# the default filename in that directory.
return os.path.join(filename, basename)
elif os.path.isabs(filename):
# We got an absolute filename from the user, so we save it under
# that filename.
return filename
return None
def ask_for_filename(suggested_filename, win_id, *, parent=None,
prompt_download_directory=None):
"""Prepare a question for a download-path.
If a filename can be determined directly, it is returned instead.
Returns a (filename, question)-namedtuple, in which one component is
None. filename is a string, question is a usertypes.Question. The
question has a special .ask() method that takes no arguments for
convenience, as this function does not yet ask the question, it
only prepares it.
Args:
suggested_filename: The "default"-name that is pre-entered as path.
win_id: The window where the question will be asked.
parent: The parent of the question (a QObject).
prompt_download_directory: If this is something else than None, it
will overwrite the
storage->prompt-download-directory setting.
"""
if prompt_download_directory is None:
prompt_download_directory = config.get('storage',
'prompt-download-directory')
if not prompt_download_directory:
return DownloadPath(filename=download_dir(), question=None)
encoding = sys.getfilesystemencoding()
suggested_filename = utils.force_encoding(suggested_filename,
encoding)
q = usertypes.Question(parent)
q.text = "Save file to:"
q.mode = usertypes.PromptMode.text
q.completed.connect(q.deleteLater)
q.default = path_suggestion(suggested_filename)
message_bridge = objreg.get('message-bridge', scope='window',
window=win_id)
q.ask = lambda: message_bridge.ask(q, blocking=False)
return DownloadPath(filename=None, question=q)
class DownloadItemStats(QObject):
"""Statistics (bytes done, total bytes, time, etc.) about a download.
@@ -201,6 +270,7 @@ class DownloadItem(QObject):
fileobj: The file object to download the file to.
reply: The QNetworkReply associated with this download.
retry_info: A RetryInfo instance.
raw_headers: The headers sent by the server.
_filename: The filename of the download.
_redirects: How many time we were redirected already.
_buffer: A BytesIO object to buffer incoming data until we know the
@@ -255,6 +325,7 @@ class DownloadItem(QObject):
self._filename = None
self.init_reply(reply)
self._win_id = win_id
self.raw_headers = {}
def __repr__(self):
return utils.get_repr(self, basename=self.basename)
@@ -354,6 +425,7 @@ class DownloadItem(QObject):
reply.finished.connect(self.on_reply_finished)
reply.error.connect(self.on_reply_error)
reply.readyRead.connect(self.on_ready_read)
reply.metaDataChanged.connect(self.on_meta_data_changed)
self.retry_info = RetryInfo(request=reply.request(),
manager=reply.manager())
if not self.fileobj:
@@ -420,6 +492,8 @@ class DownloadItem(QObject):
@pyqtSlot()
def retry(self):
"""Retry a failed download."""
assert self.done
assert not self.successful
download_manager = objreg.get('download-manager', scope='window',
window=self._win_id)
new_reply = self.retry_info.manager.get(self.retry_info.request)
@@ -442,7 +516,7 @@ class DownloadItem(QObject):
filename: The full filename to save the download to.
None: special value to stop the download.
"""
global _last_used_directory
global last_used_directory
if self.fileobj is not None:
raise ValueError("fileobj was already set! filename: {}, "
"existing: {}, fileobj {}".format(
@@ -452,13 +526,16 @@ class DownloadItem(QObject):
# See https://github.com/The-Compiler/qutebrowser/issues/427
encoding = sys.getfilesystemencoding()
filename = utils.force_encoding(filename, encoding)
if not self._create_full_filename(filename):
self._filename = create_full_filename(self.basename, filename)
if self._filename is None:
# We only got a filename (without directory) or a relative path
# from the user, so we append that to the default directory and
# try again.
self._create_full_filename(os.path.join(_download_dir(), filename))
self._filename = create_full_filename(
self.basename, os.path.join(download_dir(), filename))
_last_used_directory = os.path.dirname(self._filename)
self.basename = os.path.basename(self._filename)
last_used_directory = os.path.dirname(self._filename)
log.downloads.debug("Setting filename to {}".format(filename))
if os.path.isfile(self._filename):
@@ -475,25 +552,6 @@ class DownloadItem(QObject):
else:
self._create_fileobj()
def _create_full_filename(self, filename):
"""Try to create the full filename.
Return:
True if the full filename was created, False otherwise.
"""
if os.path.isabs(filename) and os.path.isdir(filename):
# We got an absolute directory from the user, so we save it under
# the default filename in that directory.
self._filename = os.path.join(filename, self.basename)
return True
elif os.path.isabs(filename):
# We got an absolute filename from the user, so we save it under
# that filename.
self._filename = filename
self.basename = os.path.basename(self._filename)
return True
return False
def set_fileobj(self, fileobj):
""""Set the file object to write the download to.
@@ -591,6 +649,15 @@ class DownloadItem(QObject):
if data is not None:
self._buffer.write(data)
@pyqtSlot()
def on_meta_data_changed(self):
"""Update the download's metadata."""
if self.reply is None:
return
self.raw_headers = {}
for key, value in self.reply.rawHeaderPairs():
self.raw_headers[bytes(key)] = bytes(value)
def _handle_redirect(self):
"""Handle a HTTP redirect.
@@ -649,15 +716,10 @@ class DownloadManager(QAbstractListModel):
def __repr__(self):
return utils.get_repr(self, downloads=len(self.downloads))
def _prepare_question(self):
"""Prepare a Question object to be asked."""
q = usertypes.Question(self)
q.text = "Save file to:"
q.mode = usertypes.PromptMode.text
q.completed.connect(q.deleteLater)
def _postprocess_question(self, q):
"""Postprocess a Question object that is asked."""
q.destroyed.connect(functools.partial(self.questions.remove, q))
self.questions.append(q)
return q
@pyqtSlot()
def update_gui(self):
@@ -714,11 +776,12 @@ class DownloadManager(QAbstractListModel):
QNetworkRequest.AlwaysNetwork)
suggested_fn = urlutils.filename_from_url(request.url())
if prompt_download_directory is None:
prompt_download_directory = config.get(
'storage', 'prompt-download-directory')
if not prompt_download_directory and not fileobj:
filename = config.get('storage', 'download-directory')
# We won't need a question if a filename or fileobj is already given
if fileobj is None and filename is None:
filename, q = ask_for_filename(
suggested_fn, self._win_id, parent=self,
prompt_download_directory=prompt_download_directory
)
if fileobj is not None or filename is not None:
return self.fetch_request(request,
@@ -726,21 +789,13 @@ class DownloadManager(QAbstractListModel):
filename=filename,
suggested_filename=suggested_fn,
**kwargs)
if suggested_fn is None:
suggested_fn = 'qutebrowser-download'
else:
encoding = sys.getfilesystemencoding()
suggested_fn = utils.force_encoding(suggested_fn, encoding)
q = self._prepare_question()
q.default = _path_suggestion(suggested_fn)
message_bridge = objreg.get('message-bridge', scope='window',
window=self._win_id)
q.answered.connect(
lambda fn: self.fetch_request(request,
filename=fn,
suggested_filename=suggested_fn,
**kwargs))
message_bridge.ask(q, blocking=False)
self._postprocess_question(q)
q.ask()
return None
def fetch_request(self, request, *, page=None, **kwargs):
@@ -771,7 +826,7 @@ class DownloadManager(QAbstractListModel):
fileobj: The file object to write the answer to.
filename: A path to write the data to.
auto_remove: Whether to remove the download even if
ui -> remove-finished-downloads is set to false.
ui -> remove-finished-downloads is set to -1.
Return:
The created DownloadItem.
@@ -790,9 +845,15 @@ class DownloadManager(QAbstractListModel):
download = DownloadItem(reply, self._win_id, self)
download.cancelled.connect(
functools.partial(self.remove_item, download))
if config.get('ui', 'remove-finished-downloads') or auto_remove:
delay = config.get('ui', 'remove-finished-downloads')
if delay > -1:
download.finished.connect(
functools.partial(self.remove_item_delayed, download, delay))
elif auto_remove:
download.finished.connect(
functools.partial(self.remove_item, download))
download.data_changed.connect(
functools.partial(self.on_data_changed, download))
download.error.connect(self.on_error)
@@ -808,26 +869,33 @@ class DownloadManager(QAbstractListModel):
if not self._update_timer.isActive():
self._update_timer.start()
prompt_download_directory = config.get('storage',
'prompt-download-directory')
if not prompt_download_directory and not fileobj:
filename = config.get('storage', 'download-directory')
if fileobj is not None:
download.set_fileobj(fileobj)
download.autoclose = False
return download
if filename is not None:
download.set_filename(filename)
elif fileobj is not None:
download.set_fileobj(fileobj)
download.autoclose = False
else:
q = self._prepare_question()
q.default = _path_suggestion(suggested_filename)
q.answered.connect(download.set_filename)
q.cancelled.connect(download.cancel)
download.cancelled.connect(q.abort)
download.error.connect(q.abort)
message_bridge = objreg.get('message-bridge', scope='window',
window=self._win_id)
message_bridge.ask(q, blocking=False)
return download
# Neither filename nor fileobj were given, prepare a question
filename, q = ask_for_filename(
suggested_filename, self._win_id, parent=self,
prompt_download_directory=prompt_download_directory,
)
# User doesn't want to be asked, so just use the download_dir
if filename is not None:
download.set_filename(filename)
return download
# Ask the user for a filename
self._postprocess_question(q)
q.answered.connect(download.set_filename)
q.cancelled.connect(download.cancel)
download.cancelled.connect(q.abort)
download.error.connect(q.abort)
q.ask()
return download
@@ -879,17 +947,6 @@ class DownloadManager(QAbstractListModel):
download.delete()
self.remove_item(download)
@cmdutils.register(instance='download-manager', scope='window',
deprecated="Use :download-cancel instead.",
count='count')
def cancel_download(self, count=1):
"""Cancel the first/[count]th download.
Args:
count: The index of the download to cancel.
"""
self.download_cancel(count)
@cmdutils.register(instance='download-manager', scope='window',
count='count')
def download_open(self, count=0):
@@ -908,6 +965,31 @@ class DownloadManager(QAbstractListModel):
raise cmdexc.CommandError("Download {} is not done!".format(count))
download.open_file()
@cmdutils.register(instance='download-manager', scope='window',
count='count')
def download_retry(self, count=0):
"""Retry the first failed/[count]th download.
Args:
count: The index of the download to cancel.
"""
if count:
try:
download = self.downloads[count - 1]
except IndexError:
self.raise_no_download(count)
if download.successful or not download.done:
raise cmdexc.CommandError("Download {} did not fail!".format(
count))
else:
to_retry = [d for d in self.downloads
if d.done and not d.successful]
if not to_retry:
raise cmdexc.CommandError("No failed downloads!")
else:
download = to_retry[0]
download.retry()
@pyqtSlot(QNetworkRequest, QNetworkReply)
def on_redirect(self, download, request, reply):
"""Handle a HTTP redirect of a download.
@@ -963,18 +1045,25 @@ class DownloadManager(QAbstractListModel):
"""Check if there are finished downloads to clear."""
return any(download.done for download in self.downloads)
@cmdutils.register(instance='download-manager', scope='window')
def download_clear(self):
"""Remove all finished downloads from the list."""
finished_items = [d for d in self.downloads if d.done]
self.remove_items(finished_items)
@cmdutils.register(instance='download-manager', scope='window',
count='count')
def download_remove(self, all_=False, count=0):
"""Remove the last/[count]th download from the list.
Args:
all_: If given removes all finished downloads.
all_: Deprecated argument for removing all finished downloads.
count: The index of the download to cancel.
"""
if all_:
finished_items = [d for d in self.downloads if d.done]
self.remove_items(finished_items)
message.warning(self._win_id, ":download-remove --all is "
"deprecated - use :download-clear instead!")
self.download_clear()
else:
try:
download = self.downloads[count - 1]
@@ -1011,6 +1100,10 @@ class DownloadManager(QAbstractListModel):
if not self.downloads:
self._update_timer.stop()
def remove_item_delayed(self, download, delay):
"""Remove a given download after a short delay."""
QTimer.singleShot(delay, functools.partial(self.remove_item, download))
def remove_items(self, downloads):
"""Remove an iterable of downloads."""
# On the first pass, we only generate the indices so we get the

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -64,8 +64,8 @@ class DownloadView(QListView):
STYLESHEET = """
QListView {
{{ color['downloads.bg.bar'] }}
{{ font['downloads'] }}
background-color: {{ color['downloads.bg.bar'] }};
font: {{ font['downloads'] }};
}
QListView::item {
@@ -125,6 +125,7 @@ class DownloadView(QListView):
- (QAction, callable) tuples.
- (None, None) for a separator
"""
model = self.model()
actions = []
if item is None:
pass
@@ -134,13 +135,12 @@ class DownloadView(QListView):
else:
actions.append(("Retry", item.retry))
actions.append(("Remove",
functools.partial(self.model().remove_item, item)))
functools.partial(model.remove_item, item)))
else:
actions.append(("Cancel", item.cancel))
if self.model().can_clear():
if model.can_clear():
actions.append((None, None))
actions.append(("Remove all finished", functools.partial(
self.model().download_remove, True)))
actions.append(("Remove all finished", model.download_clear))
return actions
@pyqtSlot('QPoint')

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -43,8 +43,8 @@ ElemTuple = collections.namedtuple('ElemTuple', ['elem', 'label'])
Target = usertypes.enum('Target', ['normal', 'tab', 'tab_fg', 'tab_bg',
'window', 'yank', 'yank_primary', 'run',
'fill', 'hover', 'rapid', 'rapid_win',
'download', 'userscript', 'spawn'])
'fill', 'hover', 'download', 'userscript',
'spawn'])
@pyqtSlot(usertypes.KeyMode)
@@ -69,7 +69,6 @@ class HintContext:
yank/yank_primary: Yank to clipboard/primary selection.
run: Run a command.
fill: Fill commandline with link.
rapid: Rapid mode with background tabs
download: Download the link.
userscript: Call a custom userscript.
spawn: Spawn a simple command.
@@ -415,8 +414,6 @@ class HintManager(QObject):
context: The HintContext to use.
"""
target_mapping = {
Target.rapid: usertypes.ClickTarget.tab_bg,
Target.rapid_win: usertypes.ClickTarget.window,
Target.normal: usertypes.ClickTarget.normal,
Target.tab_fg: usertypes.ClickTarget.tab,
Target.tab_bg: usertypes.ClickTarget.tab_bg,
@@ -437,7 +434,7 @@ class HintManager(QObject):
action, elem, pos.x(), pos.y()))
self.start_hinting.emit(target_mapping[context.target])
if context.target in [Target.tab, Target.tab_fg, Target.tab_bg,
Target.window, Target.rapid, Target.rapid_win]:
Target.window]:
modifiers = Qt.ControlModifier
else:
modifiers = Qt.NoModifier
@@ -749,7 +746,11 @@ class HintManager(QObject):
- With `spawn`: The executable and arguments to spawn.
`{hint-url}` will get replaced by the selected
URL.
- With `userscript`: The userscript to execute.
- With `userscript`: The userscript to execute. Either store
the userscript in
`~/.local/share/qutebrowser/userscripts`
(or `$XDG_DATA_DIR`), or use an absolute
path.
- With `fill`: The command to fill the statusbar with.
`{hint-url}` will get replaced by the selected
URL.
@@ -798,7 +799,6 @@ class HintManager(QObject):
self._context.args = args
self._context.mainframe = mainframe
self._context.group = group
self._handle_old_rapid_targets(win_id)
self._init_elements()
message_bridge = objreg.get('message-bridge', scope='window',
window=self._win_id)
@@ -807,29 +807,6 @@ class HintManager(QObject):
modeman.enter(self._win_id, usertypes.KeyMode.hint,
'HintManager.start')
def _handle_old_rapid_targets(self, win_id):
"""Switch to the new way for rapid hinting with a rapid target.
Args:
win_id: The window ID to display the warning in.
DEPRECATED.
"""
old_rapid_targets = {
Target.rapid: Target.tab_bg,
Target.rapid_win: Target.window,
}
target = self._context.target
if target in old_rapid_targets:
self._context.target = old_rapid_targets[target]
self._context.rapid = True
name = target.name.replace('_', '-')
group_name = self._context.group.name.replace('_', '-')
new_name = self._context.target.name.replace('_', '-')
message.warning(
win_id, ':hint with target {} is deprecated, use :hint '
'--rapid {} {} instead!'.format(name, group_name, new_name))
def handle_partial_key(self, keystr):
"""Handle a new partial keypress."""
log.hints.debug("Handling new keystring: '{}'".format(keystr))
@@ -855,12 +832,12 @@ class HintManager(QObject):
"""Filter displayed hints according to a text.
Args:
filterstr: The string to filer with, or None to show all.
filterstr: The string to filter with, or None to show all.
"""
for elems in self._context.elems.values():
try:
if (filterstr is None or
str(elems.elem).lower().startswith(filterstr)):
filterstr.casefold() in str(elems.elem).casefold()):
if self._is_hidden(elems.label):
# hidden element which matches again -> show it
self._show_elem(elems.label)
@@ -942,12 +919,22 @@ class HintManager(QObject):
elems.label.setInnerXml(string)
handler()
@cmdutils.register(instance='hintmanager', scope='tab', hide=True)
def follow_hint(self):
"""Follow the currently selected hint."""
if not self._context.to_follow:
raise cmdexc.CommandError("No hint to follow")
self.fire(self._context.to_follow, force=True)
@cmdutils.register(instance='hintmanager', scope='tab', hide=True,
modes=[usertypes.KeyMode.hint])
def follow_hint(self, keystring=None):
"""Follow a hint.
Args:
keystring: The hint to follow, or None.
"""
if keystring is None:
if self._context.to_follow is None:
raise cmdexc.CommandError("No hint to follow")
else:
keystring = self._context.to_follow
elif keystring not in self._context.elems:
raise cmdexc.CommandError("No hint {}!".format(keystring))
self.fire(keystring, force=True)
@pyqtSlot('QSize')
def on_contents_size_changed(self, _size):

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2015-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -52,11 +52,6 @@ class HistoryEntry:
def __str__(self):
return '{} {}'.format(int(self.atime), self.url_string)
@classmethod
def from_str(cls, s):
"""Get a history based on a 'TIME URL' string."""
return cls(*s.split(' ', maxsplit=1))
class WebHistory(QWebHistoryInterface):

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2015-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -0,0 +1,532 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2015-2016 Daniel Schadt
#
# This file is part of qutebrowser.
#
# qutebrowser is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# qutebrowser is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
"""Utils for writing a MHTML file."""
import functools
import io
import os
import re
import sys
import collections
import uuid
import email.policy
import email.generator
import email.encoders
import email.mime.multipart
import email.message
from PyQt5.QtCore import QUrl
from qutebrowser.browser import webelem, downloads
from qutebrowser.utils import log, objreg, message, usertypes, utils, urlutils
try:
import cssutils
except (ImportError, re.error):
# Catching re.error because cssutils in earlier releases (<= 1.0) is broken
# on Python 3.5
# See https://bitbucket.org/cthedot/cssutils/issues/52
cssutils = None
_File = collections.namedtuple('_File',
['content', 'content_type', 'content_location',
'transfer_encoding'])
_CSS_URL_PATTERNS = [re.compile(x) for x in [
r"@import\s+'(?P<url>[^']+)'",
r'@import\s+"(?P<url>[^"]+)"',
r'''url\((?P<url>[^'"][^)]*)\)''',
r'url\("(?P<url>[^"]+)"\)',
r"url\('(?P<url>[^']+)'\)",
]]
def _get_css_imports_regex(data):
"""Return all assets that are referenced in the given CSS document.
The returned URLs are relative to the stylesheet's URL.
Args:
data: The content of the stylesheet to scan as string.
"""
urls = []
for pattern in _CSS_URL_PATTERNS:
for match in pattern.finditer(data):
url = match.group("url")
if url:
urls.append(url)
return urls
def _get_css_imports_cssutils(data, inline=False):
"""Return all assets that are referenced in the given CSS document.
The returned URLs are relative to the stylesheet's URL.
Args:
data: The content of the stylesheet to scan as string.
inline: True if the argument is a inline HTML style attribute.
"""
# We don't care about invalid CSS data, this will only litter the log
# output with CSS errors
parser = cssutils.CSSParser(loglevel=100,
fetcher=lambda url: (None, ""), validate=False)
if not inline:
sheet = parser.parseString(data)
return list(cssutils.getUrls(sheet))
else:
urls = []
declaration = parser.parseStyle(data)
# prop = background, color, margin, ...
for prop in declaration:
# value = red, 10px, url(foobar), ...
for value in prop.propertyValue:
if isinstance(value, cssutils.css.URIValue):
if value.uri:
urls.append(value.uri)
return urls
def _get_css_imports(data, inline=False):
"""Return all assets that are referenced in the given CSS document.
The returned URLs are relative to the stylesheet's URL.
Args:
data: The content of the stylesheet to scan as string.
inline: True if the argument is a inline HTML style attribute.
"""
if cssutils is None:
return _get_css_imports_regex(data)
else:
return _get_css_imports_cssutils(data, inline)
def _check_rel(element):
"""Return true if the element's rel attribute fits our criteria.
rel has to contain 'stylesheet' or 'icon'. Also returns True if the rel
attribute is unset.
Args:
element: The WebElementWrapper which should be checked.
"""
if 'rel' not in element:
return True
must_have = {'stylesheet', 'icon'}
rels = [rel.lower() for rel in element['rel'].split(' ')]
return any(rel in rels for rel in must_have)
MHTMLPolicy = email.policy.default.clone(linesep='\r\n', max_line_length=0)
# Encode the file using base64 encoding.
E_BASE64 = email.encoders.encode_base64
# Encode the file using MIME quoted-printable encoding.
E_QUOPRI = email.encoders.encode_quopri
class MHTMLWriter:
"""A class for outputting multiple files to a MHTML document.
Attributes:
root_content: The root content as bytes.
content_location: The url of the page as str.
content_type: The MIME-type of the root content as str.
_files: Mapping of location->_File namedtuple.
"""
def __init__(self, root_content, content_location, content_type):
self.root_content = root_content
self.content_location = content_location
self.content_type = content_type
self._files = {}
def add_file(self, location, content, content_type=None,
transfer_encoding=E_QUOPRI):
"""Add a file to the given MHTML collection.
Args:
location: The original location (URL) of the file.
content: The binary content of the file.
content_type: The MIME-type of the content (if available)
transfer_encoding: The transfer encoding to use for this file.
"""
self._files[location] = _File(
content=content, content_type=content_type,
content_location=location, transfer_encoding=transfer_encoding,
)
def write_to(self, fp):
"""Output the MHTML file to the given file-like object.
Args:
fp: The file-object, opened in "wb" mode.
"""
msg = email.mime.multipart.MIMEMultipart(
'related', '---=_qute-{}'.format(uuid.uuid4()))
root = self._create_root_file()
msg.attach(root)
for _, file_data in sorted(self._files.items()):
msg.attach(self._create_file(file_data))
gen = email.generator.BytesGenerator(fp, policy=MHTMLPolicy)
gen.flatten(msg)
def _create_root_file(self):
"""Return the root document as MIMEMultipart."""
root_file = _File(
content=self.root_content, content_type=self.content_type,
content_location=self.content_location, transfer_encoding=E_QUOPRI,
)
return self._create_file(root_file)
def _create_file(self, f):
"""Return the single given file as email.message.Message."""
msg = email.message.Message()
msg['MIME-Version'] = '1.0'
msg['Content-Location'] = f.content_location
if f.content_type:
msg.set_type(f.content_type)
msg.set_payload(f.content)
f.transfer_encoding(msg)
return msg
class _Downloader:
"""A class to download whole websites.
Attributes:
web_view: The QWebView which contains the website that will be saved.
dest: Destination filename.
writer: The MHTMLWriter object which is used to save the page.
loaded_urls: A set of QUrls of finished asset downloads.
pending_downloads: A set of unfinished (url, DownloadItem) tuples.
_finished_file: A flag indicating if the file has already been
written.
_used: A flag indicating if the downloader has already been used.
_win_id: The window this downloader belongs to.
"""
def __init__(self, web_view, dest):
self.web_view = web_view
self.dest = dest
self.writer = None
self.loaded_urls = {web_view.url()}
self.pending_downloads = set()
self._finished_file = False
self._used = False
self._win_id = web_view.win_id
def run(self):
"""Download and save the page.
The object must not be reused, you should create a new one if
you want to download another page.
"""
if self._used:
raise ValueError("Downloader already used")
self._used = True
web_url = self.web_view.url()
web_frame = self.web_view.page().mainFrame()
self.writer = MHTMLWriter(
web_frame.toHtml().encode('utf-8'),
content_location=urlutils.encoded_url(web_url),
# I've found no way of getting the content type of a QWebView, but
# since we're using .toHtml, it's probably safe to say that the
# content-type is HTML
content_type='text/html; charset="UTF-8"',
)
# Currently only downloading <link> (stylesheets), <script>
# (javascript) and <img> (image) elements.
elements = web_frame.findAllElements('link, script, img')
for element in elements:
element = webelem.WebElementWrapper(element)
# Websites are free to set whatever rel=... attribute they want.
# We just care about stylesheets and icons.
if not _check_rel(element):
continue
if 'src' in element:
element_url = element['src']
elif 'href' in element:
element_url = element['href']
else:
# Might be a local <script> tag or something else
continue
absolute_url = web_url.resolved(QUrl(element_url))
self._fetch_url(absolute_url)
styles = web_frame.findAllElements('style')
for style in styles:
style = webelem.WebElementWrapper(style)
# The Mozilla Developer Network says:
# type: This attribute defines the styling language as a MIME type
# (charset should not be specified). This attribute is optional and
# default to text/css if it's missing.
# https://developer.mozilla.org/en/docs/Web/HTML/Element/style
if 'type' in style and style['type'] != 'text/css':
continue
for element_url in _get_css_imports(str(style)):
self._fetch_url(web_url.resolved(QUrl(element_url)))
# Search for references in inline styles
for element in web_frame.findAllElements('[style]'):
element = webelem.WebElementWrapper(element)
style = element['style']
for element_url in _get_css_imports(style, inline=True):
self._fetch_url(web_url.resolved(QUrl(element_url)))
# Shortcut if no assets need to be downloaded, otherwise the file would
# never be saved. Also might happen if the downloads are fast enough to
# complete before connecting their finished signal.
self._collect_zombies()
if not self.pending_downloads and not self._finished_file:
self._finish_file()
def _fetch_url(self, url):
"""Download the given url and add the file to the collection.
Args:
url: The file to download as QUrl.
"""
if url.scheme() not in {'http', 'https'}:
return
# Prevent loading an asset twice
if url in self.loaded_urls:
return
self.loaded_urls.add(url)
log.downloads.debug("loading asset at {}".format(url))
# Using the download manager to download host-blocked urls might crash
# qute, see the comments/discussion on
# https://github.com/The-Compiler/qutebrowser/pull/962#discussion_r40256987
# and https://github.com/The-Compiler/qutebrowser/issues/1053
host_blocker = objreg.get('host-blocker')
if host_blocker.is_blocked(url):
log.downloads.debug("Skipping {}, host-blocked".format(url))
# We still need an empty file in the output, QWebView can be pretty
# picky about displaying a file correctly when not all assets are
# at least referenced in the mhtml file.
self.writer.add_file(urlutils.encoded_url(url), b'')
return
download_manager = objreg.get('download-manager', scope='window',
window=self._win_id)
item = download_manager.get(url, fileobj=_NoCloseBytesIO(),
auto_remove=True)
self.pending_downloads.add((url, item))
item.finished.connect(
functools.partial(self._finished, url, item))
item.error.connect(
functools.partial(self._error, url, item))
item.cancelled.connect(
functools.partial(self._error, url, item))
def _finished(self, url, item):
"""Callback when a single asset is downloaded.
Args:
url: The original url of the asset as QUrl.
item: The DownloadItem given by the DownloadManager
"""
self.pending_downloads.remove((url, item))
mime = item.raw_headers.get(b'Content-Type', b'')
# Note that this decoding always works and doesn't produce errors
# RFC 7230 (https://tools.ietf.org/html/rfc7230) states:
# Historically, HTTP has allowed field content with text in the
# ISO-8859-1 charset [ISO-8859-1], supporting other charsets only
# through use of [RFC2047] encoding. In practice, most HTTP header
# field values use only a subset of the US-ASCII charset [USASCII].
# Newly defined header fields SHOULD limit their field values to
# US-ASCII octets. A recipient SHOULD treat other octets in field
# content (obs-text) as opaque data.
mime = mime.decode('iso-8859-1')
if mime.lower() == 'text/css' or url.fileName().endswith('.css'):
# We can't always assume that CSS files are UTF-8, but CSS files
# shouldn't contain many non-ASCII characters anyway (in most
# cases). Using "ignore" lets us decode the file even if it's
# invalid UTF-8 data.
# The file written to the MHTML file won't be modified by this
# decoding, since there we're taking the original bytestream.
try:
css_string = item.fileobj.getvalue().decode('utf-8')
except UnicodeDecodeError:
log.downloads.warning("Invalid UTF-8 data in {}".format(url))
css_string = item.fileobj.getvalue().decode('utf-8', 'ignore')
import_urls = _get_css_imports(css_string)
for import_url in import_urls:
absolute_url = url.resolved(QUrl(import_url))
self._fetch_url(absolute_url)
encode = E_QUOPRI if mime.startswith('text/') else E_BASE64
# Our MHTML handler refuses non-ASCII headers. This will replace every
# non-ASCII char with '?'. This is probably okay, as official Content-
# Type headers contain ASCII only anyway. Anything else is madness.
mime = utils.force_encoding(mime, 'ascii')
self.writer.add_file(urlutils.encoded_url(url),
item.fileobj.getvalue(), mime, encode)
item.fileobj.actual_close()
if self.pending_downloads:
return
self._finish_file()
def _error(self, url, item, *_args):
"""Callback when a download error occurred.
Args:
url: The orignal url of the asset as QUrl.
item: The DownloadItem given by the DownloadManager.
"""
try:
self.pending_downloads.remove((url, item))
except KeyError:
# This might happen if .collect_zombies() calls .finished() and the
# error handler will be called after .collect_zombies
log.downloads.debug("Oops! Download already gone: {}".format(item))
return
item.fileobj.actual_close()
# Add a stub file, see comment in .fetch_url() for more information
self.writer.add_file(urlutils.encoded_url(url), b'')
if self.pending_downloads:
return
self._finish_file()
def _finish_file(self):
"""Save the file to the filename given in __init__."""
if self._finished_file:
log.downloads.debug("finish_file called twice, ignored!")
return
self._finished_file = True
log.downloads.debug("All assets downloaded, ready to finish off!")
try:
with open(self.dest, 'wb') as file_output:
self.writer.write_to(file_output)
except OSError as error:
message.error(self._win_id,
"Could not save file: {}".format(error))
return
log.downloads.debug("File successfully written.")
message.info(self._win_id, "Page saved as {}".format(self.dest))
def _collect_zombies(self):
"""Collect done downloads and add their data to the MHTML file.
This is needed if a download finishes before attaching its
finished signal.
"""
items = set((url, item) for url, item in self.pending_downloads
if item.done)
log.downloads.debug("Zombie downloads: {}".format(items))
for url, item in items:
self._finished(url, item)
class _NoCloseBytesIO(io.BytesIO):
"""BytesIO that can't be .closed().
This is needed to prevent the DownloadManager from closing the stream, thus
discarding the data.
"""
def close(self):
"""Do nothing."""
pass
def actual_close(self):
"""Close the stream."""
super().close()
def _start_download(dest, web_view):
"""Start downloading the current page and all assets to a MHTML file.
This will overwrite dest if it already exists.
Args:
dest: The filename where the resulting file should be saved.
web_view: Specify the webview whose page should be loaded.
"""
loader = _Downloader(web_view, dest)
loader.run()
def start_download_checked(dest, web_view):
"""First check if dest is already a file, then start the download.
Args:
dest: The filename where the resulting file should be saved.
web_view: Specify the webview whose page should be loaded.
"""
# The default name is 'page title.mht'
title = web_view.title()
default_name = utils.sanitize_filename(title + '.mht')
# Remove characters which cannot be expressed in the file system encoding
encoding = sys.getfilesystemencoding()
default_name = utils.force_encoding(default_name, encoding)
dest = utils.force_encoding(dest, encoding)
dest = os.path.expanduser(dest)
# See if we already have an absolute path
path = downloads.create_full_filename(default_name, dest)
if path is None:
# We still only have a relative path, prepend download_dir and
# try again.
path = downloads.create_full_filename(
default_name, os.path.join(downloads.download_dir(), dest))
downloads.last_used_directory = os.path.dirname(path)
# Avoid downloading files if we can't save the output anyway...
# Yes, this is prone to race conditions, but we're checking again before
# saving the file anyway.
if not os.path.isdir(os.path.dirname(path)):
folder = os.path.dirname(path)
message.error(web_view.win_id,
"Directory {} does not exist.".format(folder))
return
if not os.path.isfile(path):
_start_download(path, web_view=web_view)
return
q = usertypes.Question()
q.mode = usertypes.PromptMode.yesno
q.text = "{} exists. Overwrite?".format(path)
q.completed.connect(q.deleteLater)
q.answered_yes.connect(functools.partial(
_start_download, path, web_view=web_view))
message_bridge = objreg.get('message-bridge', scope='window',
window=web_view.win_id)
message_bridge.ask(q, blocking=False)

View File

@@ -1,7 +1,7 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2015 Antoni Boucher (antoyo) <bouanto@zoho.com>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2015-2016 Antoni Boucher (antoyo) <bouanto@zoho.com>
#
# This file is part of qutebrowser.
#
@@ -25,10 +25,8 @@
import os
from PyQt5.QtCore import QUrl
from qutebrowser.browser.network import schemehandler, networkreply
from qutebrowser.utils import utils, jinja
from qutebrowser.utils import jinja
def get_file_list(basedir, all_files, filterfunc):
@@ -74,13 +72,7 @@ def dirbrowser_html(path):
title = "Browse directory: {}".format(path)
template = jinja.env.get_template('dirbrowser.html')
# pylint: disable=no-member
# https://bitbucket.org/logilab/pylint/issue/490/
folder_icon = utils.resource_filename('img/folder.svg')
file_icon = utils.resource_filename('img/file.svg')
folder_url = QUrl.fromLocalFile(folder_icon).toString(QUrl.FullyEncoded)
file_url = QUrl.fromLocalFile(file_icon).toString(QUrl.FullyEncoded)
# WORKAROUND for https://bitbucket.org/logilab/pylint/issue/490/
if is_root(path):
parent = None
@@ -101,8 +93,7 @@ def dirbrowser_html(path):
directories = get_file_list(path, all_files, os.path.isdir)
html = template.render(title=title, url=path, icon='',
parent=parent, files=files,
directories=directories, folder_url=folder_url,
file_url=file_url)
directories=directories)
return html.encode('UTF-8', errors='xmlcharrefreplace')

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -20,6 +20,7 @@
"""Our own QNetworkAccessManager."""
import collections
import netrc
from PyQt5.QtCore import (pyqtSlot, pyqtSignal, PYQT_VERSION, QCoreApplication,
QUrl, QByteArray)
@@ -56,6 +57,7 @@ class SslError(QSslError):
def __hash__(self):
try:
# Qt >= 5.4
# pylint: disable=not-callable,useless-suppression
return super().__hash__()
except TypeError:
return hash((self.certificate().toDer(), self.error()))
@@ -241,12 +243,32 @@ class NetworkManager(QNetworkAccessManager):
@pyqtSlot('QNetworkReply', 'QAuthenticator')
def on_authentication_required(self, reply, authenticator):
"""Called when a website needs authentication."""
answer = self._ask("Username ({}):".format(authenticator.realm()),
mode=usertypes.PromptMode.user_pwd,
owner=reply)
if answer is not None:
authenticator.setUser(answer.user)
authenticator.setPassword(answer.password)
user, password = None, None
if not hasattr(reply, "netrc_used"):
reply.netrc_used = True
try:
net = netrc.netrc()
authenticators = net.authenticators(reply.url().host())
if authenticators is not None:
(user, _account, password) = authenticators
except FileNotFoundError:
log.misc.debug("No .netrc file found")
except OSError:
log.misc.exception("Unable to read the netrc file")
except netrc.NetrcParseError:
log.misc.exception("Error when parsing the netrc file")
if user is None:
# netrc check failed
answer = self._ask(
"Username ({}):".format(authenticator.realm()),
mode=usertypes.PromptMode.user_pwd,
owner=reply)
if answer is not None:
user, password = answer.user, answer.password
if user is not None:
authenticator.setUser(user)
authenticator.setPassword(password)
@pyqtSlot('QNetworkProxy', 'QAuthenticator')
def on_proxy_authentication_required(self, proxy, authenticator):
@@ -346,8 +368,7 @@ class NetworkManager(QNetworkAccessManager):
host_blocker = objreg.get('host-blocker')
if (op == QNetworkAccessManager.GetOperation and
req.url().host() in host_blocker.blocked_hosts and
config.get('content', 'host-blocking-enabled')):
host_blocker.is_blocked(req.url())):
log.webview.info("Request to {} blocked by host blocker.".format(
req.url().host()))
return networkreply.ErrorNetworkReply(
@@ -361,12 +382,21 @@ class NetworkManager(QNetworkAccessManager):
req.setRawHeader('DNT'.encode('ascii'), dnt)
req.setRawHeader('X-Do-Not-Track'.encode('ascii'), dnt)
if self._tab_id is None:
current_url = QUrl() # generic NetworkManager, e.g. for downloads
else:
webview = objreg.get('webview', scope='tab', window=self._win_id,
tab=self._tab_id)
current_url = webview.url()
# There are some scenarios where we can't figure out current_url:
# - There's a generic NetworkManager, e.g. for downloads
# - The download was in a tab which is now closed.
current_url = QUrl()
if self._tab_id is not None:
try:
webview = objreg.get('webview', scope='tab',
window=self._win_id, tab=self._tab_id)
current_url = webview.url()
except (KeyError, RuntimeError, TypeError):
# https://github.com/The-Compiler/qutebrowser/issues/889
# Catching RuntimeError and TypeError because we could be in
# the middle of the webpage shutdown here.
current_url = QUrl()
self.set_referer(req, current_url)

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# Based on the Eric5 helpviewer,
# Copyright (c) 2009 - 2014 Detlev Offenbach <detlev@die-offenbachs.de>
@@ -127,7 +127,7 @@ class ErrorNetworkReply(QNetworkReply):
"""We always have 0 bytes available."""
return 0
def readData(self):
def readData(self, _maxlen):
"""No data available."""
return bytes()

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -21,7 +21,7 @@
# up for this whole module.
# pylint: disable=no-member
# https://bitbucket.org/logilab/pylint/issue/490/
# WORKAROUND for https://bitbucket.org/logilab/pylint/issue/490/
"""Handler functions for different qute:... pages.
@@ -31,11 +31,13 @@ Module attributes:
import functools
import configparser
import mimetypes
from PyQt5.QtCore import pyqtSlot, QObject
from PyQt5.QtNetwork import QNetworkReply
import qutebrowser
from qutebrowser.browser import pdfjs
from qutebrowser.browser.network import schemehandler, networkreply
from qutebrowser.utils import (version, utils, jinja, log, message, docutils,
objreg)
@@ -45,6 +47,17 @@ from qutebrowser.config import configexc, configdata
pyeval_output = ":pyeval was never called"
HANDLERS = {}
def add_handler(name):
"""Add a handler to the qute: scheme."""
def namedecorator(function):
HANDLERS[name] = function
return function
return namedecorator
class QuteSchemeHandler(schemehandler.SchemeHandler):
"""Scheme handler for qute: URLs."""
@@ -82,8 +95,11 @@ class QuteSchemeHandler(schemehandler.SchemeHandler):
return networkreply.ErrorNetworkReply(
request, str(e), QNetworkReply.ContentNotFoundError,
self.parent())
mimetype, _encoding = mimetypes.guess_type(request.url().fileName())
if mimetype is None:
mimetype = 'text/html'
return networkreply.FixedDataNetworkReply(
request, data, 'text/html', self.parent())
request, data, mimetype, self.parent())
class JSBridge(QObject):
@@ -108,6 +124,7 @@ class JSBridge(QObject):
message.error(win_id, e)
@add_handler('pyeval')
def qute_pyeval(_win_id, _request):
"""Handler for qute:pyeval. Return HTML content as bytes."""
html = jinja.env.get_template('pre.html').render(
@@ -115,6 +132,7 @@ def qute_pyeval(_win_id, _request):
return html.encode('UTF-8', errors='xmlcharrefreplace')
@add_handler('version')
def qute_version(_win_id, _request):
"""Handler for qute:version. Return HTML content as bytes."""
html = jinja.env.get_template('version.html').render(
@@ -123,6 +141,7 @@ def qute_version(_win_id, _request):
return html.encode('UTF-8', errors='xmlcharrefreplace')
@add_handler('plainlog')
def qute_plainlog(_win_id, _request):
"""Handler for qute:plainlog. Return HTML content as bytes."""
if log.ram_handler is None:
@@ -133,6 +152,7 @@ def qute_plainlog(_win_id, _request):
return html.encode('UTF-8', errors='xmlcharrefreplace')
@add_handler('log')
def qute_log(_win_id, _request):
"""Handler for qute:log. Return HTML content as bytes."""
if log.ram_handler is None:
@@ -144,11 +164,13 @@ def qute_log(_win_id, _request):
return html.encode('UTF-8', errors='xmlcharrefreplace')
@add_handler('gpl')
def qute_gpl(_win_id, _request):
"""Handler for qute:gpl. Return HTML content as bytes."""
return utils.read_file('html/COPYING.html').encode('ASCII')
@add_handler('help')
def qute_help(win_id, request):
"""Handler for qute:help. Return HTML content as bytes."""
try:
@@ -176,6 +198,7 @@ def qute_help(win_id, request):
return utils.read_file(path).encode('UTF-8', errors='xmlcharrefreplace')
@add_handler('settings')
def qute_settings(win_id, _request):
"""Handler for qute:settings. View/change qute configuration."""
config_getter = functools.partial(objreg.get('config').get, raw=True)
@@ -185,12 +208,8 @@ def qute_settings(win_id, _request):
return html.encode('UTF-8', errors='xmlcharrefreplace')
HANDLERS = {
'pyeval': qute_pyeval,
'version': qute_version,
'plainlog': qute_plainlog,
'log': qute_log,
'gpl': qute_gpl,
'help': qute_help,
'settings': qute_settings,
}
@add_handler('pdfjs')
def qute_pdfjs(_win_id, request):
"""Handler for qute://pdfjs. Return the pdf.js viewer."""
urlpath = request.url().path()
return pdfjs.get_pdfjs_res(urlpath)

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# Based on the Eric5 helpviewer,
# Copyright (c) 2009 - 2014 Detlev Offenbach <detlev@die-offenbachs.de>

View File

@@ -0,0 +1,175 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2015 Daniel Schadt
#
# This file is part of qutebrowser.
#
# qutebrowser is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# qutebrowser is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
"""pdf.js integration for qutebrowser."""
import os
from PyQt5.QtCore import QUrl
from qutebrowser.browser import webelem
from qutebrowser.utils import utils
class PDFJSNotFound(Exception):
"""Raised when no pdf.js installation is found."""
pass
def generate_pdfjs_page(url):
"""Return the html content of a page that displays url with pdfjs.
Returns a string.
Args:
url: The url of the pdf as QUrl.
"""
viewer = get_pdfjs_res('web/viewer.html').decode('utf-8')
script = _generate_pdfjs_script(url)
html_page = viewer.replace(
'</body>', '</body><script>{}</script>'.format(script)
)
return html_page
def _generate_pdfjs_script(url):
"""Generate the script that shows the pdf with pdf.js.
Args:
url: The url of the pdf page as QUrl.
"""
return (
'PDFJS.verbosity = PDFJS.VERBOSITY_LEVELS.info;\n'
'PDFView.open("{url}");\n'
).format(url=webelem.javascript_escape(url.toString(QUrl.FullyEncoded)))
def fix_urls(asset):
"""Take a html page and replace each relative URL wth an absolute.
This is specialized for pdf.js files and not a general purpose function.
Args:
asset: js file or html page as string.
"""
new_urls = {
'viewer.css': 'qute://pdfjs/web/viewer.css',
'compatibility.js': 'qute://pdfjs/web/compatibility.js',
'locale/locale.properties':
'qute://pdfjs/web/locale/locale.properties',
'l10n.js': 'qute://pdfjs/web/l10n.js',
'../build/pdf.js': 'qute://pdfjs/build/pdf.js',
'debugger.js': 'qute://pdfjs/web/debugger.js',
'viewer.js': 'qute://pdfjs/web/viewer.js',
'compressed.tracemonkey-pldi-09.pdf': '',
'./images/': 'qute://pdfjs/web/images/',
'../build/pdf.worker.js': 'qute://pdfjs/build/pdf.worker.js',
'../web/cmaps/': 'qute://pdfjs/web/cmaps/',
}
for original, new in new_urls.items():
asset = asset.replace(original, new)
return asset
SYSTEM_PDFJS_PATHS = [
'/usr/share/pdf.js/', # Debian pdf.js-common
'/usr/share/javascript/pdf/', # Debian libjs-pdf
os.path.expanduser('~/.local/share/qutebrowser/pdfjs/'), # fallback
]
def get_pdfjs_res(path):
"""Get a pdf.js resource in binary format.
Args:
path: The path inside the pdfjs directory.
"""
path = path.lstrip('/')
content = None
# First try a system wide installation
# System installations might strip off the 'build/' or 'web/' prefixes.
# qute expects them, so we need to adjust for it.
names_to_try = [path, _remove_prefix(path)]
for system_path in SYSTEM_PDFJS_PATHS:
content = _read_from_system(system_path, names_to_try)
if content is not None:
break
# Fallback to bundled pdf.js
if content is None:
res_path = '3rdparty/pdfjs/{}'.format(path)
try:
content = utils.read_file(res_path, binary=True)
except FileNotFoundError:
raise PDFJSNotFound
try:
# Might be script/html or might be binary
text_content = content.decode('utf-8')
except UnicodeDecodeError:
return content
text_content = fix_urls(text_content)
return text_content.encode('utf-8')
def _remove_prefix(path):
"""Remove the web/ or build/ prefix of a pdfjs-file-path.
Args:
path: Path as string where the prefix should be stripped off.
"""
prefixes = {'web/', 'build/'}
if any(path.startswith(prefix) for prefix in prefixes):
return path.split('/', maxsplit=1)[1]
# Return the unchanged path if no prefix is found
return path
def _read_from_system(system_path, names):
"""Try to read a file with one of the given names in system_path.
Each file in names is considered equal, the first file that is found
is read and its binary content returned.
Returns None if no file could be found
Args:
system_path: The folder where the file should be searched.
names: List of possible file names.
"""
for name in names:
try:
with open(os.path.join(system_path, name), 'rb') as f:
return f.read()
except OSError:
continue
return None
def is_available():
"""Return true if a pdfjs installation is available."""
try:
get_pdfjs_res('build/pdf.js')
except PDFJSNotFound:
return False
else:
return True

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -40,9 +40,7 @@ class UniqueNamespace(peg.Namespace):
# RFC 2616
separator_chars = "()<>@,;:\\\"/[]?={} \t"
ctl_chars = ''.join(chr(i) for i in range(32)) + chr(127)
nontoken_chars = separator_chars + ctl_chars
# RFC 5987
@@ -288,7 +286,7 @@ def normalize_ws(text):
def parse_headers(content_disposition):
"""Build a _ContentDisposition from header values."""
# https://bitbucket.org/logilab/pylint/issue/492/
# WORKAROUND for https://bitbucket.org/logilab/pylint/issue/492/
# pylint: disable=no-member
# We allow non-ascii here (it will only be parsed inside of qdtext, and

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -55,7 +55,7 @@ class SignalFilter(QObject):
tab: The WebView to create filters for.
Return:
A partial functon calling _filter_signals with a signal.
A partial function calling _filter_signals with a signal.
"""
return functools.partial(self._filter_signals, signal, tab)

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2015-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -138,7 +138,7 @@ def serialize(items):
Return:
A (stream, data, user_data) tuple.
stream: The reseted QDataStream.
stream: The reset QDataStream.
data: The QByteArray with the raw data.
user_data: A list with each item's user data.

View File

@@ -1,7 +1,7 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2015 Antoni Boucher <bouanto@zoho.com>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2015-2016 Antoni Boucher <bouanto@zoho.com>
#
# This file is part of qutebrowser.
#
@@ -247,11 +247,13 @@ class BookmarkManager(UrlMarkManager):
bookmarks_directory = os.path.join(standarddir.config(), 'bookmarks')
if not os.path.isdir(bookmarks_directory):
os.makedirs(bookmarks_directory)
bookmarks_subdir = os.path.join('bookmarks', 'urls')
self._lineparser = lineparser.LineParser(
standarddir.config(), 'bookmarks/urls', parent=self)
standarddir.config(), bookmarks_subdir, parent=self)
def _init_savemanager(self, save_manager):
filename = os.path.join(standarddir.config(), 'bookmarks/urls')
filename = os.path.join(standarddir.config(), 'bookmarks', 'urls')
save_manager.add_saveable('bookmark-manager', self.save, self.changed,
filename=filename)

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -106,7 +106,6 @@ class WebElementWrapper(collections.abc.MutableMapping):
method = getattr(self._elem, name)
def _wrapper(meth, *args, **kwargs):
# pylint: disable=missing-docstring
self._check_vanished()
return meth(*args, **kwargs)
@@ -308,6 +307,10 @@ def javascript_escape(text):
('\n', r'\n'), # We also need to escape newlines for some reason.
('\r', r'\r'),
('\x00', r'\x00'),
('\ufeff', r'\ufeff'),
# http://stackoverflow.com/questions/2965293/
('\u2028', r'\u2028'),
('\u2029', r'\u2029'),
)
for orig, repl in replacements:
text = text.replace(orig, repl)

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -30,7 +30,7 @@ from PyQt5.QtPrintSupport import QPrintDialog
from PyQt5.QtWebKitWidgets import QWebPage
from qutebrowser.config import config
from qutebrowser.browser import http, tabhistory
from qutebrowser.browser import http, tabhistory, pdfjs
from qutebrowser.browser.network import networkmanager
from qutebrowser.utils import (message, usertypes, log, jinja, qtutils, utils,
objreg, debug)
@@ -168,7 +168,7 @@ class BrowserPage(QWebPage):
title = "Error loading page: {}".format(urlstr)
template = jinja.env.get_template('error.html')
# pylint: disable=no-member
# https://bitbucket.org/logilab/pylint/issue/490/
# WORKAROUND for https://bitbucket.org/logilab/pylint/issue/490/
html = template.render(
title=title, url=urlstr, error=error_str, icon='')
errpage.content = html.encode('utf-8')
@@ -218,6 +218,19 @@ class BrowserPage(QWebPage):
q.deleteLater()
return q.answer
def _show_pdfjs(self, reply):
"""Show the reply with pdfjs."""
try:
page = pdfjs.generate_pdfjs_page(reply.url()).encode('utf-8')
except pdfjs.PDFJSNotFound:
# pylint: disable=no-member
# WORKAROUND for https://bitbucket.org/logilab/pylint/issue/490/
page = (jinja.env.get_template('no_pdfjs.html')
.render(url=reply.url().toDisplayString())
.encode('utf-8'))
self.mainFrame().setContent(page, 'text/html', reply.url())
reply.deleteLater()
def shutdown(self):
"""Prepare the web page for being deleted."""
self._is_shutting_down = True
@@ -305,6 +318,10 @@ class BrowserPage(QWebPage):
else:
reply.finished.connect(functools.partial(
self.display_content, reply, 'image/jpeg'))
elif (mimetype in {'application/pdf', 'application/x-pdf'} and
config.get('content', 'enable-pdfjs')):
# Use pdf.js to display the page
self._show_pdfjs(reply)
else:
# Unknown mimetype, so download anyways.
download_manager.fetch(reply,
@@ -503,8 +520,15 @@ class BrowserPage(QWebPage):
def javaScriptConsoleMessage(self, msg, line, source):
"""Override javaScriptConsoleMessage to use debug log."""
if config.get('general', 'log-javascript-console'):
log.js.debug("[{}:{}] {}".format(source, line, msg))
log_javascript_console = config.get('general',
'log-javascript-console')
logstring = "[{}:{}] {}".format(source, line, msg)
logmap = {
'debug': log.js.debug,
'info': log.js.info,
'none': lambda arg: None
}
logmap[log_javascript_console](logstring)
def chooseFile(self, _frame, suggested_file):
"""Override QWebPage's chooseFile to be able to chose a file to upload.

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -35,8 +35,8 @@ from qutebrowser.utils import message, log, usertypes, utils, qtutils, objreg
from qutebrowser.browser import webpage, hints, webelem
LoadStatus = usertypes.enum('LoadStatus', ['none', 'success', 'error', 'warn',
'loading'])
LoadStatus = usertypes.enum('LoadStatus', ['none', 'success', 'success_https',
'error', 'warn', 'loading'])
tab_id_gen = itertools.count(0)
@@ -64,13 +64,14 @@ class WebView(QWebView):
win_id: The window ID of the view.
search_text: The text of the last search.
search_flags: The search flags of the last search.
_cur_url: The current URL (accessed via cur_url property).
_has_ssl_errors: Whether SSL errors occurred during loading.
_zoom: A NeighborList with the zoom levels.
_old_scroll_pos: The old scroll position.
_check_insertmode: If True, in mouseReleaseEvent we should check if we
need to enter/leave insert mode.
_default_zoom_changed: Whether the zoom was changed from the default.
_ignore_wheel_event: Ignore the next wheel event.
See https://github.com/The-Compiler/qutebrowser/issues/395
Signals:
scroll_pos_changed: Scroll percentage of current tab changed.
@@ -103,6 +104,7 @@ class WebView(QWebView):
self._old_scroll_pos = (-1, -1)
self._zoom = None
self._has_ssl_errors = False
self._ignore_wheel_event = False
self.keep_icon = False
self.search_text = None
self.search_flags = 0
@@ -116,7 +118,6 @@ class WebView(QWebView):
# See https://github.com/The-Compiler/qutebrowser/issues/390
self.destroyed.connect(functools.partial(
cfg.changed.disconnect, self.init_neighborlist))
self._cur_url = None
self.cur_url = QUrl()
self.progress = 0
self.registry = objreg.ObjectRegistry()
@@ -158,7 +159,7 @@ class WebView(QWebView):
return page
def __repr__(self):
url = utils.elide(self.url().toDisplayString(), 50)
url = utils.elide(self.url().toDisplayString(QUrl.EncodeUnicode), 100)
return utils.get_repr(self, tab_id=self.tab_id, url=url)
def __del__(self):
@@ -291,7 +292,7 @@ class WebView(QWebView):
try:
elem = webelem.focus_elem(self.page().currentFrame())
except (webelem.IsNullError, RuntimeError):
log.mouse.warning("Element/page vanished!")
log.mouse.debug("Element/page vanished!")
return
if elem.is_editable():
log.mouse.debug("Clicked editable element (delayed)!")
@@ -422,7 +423,11 @@ class WebView(QWebView):
"""
ok = not self.page().error_occurred
if ok and not self._has_ssl_errors:
self._set_load_status(LoadStatus.success)
if self.cur_url.scheme() == 'https':
self._set_load_status(LoadStatus.success_https)
else:
self._set_load_status(LoadStatus.success)
elif ok:
self._set_load_status(LoadStatus.warn)
else:
@@ -525,8 +530,8 @@ class WebView(QWebView):
"match for: {}".format(text),
immediately=True)
else:
message.error(self.win_id, "Text '{}' not found on "
"page!".format(text), immediately=True)
message.warning(self.win_id, "Text '{}' not found on "
"page!".format(text), immediately=True)
else:
def check_scroll_pos():
"""Check if the scroll position got smaller and show info."""
@@ -616,6 +621,7 @@ class WebView(QWebView):
return
self._mousepress_insertmode(e)
self._mousepress_opentarget(e)
self._ignore_wheel_event = True
super().mousePressEvent(e)
def mouseReleaseEvent(self, e):
@@ -638,6 +644,10 @@ class WebView(QWebView):
Args:
e: The QWheelEvent.
"""
if self._ignore_wheel_event:
self._ignore_wheel_event = False
# See https://github.com/The-Compiler/qutebrowser/issues/395
return
if e.modifiers() & Qt.ControlModifier:
e.accept()
divider = config.get('input', 'mouse-zoom-divider')

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -38,7 +38,7 @@ class ArgumentParserError(Exception):
class ArgumentParserExit(Exception):
"""Exception raised when the argument parser exitted.
"""Exception raised when the argument parser exited.
Attributes:
status: The exit status.

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -42,13 +42,6 @@ class NoSuchCommandError(CommandMetaError):
pass
class ArgumentCountError(CommandMetaError):
"""Raised when a command was called with an invalid count of arguments."""
pass
class ArgumentTypeError(CommandMetaError):
"""Raised when an argument had an invalid type."""

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -75,7 +75,7 @@ class Command:
deprecated=False, no_cmd_split=False, scope='global',
count=None, win_id=None):
# I really don't know how to solve this in a better way, I tried.
# pylint: disable=too-many-arguments,too-many-locals
# pylint: disable=too-many-locals
if modes is not None and not_modes is not None:
raise ValueError("Only modes or not_modes can be given!")
if modes is not None:

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -29,7 +29,8 @@ from qutebrowser.utils import message, log, objreg, qtutils
from qutebrowser.misc import split
ParseResult = collections.namedtuple('ParseResult', 'cmd, args, cmdline')
ParseResult = collections.namedtuple('ParseResult', ['cmd', 'args', 'cmdline',
'count'])
def replace_variables(win_id, arglist):
@@ -117,6 +118,26 @@ class CommandRunner(QObject):
for sub in sub_texts:
yield self.parse(sub, *args, **kwargs)
def _parse_count(self, cmdstr):
"""Split a count prefix off from a command for parse().
Args:
cmdstr: The command/args including the count.
Return:
A (count, cmdstr) tuple, with count being None or int.
"""
if ':' not in cmdstr:
return (None, cmdstr)
count, cmdstr = cmdstr.split(':', maxsplit=1)
try:
count = int(count)
except ValueError:
# We just ignore invalid prefixes
count = None
return (count, cmdstr)
def parse(self, text, *, aliases=True, fallback=False, keep=False):
"""Split the commandline text into command and arguments.
@@ -128,9 +149,11 @@ class CommandRunner(QObject):
keep: Whether to keep special chars and whitespace
Return:
A (cmd, args, cmdline) ParseResult tuple.
A ParseResult tuple.
"""
cmdstr, sep, argstr = text.partition(' ')
count, cmdstr = self._parse_count(cmdstr)
if not cmdstr and not fallback:
raise cmdexc.NoSuchCommandError("No command given")
if aliases:
@@ -161,7 +184,7 @@ class CommandRunner(QObject):
cmdline = [cmdstr, sep]
else:
cmdline = [cmdstr] + args[:]
return ParseResult(cmd=cmd, args=args, cmdline=cmdline)
return ParseResult(cmd=cmd, args=args, cmdline=cmdline, count=count)
def _split_args(self, cmd, argstr, keep):
"""Split the arguments from an arg string.
@@ -172,7 +195,7 @@ class CommandRunner(QObject):
keep: Whether to keep special chars and whitespace
Return:
A list containing the splitted strings.
A list containing the split strings.
"""
if not argstr:
return []
@@ -201,10 +224,10 @@ class CommandRunner(QObject):
maxsplit = i + cmd.maxsplit + flag_arg_count
return split.simple_split(argstr, keep=keep,
maxsplit=maxsplit)
else: # pylint: disable=useless-else-on-loop
# If there are only flags, we got it right on the first try
# already.
return split_args
# If there are only flags, we got it right on the first try
# already.
return split_args
def run(self, text, count=None):
"""Parse a command from a line of text and run it.
@@ -216,7 +239,12 @@ class CommandRunner(QObject):
for result in self.parse_all(text):
args = replace_variables(self._win_id, result.args)
if count is not None:
if result.count is not None:
raise cmdexc.CommandMetaError("Got count via command and "
"prefix!")
result.cmd.run(self._win_id, args, count=count)
elif result.count is not None:
result.cmd.run(self._win_id, args, count=result.count)
else:
result.cmd.run(self._win_id, args)

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -33,7 +33,16 @@ from qutebrowser.misc import guiprocess
class _QtFIFOReader(QObject):
"""A FIFO reader based on a QSocketNotifier."""
"""A FIFO reader based on a QSocketNotifier.
Attributes:
_filepath: The path to the opened FIFO.
_fifo: The Python file object for the FIFO.
_notifier: The QSocketNotifier used.
Signals:
got_line: Emitted when a whole line arrived.
"""
got_line = pyqtSignal(str)
@@ -44,9 +53,9 @@ class _QtFIFOReader(QObject):
# See http://www.outflux.net/blog/archives/2008/03/09/using-select-on-a-fifo/
# We also use os.open and os.fdopen rather than built-in open so we
# can add O_NONBLOCK.
fd = os.open(filepath, os.O_RDWR |
os.O_NONBLOCK) # pylint: disable=no-member
self.fifo = os.fdopen(fd, 'r')
# pylint: disable=no-member,useless-suppression
fd = os.open(filepath, os.O_RDWR | os.O_NONBLOCK)
self._fifo = os.fdopen(fd, 'r')
self._notifier = QSocketNotifier(fd, QSocketNotifier.Read, self)
self._notifier.activated.connect(self.read_line)
@@ -55,13 +64,14 @@ class _QtFIFOReader(QObject):
"""(Try to) read a line from the FIFO."""
log.procs.debug("QSocketNotifier triggered!")
self._notifier.setEnabled(False)
for line in self.fifo:
for line in self._fifo:
self.got_line.emit(line.rstrip('\r\n'))
self._notifier.setEnabled(True)
def cleanup(self):
"""Clean up so the FIFO can be closed."""
self._notifier.setEnabled(False)
self._fifo.close()
class _BaseUserscriptRunner(QObject):
@@ -98,11 +108,11 @@ class _BaseUserscriptRunner(QObject):
verbose: Show notifications when the command started/exited.
"""
self._env = {'QUTE_FIFO': self._filepath}
self._env.update(env)
if env is not None:
self._env.update(env)
self._proc = guiprocess.GUIProcess(self._win_id, 'userscript',
additional_env=self._env,
verbose=verbose, parent=self)
self._proc.error.connect(self.on_proc_error)
self._proc.finished.connect(self.on_proc_finished)
self._proc.start(cmd, args)
@@ -147,10 +157,6 @@ class _BaseUserscriptRunner(QObject):
"""
raise NotImplementedError
def on_proc_error(self, error):
"""Called when the process encountered an error."""
raise NotImplementedError
class _POSIXUserscriptRunner(_BaseUserscriptRunner):
@@ -175,7 +181,8 @@ class _POSIXUserscriptRunner(_BaseUserscriptRunner):
# exist, it shouldn't be a big issue.
self._filepath = tempfile.mktemp(prefix='qutebrowser-userscript-',
dir=standarddir.runtime())
os.mkfifo(self._filepath) # pylint: disable=no-member
# pylint: disable=no-member,useless-suppression
os.mkfifo(self._filepath)
except OSError as e:
message.error(self._win_id, "Error while creating FIFO: {}".format(
e))
@@ -190,15 +197,10 @@ class _POSIXUserscriptRunner(_BaseUserscriptRunner):
"""Interrupt the reader when the process finished."""
self.finish()
def on_proc_error(self, error):
"""Interrupt the reader when the process had an error."""
self.finish()
def finish(self):
"""Quit the thread and clean up when the reader finished."""
log.procs.debug("Cleaning up")
self._reader.cleanup()
self._reader.fifo.close()
self._reader.deleteLater()
self._reader = None
super()._cleanup()
@@ -245,11 +247,6 @@ class _WindowsUserscriptRunner(_BaseUserscriptRunner):
self._cleanup()
self.finished.emit()
def on_proc_error(self, error):
"""Clean up when the process had an error."""
self._cleanup()
self.finished.emit()
def run(self, cmd, *args, env=None, verbose=False):
try:
self._oshandle, self._filepath = tempfile.mkstemp(text=True)
@@ -260,7 +257,7 @@ class _WindowsUserscriptRunner(_BaseUserscriptRunner):
self._run_process(cmd, *args, env=env, verbose=verbose)
class _DummyUserscriptRunner:
class _DummyUserscriptRunner(QObject):
"""Simple dummy runner which displays an error when using userscripts.
@@ -273,6 +270,10 @@ class _DummyUserscriptRunner:
finished = pyqtSignal()
def __init__(self, win_id, parent=None):
# pylint: disable=unused-argument
super().__init__(parent)
def run(self, cmd, *args, env=None, verbose=False):
"""Print an error as userscripts are not supported."""
# pylint: disable=unused-argument,unused-variable
@@ -285,9 +286,9 @@ class _DummyUserscriptRunner:
# right thing depending on the platform.
if os.name == 'posix':
UserscriptRunner = _POSIXUserscriptRunner
elif os.name == 'nt':
elif os.name == 'nt': # pragma: no cover
UserscriptRunner = _WindowsUserscriptRunner
else:
else: # pragma: no cover
UserscriptRunner = _DummyUserscriptRunner
@@ -344,6 +345,13 @@ def run(cmd, *args, win_id, env, verbose=False):
if user_agent is not None:
env['QUTE_USER_AGENT'] = user_agent
cmd = os.path.expanduser(cmd)
# if cmd is not given as an absolute path, look it up
# ~/.local/share/qutebrowser/userscripts (or $XDG_DATA_DIR)
if not os.path.isabs(cmd):
log.misc.debug("{} is no absolute path".format(cmd))
cmd = os.path.join(standarddir.data(), "userscripts", cmd)
runner.run(cmd, *args, env=env, verbose=verbose)
runner.finished.connect(commandrunner.deleteLater)
runner.finished.connect(runner.deleteLater)

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -124,7 +124,7 @@ class Completer(QObject):
self.update_completion()
def _model(self):
"""Convienience method to get the current completion model."""
"""Convenience method to get the current completion model."""
completion = objreg.get('completion', scope='window',
window=self._win_id)
return completion.model()
@@ -254,7 +254,7 @@ class Completer(QObject):
Args:
selected: New selection.
_delected: Previous selection.
_deselected: Previous selection.
"""
indexes = selected.indexes()
if not indexes:
@@ -383,10 +383,7 @@ class Completer(QObject):
"""Get the part index of the commandline where the cursor is over."""
cursor_pos = self._cmd.cursorPosition()
snippet = slice(cursor_pos - 1, cursor_pos + 1)
if self._cmd.text()[snippet] == ' ':
spaces = True
else:
spaces = False
spaces = self._cmd.text()[snippet] == ' '
cursor_pos -= len(self._cmd.prefix())
parts = self.split(keep=True)
log.completion.vdebug(

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -188,7 +188,7 @@ class CompletionItemDelegate(QStyledItemDelegate):
self._doc.setDefaultTextOption(text_option)
self._doc.setDefaultStyleSheet(style.get_stylesheet("""
.highlight {
{{ color['completion.match.fg'] }}
color: {{ color['completion.match.fg'] }};
}
"""))
self._doc.setDocumentMargin(2)

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -55,15 +55,15 @@ class CompletionView(QTreeView):
# don't define that in this stylesheet.
STYLESHEET = """
QTreeView {
{{ font['completion'] }}
{{ color['completion.bg'] }}
font: {{ font['completion'] }};
background-color: {{ color['completion.bg'] }};
alternate-background-color: {{ color['completion.alternate-bg'] }};
outline: 0;
border: 0px;
}
QTreeView::item:disabled {
{{ color['completion.category.bg'] }}
background-color: {{ color['completion.category.bg'] }};
border-top: 1px solid
{{ color['completion.category.border.top'] }};
border-bottom: 1px solid
@@ -75,16 +75,30 @@ class CompletionView(QTreeView):
{{ color['completion.item.selected.border.top'] }};
border-bottom: 1px solid
{{ color['completion.item.selected.border.bottom'] }};
{{ color['completion.item.selected.bg'] }}
background-color: {{ color['completion.item.selected.bg'] }};
}
QTreeView:item::hover {
border: 0px;
}
"""
# FIXME style scrollbar
# https://github.com/The-Compiler/qutebrowser/issues/117
QTreeView QScrollBar {
width: {{ config.get('completion', 'scrollbar-width') }}px;
background: {{ color['completion.scrollbar.bg'] }};
}
QTreeView QScrollBar::handle {
background: {{ color['completion.scrollbar.fg'] }};
border: {{ config.get('completion', 'scrollbar-padding') }}px solid
{{ color['completion.scrollbar.bg'] }};
min-height: 10px;
}
QTreeView QScrollBar::sub-line, QScrollBar::add-line {
border: none;
background: none;
}
"""
resize_completion = pyqtSignal()

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -30,6 +30,7 @@ class SettingSectionCompletionModel(base.BaseCompletionModel):
"""A CompletionModel filled with settings sections."""
# https://github.com/The-Compiler/qutebrowser/issues/545
# pylint: disable=abstract-method
COLUMN_WIDTHS = (20, 70, 10)
@@ -37,7 +38,7 @@ class SettingSectionCompletionModel(base.BaseCompletionModel):
def __init__(self, parent=None):
super().__init__(parent)
cat = self.new_category("Sections")
for name in configdata.DATA.keys():
for name in configdata.DATA:
desc = configdata.SECTION_DESC[name].splitlines()[0].strip()
self.new_item(cat, name, desc)
@@ -51,6 +52,7 @@ class SettingOptionCompletionModel(base.BaseCompletionModel):
_section: The config section this model shows.
"""
# https://github.com/The-Compiler/qutebrowser/issues/545
# pylint: disable=abstract-method
COLUMN_WIDTHS = (20, 70, 10)
@@ -62,7 +64,7 @@ class SettingOptionCompletionModel(base.BaseCompletionModel):
self._misc_items = {}
self._section = section
objreg.get('config').changed.connect(self.update_misc_column)
for name in sectdata.keys():
for name in sectdata:
try:
desc = sectdata.descriptions[name]
except (KeyError, AttributeError):
@@ -106,6 +108,7 @@ class SettingValueCompletionModel(base.BaseCompletionModel):
_option: The config option this model shows.
"""
# https://github.com/The-Compiler/qutebrowser/issues/545
# pylint: disable=abstract-method
COLUMN_WIDTHS = (20, 70, 10)

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2015-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -67,12 +67,12 @@ def _init_setting_completions():
_instances[usertypes.Completion.option] = {}
_instances[usertypes.Completion.value] = {}
for sectname in configdata.DATA:
model = configmodel.SettingOptionCompletionModel(sectname)
_instances[usertypes.Completion.option][sectname] = model
opt_model = configmodel.SettingOptionCompletionModel(sectname)
_instances[usertypes.Completion.option][sectname] = opt_model
_instances[usertypes.Completion.value][sectname] = {}
for opt in configdata.DATA[sectname].keys():
model = configmodel.SettingValueCompletionModel(sectname, opt)
_instances[usertypes.Completion.value][sectname][opt] = model
for opt in configdata.DATA[sectname]:
val_model = configmodel.SettingValueCompletionModel(sectname, opt)
_instances[usertypes.Completion.value][sectname][opt] = val_model
@pyqtSlot()

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -29,6 +29,7 @@ class CommandCompletionModel(base.BaseCompletionModel):
"""A CompletionModel filled with all commands and descriptions."""
# https://github.com/The-Compiler/qutebrowser/issues/545
# pylint: disable=abstract-method
def __init__(self, parent=None):
@@ -52,6 +53,7 @@ class HelpCompletionModel(base.BaseCompletionModel):
"""A CompletionModel filled with help topics."""
# https://github.com/The-Compiler/qutebrowser/issues/545
# pylint: disable=abstract-method
def __init__(self, parent=None):
@@ -77,7 +79,7 @@ class HelpCompletionModel(base.BaseCompletionModel):
"""Fill completion with section->option entries."""
cat = self.new_category("Settings")
for sectname, sectdata in configdata.DATA.items():
for optname in sectdata.keys():
for optname in sectdata:
try:
desc = sectdata.descriptions[optname]
except (KeyError, AttributeError):
@@ -94,6 +96,7 @@ class QuickmarkCompletionModel(base.BaseCompletionModel):
"""A CompletionModel filled with all quickmarks."""
# https://github.com/The-Compiler/qutebrowser/issues/545
# pylint: disable=abstract-method
def __init__(self, parent=None):
@@ -108,6 +111,7 @@ class BookmarkCompletionModel(base.BaseCompletionModel):
"""A CompletionModel filled with all bookmarks."""
# https://github.com/The-Compiler/qutebrowser/issues/545
# pylint: disable=abstract-method
def __init__(self, parent=None):
@@ -122,6 +126,7 @@ class SessionCompletionModel(base.BaseCompletionModel):
"""A CompletionModel filled with session names."""
# https://github.com/The-Compiler/qutebrowser/issues/545
# pylint: disable=abstract-method
def __init__(self, parent=None):

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -34,6 +34,7 @@ class UrlCompletionModel(base.BaseCompletionModel):
Used for the `open` command."""
# https://github.com/The-Compiler/qutebrowser/issues/545
# pylint: disable=abstract-method
URL_COLUMN = 0
@@ -69,8 +70,8 @@ class UrlCompletionModel(base.BaseCompletionModel):
bookmark_manager.removed.connect(self.on_bookmark_removed)
self._history = objreg.get('web-history')
max_history = config.get('completion', 'web-history-max-items')
history = utils.newest_slice(self._history, max_history)
self._max_history = config.get('completion', 'web-history-max-items')
history = utils.newest_slice(self._history, self._max_history)
for entry in history:
self._add_history_entry(entry)
self._history.add_completion_item.connect(
@@ -92,12 +93,20 @@ class UrlCompletionModel(base.BaseCompletionModel):
else:
return dt.strftime(fmt)
def _remove_oldest_history(self):
"""Remove the oldest history entry."""
self._history_cat.removeRow(0)
def _add_history_entry(self, entry):
"""Add a new history entry to the completion."""
self.new_item(self._history_cat, entry.url.toDisplayString(), "",
self._fmt_atime(entry.atime), sort=int(entry.atime),
userdata=entry.url)
if (self._max_history != -1 and
self._history_cat.rowCount() > self._max_history):
self._remove_oldest_history()
@config.change_filter('completion', 'timestamp-format')
def reformat_timestamps(self):
"""Reformat the timestamps if the config option was changed."""
@@ -161,8 +170,9 @@ class UrlCompletionModel(base.BaseCompletionModel):
"""
index = completion.currentIndex()
qtutils.ensure_valid(index)
url = index.data()
category = index.parent()
index = category.child(index.row(), self.URL_COLUMN)
url = index.data()
qtutils.ensure_valid(category)
if category.data() == 'Bookmarks':

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -29,6 +29,7 @@ import sys
import os.path
import functools
import configparser
import contextlib
import collections
import collections.abc
@@ -42,6 +43,9 @@ from qutebrowser.utils import (message, objreg, utils, standarddir, log,
from qutebrowser.utils.usertypes import Completion
UNSET = object()
class change_filter: # pylint: disable=invalid-name
"""Decorator to filter calls based on a config section/option matching.
@@ -93,7 +97,6 @@ class change_filter: # pylint: disable=invalid-name
@pyqtSlot(str, str)
@functools.wraps(func)
def wrapper(sectname=None, optname=None):
# pylint: disable=missing-docstring
if sectname is None and optname is None:
# Called directly, not from a config change event.
return func()
@@ -107,7 +110,6 @@ class change_filter: # pylint: disable=invalid-name
@pyqtSlot(str, str)
@functools.wraps(func)
def wrapper(wrapper_self, sectname=None, optname=None):
# pylint: disable=missing-docstring
if sectname is None and optname is None:
# Called directly, not from a config change event.
return func(wrapper_self)
@@ -138,15 +140,16 @@ def _init_main_config(parent=None):
parent: The parent to pass to ConfigManager.
"""
args = objreg.get('args')
config_obj = ConfigManager(parent=parent)
try:
config_obj = ConfigManager(standarddir.config(), 'qutebrowser.conf',
args.relaxed_config, parent=parent)
config_obj.read(standarddir.config(), 'qutebrowser.conf',
relaxed=args.relaxed_config)
except (configexc.Error, configparser.Error, UnicodeDecodeError) as e:
log.init.exception(e)
errstr = "Error while reading config:"
try:
errstr += "\n\n{} -> {}:".format(
e.section, e.option) # pylint: disable=no-member
e.section, e.option)
except AttributeError:
pass
errstr += "\n"
@@ -252,21 +255,20 @@ def init(parent=None):
_init_misc()
def _get_value_transformer(old, new):
def _get_value_transformer(mapping):
"""Get a function which transforms a value for CHANGED_OPTIONS.
Args:
old: The old value - if the supplied value doesn't match this, it's
returned untransformed.
new: The new value.
mapping: A dictionary mapping old values to new values. Value is not
transformed if the supplied value doesn't match the old value.
Return:
A function which takes a value and transforms it.
"""
def transformer(val):
if val == old:
return new
else:
try:
return mapping[val]
except KeyError:
return val
return transformer
@@ -324,16 +326,17 @@ class ConfigManager(QObject):
RENAMED_OPTIONS = {
('colors', 'tab.fg.odd'): 'tabs.fg.odd',
('colors', 'tab.fg.even'): 'tabs.fg.even',
('colors', 'tab.fg.selected'): 'tabs.fg.selected',
('colors', 'tab.fg.selected'): 'tabs.fg.selected.odd',
('colors', 'tabs.fg.selected'): 'tabs.fg.selected.odd',
('colors', 'tab.bg.odd'): 'tabs.bg.odd',
('colors', 'tab.bg.even'): 'tabs.bg.even',
('colors', 'tab.bg.selected'): 'tabs.bg.selected',
('colors', 'tab.bg.selected'): 'tabs.bg.selected.odd',
('colors', 'tabs.bg.selected'): 'tabs.bg.selected.odd',
('colors', 'tab.bg.bar'): 'tabs.bg.bar',
('colors', 'tab.indicator.start'): 'tabs.indicator.start',
('colors', 'tab.indicator.stop'): 'tabs.indicator.stop',
('colors', 'tab.indicator.error'): 'tabs.indicator.error',
('colors', 'tab.indicator.system'): 'tabs.indicator.system',
('tabs', 'auto-hide'): 'hide-auto',
('completion', 'history-length'): 'cmd-history-max-items',
('colors', 'downloads.fg'): 'downloads.fg.start',
}
@@ -343,36 +346,33 @@ class ConfigManager(QObject):
('colors', 'completion.item.bg'),
('tabs', 'indicator-space'),
('tabs', 'hide-auto'),
('tabs', 'auto-hide'),
('tabs', 'hide-always'),
]
CHANGED_OPTIONS = {
('content', 'cookies-accept'):
_get_value_transformer('default', 'no-3rdparty'),
_get_value_transformer({'default': 'no-3rdparty'}),
('tabs', 'position'): _transform_position,
('ui', 'downloads-position'): _transform_position,
('ui', 'remove-finished-downloads'):
_get_value_transformer({'false': '-1', 'true': '1000'}),
('general', 'log-javascript-console'):
_get_value_transformer({'false': 'none', 'true': 'debug'}),
}
changed = pyqtSignal(str, str)
style_changed = pyqtSignal(str, str)
def __init__(self, configdir, fname, relaxed=False, parent=None):
def __init__(self, parent=None):
super().__init__(parent)
self._initialized = False
self._configdir = None
self._fname = None
self.sections = configdata.data()
self._interpolation = configparser.ExtendedInterpolation()
self._proxies = {}
for sectname in self.sections.keys():
for sectname in self.sections:
self._proxies[sectname] = SectionProxy(self, sectname)
self._fname = fname
if configdir is None:
self._configdir = None
self._initialized = True
else:
self._configdir = configdir
parser = ini.ReadConfigParser(configdir, fname)
self._from_cp(parser, relaxed)
self._initialized = True
self._validate_all()
def __getitem__(self, key):
"""Get a section from the config."""
@@ -414,10 +414,7 @@ class ConfigManager(QObject):
for optname, option in sect.items():
lines.append('#')
if option.typ.special:
typestr = ''
else:
typestr = ' ({})'.format(option.typ.__class__.__name__)
typestr = ' ({})'.format(option.typ.__class__.__name__)
lines.append("# {}{}:".format(optname, typestr))
try:
@@ -553,7 +550,8 @@ class ConfigManager(QObject):
def _after_set(self, changed_sect, changed_opt):
"""Clean up caches and emit signals after an option has been set."""
self.get.cache_clear()
# WORKAROUND for https://bitbucket.org/logilab/pylint/issues/659/
self.get.cache_clear() # pylint: disable=no-member
self._changed(changed_sect, changed_opt)
# Options in the same section and ${optname} interpolation.
for optname, option in self.sections[changed_sect].items():
@@ -566,6 +564,19 @@ class ConfigManager(QObject):
option.value()):
self._changed(sectname, optname)
def read(self, configdir, fname, relaxed=False):
"""Read the config from the given directory/file."""
self._fname = fname
if configdir is None:
self._configdir = None
self._initialized = True
else:
self._configdir = configdir
parser = ini.ReadConfigParser(configdir, fname)
self._from_cp(parser, relaxed)
self._initialized = True
self._validate_all()
def items(self, sectname, raw=True):
"""Get a list of (optname, value) tuples for a section.
@@ -614,14 +625,19 @@ class ConfigManager(QObject):
optname = self.optionxform(optname)
existed = optname in sectdict
if existed:
del sectdict[optname]
self.get.cache_clear()
sectdict.delete(optname)
# WORKAROUND for https://bitbucket.org/logilab/pylint/issues/659/
self.get.cache_clear() # pylint: disable=no-member
return existed
@functools.lru_cache()
def get(self, sectname, optname, raw=False, transformed=True):
def get(self, sectname, optname, raw=False, transformed=True,
fallback=UNSET):
"""Get the value from a section/option.
We don't support the vars argument from configparser.get as it's not
hashable.
Args:
sectname: The section to get the option from.
optname: The option name
@@ -634,13 +650,18 @@ class ConfigManager(QObject):
if not self._initialized:
raise Exception("get got called before initialization was "
"complete!")
try:
sect = self.sections[sectname]
except KeyError:
if fallback is not UNSET:
return fallback
raise configexc.NoSectionError(sectname)
try:
val = sect[optname]
except KeyError:
if fallback is not UNSET:
return fallback
raise configexc.NoOptionError(optname, sectname)
if raw:
return val.value()
@@ -651,6 +672,18 @@ class ConfigManager(QObject):
newval = val.typ.transform(newval)
return newval
@contextlib.contextmanager
def _handle_config_error(self):
"""Catch errors in set_command and raise CommandError."""
try:
yield
except (configexc.NoOptionError, configexc.NoSectionError,
configexc.ValidationError) as e:
raise cmdexc.CommandError("set: {}".format(e))
except (configexc.Error, configparser.Error) as e:
raise cmdexc.CommandError("set: {} - {}".format(
e.__class__.__name__, e))
@cmdutils.register(name='set', instance='config', win_id='win_id',
completion=[Completion.section, Completion.option,
Completion.value])
@@ -684,12 +717,12 @@ class ConfigManager(QObject):
tabbed_browser.openurl(QUrl('qute:settings'), newtab=False)
return
if option.endswith('?'):
if option.endswith('?') and option != '?':
option = option[:-1]
print_ = True
else:
try:
if option.endswith('!') and value is None:
with self._handle_config_error():
if option.endswith('!') and option != '!' and value is None:
option = option[:-1]
val = self.get(section_, option)
layer = 'temp' if temp else 'conf'
@@ -704,12 +737,10 @@ class ConfigManager(QObject):
else:
raise cmdexc.CommandError("set: The following arguments "
"are required: value")
except (configexc.Error, configparser.Error) as e:
raise cmdexc.CommandError("set: {} - {}".format(
e.__class__.__name__, e))
if print_:
val = self.get(section_, option, transformed=False)
with self._handle_config_error():
val = self.get(section_, option, transformed=False)
message.info(win_id, "{} {} = {}".format(
section_, option, val), immediately=True)

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -140,7 +140,7 @@ def data(readonly=False):
"end."),
('startpage',
SettingValue(typ.List(), 'https://www.duckduckgo.com'),
SettingValue(typ.List(), 'https://duckduckgo.com'),
"The default page(s) to open at the start, separated by commas."),
('default-page',
@@ -165,8 +165,9 @@ def data(readonly=False):
SettingValue(typ.ShellCommand(placeholder=True), 'gvim -f "{}"'),
"The editor (and arguments) to use for the `open-editor` "
"command.\n\n"
"Use `{}` for the filename. The value gets split like in a "
"shell, so you can use `\"` or `'` to quote arguments."),
"The arguments get split like in a shell, so you can use `\"` or "
"`'` to quote them.\n"
"`{}` gets replaced by the filename of the file to be edited."),
('editor-encoding',
SettingValue(typ.Encoding(), 'utf-8'),
@@ -208,13 +209,33 @@ def data(readonly=False):
"be used."),
('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 "
"launched."),
('log-javascript-console',
SettingValue(typ.Bool(), 'false'),
"Whether to log javascript console messages."),
SettingValue(typ.String(
valid_values=typ.ValidValues(
('none', "Don't log messages."),
('debug', "Log messages with debug level."),
('info', "Log messages with info level.")
)), 'debug'),
"How to log javascript console messages."),
('save-session',
SettingValue(typ.Bool(), 'false'),
@@ -225,6 +246,14 @@ def data(readonly=False):
"The name of the session to save by default, or empty for the "
"last loaded session."),
('url-incdec-segments',
SettingValue(
typ.FlagList(valid_values=typ.ValidValues(
'host', 'path', 'query', 'anchor')),
'path,query'),
"The URL segments where `:navigate increment/decrement` will "
"search for a number."),
readonly=readonly
)),
@@ -286,8 +315,9 @@ def data(readonly=False):
"Whether to enable smooth scrolling for webpages."),
('remove-finished-downloads',
SettingValue(typ.Bool(), 'false'),
"Whether to remove finished downloads automatically."),
SettingValue(typ.Int(minval=-1), '-1'),
"Number of milliseconds to wait before removing finished "
"downloads. Will not be removed if value is -1."),
('hide-statusbar',
SettingValue(typ.Bool(), 'false'),
@@ -299,7 +329,8 @@ def data(readonly=False):
('window-title-format',
SettingValue(typ.FormatString(fields=['perc', 'perc_raw', 'title',
'title_sep', 'id']),
'title_sep', 'id',
'scroll_pos']),
'{perc}{title}{title_sep}qutebrowser'),
"The format to use for the window title. The following "
"placeholders are defined:\n\n"
@@ -308,7 +339,8 @@ def data(readonly=False):
"* `{title}`: The title of the current web page\n"
"* `{title_sep}`: The string ` - ` if a title is set, empty "
"otherwise.\n"
"* `{id}`: The internal window ID of this window."),
"* `{id}`: The internal window ID of this window.\n"
"* `{scroll_pos}`: The page scroll position."),
('hide-mouse-cursor',
SettingValue(typ.Bool(), 'false'),
@@ -318,6 +350,11 @@ def data(readonly=False):
SettingValue(typ.Bool(), 'false'),
"Use standard JavaScript modal dialog for alert() and confirm()"),
('hide-wayland-decoration',
SettingValue(typ.Bool(), 'false'),
"Hide the window decoration when using wayland "
"(requires restart)"),
readonly=readonly
)),
@@ -331,7 +368,15 @@ def data(readonly=False):
"Value to send in the `accept-language` 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"),
('user-agent',
@@ -365,11 +410,16 @@ def data(readonly=False):
"Automatically open completion when typing."),
('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."),
('timestamp-format',
SettingValue(typ.String(none_ok=True), '%Y-%m-%d'),
SettingValue(typ.TimestampTemplate(none_ok=True), '%Y-%m-%d'),
"How to format timestamps (e.g. for history)"),
('show',
@@ -402,6 +452,14 @@ def data(readonly=False):
"Whether to shrink the completion to be smaller than the "
"configured size if there are no scrollbars."),
('scrollbar-width',
SettingValue(typ.Int(minval=0), '12'),
"Width of the scrollbar in the completion window (in px)."),
('scrollbar-padding',
SettingValue(typ.Int(minval=0), '2'),
"Padding of scrollbar handle in completion window (in px)."),
readonly=readonly
)),
@@ -430,7 +488,13 @@ def data(readonly=False):
"element is focused after page load."),
('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."),
('spatial-navigation',
@@ -480,11 +544,26 @@ def data(readonly=False):
"How new tabs opened explicitly are positioned."),
('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."),
('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"),
('show-switching-delay',
@@ -501,7 +580,12 @@ def data(readonly=False):
"Whether tabs should be movable."),
('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."),
('position',
@@ -529,7 +613,7 @@ def data(readonly=False):
('title-format',
SettingValue(typ.FormatString(
fields=['perc', 'perc_raw', 'title', 'title_sep', 'index',
'id']), '{index}: {title}'),
'id', 'scroll_pos']), '{index}: {title}'),
"The format to use for the tab title. The following placeholders "
"are defined:\n\n"
"* `{perc}`: The percentage as a string like `[10%]`.\n"
@@ -538,7 +622,12 @@ def data(readonly=False):
"* `{title_sep}`: The string ` - ` if a title is set, empty "
"otherwise.\n"
"* `{index}`: The index of this tab.\n"
"* `{id}`: The internal tab ID of this tab."),
"* `{id}`: The internal tab ID of this tab.\n"
"* `{scroll_pos}`: The page scroll position."),
('title-alignment',
SettingValue(typ.TextAlignment(), 'left'),
"Alignment of the text inside of tabs"),
('mousewheel-tab-switching',
SettingValue(typ.Bool(), 'true'),
@@ -708,7 +797,16 @@ def data(readonly=False):
"local urls."),
('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."),
('cookies-store',
@@ -735,6 +833,19 @@ def data(readonly=False):
SettingValue(typ.Bool(), 'true'),
"Whether host blocking is enabled."),
('host-blocking-whitelist',
SettingValue(typ.List(none_ok=True), 'piwik.org'),
"List of domains that should always be loaded, despite being "
"ad-blocked.\n\n"
"Domains may contain * and ? wildcards and are otherwise "
"required to exactly match the requested domain.\n\n"
"Local domains are always exempt from hostblocking."),
('enable-pdfjs', SettingValue(typ.Bool(), 'false'),
"Enable pdf.js to view PDF files in the browser.\n\n"
"Note that the files can still be downloaded by clicking"
" the download button in the pdf.js viewer."),
readonly=readonly
)),
@@ -748,16 +859,25 @@ def data(readonly=False):
"Opacity for hints."),
('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."),
('chars',
SettingValue(typ.String(minlen=2), 'asdfghjkl'),
SettingValue(typ.String(minlen=2, completions=[
('asdfghjkl', "Home row"),
('dhtnaoeu', "Home row (Dvorak)"),
('abcdefghijklmnopqrstuvwxyz', "All letters"),
]), 'asdfghjkl'),
"Chars used for hint strings."),
('min-chars',
SettingValue(typ.Int(minval=1), '1'),
"Mininum number of chars used for hint strings."),
"Minimum number of chars used for hint strings."),
('scatter',
SettingValue(typ.Bool(), 'true'),
@@ -851,13 +971,21 @@ def data(readonly=False):
SettingValue(typ.QssColor(), '#ff4444'),
"Foreground color of the matched text in the completion."),
('completion.scrollbar.fg',
SettingValue(typ.QssColor(), '${completion.fg}'),
"Color of the scrollbar handle in completion view."),
('completion.scrollbar.bg',
SettingValue(typ.QssColor(), '${completion.bg}'),
"Color of the scrollbar in completion view"),
('statusbar.fg',
SettingValue(typ.QssColor(), 'white'),
"Foreground color of the statusbar."),
('statusbar.bg',
SettingValue(typ.QssColor(), 'black'),
"Foreground color of the statusbar."),
"Background color of the statusbar."),
('statusbar.fg.error',
SettingValue(typ.QssColor(), '${statusbar.fg}'),
@@ -926,9 +1054,14 @@ def data(readonly=False):
"Default foreground color of the URL in the statusbar."),
('statusbar.url.fg.success',
SettingValue(typ.QssColor(), 'white'),
"Foreground color of the URL in the statusbar on successful "
"load (http)."),
('statusbar.url.fg.success.https',
SettingValue(typ.QssColor(), 'lime'),
"Foreground color of the URL in the statusbar on successful "
"load."),
"load (https)."),
('statusbar.url.fg.error',
SettingValue(typ.QssColor(), 'orange'),
@@ -960,13 +1093,21 @@ def data(readonly=False):
SettingValue(typ.QtColor(), 'darkgrey'),
"Background color of unselected even tabs."),
('tabs.fg.selected',
('tabs.fg.selected.odd',
SettingValue(typ.QtColor(), 'white'),
"Foreground color of selected tabs."),
"Foreground color of selected odd tabs."),
('tabs.bg.selected',
('tabs.bg.selected.odd',
SettingValue(typ.QtColor(), 'black'),
"Background color of selected tabs."),
"Background color of selected odd tabs."),
('tabs.fg.selected.even',
SettingValue(typ.QtColor(), '${tabs.fg.selected.odd}'),
"Foreground color of selected even tabs."),
('tabs.bg.selected.even',
SettingValue(typ.QtColor(), '${tabs.bg.selected.odd}'),
"Background color of selected even tabs."),
('tabs.bg.bar',
SettingValue(typ.QtColor(), '#555555'),
@@ -1165,6 +1306,14 @@ KEY_FIRST_COMMENT = """
# with Shift. For special keys (with `<>`-signs), you need to explicitly add
# `Shift-` to match a key pressed with shift. You can bind multiple commands
# by separating them with `;;`.
#
# Note that default keybindings are always bound, and need to be explicitly
# unbound if you wish to remove them:
#
# <unbound>
# keychain
# keychain2
# ...
"""
KEY_SECTION_DESC = {
@@ -1318,7 +1467,7 @@ KEY_DATA = collections.OrderedDict([
('inspector', ['wi']),
('download', ['gd']),
('download-cancel', ['ad']),
('download-remove --all', ['cd']),
('download-clear', ['cd']),
('view-source', ['gf']),
('tab-focus last', ['<Ctrl-Tab>']),
('enter-mode passthrough', ['<Ctrl-V>']),
@@ -1442,4 +1591,6 @@ CHANGED_KEY_COMMANDS = [
(re.compile(r'^search *;; *clear-keychain$'), r'clear-keychain ;; search'),
(re.compile(r'^leave-mode$'), r'clear-keychain ;; leave-mode'),
(re.compile(r'^download-remove --all$'), r'download-clear'),
]

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -24,11 +24,12 @@ import shlex
import base64
import codecs
import os.path
import sre_constants
import itertools
import collections
import warnings
import datetime
from PyQt5.QtCore import QUrl
from PyQt5.QtCore import QUrl, Qt
from PyQt5.QtGui import QColor, QFont
from PyQt5.QtNetwork import QNetworkProxy
from PyQt5.QtWidgets import QTabWidget, QTabBar
@@ -45,6 +46,33 @@ BOOLEAN_STATES = {'1': True, 'yes': True, 'true': True, 'on': True,
'0': False, 'no': False, 'false': False, 'off': False}
def _validate_regex(pattern, flags):
"""Check if the given regex is valid.
This is more complicated than it could be since there's a warning on
invalid escapes with newer Python versions, and we want to catch that case
and treat it as invalid.
"""
with warnings.catch_warnings(record=True) as recorded_warnings:
warnings.simplefilter('always')
try:
re.compile(pattern, flags)
except re.error as e:
raise configexc.ValidationError(
pattern, "must be a valid regex - " + str(e))
except RuntimeError:
raise configexc.ValidationError(
pattern, "must be a valid regex - recursion depth exceeded")
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:
"""Container for valid values for a given type.
@@ -55,6 +83,8 @@ class ValidValues:
"""
def __init__(self, *vals):
if not vals:
raise ValueError("ValidValues with no values makes no sense!")
self.descriptions = {}
self.values = []
for v in vals:
@@ -87,15 +117,11 @@ class BaseType:
Class attributes:
valid_values: Possible values if they can be expressed as a fixed
string. ValidValues instance.
special: If set, the type is only used for one option and isn't
mentioned in the config file.
"""
valid_values = None
special = False
def __init__(self, none_ok=False):
self.none_ok = none_ok
self.valid_values = None
def _basic_validation(self, value):
"""Do some basic validation for the value (empty, non-printable chars).
@@ -186,11 +212,10 @@ class MappingType(BaseType):
MAPPING = {}
def __init__(self, none_ok=False):
def __init__(self, none_ok=False,
valid_values=None):
super().__init__(none_ok)
if list(sorted(self.MAPPING)) != list(sorted(self.valid_values)):
raise ValueError("Mapping {!r} doesn't match valid values "
"{!r}".format(self.MAPPING, self.valid_values))
self.valid_values = valid_values
def validate(self, value):
super().validate(value.lower())
@@ -209,11 +234,14 @@ class String(BaseType):
minlen: Minimum length (inclusive).
maxlen: Maximum length (inclusive).
forbidden: Forbidden chars in the string.
_completions: completions to be used, or None
"""
def __init__(self, minlen=None, maxlen=None, forbidden=None,
none_ok=False):
none_ok=False, completions=None, valid_values=None):
super().__init__(none_ok)
self.valid_values = valid_values
if minlen is not None and minlen < 1:
raise ValueError("minlen ({}) needs to be >= 1!".format(minlen))
elif maxlen is not None and maxlen < 1:
@@ -224,6 +252,7 @@ class String(BaseType):
self.minlen = minlen
self.maxlen = maxlen
self.forbidden = forbidden
self._completions = completions
def validate(self, value):
self._basic_validation(value)
@@ -240,11 +269,18 @@ class String(BaseType):
raise configexc.ValidationError(value, "must be at most {} chars "
"long!".format(self.maxlen))
def complete(self):
return self._completions
class List(BaseType):
"""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):
if not value:
return None
@@ -260,11 +296,65 @@ class List(BaseType):
raise configexc.ValidationError(value, "items may not be empty!")
class FlagList(List):
"""Base class for a list setting that contains one or more flags.
Lists with duplicate flags are invalid and each item is checked against
self.valid_values (if not empty).
"""
combinable_values = None
def validate(self, value):
self._basic_validation(value)
if not value:
return
vals = self.transform(value)
if None in vals and not self.none_ok:
raise configexc.ValidationError(
value, "May not contain empty values!")
# Check for duplicate values
if len(set(vals)) != len(vals):
raise configexc.ValidationError(
value, "List contains duplicate values!")
# Check if each value is valid, ignores None values
set_vals = set(val for val in vals if val)
if (self.valid_values is not None and
not set_vals.issubset(set(self.valid_values))):
raise configexc.ValidationError(
value, "List contains invalid values!")
def complete(self):
if self.valid_values is None:
return None
out = []
# Single value completions
for value in self.valid_values:
desc = self.valid_values.descriptions.get(value, "")
out.append((value, desc))
combinables = self.combinable_values
if combinables is None:
combinables = list(self.valid_values)
# Generate combinations of each possible value combination
for size in range(2, len(combinables) + 1):
for combination in itertools.combinations(combinables, size):
out.append((','.join(combination), ''))
return out
class Bool(BaseType):
"""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):
if not value:
@@ -284,7 +374,9 @@ class BoolAsk(Bool):
"""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):
if value.lower() == 'ask':
@@ -547,8 +639,8 @@ class Command(BaseType):
self._basic_validation(value)
if not value:
return
splitted = value.split()
if not splitted or splitted[0] not in cmdutils.cmd_dict:
split = value.split()
if not split or split[0] not in cmdutils.cmd_dict:
raise configexc.ValidationError(value, "must be a valid command!")
def complete(self):
@@ -562,15 +654,20 @@ class ColorSystem(MappingType):
"""Color systems for interpolation."""
special = True
valid_values = ValidValues(('rgb', "Interpolate in the RGB color system."),
('hsv', "Interpolate in the HSV color system."),
('hsl', "Interpolate in the HSL color system."))
def __init__(self, none_ok=False):
super().__init__(
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 = {
'rgb': QColor.Rgb,
'hsv': QColor.Hsv,
'hsl': QColor.Hsl,
'none': None,
}
@@ -751,11 +848,7 @@ class Regex(BaseType):
self._basic_validation(value)
if not value:
return
try:
re.compile(value, self.flags)
except sre_constants.error as e:
raise configexc.ValidationError(value, "must be a valid regex - " +
str(e))
_validate_regex(value, self.flags)
def transform(self, value):
if not value:
@@ -783,13 +876,15 @@ class RegexList(List):
self._basic_validation(value)
if not value:
return
try:
vals = self.transform(value)
except sre_constants.error as e:
raise configexc.ValidationError(value, "must be a list valid "
"regexes - " + str(e))
if not self.none_ok and None in vals:
raise configexc.ValidationError(value, "items may not be empty!")
vals = super().transform(value)
for val in vals:
if val is None:
if not self.none_ok:
raise configexc.ValidationError(
value, "items may not be empty!")
else:
_validate_regex(val, self.flags)
class File(BaseType):
@@ -1000,30 +1095,22 @@ class ShellCommand(BaseType):
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):
"""A proxy URL or special value."""
special = True
valid_values = ValidValues(('system', "Use the system wide proxy."),
('none', "Don't use any proxy"))
PROXY_TYPES = {
'http': QNetworkProxy.HttpProxy,
'socks': 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):
self._basic_validation(value)
if not value:
@@ -1070,8 +1157,6 @@ class SearchEngineName(BaseType):
"""A search engine name."""
special = True
def validate(self, value):
self._basic_validation(value)
@@ -1080,8 +1165,6 @@ class SearchEngineUrl(BaseType):
"""A search engine URL."""
special = True
def validate(self, value):
self._basic_validation(value)
if not value:
@@ -1173,8 +1256,6 @@ class UserStyleSheet(File):
"""QWebSettings UserStyleSheet."""
special = True
def transform(self, value):
if not value:
return None
@@ -1209,14 +1290,13 @@ class AutoSearch(BaseType):
"""Whether to start a search when something else than a URL is entered."""
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):
super().__init__(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):
self._basic_validation(value)
@@ -1243,8 +1323,6 @@ class Position(MappingType):
"""The position of the tab bar."""
valid_values = ValidValues('top', 'bottom', 'left', 'right')
MAPPING = {
'top': QTabWidget.North,
'bottom': QTabWidget.South,
@@ -1252,12 +1330,35 @@ class Position(MappingType):
'right': QTabWidget.East,
}
def __init__(self, none_ok=False):
super().__init__(
none_ok,
valid_values=ValidValues('top', 'bottom', 'left', 'right'))
class TextAlignment(MappingType):
"""Alignment of text."""
MAPPING = {
'left': Qt.AlignLeft,
'right': Qt.AlignRight,
'center': Qt.AlignCenter,
}
def __init__(self, none_ok=False):
super().__init__(
none_ok,
valid_values=ValidValues('left', 'right', 'center'))
class VerticalPosition(BaseType):
"""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):
@@ -1289,8 +1390,6 @@ class SessionName(BaseType):
"""The name of a session."""
special = True
def validate(self, value):
self._basic_validation(value)
if value.startswith('_'):
@@ -1301,72 +1400,44 @@ class SelectOnRemove(MappingType):
"""Which tab to select when the focused tab is removed."""
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 = {
'left': QTabBar.SelectLeftTab,
'right': QTabBar.SelectRightTab,
'previous': QTabBar.SelectPreviousTab,
}
class LastClose(BaseType):
"""Behavior when the last tab is closed."""
special = True
valid_values = 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."))
def __init__(self, none_ok=False):
super().__init__(
none_ok,
valid_values=ValidValues(
('left', "Select the tab on the left."),
('right', "Select the tab on the right."),
('previous', "Select the previously selected tab.")))
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(List):
class ConfirmQuit(FlagList):
"""Whether to display a confirmation when the window is closed."""
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
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):
self._basic_validation(value)
super().validate(value)
if not value:
return
values = []
for v in self.transform(value):
if v:
values.append(v)
elif self.none_ok:
pass
else:
raise configexc.ValidationError(value, "May not contain empty "
"values!")
values = [x for x in self.transform(value) if x]
# Never can't be set with other options
if 'never' in values and len(values) > 1:
raise configexc.ValidationError(
@@ -1375,73 +1446,32 @@ class ConfirmQuit(List):
elif 'always' in values and len(values) > 1:
raise configexc.ValidationError(
value, "List cannot contain always!")
# Values have to be valid
elif not set(values).issubset(set(self.valid_values.values)):
raise configexc.ValidationError(
value, "List contains invalid values!")
# List can't have duplicates
elif len(set(values)) != len(values):
raise configexc.ValidationError(
value, "List contains duplicate values!")
def complete(self):
combinations = []
# Generate combinations of the options that can be combined
for size in range(2, len(self.combinable_values) + 1):
combinations += list(
itertools.combinations(self.combinable_values, size))
out = []
# Add valid single values
for val in self.valid_values:
out.append((val, self.valid_values.descriptions[val]))
# Add combinations to list of options
for val in combinations:
desc = ''
out.append((','.join(val), desc))
return out
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):
"""How new tabs are positioned."""
special = True
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."))
def __init__(self, none_ok=False):
super().__init__(none_ok)
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):
"""Whether to ignore case when searching."""
special = True
valid_values = ValidValues(('true', "Search case-insensitively"),
('false', "Search case-sensitively"),
('smart', "Search case-sensitively if there "
"are capital chars"))
def __init__(self, none_ok=False):
super().__init__(none_ok)
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):
if value.lower() == 'smart':
@@ -1459,103 +1489,48 @@ class IgnoreCase(Bool):
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):
"""The user agent to use."""
special = True
def __init__(self, none_ok=False):
super().__init__(none_ok)
def validate(self, value):
self._basic_validation(value)
# To update the following list of user agents, run the script 'ua_fetch.py'
# Vim-protip: Place your cursor below this comment and run
# :r!python scripts/dev/ua_fetch.py
def complete(self):
"""Complete a list of common user agents."""
out = [
('Mozilla/5.0 (Windows NT 6.1; WOW64; rv:35.0) Gecko/20100101 '
'Firefox/35.0',
"Firefox 35.0 Win7 64-bit"),
('Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:35.0) Gecko/20100101 '
'Firefox/35.0',
"Firefox 35.0 Ubuntu"),
('Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:35.0) '
'Gecko/20100101 Firefox/35.0',
"Firefox 35.0 MacOSX"),
('Mozilla/5.0 (Windows NT 6.1; WOW64; rv:41.0) Gecko/20100101 '
'Firefox/41.0',
"Firefox 41.0 Win7 64-bit"),
('Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:41.0) '
'Gecko/20100101 Firefox/41.0',
"Firefox 41.0 MacOSX"),
('Mozilla/5.0 (X11; Linux x86_64; rv:41.0) Gecko/20100101 '
'Firefox/41.0',
"Firefox 41.0 Linux"),
('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) '
'AppleWebKit/600.3.18 (KHTML, like Gecko) Version/8.0.3 '
'Safari/600.3.18',
"Safari 8.0 MacOSX"),
('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) '
'AppleWebKit/601.2.7 (KHTML, like Gecko) Version/9.0.1 '
'Safari/601.2.7',
"Safari Generic MacOSX"),
('Mozilla/5.0 (iPad; CPU OS 9_1 like Mac OS X) '
'AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 '
'Mobile/13B143 Safari/601.1',
"Mobile Safari Generic iOS"),
('Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, '
'like Gecko) Chrome/40.0.2214.111 Safari/537.36',
"Chrome 40.0 Win7 64-bit"),
('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) '
'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.111 '
'like Gecko) Chrome/46.0.2490.80 Safari/537.36',
"Chrome 46.0 Win7 64-bit"),
('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) '
'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 '
'Safari/537.36',
"Chrome 40.0 MacOSX"),
('Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 '
'(KHTML, like Gecko) Chrome/40.0.2214.111 Safari/537.36',
"Chrome 40.0 Linux"),
('Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like '
'Gecko',
"IE 11.0 Win7 64-bit"),
('Mozilla/5.0 (iPhone; CPU iPhone OS 8_1_2 like Mac OS X) '
'AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 '
'Mobile/12B440 Safari/600.1.4',
"Mobile Safari 8.0 iOS"),
('Mozilla/5.0 (Android; Mobile; rv:35.0) Gecko/35.0 Firefox/35.0',
"Firefox 35, Android"),
('Mozilla/5.0 (Linux; Android 5.0.2; One Build/KTU84L.H4) '
'AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 '
'Chrome/37.0.0.0 Mobile Safari/537.36',
"Android Browser"),
"Chrome 46.0 MacOSX"),
('Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, '
'like Gecko) Chrome/46.0.2490.80 Safari/537.36',
"Chrome 46.0 Linux"),
('Mozilla/5.0 (compatible; Googlebot/2.1; '
'+http://www.google.com/bot.html',
@@ -1563,18 +1538,32 @@ class UserAgent(BaseType):
('Wget/1.16.1 (linux-gnu)',
"wget 1.16.1"),
('curl/7.40.0',
"curl 7.40.0")
"curl 7.40.0"),
('Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like '
'Gecko',
"IE 11.0 for Desktop Win7 64-bit")
]
return out
class TabBarShow(BaseType):
class TimestampTemplate(BaseType):
"""When to show the tab bar."""
"""A strftime-like template for timestamps.
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."))
See
https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior
for reference.
"""
def validate(self, value):
self._basic_validation(value)
if not value:
return
try:
# Dummy check to see if the template is valid
datetime.datetime.now().strftime(value)
except ValueError as error:
# thrown on invalid template string
raise configexc.ValidationError(
value, "Invalid format string: {}".format(error))

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -81,7 +81,7 @@ class KeyConfigParser(QObject):
Args:
configdir: The directory to save the configs in.
fname: The filename of the config.
relaxed: If given, unknwon commands are ignored.
relaxed: If given, unknown commands are ignored.
"""
super().__init__(parent)
self.is_dirty = False
@@ -273,10 +273,8 @@ class KeyConfigParser(QObject):
return True
if keychain in bindings:
return False
elif command in bindings.values():
return False
else:
return True
return command not in bindings.values()
def _read(self, relaxed=False):
"""Read the config file from disk and parse it.
@@ -364,7 +362,7 @@ class KeyConfigParser(QObject):
def _add_binding(self, sectname, keychain, command, *, force=False):
"""Add a new binding from keychain to command in section sectname."""
log.keyboard.debug("Adding binding {} -> {} in mode {}.".format(
log.keyboard.vdebug("Adding binding {} -> {} in mode {}.".format(
keychain, command, sectname))
if sectname not in self.keybindings:
self.keybindings[sectname] = collections.OrderedDict()

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -72,6 +72,10 @@ class Section:
"""Get value keys."""
return self.values.keys()
def delete(self, key):
"""Delete item with given key."""
del self.values[key]
def setv(self, layer, key, value, interpolated):
"""Set the value on a layer.

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -41,9 +41,9 @@ def get_stylesheet(template_str):
The formatted template as string.
"""
colordict = ColorDict(config.section('colors'))
fontdict = FontDict(config.section('fonts'))
template = jinja2.Template(template_str)
return template.render(color=colordict, font=fontdict)
return template.render(color=colordict, font=config.section('fonts'),
config=objreg.get('config'))
def set_register_stylesheet(obj):
@@ -83,10 +83,7 @@ class ColorDict(collections.UserDict):
If a value wasn't found, return an empty string.
(Color not defined, so no output in the stylesheet)
If the key has a .fg. element in it, return color: X;.
If the key has a .bg. element in it, return background-color: X;.
In all other cases, return the plain value.
else, return the plain value.
"""
try:
val = self.data[key]
@@ -98,33 +95,5 @@ class ColorDict(collections.UserDict):
# QtColor instead of Color in the config, and it'd go unnoticed as
# the CSS is invalid then.
raise TypeError("QColor passed to ColorDict!")
if 'fg' in key.split('.'):
return 'color: {};'.format(val)
elif 'bg' in key.split('.'):
return 'background-color: {};'.format(val)
else:
return val
class FontDict(collections.UserDict):
"""A dict aimed at Qt stylesheet fonts."""
def __getitem__(self, key):
"""Override dict __getitem__.
Args:
key: The key to get from the dict.
Return:
If a value wasn't found, return an empty string.
(Color not defined, so no output in the stylesheet)
In all other cases, return font: <value>.
"""
try:
val = self.data[key]
except KeyError:
return ''
else:
return 'font: {};'.format(val)

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -78,9 +78,7 @@ class SettingValue:
for val in d.values():
if val is not None:
return val
else: # pylint: disable=useless-else-on-loop
# https://bitbucket.org/logilab/pylint/issue/489/
raise ValueError("No valid config value found!")
raise ValueError("No valid config value found!")
def transformed(self):
"""Get the transformed value."""

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -32,11 +32,11 @@ ul > li {
}
ul > li {
background-image: url('{{folder_url}}');
background-image: url('{{ resource_url('img/folder.svg') }}');
}
ul.files > li {
background-image: url('{{file_url}}');
background-image: url('{{ resource_url('img/file.svg') }}');
}
{% endblock %}

View File

@@ -1,25 +1,59 @@
{% extends "base.html" %}
{% block style %}
{{ super() }}
#errorContainer {
background: #fff;
min-width: 35em;
max-width: 35em;
position: absolute;
top: 2em;
left: 1em;
padding: 10px;
border: 2px solid #eee;
-webkit-border-radius: 5px;
* {
margin: 0px 0px;
padding: 0px 0px;
}
#errorTitleText {
font-size: 118%;
font-weight: bold;
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
-webkit-text-size-adjust: none;
color: #333333;
background-color: #EEEEEE;
font-size: 1.2em;
}
#errorMessageText {
font-size: 80%;
#error-container {
margin-left: 20px;
margin-right: 20px;
margin-top: 20px;
border: 1px solid #CCCCCC;
box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.20);
border-radius: 5px;
background-color: #FFFFFF;
padding: 20px 20px;
}
#header {
border-bottom: 1px solid #CCC;
}
.qutebrowser-broken {
display: block;
width: 100%;
}
td {
margin-top: 20px;
color: #555;
}
h1 {
font-weight: normal;
color: #1e89c6;
margin-bottom: 10px;
}
ul {
margin-left: 20px;
margin-top: 20px;
margin-bottom: 20px;
}
li {
margin-top: 10px;
margin-bottom: 10px;
}
{% endblock %}
@@ -35,19 +69,22 @@ function searchFor(uri) {
{% endblock %}
{% block content %}
<div id="errorContainer">
<div id="errorTitle">
<p id="errorTitleText">Unable to load page</p>
</div>
<div id="errorMessage">
<p>Problem occurred while loading the URL {{ url }}</p>
<p id="errorMessageText">{{ error }}</p>
</p>
</div>
<form name="bl">
<input type="button" value="Try again" onclick="javascript:tryagain()" />
<!--<input type="button" value="Search" style="visibility:%s" onclick="javascript:searchFor('%s')" />-->
</form>
<div id="error-container">
<table>
<tr>
<td style="width: 10%; vertical-align: top;">
<img style="width: 100%; display: block; max-width: 256px;" src="{{ resource_url('img/broken_qutebrowser_logo.png') }}" />
</td>
<td style="padding-left: 40px;">
<h1>Unable to load page</h1>
Error while opening {{ url }}: <br>
<p id="error-message-text" style="color: #a31a1a;">{{ error }}</p><br><br>
<form name="bl">
<input type="button" value="Try again" onclick="javascript:tryagain()" />
</form>
</td>
</tr>
</table>
</div>
{% endblock %}

View File

@@ -0,0 +1,129 @@
{% extends "base.html" %}
{% block style %}
{{ super() }}
* {
margin: 0px 0px;
padding: 0px 0px;
}
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
-webkit-text-size-adjust: none;
color: #333333;
background-color: #EEEEEE;
font-size: 1.2em;
}
#error-container {
margin-left: 20px;
margin-right: 20px;
margin-top: 20px;
border: 1px solid #CCCCCC;
box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.20);
border-radius: 5px;
background-color: #FFFFFF;
padding: 20px 20px;
}
#header {
border-bottom: 1px solid #CCC;
}
.qutebrowser-broken {
display: block;
width: 100%;
}
span.warning {
text-weigth: bold;
color: red;
}
td {
margin-top: 20px;
color: #555;
}
h1, h2 {
font-weight: normal;
color: #1e89c6;
margin-bottom: 10px;
}
ul {
margin-left: 20px;
margin-top: 20px;
margin-bottom: 20px;
}
li {
margin-top: 10px;
margin-bottom: 10px;
}
{% endblock %}
{% block content %}
<div id="error-container">
<table>
<tr>
<td style="width: 10%; vertical-align: top;">
<img style="width: 100%; display: block; max-width: 256px;" src="{{ resource_url('img/broken_qutebrowser_logo.png') }}" />
</td>
<td style="padding-left: 40px;">
<h1>No pdf.js installation found</h1>
<p>Error while opening {{ url }}: <br>
<p id="error-message-text" style="color: #a31a1a;">qutebrowser can't find a suitable pdf.js installation</p></p>
<p>It looks like you set <code>content -> enable-pdfjs</code>
to <em>true</em> but qutebrowser can't find the required files.</p>
<br>
<h2>Possible fixes</h2>
<ul>
<li>
Disable <code>content -> enable-pdfjs</code> and reload the page.
You will need to download the pdf-file and open it with an external
tool instead.
</li>
<li>
If you have installed a packaged version of qutebrowser, make sure
the required packages for pdf.js are also installed.
</li>
<li>
If you have installed a pdf.js package and qutebrowser still can't
find it, please send us a report with your system and the package
name, so we can add it to the list of supported packages.
</li>
<li>
If you're running a self-built version or the source version, make
sure you have pdf.js in <code>qutebrowser/3rdparty/pdfjs</code>.
You can use the <code>scripts/dev/update_3rdparty.py</code> script
to download the latest version.
</li>
<li>
You can manually download the pdf.js archive
<a href="https://mozilla.github.io/pdf.js/getting_started/#download">here</a>
and extract it to <code>~/.local/share/qutebrowser/pdfjs</code>
<br>
<span class="warning">Warning:</span> Using this method you are
responsible for yourself to keep the installation updated! If a
vulnerability is found in pdf.js, neither qutebrowser nor your
system's package manager will update your pdf.js installation.
Use it at your own risk!
</li>
</ul>
<p>
If none of these fixes work for you, please send us a bug report so
we can fix the issue.
</p>
</td>
</tr>
</table>
</div>
{% endblock %}

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -168,7 +168,9 @@ class ModeManager(QObject):
"{}".format(curmode, utils.qualname(parser)))
handled = parser.handle(event)
is_non_alnum = bool(event.modifiers()) or not event.text().strip()
is_non_alnum = (
event.modifiers() not in (Qt.NoModifier, Qt.ShiftModifier) or
not event.text().strip())
focus_widget = QApplication.instance().focusWidget()
is_tab = event.key() in (Qt.Key_Tab, Qt.Key_Backtab)

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -41,13 +41,15 @@ from qutebrowser.misc import crashsignal
win_id_gen = itertools.count(0)
def get_window(via_ipc, force_window=False, force_tab=False):
def get_window(via_ipc, force_window=False, force_tab=False,
force_target=None):
"""Helper function for app.py to get a window id.
Args:
via_ipc: Whether the request was made via IPC.
force_window: Whether to force opening in a window.
force_tab: Whether to force opening in a tab.
force_target: Override the new-instance-open-target config
"""
if force_window and force_tab:
raise ValueError("force_window and force_tab are mutually exclusive!")
@@ -55,7 +57,10 @@ def get_window(via_ipc, force_window=False, force_tab=False):
# Initial main window
return 0
window_to_raise = None
open_target = config.get('general', 'new-instance-open-target')
if force_target is not None:
open_target = force_target
else:
open_target = config.get('general', 'new-instance-open-target')
if (open_target == 'window' or force_window) and not force_tab:
window = MainWindow()
window.show()
@@ -259,7 +264,6 @@ class MainWindow(QWidget):
def _connect_signals(self):
"""Connect all mainwindow signals."""
# pylint: disable=too-many-statements
key_config = objreg.get('key-config')
status = self._get_object('statusbar')

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -110,58 +110,58 @@ class StatusBar(QWidget):
QWidget#StatusBar,
QWidget#StatusBar QLabel,
QWidget#StatusBar QLineEdit {
{{ font['statusbar'] }}
{{ color['statusbar.bg'] }}
{{ color['statusbar.fg'] }}
font: {{ font['statusbar'] }};
background-color: {{ color['statusbar.bg'] }};
color: {{ color['statusbar.fg'] }};
}
QWidget#StatusBar[caret_mode="on"],
QWidget#StatusBar[caret_mode="on"] QLabel,
QWidget#StatusBar[caret_mode="on"] QLineEdit {
{{ color['statusbar.fg.caret'] }}
{{ color['statusbar.bg.caret'] }}
color: {{ color['statusbar.fg.caret'] }};
background-color: {{ color['statusbar.bg.caret'] }};
}
QWidget#StatusBar[caret_mode="selection"],
QWidget#StatusBar[caret_mode="selection"] QLabel,
QWidget#StatusBar[caret_mode="selection"] QLineEdit {
{{ color['statusbar.fg.caret-selection'] }}
{{ color['statusbar.bg.caret-selection'] }}
color: {{ color['statusbar.fg.caret-selection'] }};
background-color: {{ color['statusbar.bg.caret-selection'] }};
}
QWidget#StatusBar[severity="error"],
QWidget#StatusBar[severity="error"] QLabel,
QWidget#StatusBar[severity="error"] QLineEdit {
{{ color['statusbar.fg.error'] }}
{{ color['statusbar.bg.error'] }}
color: {{ color['statusbar.fg.error'] }};
background-color: {{ color['statusbar.bg.error'] }};
}
QWidget#StatusBar[severity="warning"],
QWidget#StatusBar[severity="warning"] QLabel,
QWidget#StatusBar[severity="warning"] QLineEdit {
{{ color['statusbar.fg.warning'] }}
{{ color['statusbar.bg.warning'] }}
color: {{ color['statusbar.fg.warning'] }};
background-color: {{ color['statusbar.bg.warning'] }};
}
QWidget#StatusBar[prompt_active="true"],
QWidget#StatusBar[prompt_active="true"] QLabel,
QWidget#StatusBar[prompt_active="true"] QLineEdit {
{{ color['statusbar.fg.prompt'] }}
{{ color['statusbar.bg.prompt'] }}
color: {{ color['statusbar.fg.prompt'] }};
background-color: {{ color['statusbar.bg.prompt'] }};
}
QWidget#StatusBar[insert_active="true"],
QWidget#StatusBar[insert_active="true"] QLabel,
QWidget#StatusBar[insert_active="true"] QLineEdit {
{{ color['statusbar.fg.insert'] }}
{{ color['statusbar.bg.insert'] }}
color: {{ color['statusbar.fg.insert'] }};
background-color: {{ color['statusbar.bg.insert'] }};
}
QWidget#StatusBar[command_active="true"],
QWidget#StatusBar[command_active="true"] QLabel,
QWidget#StatusBar[command_active="true"] QLineEdit {
{{ color['statusbar.fg.command'] }}
{{ color['statusbar.bg.command'] }}
color: {{ color['statusbar.fg.command'] }};
background-color: {{ color['statusbar.bg.command'] }};
}
"""

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -92,7 +92,7 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit):
@cmdutils.register(instance='status-command', name='set-cmd-text',
scope='window', maxsplit=0)
def set_cmd_text_command(self, text, space=False):
def set_cmd_text_command(self, text, space=False, append=False):
"""Preset the statusbar to some text.
//
@@ -103,6 +103,7 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit):
Args:
text: The commandline to set.
space: If given, a space is added to the end.
append: If given, the text is appended to the current text.
"""
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=self._win_id)
@@ -122,8 +123,14 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit):
# I'm not sure what's the best thing to do here
# https://github.com/The-Compiler/qutebrowser/issues/123
text = text.replace('{url}', url)
if space:
text += ' '
if append:
if not self.text():
raise cmdexc.CommandError("No current text!")
text = self.text() + text
if not text or text[0] not in modeparsers.STARTCHARS:
raise cmdexc.CommandError(
"Invalid command text '{}'.".format(text))

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#

View File

@@ -1,6 +1,6 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
# Copyright 2014-2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
@@ -31,19 +31,15 @@ class Progress(QProgressBar):
"""The progress bar part of the status bar."""
# FIXME for some reason, margin-left is not shown
# https://github.com/The-Compiler/qutebrowser/issues/125
STYLESHEET = """
QProgressBar {
border-radius: 0px;
border: 2px solid transparent;
margin-left: 1px;
background-color: transparent;
}
QProgressBar::chunk {
{{ color['statusbar.progress.bg'] }}
background-color: {{ color['statusbar.progress.bg'] }};
}
"""

Some files were not shown because too many files have changed in this diff Show More