Merge branch 'master' into mark-del-no-args
This commit is contained in:
commit
3ffb726b98
2
.flake8
2
.flake8
@ -1,5 +1,5 @@
|
||||
[flake8]
|
||||
exclude = .venv,.hypothesis,.git,__pycache__,resources.py
|
||||
exclude = .*,__pycache__,resources.py
|
||||
# E128: continuation line under-indented for visual indent
|
||||
# E226: missing whitespace around arithmetic operator
|
||||
# E265: Block comment should start with '#'
|
||||
|
@ -9,6 +9,7 @@ load-plugins=qute_pylint.config,
|
||||
qute_pylint.settrace,
|
||||
pylint.extensions.bad_builtin,
|
||||
pylint.extensions.docstyle
|
||||
persistent=n
|
||||
|
||||
[MESSAGES CONTROL]
|
||||
enable=all
|
||||
|
@ -31,6 +31,7 @@ Added
|
||||
- New `:repeat-command` command (mapped to `.`) to repeat the last command.
|
||||
Note that two former default bundings conflict with that binding, unbinding
|
||||
them via `:unbind .i` and `:unbind .o` is recommended.
|
||||
- New `qute:bookmarks` page which displays all bookmarks and quickmarks.
|
||||
|
||||
Changed
|
||||
~~~~~~~
|
||||
@ -47,6 +48,7 @@ Changed
|
||||
Fixed
|
||||
-----
|
||||
|
||||
- Copmpatibility with PyQt 5.7
|
||||
- Fixed some configuration values being lost when a config option gets removed
|
||||
from qutebrowser's code.
|
||||
|
||||
|
@ -181,6 +181,7 @@ Contributors, sorted by the number of commits in descending order:
|
||||
* Tomasz Kramkowski
|
||||
* Ismail S
|
||||
* Halfwit
|
||||
* David Vogt
|
||||
* rikn00
|
||||
* kanikaa1234
|
||||
* haitaka
|
||||
@ -210,6 +211,7 @@ Contributors, sorted by the number of commits in descending order:
|
||||
* Regina Hug
|
||||
* Mathias Fussenegger
|
||||
* Marcelo Santos
|
||||
* Jean-Louis Fuchs
|
||||
* Fritz V155 Reichwald
|
||||
* Franz Fellner
|
||||
* zwarag
|
||||
|
@ -120,7 +120,7 @@ Syntax: +:bookmark-add ['url'] ['title']+
|
||||
|
||||
Save the current page as a bookmark, or a specific url.
|
||||
|
||||
If no url and title are provided, then save the current page as a bookmark. If a url and title have been provided, then save the given url as a bookmark with the provided title.
|
||||
If no url and title are provided, then save the current page as a bookmark. If a url and title have been provided, then save the given url as a bookmark with the provided title. You can view all saved bookmarks on the link:qute://bookmarks[bookmarks page].
|
||||
|
||||
==== positional arguments
|
||||
* +'url'+: url to save as a bookmark. If None, use url of current page.
|
||||
@ -512,6 +512,8 @@ Syntax: +:quickmark-add 'url' 'name'+
|
||||
|
||||
Add a new quickmark.
|
||||
|
||||
You can view all saved quickmarks on the link:qute://bookmarks[bookmarks page].
|
||||
|
||||
==== positional arguments
|
||||
* +'url'+: The url to add as quickmark.
|
||||
* +'name'+: The name for the new quickmark.
|
||||
|
@ -50,7 +50,7 @@ $ git checkout symbols
|
||||
$ export DEBUG_CFLAGS='-ggdb3 -fvar-tracking-assignments -Og'
|
||||
$ export DEBUG_CXXFLAGS='-ggdb3 -fvar-tracking-assignments -Og'
|
||||
$ cd qt5
|
||||
$ makepkg -si --pkg qt5-base-debug,qt5-webkit-debug
|
||||
$ makepkg -si --pkg qt5-base-debug,qt5-webkit-debug,qt5-webengine-debug
|
||||
$ cd ../pyqt5
|
||||
$ makepkg -si --pkg pyqt5-common-debug,python-pyqt5-debug
|
||||
----
|
||||
@ -76,7 +76,7 @@ Server = http://qutebrowser.org/qt-debug/$arch
|
||||
Then install the packages:
|
||||
|
||||
----
|
||||
# pacman -Suy 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,qt5-webengine-debug
|
||||
----
|
||||
|
||||
The `-debug` packages conflict with the non-debug variants - it's safe to
|
||||
|
@ -4,7 +4,7 @@ astroid==1.4.7
|
||||
isort==4.2.5
|
||||
lazy-object-proxy==1.2.2
|
||||
mccabe==0.5.0
|
||||
pylint==1.6.1
|
||||
pylint==1.6.4
|
||||
./scripts/dev/pylint_checkers
|
||||
requests==2.10.0
|
||||
six==1.10.0
|
||||
|
@ -1,7 +1,7 @@
|
||||
# This file is automatically generated by scripts/dev/recompile_requirements.py
|
||||
|
||||
beautifulsoup4==4.4.1
|
||||
CherryPy==6.1.0
|
||||
beautifulsoup4==4.5.0
|
||||
CherryPy==6.2.0
|
||||
coverage==4.1
|
||||
decorator==4.0.10
|
||||
Flask==0.10.1 # rq.filter: < 0.11.0
|
||||
@ -28,5 +28,5 @@ pytest-rerunfailures==2.0.0
|
||||
pytest-travis-fold==1.2.0
|
||||
pytest-xvfb==0.2.0
|
||||
six==1.10.0
|
||||
vulture==0.9
|
||||
vulture==0.10
|
||||
Werkzeug==0.11.10
|
||||
|
@ -1,3 +1,3 @@
|
||||
# This file is automatically generated by scripts/dev/recompile_requirements.py
|
||||
|
||||
vulture==0.9
|
||||
vulture==0.10
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright 2015 Zach-Button <zachrey.button@gmail.com>
|
||||
#
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/bin/bash -e
|
||||
#!/usr/bin/env 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
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/bin/bash -e
|
||||
#!/usr/bin/env bash -e
|
||||
help() {
|
||||
blink=$'\e[1;31m' reset=$'\e[0m'
|
||||
cat <<EOF
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright 2015 Zach-Button <zachrey.button@gmail.com>
|
||||
#
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Behavior:
|
||||
# Userscript for qutebrowser which adds a task to taskwarrior.
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/bin/bash -e
|
||||
#!/usr/bin/env bash -e
|
||||
#
|
||||
# Behavior:
|
||||
# Userscript for qutebrowser which views the current web page in mpv using
|
||||
|
@ -337,7 +337,6 @@ def _save_version():
|
||||
state_config['general']['version'] = qutebrowser.__version__
|
||||
|
||||
|
||||
@pyqtSlot('QWidget*', 'QWidget*')
|
||||
def on_focus_changed(_old, new):
|
||||
"""Register currently focused main window in the object registry."""
|
||||
if not isinstance(new, QWidget):
|
||||
@ -355,7 +354,6 @@ def on_focus_changed(_old, new):
|
||||
_maybe_hide_mouse_cursor()
|
||||
|
||||
|
||||
@pyqtSlot(QUrl)
|
||||
def open_desktopservices_url(url):
|
||||
"""Handler to open a URL via QDesktopServices."""
|
||||
win_id = mainwindow.get_window(via_ipc=True, force_window=False)
|
||||
@ -476,7 +474,6 @@ class Quitter:
|
||||
self._shutting_down = False
|
||||
self._args = args
|
||||
|
||||
@pyqtSlot()
|
||||
def on_last_window_closed(self):
|
||||
"""Slot which gets invoked when the last window was closed."""
|
||||
self.shutdown(last_window=True)
|
||||
|
@ -24,7 +24,6 @@ import itertools
|
||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QUrl, QObject, QPoint
|
||||
from PyQt5.QtGui import QIcon
|
||||
from PyQt5.QtWidgets import QWidget, QLayout
|
||||
from PyQt5.QtPrintSupport import QPrinter
|
||||
|
||||
from qutebrowser.keyinput import modeman
|
||||
from qutebrowser.config import config
|
||||
@ -122,7 +121,6 @@ class AbstractPrinting:
|
||||
def to_pdf(self, filename):
|
||||
raise NotImplementedError
|
||||
|
||||
@pyqtSlot(QPrinter)
|
||||
def to_printer(self, printer):
|
||||
raise NotImplementedError
|
||||
|
||||
@ -354,6 +352,9 @@ class AbstractScroller(QObject):
|
||||
self._tab = tab
|
||||
self._widget = None
|
||||
|
||||
def _init_widget(self, widget):
|
||||
self._widget = widget
|
||||
|
||||
def pos_px(self):
|
||||
raise NotImplementedError
|
||||
|
||||
@ -513,7 +514,7 @@ class AbstractTab(QWidget):
|
||||
self._layout = WrapperLayout(widget, self)
|
||||
self._widget = widget
|
||||
self.history._history = widget.history()
|
||||
self.scroll._widget = widget
|
||||
self.scroll._init_widget(widget)
|
||||
self.caret._widget = widget
|
||||
self.zoom._widget = widget
|
||||
self.search._widget = widget
|
||||
|
@ -1128,6 +1128,9 @@ class CommandDispatcher:
|
||||
If a url and title have been provided, then save the given url as
|
||||
a bookmark with the provided title.
|
||||
|
||||
You can view all saved bookmarks on the
|
||||
link:qute://bookmarks[bookmarks page].
|
||||
|
||||
Args:
|
||||
url: url to save as a bookmark. If None, use url of current page.
|
||||
title: title of the new bookmark.
|
||||
|
@ -52,7 +52,6 @@ class WordHintingError(Exception):
|
||||
"""Exception raised on errors during word hinting."""
|
||||
|
||||
|
||||
@pyqtSlot(usertypes.KeyMode)
|
||||
def on_mode_entered(mode, win_id):
|
||||
"""Stop hinting when insert mode was entered."""
|
||||
if mode == usertypes.KeyMode.insert:
|
||||
@ -201,6 +200,7 @@ class HintManager(QObject):
|
||||
window=self._win_id)
|
||||
message_bridge.maybe_reset_text(text)
|
||||
self._context = None
|
||||
self._filterstr = None
|
||||
|
||||
def _hint_strings(self, elems):
|
||||
"""Calculate the hint strings for elems.
|
||||
|
@ -179,6 +179,9 @@ class QuickmarkManager(UrlMarkManager):
|
||||
def quickmark_add(self, win_id, url, name):
|
||||
"""Add a new quickmark.
|
||||
|
||||
You can view all saved quickmarks on the
|
||||
link:qute://bookmarks[bookmarks page].
|
||||
|
||||
Args:
|
||||
win_id: The window ID to display the errors in.
|
||||
url: The url to add as quickmark.
|
||||
|
@ -25,7 +25,6 @@
|
||||
from PyQt5.QtCore import pyqtSlot, Qt, QEvent, QPoint
|
||||
from PyQt5.QtGui import QKeyEvent, QIcon
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
from PyQt5.QtPrintSupport import QPrinter
|
||||
# pylint: disable=no-name-in-module,import-error,useless-suppression
|
||||
from PyQt5.QtWebEngineWidgets import QWebEnginePage
|
||||
# pylint: enable=no-name-in-module,import-error,useless-suppression
|
||||
@ -51,7 +50,6 @@ class WebEnginePrinting(browsertab.AbstractPrinting):
|
||||
def to_pdf(self, filename):
|
||||
self._widget.page().printToPdf(filename)
|
||||
|
||||
@pyqtSlot(QPrinter)
|
||||
def to_printer(self, printer):
|
||||
# Should never be called
|
||||
assert False
|
||||
@ -182,6 +180,21 @@ class WebEngineScroller(browsertab.AbstractScroller):
|
||||
|
||||
"""QtWebEngine implementations related to scrolling."""
|
||||
|
||||
def __init__(self, tab, parent=None):
|
||||
super().__init__(tab, parent)
|
||||
self._pos_perc = (None, None)
|
||||
self._pos_px = QPoint()
|
||||
|
||||
def _init_widget(self, widget):
|
||||
super()._init_widget(widget)
|
||||
page = widget.page()
|
||||
try:
|
||||
page.scrollPositionChanged.connect(
|
||||
self._on_scroll_pos_changed)
|
||||
except AttributeError:
|
||||
log.stub('scrollPositionChanged, on Qt < 5.7')
|
||||
self._on_scroll_pos_changed()
|
||||
|
||||
def _key_press(self, key, count=1):
|
||||
# FIXME:qtwebengine Abort scrolling if the minimum/maximum was reached.
|
||||
press_evt = QKeyEvent(QEvent.KeyPress, key, Qt.NoModifier, 0, 0, 0)
|
||||
@ -193,24 +206,27 @@ class WebEngineScroller(browsertab.AbstractScroller):
|
||||
QApplication.postEvent(recipient, press_evt)
|
||||
QApplication.postEvent(recipient, release_evt)
|
||||
|
||||
@pyqtSlot()
|
||||
def _on_scroll_pos_changed(self):
|
||||
"""Update the scroll position attributes when it changed."""
|
||||
def update_scroll_pos(jsret):
|
||||
"""Callback after getting scroll position via JS."""
|
||||
assert isinstance(jsret, dict)
|
||||
self._pos_perc = (jsret['perc']['x'], jsret['perc']['y'])
|
||||
self._pos_px = QPoint(jsret['px']['x'], jsret['px']['y'])
|
||||
self.perc_changed.emit(*self._pos_perc)
|
||||
|
||||
js_code = """
|
||||
{scroll_js}
|
||||
scroll_pos();
|
||||
""".format(scroll_js=utils.read_file('javascript/scroll.js'))
|
||||
self._tab.run_js_async(js_code, update_scroll_pos)
|
||||
|
||||
def pos_px(self):
|
||||
log.stub()
|
||||
return QPoint(0, 0)
|
||||
return self._pos_px
|
||||
|
||||
def pos_perc(self):
|
||||
page = self._widget.page()
|
||||
try:
|
||||
size = page.contentsSize()
|
||||
pos = page.scrollPosition()
|
||||
except AttributeError:
|
||||
# Added in Qt 5.7
|
||||
log.stub('on Qt < 5.7')
|
||||
return (None, None)
|
||||
else:
|
||||
# FIXME:qtwebengine is this correct?
|
||||
perc_x = 100 / size.width() * pos.x()
|
||||
perc_y = 100 / size.height() * pos.y()
|
||||
return (perc_x, perc_y)
|
||||
return self._pos_perc
|
||||
|
||||
def to_perc(self, x=None, y=None):
|
||||
js_code = """
|
||||
@ -260,7 +276,7 @@ class WebEngineScroller(browsertab.AbstractScroller):
|
||||
self._key_press(Qt.Key_PageDown, count)
|
||||
|
||||
def at_top(self):
|
||||
log.stub()
|
||||
return self.pos_px().y() == 0
|
||||
|
||||
def at_bottom(self):
|
||||
log.stub()
|
||||
@ -409,5 +425,3 @@ class WebEngineTab(browsertab.AbstractTab):
|
||||
view.iconChanged.connect(self.icon_changed)
|
||||
except AttributeError:
|
||||
log.stub('iconChanged, on Qt < 5.7')
|
||||
# FIXME:qtwebengine stub this?
|
||||
# view.scroll.pos_changed.connect(self.scroll.perc_changed)
|
||||
|
@ -261,3 +261,18 @@ def qute_pdfjs(_win_id, request):
|
||||
"pdfjs resource requested but not found: {}".format(e.path))
|
||||
raise QuteSchemeError("Can't find pdfjs resource '{}'".format(e.path),
|
||||
QNetworkReply.ContentNotFoundError)
|
||||
|
||||
|
||||
@add_handler('bookmarks')
|
||||
def qute_bookmarks(_win_id, _request):
|
||||
"""Handler for qute:bookmarks. Display all quickmarks / bookmarks."""
|
||||
bookmarks = sorted(objreg.get('bookmark-manager').marks.items(),
|
||||
key=lambda x: x[1]) # Sort by title
|
||||
quickmarks = sorted(objreg.get('quickmark-manager').marks.items(),
|
||||
key=lambda x: x[0]) # Sort by name
|
||||
|
||||
html = jinja.render('bookmarks.html',
|
||||
title='Bookmarks',
|
||||
bookmarks=bookmarks,
|
||||
quickmarks=quickmarks)
|
||||
return html.encode('UTF-8', errors='xmlcharrefreplace')
|
||||
|
@ -55,7 +55,6 @@ class WebKitPrinting(browsertab.AbstractPrinting):
|
||||
printer.setOutputFileName(filename)
|
||||
self.to_printer(printer)
|
||||
|
||||
@pyqtSlot(QPrinter)
|
||||
def to_printer(self, printer):
|
||||
self._widget.print(printer)
|
||||
|
||||
|
@ -27,8 +27,6 @@ Module attributes:
|
||||
|
||||
import functools
|
||||
|
||||
from PyQt5.QtCore import pyqtSlot
|
||||
|
||||
from qutebrowser.completion.models import (miscmodels, urlmodel, configmodel,
|
||||
base)
|
||||
from qutebrowser.utils import objreg, usertypes, log, debug
|
||||
@ -84,7 +82,6 @@ def _init_setting_completions():
|
||||
_instances[usertypes.Completion.value][sectname][opt] = val_model
|
||||
|
||||
|
||||
@pyqtSlot()
|
||||
def init_quickmark_completions():
|
||||
"""Initialize quickmark completion models."""
|
||||
log.completion.debug("Initializing quickmark completion.")
|
||||
@ -96,7 +93,6 @@ def init_quickmark_completions():
|
||||
_instances[usertypes.Completion.quickmark_by_name] = model
|
||||
|
||||
|
||||
@pyqtSlot()
|
||||
def init_bookmark_completions():
|
||||
"""Initialize bookmark completion models."""
|
||||
log.completion.debug("Initializing bookmark completion.")
|
||||
@ -108,7 +104,6 @@ def init_bookmark_completions():
|
||||
_instances[usertypes.Completion.bookmark_by_url] = model
|
||||
|
||||
|
||||
@pyqtSlot()
|
||||
def init_session_completion():
|
||||
"""Initialize session completion model."""
|
||||
log.completion.debug("Initializing session completion.")
|
||||
|
@ -33,7 +33,7 @@ import contextlib
|
||||
import collections
|
||||
import collections.abc
|
||||
|
||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QUrl, QSettings
|
||||
from PyQt5.QtCore import pyqtSignal, QObject, QUrl, QSettings
|
||||
|
||||
from qutebrowser.config import configdata, configexc, textwrapper
|
||||
from qutebrowser.config.parsers import ini, keyconf
|
||||
@ -94,8 +94,6 @@ class change_filter: # pylint: disable=invalid-name
|
||||
The decorated function.
|
||||
"""
|
||||
if self._function:
|
||||
@pyqtSlot(str, str)
|
||||
@pyqtSlot()
|
||||
@functools.wraps(func)
|
||||
def wrapper(sectname=None, optname=None):
|
||||
if sectname is None and optname is None:
|
||||
@ -108,8 +106,6 @@ class change_filter: # pylint: disable=invalid-name
|
||||
else:
|
||||
return func()
|
||||
else:
|
||||
@pyqtSlot(str, str)
|
||||
@pyqtSlot()
|
||||
@functools.wraps(func)
|
||||
def wrapper(wrapper_self, sectname=None, optname=None):
|
||||
if sectname is None and optname is None:
|
||||
@ -346,8 +342,8 @@ class ConfigManager(QObject):
|
||||
DELETED_OPTIONS = [
|
||||
('colors', 'tab.separator'),
|
||||
('colors', 'tabs.separator'),
|
||||
('colors', 'tab.seperator'),
|
||||
('colors', 'tabs.seperator'),
|
||||
('colors', 'tab.seperator'), # pragma: no spellcheck
|
||||
('colors', 'tabs.seperator'), # pragma: no spellcheck
|
||||
('colors', 'completion.item.bg'),
|
||||
('tabs', 'indicator-space'),
|
||||
('tabs', 'hide-auto'),
|
||||
|
34
qutebrowser/html/bookmarks.html
Normal file
34
qutebrowser/html/bookmarks.html
Normal file
@ -0,0 +1,34 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block style %}
|
||||
table { border: 1px solid grey; border-collapse: collapse; width: 100%;}
|
||||
th, td { border: 1px solid grey; padding: 0px 5px; }
|
||||
th { background: lightgrey; }
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th><h3>Bookmark</h3></th>
|
||||
<th><h3>URL</h3></th>
|
||||
</tr>
|
||||
{% for url, title in bookmarks %}
|
||||
<tr>
|
||||
<td><a href="{{url}}">{{title}}</a></td>
|
||||
<td>{{url}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<th><h3>Quickmark</h3></th>
|
||||
<th><h3>URL</h3></th>
|
||||
</tr>
|
||||
{% for name, url in quickmarks %}
|
||||
<tr>
|
||||
<td><a href="{{url}}">{{name}}</a></td>
|
||||
<td>{{url}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
@ -38,3 +38,30 @@ function scroll_delta_page(x, y) {
|
||||
var dy = document.documentElement.clientHeight * y;
|
||||
window.scrollBy(dx, dy);
|
||||
}
|
||||
|
||||
function scroll_pos() {
|
||||
var elem = document.documentElement;
|
||||
var dx = (elem.scrollWidth - elem.clientWidth);
|
||||
var dy = (elem.scrollHeight - elem.clientHeight);
|
||||
|
||||
var perc_x, perc_y;
|
||||
|
||||
if (dx === 0) {
|
||||
perc_x = 0;
|
||||
} else {
|
||||
perc_x = 100 / dx * window.scrollX;
|
||||
}
|
||||
|
||||
if (dy === 0) {
|
||||
perc_y = 0;
|
||||
} else {
|
||||
perc_y = 100 / dy * window.scrollY;
|
||||
}
|
||||
|
||||
var pos_perc = {'x': perc_x, 'y': perc_y};
|
||||
var pos_px = {'x': window.scrollX, 'y': window.scrollY};
|
||||
var pos = {'perc': pos_perc, 'px': pos_px};
|
||||
|
||||
// console.log(JSON.stringify(pos));
|
||||
return pos;
|
||||
}
|
||||
|
@ -673,7 +673,6 @@ class TabbedBrowser(tabwidget.TabWidget):
|
||||
if key in self._global_marks:
|
||||
point, url = self._global_marks[key]
|
||||
|
||||
@pyqtSlot(bool)
|
||||
def callback(ok):
|
||||
if ok:
|
||||
self.cur_load_finished.disconnect(callback)
|
||||
|
@ -477,29 +477,6 @@ class ExceptionCrashDialog(_CrashDialog):
|
||||
else:
|
||||
self.reject()
|
||||
|
||||
@pyqtSlot()
|
||||
def on_report_clicked(self):
|
||||
"""Ignore reports with the QtWebEngine backend.
|
||||
|
||||
FIXME:qtwebengine Remove this when QtWebEngine is working better!
|
||||
"""
|
||||
try:
|
||||
backend = objreg.get('args').backend
|
||||
except Exception:
|
||||
backend = 'webkit'
|
||||
|
||||
if backend == 'webkit':
|
||||
super().on_report_clicked()
|
||||
return
|
||||
|
||||
title = "Crash reports disabled with QtWebEngine!"
|
||||
text = ("You're using the QtWebEngine backend which is not intended "
|
||||
"for general usage yet. Crash reports with that backend have "
|
||||
"been disabled.")
|
||||
box = msgbox.msgbox(parent=self, title=title, text=text,
|
||||
icon=QMessageBox.Critical)
|
||||
box.finished.connect(self.finish)
|
||||
|
||||
|
||||
class FatalCrashDialog(_CrashDialog):
|
||||
|
||||
|
@ -309,13 +309,14 @@ def earlyinit(args):
|
||||
# Here we check if QtCore is available, and if not, print a message to the
|
||||
# console or via Tk.
|
||||
check_pyqt_core()
|
||||
# Init logging as early as possible
|
||||
init_log(args)
|
||||
# Now the faulthandler is enabled we fix the Qt harfbuzzing library, before
|
||||
# importing QtWidgets.
|
||||
fix_harfbuzz(args)
|
||||
# Now we can be sure QtCore is available, so we can print dialogs on
|
||||
# errors, so people only using the GUI notice them as well.
|
||||
check_qt_version()
|
||||
check_ssl_support()
|
||||
remove_inputhook()
|
||||
check_libraries(args)
|
||||
init_log(args)
|
||||
check_ssl_support()
|
||||
|
@ -67,7 +67,6 @@ class Saveable:
|
||||
save_on_exit=self._save_on_exit,
|
||||
filename=self._filename)
|
||||
|
||||
@pyqtSlot()
|
||||
def mark_dirty(self):
|
||||
"""Mark this saveable as dirty (having changes)."""
|
||||
log.save.debug("Marking {} as dirty.".format(self._name))
|
||||
|
@ -167,9 +167,14 @@ def init_log(args):
|
||||
root.addHandler(ram)
|
||||
root.setLevel(logging.NOTSET)
|
||||
logging.captureWarnings(True)
|
||||
_init_py_warnings()
|
||||
QtCore.qInstallMessageHandler(qt_message_handler)
|
||||
|
||||
|
||||
def _init_py_warnings():
|
||||
"""Initialize Python warning handling."""
|
||||
warnings.simplefilter('default')
|
||||
warnings.filterwarnings('ignore', module='pdb', category=ResourceWarning)
|
||||
QtCore.qInstallMessageHandler(qt_message_handler)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
@ -182,6 +187,14 @@ def disable_qt_msghandler():
|
||||
QtCore.qInstallMessageHandler(old_handler)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def ignore_py_warnings(**kwargs):
|
||||
"""Contextmanager to temporarily hke certain Python warnings."""
|
||||
warnings.filterwarnings('ignore', **kwargs)
|
||||
yield
|
||||
_init_py_warnings()
|
||||
|
||||
|
||||
def _init_handlers(level, color, force_color, json_logging, ram_capacity):
|
||||
"""Init log handlers.
|
||||
|
||||
@ -330,6 +343,10 @@ def qt_message_handler(msg_type, context, msg):
|
||||
"Image of format '' blocked because it is not considered safe. If you "
|
||||
"are sure it is safe to do so, you can white-list the format by "
|
||||
"setting the environment variable QTWEBKIT_IMAGEFORMAT_WHITELIST=",
|
||||
# Installing Qt from the installer may cause it looking for SSL3 which
|
||||
# may not be available on the system
|
||||
"QSslSocket: cannot resolve SSLv3_client_method",
|
||||
"QSslSocket: cannot resolve SSLv3_server_method",
|
||||
]
|
||||
if sys.platform == 'darwin':
|
||||
suppressed_msgs += [
|
||||
|
@ -26,7 +26,7 @@ import datetime
|
||||
import collections
|
||||
import traceback
|
||||
|
||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject
|
||||
from PyQt5.QtCore import pyqtSignal, QObject
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
|
||||
from qutebrowser.utils import usertypes, log, objreg, utils
|
||||
@ -108,7 +108,6 @@ def _get_bridge(win_id):
|
||||
return objreg.get('message-bridge', scope='window', window=win_id)
|
||||
|
||||
|
||||
@pyqtSlot()
|
||||
def on_focus_changed():
|
||||
"""Show queued messages when a new window has been focused.
|
||||
|
||||
|
@ -33,11 +33,21 @@ import sys
|
||||
import operator
|
||||
import contextlib
|
||||
|
||||
import pkg_resources
|
||||
from PyQt5.QtCore import (qVersion, QEventLoop, QDataStream, QByteArray,
|
||||
QIODevice, QSaveFile)
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
|
||||
from qutebrowser.utils import log
|
||||
|
||||
with log.ignore_py_warnings(category=PendingDeprecationWarning, module='imp'):
|
||||
with log.ignore_py_warnings(category=ImportWarning):
|
||||
# This imports 'imp' and gives us a PendingDeprecationWarning on
|
||||
# Debian Jessie.
|
||||
#
|
||||
# On Archlinux, we get ImportWarning from
|
||||
# importlib/_bootstrap_external.py for modules with missing __init__.
|
||||
import pkg_resources
|
||||
|
||||
|
||||
MAXVALS = {
|
||||
'int': 2 ** 31 - 1,
|
||||
|
@ -34,7 +34,8 @@ class FakeTypingMeta(type):
|
||||
|
||||
"""Fake typing metaclass like typing.TypingMeta."""
|
||||
|
||||
def __init__(self, *args, **kwds): # pylint: disable=super-init-not-called
|
||||
def __init__(self, *args, # pylint: disable=super-init-not-called
|
||||
**_kwds):
|
||||
pass
|
||||
|
||||
def __subclasscheck__(self, cls):
|
||||
|
@ -31,11 +31,6 @@ from __future__ import print_function
|
||||
import subprocess
|
||||
import urllib
|
||||
|
||||
try:
|
||||
import _winreg as winreg
|
||||
except ImportError:
|
||||
winreg = None
|
||||
|
||||
|
||||
def check_setup(executable):
|
||||
subprocess.check_call([executable, '-c', 'import PyQt5'])
|
||||
@ -56,12 +51,6 @@ pyqt_url = ('http://www.qutebrowser.org/pyqt/'
|
||||
pyqt_version, qt_version))
|
||||
urllib.urlretrieve(pyqt_url, r'C:\install-PyQt5.exe')
|
||||
|
||||
print("Fixing registry...")
|
||||
with winreg.OpenKey(winreg.HKEY_CURRENT_USER,
|
||||
r'Software\Python\PythonCore\3.4', 0,
|
||||
winreg.KEY_WRITE) as key:
|
||||
winreg.SetValue(key, 'InstallPath', winreg.REG_SZ, r'C:\Python34')
|
||||
|
||||
print("Installing PyQt5...")
|
||||
subprocess.check_call([r'C:\install-PyQt5.exe', '/S'])
|
||||
|
||||
|
@ -56,7 +56,7 @@ def get_build_exe_options():
|
||||
opts['includes'] += pytest.freeze_includes() # pylint: disable=no-member
|
||||
opts['includes'] += ['unittest.mock', 'PyQt5.QtTest', 'hypothesis', 'bs4',
|
||||
'httpbin', 'jinja2.ext', 'cherrypy.wsgiserver',
|
||||
'cherrypy.wsgiserver.wsgiserver3', 'pstats']
|
||||
'pstats']
|
||||
|
||||
httpbin_dir = os.path.dirname(httpbin.__file__)
|
||||
opts['include_files'] += [
|
||||
|
@ -112,7 +112,9 @@ def check_spelling():
|
||||
continue
|
||||
for line in f:
|
||||
for w in words:
|
||||
if re.search(w, line) and fn not in seen[w]:
|
||||
if (re.search(w, line) and
|
||||
fn not in seen[w] and
|
||||
'# pragma: no spellcheck' not in line):
|
||||
print('Found "{}" in {}!'.format(w, fn))
|
||||
seen[w].append(fn)
|
||||
ok = False
|
||||
|
@ -238,3 +238,13 @@ Feature: Using hints
|
||||
And I press the key "2"
|
||||
And I wait for "Leaving mode KeyMode.hint (reason: all filtered)" in the log
|
||||
Then no crash should happen
|
||||
|
||||
# https://github.com/The-Compiler/qutebrowser/issues/1657
|
||||
Scenario: Using rapid number hinting twice
|
||||
When I open data/hints/number.html
|
||||
And I set hints -> mode to number
|
||||
And I run :hint --rapid
|
||||
And I run :leave-mode
|
||||
And I run :hint --rapid
|
||||
And I run :follow-hint 00
|
||||
Then data/numbers/1.txt should be loaded
|
||||
|
@ -208,3 +208,16 @@ Feature: quickmarks and bookmarks
|
||||
And I run :quickmark-add http://localhost:(port)/data/numbers/1.txt seventeen
|
||||
And I run :quickmark-del
|
||||
Then the quickmark file should not contain "seventeen http://localhost:*/data/numbers/1.txt"
|
||||
|
||||
Scenario: Listing quickmarks
|
||||
When I run :quickmark-add http://localhost:(port)/data/numbers/15.txt fifteen
|
||||
And I run :quickmark-add http://localhost:(port)/data/numbers/14.txt fourteen
|
||||
And I open qute:bookmarks
|
||||
Then the page should contain the plaintext "fifteen"
|
||||
And the page should contain the plaintext "fourteen"
|
||||
|
||||
Scenario: Listing bookmarks
|
||||
When I open data/title.html
|
||||
And I run :bookmark-add
|
||||
And I open qute:bookmarks
|
||||
Then the page should contain the plaintext "Test title"
|
||||
|
@ -106,9 +106,6 @@ class WSGIServer(cherrypy.wsgiserver.CherryPyWSGIServer):
|
||||
_printed_ready: Whether the initial ready message was printed.
|
||||
"""
|
||||
|
||||
# pylint: disable=no-member
|
||||
# WORKAROUND for https://bitbucket.org/logilab/pylint/issues/702
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self._ready = False
|
||||
|
@ -30,6 +30,7 @@ import itertools
|
||||
import textwrap
|
||||
import unittest.mock
|
||||
import types
|
||||
import os
|
||||
|
||||
import pytest
|
||||
|
||||
@ -405,3 +406,40 @@ def mode_manager(win_registry, config_stub, qapp):
|
||||
objreg.register('mode-manager', mm, scope='window', window=0)
|
||||
yield mm
|
||||
objreg.delete('mode-manager', scope='window', window=0)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def config_tmpdir(monkeypatch, tmpdir):
|
||||
"""Set tmpdir/config as the configdir.
|
||||
|
||||
Use this to avoid creating a 'real' config dir (~/.config/qute_test).
|
||||
"""
|
||||
confdir = tmpdir / 'config'
|
||||
path = str(confdir)
|
||||
os.mkdir(path)
|
||||
monkeypatch.setattr('qutebrowser.utils.standarddir.config', lambda: path)
|
||||
return confdir
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def data_tmpdir(monkeypatch, tmpdir):
|
||||
"""Set tmpdir/data as the datadir.
|
||||
|
||||
Use this to avoid creating a 'real' data dir (~/.local/share/qute_test).
|
||||
"""
|
||||
datadir = tmpdir / 'data'
|
||||
path = str(datadir)
|
||||
os.mkdir(path)
|
||||
monkeypatch.setattr('qutebrowser.utils.standarddir.data', lambda: path)
|
||||
return datadir
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def redirect_xdg_data(data_tmpdir, monkeypatch):
|
||||
"""Set XDG_DATA_HOME to a temp location.
|
||||
|
||||
While data_tmpdir covers most cases by redirecting standarddir.data(), this
|
||||
is not enough for places Qt references the data dir internally. For these,
|
||||
we need to set the environment variable to redirect data access.
|
||||
"""
|
||||
monkeypatch.setenv('XDG_DATA_HOME', str(data_tmpdir))
|
||||
|
@ -46,6 +46,9 @@ class LogFailHandler(logging.Handler):
|
||||
logger = logging.getLogger(record.name)
|
||||
root_logger = logging.getLogger()
|
||||
|
||||
if logger.name == 'messagemock':
|
||||
return
|
||||
|
||||
for h in root_logger.handlers:
|
||||
if isinstance(h, catchlog_mod.LogCaptureHandler):
|
||||
catchlog_handler = h
|
||||
|
@ -62,9 +62,7 @@ class MessageMock:
|
||||
}
|
||||
log_level = log_levels[level]
|
||||
|
||||
with self._caplog.at_level(log_level): # needed so we don't fail
|
||||
logging.getLogger('message').log(log_level, text)
|
||||
|
||||
logging.getLogger('messagemock').log(log_level, text)
|
||||
self.messages.append(Message(level, win_id, text, immediately))
|
||||
|
||||
def _handle_error(self, *args, **kwargs):
|
||||
|
@ -30,7 +30,7 @@ from qutebrowser.browser import adblock
|
||||
from qutebrowser.utils import objreg
|
||||
from qutebrowser.commands import cmdexc
|
||||
|
||||
pytestmark = pytest.mark.usefixtures('qapp')
|
||||
pytestmark = pytest.mark.usefixtures('qapp', 'config_tmpdir')
|
||||
|
||||
# TODO See ../utils/test_standarddirutils for OSError and caplog assertion
|
||||
|
||||
@ -54,13 +54,6 @@ URLS_TO_CHECK = ('http://localhost',
|
||||
'http://qutebrowser.org')
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def data_tmpdir(monkeypatch, tmpdir):
|
||||
"""Set tmpdir as datadir."""
|
||||
tmpdir = str(tmpdir)
|
||||
monkeypatch.setattr('qutebrowser.utils.standarddir.data', lambda: tmpdir)
|
||||
|
||||
|
||||
class BaseDirStub:
|
||||
|
||||
"""Mock for objreg.get('args') called in adblock.HostBlocker.read_hosts."""
|
||||
@ -348,7 +341,7 @@ def test_blocking_with_whitelist(config_stub, basedir, download_stub,
|
||||
# by creating a file named blocked-hosts,
|
||||
# Exclude localhost from it, since localhost is in HostBlocker.WHITELISTED
|
||||
filtered_blocked_hosts = BLOCKLIST_HOSTS[1:]
|
||||
blocklist = create_blocklist(tmpdir,
|
||||
blocklist = create_blocklist(data_tmpdir,
|
||||
blocked_hosts=filtered_blocked_hosts,
|
||||
name='blocked-hosts',
|
||||
line_format='one_per_line')
|
||||
|
@ -25,6 +25,8 @@ from qutebrowser.browser import browsertab
|
||||
from qutebrowser.keyinput import modeman
|
||||
from qutebrowser.utils import objreg
|
||||
|
||||
pytestmark = pytest.mark.usefixtures('redirect_xdg_data')
|
||||
|
||||
try:
|
||||
from PyQt5.QtWebKitWidgets import QWebView
|
||||
|
||||
|
@ -24,6 +24,8 @@ import pytest
|
||||
from qutebrowser.browser.webkit import cookies
|
||||
from qutebrowser.misc import lineparser
|
||||
|
||||
pytestmark = pytest.mark.usefixtures('data_tmpdir')
|
||||
|
||||
CONFIG_ALL_COOKIES = {'content': {'cookies-accept': 'all'}}
|
||||
CONFIG_NEVER_COOKIES = {'content': {'cookies-accept': 'never'}}
|
||||
CONFIG_COOKIES_ENABLED = {'content': {'cookies-store': True}}
|
||||
|
@ -64,6 +64,7 @@ def test_element_js_webkit(webview, js_enabled, expected):
|
||||
assert result == expected
|
||||
|
||||
|
||||
@pytest.mark.usefixtures('redirect_xdg_data')
|
||||
@pytest.mark.parametrize('js_enabled, expected', [(True, 2.0), (False, 2.0)])
|
||||
def test_simple_js_webengine(qtbot, webengineview, js_enabled, expected):
|
||||
"""With QtWebEngine, runJavaScript works even when JS is off."""
|
||||
|
@ -295,6 +295,7 @@ class TestKeyConfigParser:
|
||||
assert new == new_expected
|
||||
|
||||
|
||||
@pytest.mark.usefixtures('config_tmpdir')
|
||||
@pytest.mark.integration
|
||||
class TestDefaultConfig:
|
||||
|
||||
|
@ -1282,6 +1282,7 @@ def unrequired_class(**kwargs):
|
||||
|
||||
|
||||
@pytest.mark.usefixtures('qapp')
|
||||
@pytest.mark.usefixtures('config_tmpdir')
|
||||
class TestFileAndUserStyleSheet:
|
||||
|
||||
"""Test File/UserStyleSheet."""
|
||||
|
@ -42,7 +42,7 @@ def gen_classes():
|
||||
yield member
|
||||
|
||||
|
||||
@pytest.mark.usefixtures('qapp')
|
||||
@pytest.mark.usefixtures('qapp', 'config_tmpdir')
|
||||
@pytest.mark.parametrize('klass', gen_classes())
|
||||
@hypothesis.given(strategies.text())
|
||||
@hypothesis.example('\x00')
|
||||
|
@ -24,7 +24,7 @@ import pytest
|
||||
|
||||
from qutebrowser.misc import msgbox
|
||||
|
||||
from PyQt5.QtCore import pyqtSlot, Qt
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import QMessageBox, QWidget
|
||||
|
||||
|
||||
@ -64,7 +64,6 @@ def test_finished_signal(qtbot):
|
||||
"""Make sure we can pass a slot to be called when the dialog finished."""
|
||||
signal_triggered = False
|
||||
|
||||
@pyqtSlot()
|
||||
def on_finished():
|
||||
nonlocal signal_triggered
|
||||
signal_triggered = True
|
||||
|
@ -26,7 +26,7 @@ import pytest
|
||||
from qutebrowser.utils import error
|
||||
from qutebrowser.misc import ipc
|
||||
|
||||
from PyQt5.QtCore import pyqtSlot, QTimer
|
||||
from PyQt5.QtCore import QTimer
|
||||
from PyQt5.QtWidgets import QMessageBox
|
||||
|
||||
|
||||
@ -81,7 +81,6 @@ def test_no_err_windows(caplog, exc, name, exc_text, fake_args):
|
||||
], ids=repr)
|
||||
def test_err_windows(qtbot, qapp, fake_args, pre_text, post_text, expected):
|
||||
|
||||
@pyqtSlot()
|
||||
def err_window_check():
|
||||
w = qapp.activeModalWidget()
|
||||
try:
|
||||
|
@ -23,6 +23,7 @@ import logging
|
||||
import argparse
|
||||
import itertools
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
import pytest
|
||||
import pytest_catchlog
|
||||
@ -36,6 +37,7 @@ def restore_loggers():
|
||||
|
||||
Based on CPython's Lib/test/test_logging.py.
|
||||
"""
|
||||
logging.captureWarnings(False)
|
||||
logger_dict = logging.getLogger().manager.loggerDict
|
||||
logging._acquireLock()
|
||||
try:
|
||||
@ -278,3 +280,14 @@ def test_stub(caplog, suffix, expected):
|
||||
log.stub(suffix)
|
||||
assert len(caplog.records) == 1
|
||||
assert caplog.records[0].message == expected
|
||||
|
||||
|
||||
def test_ignore_py_warnings(caplog):
|
||||
logging.captureWarnings(True)
|
||||
with log.ignore_py_warnings(category=UserWarning):
|
||||
warnings.warn("hidden", UserWarning)
|
||||
with caplog.at_level(logging.WARNING):
|
||||
warnings.warn("not hidden", UserWarning)
|
||||
assert len(caplog.records) == 1
|
||||
msg = caplog.records[0].message.splitlines()[0]
|
||||
assert msg.endswith("UserWarning: not hidden")
|
||||
|
@ -52,15 +52,15 @@ def no_cachedir_tag(monkeypatch):
|
||||
lambda: None)
|
||||
|
||||
|
||||
@pytest.yield_fixture(autouse=True)
|
||||
@pytest.mark.usefixtures('no_cachedir_tag')
|
||||
def reset_standarddir():
|
||||
@pytest.yield_fixture
|
||||
def reset_standarddir(no_cachedir_tag):
|
||||
"""Clean up standarddir arguments before and after each test."""
|
||||
standarddir.init(None)
|
||||
yield
|
||||
standarddir.init(None)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures('reset_standarddir')
|
||||
@pytest.mark.parametrize('data_subdir, config_subdir, expected', [
|
||||
('foo', 'foo', 'foo/data'),
|
||||
('foo', 'bar', 'foo'),
|
||||
@ -80,6 +80,7 @@ def test_get_fake_windows_equal_dir(data_subdir, config_subdir, expected,
|
||||
assert standarddir.data() == expected
|
||||
|
||||
|
||||
@pytest.mark.usefixtures('reset_standarddir')
|
||||
class TestWritableLocation:
|
||||
|
||||
"""Tests for _writable_location."""
|
||||
@ -100,7 +101,7 @@ class TestWritableLocation:
|
||||
assert '\\' in loc
|
||||
|
||||
|
||||
@pytest.mark.usefixtures('no_cachedir_tag')
|
||||
@pytest.mark.usefixtures('reset_standarddir')
|
||||
class TestStandardDir:
|
||||
|
||||
"""Tests for standarddir."""
|
||||
@ -159,7 +160,7 @@ class TestStandardDir:
|
||||
DirArgTest = collections.namedtuple('DirArgTest', 'arg, expected')
|
||||
|
||||
|
||||
@pytest.mark.usefixtures('no_cachedir_tag')
|
||||
@pytest.mark.usefixtures('reset_standarddir')
|
||||
class TestArguments:
|
||||
|
||||
"""Tests with confdir/cachedir/datadir arguments."""
|
||||
@ -195,8 +196,10 @@ class TestArguments:
|
||||
standarddir.init(args)
|
||||
assert standarddir.data() == testcase.expected
|
||||
|
||||
def test_confdir_none(self):
|
||||
def test_confdir_none(self, mocker):
|
||||
"""Test --confdir with None given."""
|
||||
# patch makedirs to a noop so we don't really create a directory
|
||||
mocker.patch('qutebrowser.utils.standarddir.os.makedirs')
|
||||
args = types.SimpleNamespace(confdir=None, cachedir=None, datadir=None,
|
||||
basedir=None)
|
||||
standarddir.init(args)
|
||||
@ -294,6 +297,7 @@ class TestCreatingDir:
|
||||
if os.name == 'posix':
|
||||
assert basedir.stat().mode & 0o777 == 0o700
|
||||
|
||||
@pytest.mark.usefixtures('reset_standarddir')
|
||||
@pytest.mark.parametrize('typ', DIR_TYPES)
|
||||
def test_exists_race_condition(self, mocker, tmpdir, typ):
|
||||
"""Make sure there can't be a TOCTOU issue when creating the file.
|
||||
@ -315,6 +319,7 @@ class TestCreatingDir:
|
||||
func()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures('reset_standarddir')
|
||||
class TestSystemData:
|
||||
|
||||
"""Test system data path."""
|
||||
@ -326,12 +331,18 @@ class TestSystemData:
|
||||
assert standarddir.system_data() == "/usr/share/qutebrowser"
|
||||
|
||||
@pytest.mark.linux
|
||||
def test_system_datadir_not_exist_linux(self, monkeypatch):
|
||||
def test_system_datadir_not_exist_linux(self, monkeypatch, tmpdir,
|
||||
fake_args):
|
||||
"""Test that system-wide path isn't used on linux if path not exist."""
|
||||
fake_args.basedir = str(tmpdir)
|
||||
standarddir.init(fake_args)
|
||||
monkeypatch.setattr(os.path, 'exists', lambda path: False)
|
||||
assert standarddir.system_data() == standarddir.data()
|
||||
|
||||
def test_system_datadir_unsupportedos(self, monkeypatch):
|
||||
def test_system_datadir_unsupportedos(self, monkeypatch, tmpdir,
|
||||
fake_args):
|
||||
"""Test that system-wide path is not used on non-Linux OS."""
|
||||
fake_args.basedir = str(tmpdir)
|
||||
standarddir.init(fake_args)
|
||||
monkeypatch.setattr('sys.platform', "potato")
|
||||
assert standarddir.system_data() == standarddir.data()
|
||||
|
Loading…
Reference in New Issue
Block a user