Merge branch 'master' into es6ify-js
This commit is contained in:
commit
6e624bcd3c
@ -51,7 +51,7 @@ matrix:
|
|||||||
env: TESTENV=eslint
|
env: TESTENV=eslint
|
||||||
language: node_js
|
language: node_js
|
||||||
python: null
|
python: null
|
||||||
node_js: node
|
node_js: "lts/*"
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
|
@ -34,6 +34,8 @@ Added
|
|||||||
widget.
|
widget.
|
||||||
- `:edit-url` now handles the `--private` and `--related` flags, which have the
|
- `:edit-url` now handles the `--private` and `--related` flags, which have the
|
||||||
same effect they have with `:open`.
|
same effect they have with `:open`.
|
||||||
|
- New `{line}` and `{column}` replacements for `editor.command` to position the
|
||||||
|
cursor correctly.
|
||||||
|
|
||||||
Changed
|
Changed
|
||||||
~~~~~~~
|
~~~~~~~
|
||||||
@ -76,6 +78,8 @@ Fixed
|
|||||||
~~~~~
|
~~~~~
|
||||||
|
|
||||||
- Handle accessing a locked sqlite database gracefully
|
- Handle accessing a locked sqlite database gracefully
|
||||||
|
- Abort pinned tab dialogs properly when a tab is closed e.g. by closing a
|
||||||
|
window.
|
||||||
|
|
||||||
v1.0.2
|
v1.0.2
|
||||||
------
|
------
|
||||||
|
@ -152,7 +152,7 @@ For QtWebEngine:
|
|||||||
`:set spellcheck.languages "['en-US', 'pl-PL']"`
|
`:set spellcheck.languages "['en-US', 'pl-PL']"`
|
||||||
|
|
||||||
How do I use Tor with qutebrowser?::
|
How do I use Tor with qutebrowser?::
|
||||||
Start tor on your machine, and do `:set network proxy socks://localhost:9050/`
|
Start tor on your machine, and do `:set content.proxy socks://localhost:9050/`
|
||||||
in qutebrowser. Note this won't give you the same amount of fingerprinting
|
in qutebrowser. Note this won't give you the same amount of fingerprinting
|
||||||
protection that the Tor Browser does, but it's useful to be able to access
|
protection that the Tor Browser does, but it's useful to be able to access
|
||||||
`.onion` sites.
|
`.onion` sites.
|
||||||
@ -162,7 +162,7 @@ Why does J move to the next (right) tab, and K to the previous (left) one?::
|
|||||||
and qutebrowser's keybindings are designed to be compatible with dwb's.
|
and qutebrowser's keybindings are designed to be compatible with dwb's.
|
||||||
The rationale behind it is that J is "down" in vim, and K is "up", which
|
The rationale behind it is that J is "down" in vim, and K is "up", which
|
||||||
corresponds nicely to "next"/"previous". It also makes much more sense with
|
corresponds nicely to "next"/"previous". It also makes much more sense with
|
||||||
vertical tabs (e.g. `:set tabs position left`).
|
vertical tabs (e.g. `:set tabs.position left`).
|
||||||
|
|
||||||
What's the difference between insert and passthrough mode?::
|
What's the difference between insert and passthrough mode?::
|
||||||
They are quite similar, but insert mode has some bindings (like `Ctrl-e` to
|
They are quite similar, but insert mode has some bindings (like `Ctrl-e` to
|
||||||
|
@ -1961,7 +1961,14 @@ Default: +pass:[-1]+
|
|||||||
[[editor.command]]
|
[[editor.command]]
|
||||||
=== editor.command
|
=== editor.command
|
||||||
The editor (and arguments) to use for the `open-editor` command.
|
The editor (and arguments) to use for the `open-editor` command.
|
||||||
`{}` gets replaced by the filename of the file to be edited.
|
Several placeholders are supported. Placeholders are substituted by the
|
||||||
|
respective value when executing the command.
|
||||||
|
|
||||||
|
`{file}` gets replaced by the filename of the file to be edited.
|
||||||
|
`{line}` gets replaced by the line in which the caret is found in the text.
|
||||||
|
`{column}` gets replaced by the column in which the caret is found in the text.
|
||||||
|
`{line0}` same as `{line}`, but starting from index 0.
|
||||||
|
`{column0}` same as `{column}`, but starting from index 0.
|
||||||
|
|
||||||
Type: <<types,ShellCommand>>
|
Type: <<types,ShellCommand>>
|
||||||
|
|
||||||
|
@ -660,9 +660,9 @@ class Quitter:
|
|||||||
try:
|
try:
|
||||||
args, cwd = self._get_restart_args(pages, session, override_args)
|
args, cwd = self._get_restart_args(pages, session, override_args)
|
||||||
if cwd is None:
|
if cwd is None:
|
||||||
subprocess.Popen(args)
|
subprocess.run(args)
|
||||||
else:
|
else:
|
||||||
subprocess.Popen(args, cwd=cwd)
|
subprocess.run(args, cwd=cwd)
|
||||||
except OSError:
|
except OSError:
|
||||||
log.destroy.exception("Failed to restart")
|
log.destroy.exception("Failed to restart")
|
||||||
return False
|
return False
|
||||||
|
@ -1618,10 +1618,12 @@ class CommandDispatcher:
|
|||||||
return
|
return
|
||||||
assert isinstance(text, str), text
|
assert isinstance(text, str), text
|
||||||
|
|
||||||
|
caret_position = elem.caret_position()
|
||||||
|
|
||||||
ed = editor.ExternalEditor(self._tabbed_browser)
|
ed = editor.ExternalEditor(self._tabbed_browser)
|
||||||
ed.editing_finished.connect(functools.partial(
|
ed.editing_finished.connect(functools.partial(
|
||||||
self.on_editing_finished, elem))
|
self.on_editing_finished, elem))
|
||||||
ed.edit(text)
|
ed.edit(text, caret_position)
|
||||||
|
|
||||||
@cmdutils.register(instance='command-dispatcher', hide=True,
|
@cmdutils.register(instance='command-dispatcher', hide=True,
|
||||||
scope='window')
|
scope='window')
|
||||||
|
@ -47,6 +47,7 @@ class WebEngineElement(webelem.AbstractWebElement):
|
|||||||
'class_name': str,
|
'class_name': str,
|
||||||
'rects': list,
|
'rects': list,
|
||||||
'attributes': dict,
|
'attributes': dict,
|
||||||
|
'caret_position': int,
|
||||||
}
|
}
|
||||||
assert set(js_dict.keys()).issubset(js_dict_types.keys())
|
assert set(js_dict.keys()).issubset(js_dict_types.keys())
|
||||||
for name, typ in js_dict_types.items():
|
for name, typ in js_dict_types.items():
|
||||||
@ -132,6 +133,10 @@ class WebEngineElement(webelem.AbstractWebElement):
|
|||||||
def set_value(self, value):
|
def set_value(self, value):
|
||||||
self._js_call('set_value', value)
|
self._js_call('set_value', value)
|
||||||
|
|
||||||
|
def caret_position(self):
|
||||||
|
"""Get the text caret position for the current element."""
|
||||||
|
return self._js_dict.get('caret_position', 0)
|
||||||
|
|
||||||
def insert_text(self, text):
|
def insert_text(self, text):
|
||||||
if not self.is_editable(strict=True):
|
if not self.is_editable(strict=True):
|
||||||
raise webelem.Error("Element is not editable!")
|
raise webelem.Error("Element is not editable!")
|
||||||
|
@ -126,6 +126,14 @@ class WebKitElement(webelem.AbstractWebElement):
|
|||||||
value = javascript.string_escape(value)
|
value = javascript.string_escape(value)
|
||||||
self._elem.evaluateJavaScript("this.value='{}'".format(value))
|
self._elem.evaluateJavaScript("this.value='{}'".format(value))
|
||||||
|
|
||||||
|
def caret_position(self):
|
||||||
|
"""Get the text caret position for the current element."""
|
||||||
|
self._check_vanished()
|
||||||
|
pos = self._elem.evaluateJavaScript('this.selectionStart')
|
||||||
|
if pos is None:
|
||||||
|
return 0
|
||||||
|
return int(pos)
|
||||||
|
|
||||||
def insert_text(self, text):
|
def insert_text(self, text):
|
||||||
self._check_vanished()
|
self._check_vanished()
|
||||||
if not self.is_editable(strict=True):
|
if not self.is_editable(strict=True):
|
||||||
|
@ -766,11 +766,11 @@ editor.command:
|
|||||||
type:
|
type:
|
||||||
name: ShellCommand
|
name: ShellCommand
|
||||||
placeholder: true
|
placeholder: true
|
||||||
default: ["gvim", "-f", "{}"]
|
default: ["gvim", "-f", "{file}", "-c", "normal {line}G{column0}l"]
|
||||||
desc: >-
|
desc: >-
|
||||||
The editor (and arguments) to use for the `open-editor` command.
|
The editor (and arguments) to use for the `open-editor` command.
|
||||||
|
|
||||||
`{}` gets replaced by the filename of the file to be edited.
|
`{file}` gets replaced by the filename of the file to be edited.
|
||||||
|
|
||||||
editor.encoding:
|
editor.encoding:
|
||||||
type: Encoding
|
type: Encoding
|
||||||
|
@ -755,6 +755,6 @@ def get_diff():
|
|||||||
lexer = pygments.lexers.DiffLexer()
|
lexer = pygments.lexers.DiffLexer()
|
||||||
formatter = pygments.formatters.HtmlFormatter(
|
formatter = pygments.formatters.HtmlFormatter(
|
||||||
full=True, linenos='table',
|
full=True, linenos='table',
|
||||||
title='Config diff')
|
title='Diffing pre-1.0 default config with pre-1.0 modified config')
|
||||||
# pylint: enable=no-member
|
# pylint: enable=no-member
|
||||||
return pygments.highlight(conf_diff + key_diff, lexer, formatter)
|
return pygments.highlight(conf_diff + key_diff, lexer, formatter)
|
||||||
|
@ -1341,9 +1341,12 @@ class ShellCommand(List):
|
|||||||
if not value:
|
if not value:
|
||||||
return value
|
return value
|
||||||
|
|
||||||
if self.placeholder and '{}' not in ' '.join(value):
|
if (self.placeholder and
|
||||||
|
'{}' not in ' '.join(value) and
|
||||||
|
'{file}' not in ' '.join(value)):
|
||||||
raise configexc.ValidationError(value, "needs to contain a "
|
raise configexc.ValidationError(value, "needs to contain a "
|
||||||
"{}-placeholder.")
|
"{}-placeholder or a "
|
||||||
|
"{file}-placeholder.")
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,11 +48,26 @@ window._qutebrowser.webelem = (function() {
|
|||||||
const id = elements.length;
|
const id = elements.length;
|
||||||
elements[id] = elem;
|
elements[id] = elem;
|
||||||
|
|
||||||
|
// InvalidStateError will be thrown if elem doesn't have selectionStart
|
||||||
|
let caret_position = 0;
|
||||||
|
try {
|
||||||
|
caret_position = elem.selectionStart;
|
||||||
|
} catch (err) {
|
||||||
|
if (err instanceof DOMException &&
|
||||||
|
err.name === "InvalidStateError") {
|
||||||
|
// nothing to do, caret_position is already 0
|
||||||
|
} else {
|
||||||
|
// not the droid we're looking for
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const out = {
|
const out = {
|
||||||
"id": id,
|
"id": id,
|
||||||
"value": elem.value,
|
"value": elem.value,
|
||||||
"outer_xml": elem.outerHTML,
|
"outer_xml": elem.outerHTML,
|
||||||
"rects": [], // Gets filled up later
|
"rects": [], // Gets filled up later
|
||||||
|
"caret_position": caret_position,
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://github.com/qutebrowser/qutebrowser/issues/2569
|
// https://github.com/qutebrowser/qutebrowser/issues/2569
|
||||||
|
@ -259,13 +259,14 @@ class TabbedBrowser(tabwidget.TabWidget):
|
|||||||
def tab_close_prompt_if_pinned(self, tab, force, yes_action):
|
def tab_close_prompt_if_pinned(self, tab, force, yes_action):
|
||||||
"""Helper method for tab_close.
|
"""Helper method for tab_close.
|
||||||
|
|
||||||
If tab is pinned, prompt. If everything is good, run yes_action.
|
If tab is pinned, prompt. If not, run yes_action.
|
||||||
|
If tab is destroyed, abort question.
|
||||||
"""
|
"""
|
||||||
if tab.data.pinned and not force:
|
if tab.data.pinned and not force:
|
||||||
message.confirm_async(
|
message.confirm_async(
|
||||||
title='Pinned Tab',
|
title='Pinned Tab',
|
||||||
text="Are you sure you want to close a pinned tab?",
|
text="Are you sure you want to close a pinned tab?",
|
||||||
yes_action=yes_action, default=False)
|
yes_action=yes_action, default=False, abort_on=[tab.destroyed])
|
||||||
else:
|
else:
|
||||||
yes_action()
|
yes_action()
|
||||||
|
|
||||||
|
@ -96,11 +96,12 @@ class ExternalEditor(QObject):
|
|||||||
def on_proc_error(self, _err):
|
def on_proc_error(self, _err):
|
||||||
self._cleanup()
|
self._cleanup()
|
||||||
|
|
||||||
def edit(self, text):
|
def edit(self, text, caret_position=0):
|
||||||
"""Edit a given text.
|
"""Edit a given text.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
text: The initial text to edit.
|
text: The initial text to edit.
|
||||||
|
caret_position: The position of the caret in the text.
|
||||||
"""
|
"""
|
||||||
if self._filename is not None:
|
if self._filename is not None:
|
||||||
raise ValueError("Already editing a file!")
|
raise ValueError("Already editing a file!")
|
||||||
@ -121,7 +122,9 @@ class ExternalEditor(QObject):
|
|||||||
return
|
return
|
||||||
|
|
||||||
self._remove_file = True
|
self._remove_file = True
|
||||||
self._start_editor()
|
|
||||||
|
line, column = self._calc_line_and_column(text, caret_position)
|
||||||
|
self._start_editor(line=line, column=column)
|
||||||
|
|
||||||
def edit_file(self, filename):
|
def edit_file(self, filename):
|
||||||
"""Edit the file with the given filename."""
|
"""Edit the file with the given filename."""
|
||||||
@ -129,13 +132,82 @@ class ExternalEditor(QObject):
|
|||||||
self._remove_file = False
|
self._remove_file = False
|
||||||
self._start_editor()
|
self._start_editor()
|
||||||
|
|
||||||
def _start_editor(self):
|
def _start_editor(self, line=1, column=1):
|
||||||
"""Start the editor with the file opened as self._filename."""
|
"""Start the editor with the file opened as self._filename.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
line: the line number to pass to the editor
|
||||||
|
column: the column number to pass to the editor
|
||||||
|
"""
|
||||||
self._proc = guiprocess.GUIProcess(what='editor', parent=self)
|
self._proc = guiprocess.GUIProcess(what='editor', parent=self)
|
||||||
self._proc.finished.connect(self.on_proc_closed)
|
self._proc.finished.connect(self.on_proc_closed)
|
||||||
self._proc.error.connect(self.on_proc_error)
|
self._proc.error.connect(self.on_proc_error)
|
||||||
editor = config.val.editor.command
|
editor = config.val.editor.command
|
||||||
executable = editor[0]
|
executable = editor[0]
|
||||||
args = [arg.replace('{}', self._filename) for arg in editor[1:]]
|
|
||||||
|
args = [self._sub_placeholder(arg, line, column) for arg in editor[1:]]
|
||||||
log.procs.debug("Calling \"{}\" with args {}".format(executable, args))
|
log.procs.debug("Calling \"{}\" with args {}".format(executable, args))
|
||||||
self._proc.start(executable, args)
|
self._proc.start(executable, args)
|
||||||
|
|
||||||
|
def _calc_line_and_column(self, text, caret_position):
|
||||||
|
r"""Calculate line and column numbers given a text and caret position.
|
||||||
|
|
||||||
|
Both line and column are 1-based indexes, because that's what most
|
||||||
|
editors use as line and column starting index. By "most" we mean at
|
||||||
|
least vim, nvim, gvim, emacs, atom, sublimetext, notepad++, brackets,
|
||||||
|
visual studio, QtCreator and so on.
|
||||||
|
|
||||||
|
To find the line we just count how many newlines there are before the
|
||||||
|
caret and add 1.
|
||||||
|
|
||||||
|
To find the column we calculate the difference between the caret and
|
||||||
|
the last newline before the caret.
|
||||||
|
|
||||||
|
For example in the text `aaa\nbb|bbb` (| represents the caret):
|
||||||
|
caret_position = 6
|
||||||
|
text[:caret_position] = `aaa\nbb`
|
||||||
|
text[:caret_position].count('\n') = 1
|
||||||
|
caret_position - text[:caret_position].rfind('\n') = 3
|
||||||
|
|
||||||
|
Thus line, column = 2, 3, and the caret is indeed in the second
|
||||||
|
line, third column
|
||||||
|
|
||||||
|
Args:
|
||||||
|
text: the text for which the numbers must be calculated
|
||||||
|
caret_position: the position of the caret in the text
|
||||||
|
|
||||||
|
Return:
|
||||||
|
A (line, column) tuple of (int, int)
|
||||||
|
"""
|
||||||
|
line = text[:caret_position].count('\n') + 1
|
||||||
|
column = caret_position - text[:caret_position].rfind('\n')
|
||||||
|
return line, column
|
||||||
|
|
||||||
|
def _sub_placeholder(self, arg, line, column):
|
||||||
|
"""Substitute a single placeholder.
|
||||||
|
|
||||||
|
If the `arg` input to this function is a valid placeholder it will
|
||||||
|
be substituted with the appropriate value, otherwise it will be left
|
||||||
|
unchanged.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
arg: an argument of editor.command.
|
||||||
|
line: the previously-calculated line number for the text caret.
|
||||||
|
column: the previously-calculated column number for the text caret.
|
||||||
|
|
||||||
|
Return:
|
||||||
|
The substituted placeholder or the original argument.
|
||||||
|
"""
|
||||||
|
replacements = {
|
||||||
|
'{}': self._filename,
|
||||||
|
'{file}': self._filename,
|
||||||
|
'{line}': str(line),
|
||||||
|
'{line0}': str(line-1),
|
||||||
|
'{column}': str(column),
|
||||||
|
'{column0}': str(column-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
for old, new in replacements.items():
|
||||||
|
arg = arg.replace(old, new)
|
||||||
|
|
||||||
|
return arg
|
||||||
|
@ -151,12 +151,14 @@ def _git_str_subprocess(gitpath):
|
|||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
# https://stackoverflow.com/questions/21017300/21017394#21017394
|
# https://stackoverflow.com/questions/21017300/21017394#21017394
|
||||||
commit_hash = subprocess.check_output(
|
commit_hash = subprocess.run(
|
||||||
['git', 'describe', '--match=NeVeRmAtCh', '--always', '--dirty'],
|
['git', 'describe', '--match=NeVeRmAtCh', '--always', '--dirty'],
|
||||||
cwd=gitpath).decode('UTF-8').strip()
|
cwd=gitpath, check=True,
|
||||||
date = subprocess.check_output(
|
stdout=subprocess.PIPE).stdout.decode('UTF-8').strip()
|
||||||
|
date = subprocess.run(
|
||||||
['git', 'show', '-s', '--format=%ci', 'HEAD'],
|
['git', 'show', '-s', '--format=%ci', 'HEAD'],
|
||||||
cwd=gitpath).decode('UTF-8').strip()
|
cwd=gitpath, check=True,
|
||||||
|
stdout=subprocess.PIPE).stdout.decode('UTF-8').strip()
|
||||||
return '{} ({})'.format(commit_hash, date)
|
return '{} ({})'.format(commit_hash, date)
|
||||||
except (subprocess.CalledProcessError, OSError):
|
except (subprocess.CalledProcessError, OSError):
|
||||||
return None
|
return None
|
||||||
|
@ -224,7 +224,7 @@ class AsciiDoc:
|
|||||||
return self._args.asciidoc
|
return self._args.asciidoc
|
||||||
|
|
||||||
try:
|
try:
|
||||||
subprocess.call(['asciidoc'], stdout=subprocess.DEVNULL,
|
subprocess.run(['asciidoc'], stdout=subprocess.DEVNULL,
|
||||||
stderr=subprocess.DEVNULL)
|
stderr=subprocess.DEVNULL)
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
@ -232,7 +232,7 @@ class AsciiDoc:
|
|||||||
return ['asciidoc']
|
return ['asciidoc']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
subprocess.call(['asciidoc.py'], stdout=subprocess.DEVNULL,
|
subprocess.run(['asciidoc.py'], stdout=subprocess.DEVNULL,
|
||||||
stderr=subprocess.DEVNULL)
|
stderr=subprocess.DEVNULL)
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
@ -258,7 +258,7 @@ class AsciiDoc:
|
|||||||
try:
|
try:
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
env['HOME'] = self._homedir
|
env['HOME'] = self._homedir
|
||||||
subprocess.check_call(cmdline, env=env)
|
subprocess.run(cmdline, check=True, env=env)
|
||||||
except (subprocess.CalledProcessError, OSError) as e:
|
except (subprocess.CalledProcessError, OSError) as e:
|
||||||
self._failed = True
|
self._failed = True
|
||||||
utils.print_col(str(e), 'red')
|
utils.print_col(str(e), 'red')
|
||||||
|
@ -50,7 +50,7 @@ def call_script(name, *args, python=sys.executable):
|
|||||||
python: The python interpreter to use.
|
python: The python interpreter to use.
|
||||||
"""
|
"""
|
||||||
path = os.path.join(os.path.dirname(__file__), os.pardir, name)
|
path = os.path.join(os.path.dirname(__file__), os.pardir, name)
|
||||||
subprocess.check_call([python, path] + list(args))
|
subprocess.run([python, path] + list(args), check=True)
|
||||||
|
|
||||||
|
|
||||||
def call_tox(toxenv, *args, python=sys.executable):
|
def call_tox(toxenv, *args, python=sys.executable):
|
||||||
@ -64,9 +64,9 @@ def call_tox(toxenv, *args, python=sys.executable):
|
|||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
env['PYTHON'] = python
|
env['PYTHON'] = python
|
||||||
env['PATH'] = os.environ['PATH'] + os.pathsep + os.path.dirname(python)
|
env['PATH'] = os.environ['PATH'] + os.pathsep + os.path.dirname(python)
|
||||||
subprocess.check_call(
|
subprocess.run(
|
||||||
[sys.executable, '-m', 'tox', '-vv', '-e', toxenv] + list(args),
|
[sys.executable, '-m', 'tox', '-vv', '-e', toxenv] + list(args),
|
||||||
env=env)
|
env=env, check=True)
|
||||||
|
|
||||||
|
|
||||||
def run_asciidoc2html(args):
|
def run_asciidoc2html(args):
|
||||||
@ -89,8 +89,9 @@ def _maybe_remove(path):
|
|||||||
|
|
||||||
def smoke_test(executable):
|
def smoke_test(executable):
|
||||||
"""Try starting the given qutebrowser executable."""
|
"""Try starting the given qutebrowser executable."""
|
||||||
subprocess.check_call([executable, '--no-err-windows', '--nowindow',
|
subprocess.run([executable, '--no-err-windows', '--nowindow',
|
||||||
'--temp-basedir', 'about:blank', ':later 500 quit'])
|
'--temp-basedir', 'about:blank', ':later 500 quit'],
|
||||||
|
check=True)
|
||||||
|
|
||||||
|
|
||||||
def patch_mac_app():
|
def patch_mac_app():
|
||||||
@ -178,7 +179,7 @@ def build_mac():
|
|||||||
utils.print_title("Patching .app")
|
utils.print_title("Patching .app")
|
||||||
patch_mac_app()
|
patch_mac_app()
|
||||||
utils.print_title("Building .dmg")
|
utils.print_title("Building .dmg")
|
||||||
subprocess.check_call(['make', '-f', 'scripts/dev/Makefile-dmg'])
|
subprocess.run(['make', '-f', 'scripts/dev/Makefile-dmg'], check=True)
|
||||||
|
|
||||||
dmg_name = 'qutebrowser-{}.dmg'.format(qutebrowser.__version__)
|
dmg_name = 'qutebrowser-{}.dmg'.format(qutebrowser.__version__)
|
||||||
os.rename('qutebrowser.dmg', dmg_name)
|
os.rename('qutebrowser.dmg', dmg_name)
|
||||||
@ -187,14 +188,14 @@ def build_mac():
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
subprocess.check_call(['hdiutil', 'attach', dmg_name,
|
subprocess.run(['hdiutil', 'attach', dmg_name,
|
||||||
'-mountpoint', tmpdir])
|
'-mountpoint', tmpdir], check=True)
|
||||||
try:
|
try:
|
||||||
binary = os.path.join(tmpdir, 'qutebrowser.app', 'Contents',
|
binary = os.path.join(tmpdir, 'qutebrowser.app', 'Contents',
|
||||||
'MacOS', 'qutebrowser')
|
'MacOS', 'qutebrowser')
|
||||||
smoke_test(binary)
|
smoke_test(binary)
|
||||||
finally:
|
finally:
|
||||||
subprocess.call(['hdiutil', 'detach', tmpdir])
|
subprocess.run(['hdiutil', 'detach', tmpdir])
|
||||||
except PermissionError as e:
|
except PermissionError as e:
|
||||||
print("Failed to remove tempdir: {}".format(e))
|
print("Failed to remove tempdir: {}".format(e))
|
||||||
|
|
||||||
@ -242,13 +243,13 @@ def build_windows():
|
|||||||
patch_windows(out_64)
|
patch_windows(out_64)
|
||||||
|
|
||||||
utils.print_title("Building installers")
|
utils.print_title("Building installers")
|
||||||
subprocess.check_call(['makensis.exe',
|
subprocess.run(['makensis.exe',
|
||||||
'/DVERSION={}'.format(qutebrowser.__version__),
|
'/DVERSION={}'.format(qutebrowser.__version__),
|
||||||
'misc/qutebrowser.nsi'])
|
'misc/qutebrowser.nsi'], check=True)
|
||||||
subprocess.check_call(['makensis.exe',
|
subprocess.run(['makensis.exe',
|
||||||
'/DX64',
|
'/DX64',
|
||||||
'/DVERSION={}'.format(qutebrowser.__version__),
|
'/DVERSION={}'.format(qutebrowser.__version__),
|
||||||
'misc/qutebrowser.nsi'])
|
'misc/qutebrowser.nsi'], check=True)
|
||||||
|
|
||||||
name_32 = 'qutebrowser-{}-win32.exe'.format(qutebrowser.__version__)
|
name_32 = 'qutebrowser-{}-win32.exe'.format(qutebrowser.__version__)
|
||||||
name_64 = 'qutebrowser-{}-amd64.exe'.format(qutebrowser.__version__)
|
name_64 = 'qutebrowser-{}-amd64.exe'.format(qutebrowser.__version__)
|
||||||
@ -292,12 +293,12 @@ def build_sdist():
|
|||||||
|
|
||||||
_maybe_remove('dist')
|
_maybe_remove('dist')
|
||||||
|
|
||||||
subprocess.check_call([sys.executable, 'setup.py', 'sdist'])
|
subprocess.run([sys.executable, 'setup.py', 'sdist'], check=True)
|
||||||
dist_files = os.listdir(os.path.abspath('dist'))
|
dist_files = os.listdir(os.path.abspath('dist'))
|
||||||
assert len(dist_files) == 1
|
assert len(dist_files) == 1
|
||||||
|
|
||||||
dist_file = os.path.join('dist', dist_files[0])
|
dist_file = os.path.join('dist', dist_files[0])
|
||||||
subprocess.check_call(['gpg', '--detach-sign', '-a', dist_file])
|
subprocess.run(['gpg', '--detach-sign', '-a', dist_file], check=True)
|
||||||
|
|
||||||
tar = tarfile.open(dist_file)
|
tar = tarfile.open(dist_file)
|
||||||
by_ext = collections.defaultdict(list)
|
by_ext = collections.defaultdict(list)
|
||||||
@ -366,7 +367,7 @@ def github_upload(artifacts, tag):
|
|||||||
def pypi_upload(artifacts):
|
def pypi_upload(artifacts):
|
||||||
"""Upload the given artifacts to PyPI using twine."""
|
"""Upload the given artifacts to PyPI using twine."""
|
||||||
filenames = [a[0] for a in artifacts]
|
filenames = [a[0] for a in artifacts]
|
||||||
subprocess.check_call(['twine', 'upload'] + filenames)
|
subprocess.run(['twine', 'upload'] + filenames, check=True)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -285,8 +285,8 @@ def main_check():
|
|||||||
print(msg.text)
|
print(msg.text)
|
||||||
print()
|
print()
|
||||||
filters = ','.join('qutebrowser/' + msg.filename for msg in messages)
|
filters = ','.join('qutebrowser/' + msg.filename for msg in messages)
|
||||||
subprocess.check_call([sys.executable, '-m', 'coverage', 'report',
|
subprocess.run([sys.executable, '-m', 'coverage', 'report',
|
||||||
'--show-missing', '--include', filters])
|
'--show-missing', '--include', filters], check=True)
|
||||||
print()
|
print()
|
||||||
print("To debug this, run 'tox -e py36-pyqt59-cov' "
|
print("To debug this, run 'tox -e py36-pyqt59-cov' "
|
||||||
"(or py35-pyqt59-cov) locally and check htmlcov/index.html")
|
"(or py35-pyqt59-cov) locally and check htmlcov/index.html")
|
||||||
@ -312,9 +312,9 @@ def main_check_all():
|
|||||||
for test_file, src_file in PERFECT_FILES:
|
for test_file, src_file in PERFECT_FILES:
|
||||||
if test_file is None:
|
if test_file is None:
|
||||||
continue
|
continue
|
||||||
subprocess.check_call(
|
subprocess.run(
|
||||||
[sys.executable, '-m', 'pytest', '--cov', 'qutebrowser',
|
[sys.executable, '-m', 'pytest', '--cov', 'qutebrowser',
|
||||||
'--cov-report', 'xml', test_file])
|
'--cov-report', 'xml', test_file], check=True)
|
||||||
with open('coverage.xml', encoding='utf-8') as f:
|
with open('coverage.xml', encoding='utf-8') as f:
|
||||||
messages = check(f, [(test_file, src_file)])
|
messages = check(f, [(test_file, src_file)])
|
||||||
os.remove('coverage.xml')
|
os.remove('coverage.xml')
|
||||||
|
@ -24,7 +24,8 @@ import sys
|
|||||||
import subprocess
|
import subprocess
|
||||||
import os
|
import os
|
||||||
|
|
||||||
code = subprocess.call(['git', '--no-pager', 'diff', '--exit-code', '--stat'])
|
code = subprocess.run(['git', '--no-pager', 'diff',
|
||||||
|
'--exit-code', '--stat']).returncode
|
||||||
|
|
||||||
if os.environ.get('TRAVIS_PULL_REQUEST', 'false') != 'false':
|
if os.environ.get('TRAVIS_PULL_REQUEST', 'false') != 'false':
|
||||||
if code != 0:
|
if code != 0:
|
||||||
@ -42,6 +43,6 @@ if code != 0:
|
|||||||
if 'TRAVIS' in os.environ:
|
if 'TRAVIS' in os.environ:
|
||||||
print()
|
print()
|
||||||
print("travis_fold:start:gitdiff")
|
print("travis_fold:start:gitdiff")
|
||||||
subprocess.call(['git', '--no-pager', 'diff'])
|
subprocess.run(['git', '--no-pager', 'diff'])
|
||||||
print("travis_fold:end:gitdiff")
|
print("travis_fold:end:gitdiff")
|
||||||
sys.exit(code)
|
sys.exit(code)
|
||||||
|
@ -23,4 +23,4 @@
|
|||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
with open('qutebrowser/resources.py', 'w', encoding='utf-8') as f:
|
with open('qutebrowser/resources.py', 'w', encoding='utf-8') as f:
|
||||||
subprocess.check_call(['pyrcc5', 'qutebrowser.rcc'], stdout=f)
|
subprocess.run(['pyrcc5', 'qutebrowser.rcc'], stdout=f, check=True)
|
||||||
|
@ -84,7 +84,8 @@ def parse_coredumpctl_line(line):
|
|||||||
def get_info(pid):
|
def get_info(pid):
|
||||||
"""Get and parse "coredumpctl info" output for the given PID."""
|
"""Get and parse "coredumpctl info" output for the given PID."""
|
||||||
data = {}
|
data = {}
|
||||||
output = subprocess.check_output(['coredumpctl', 'info', str(pid)])
|
output = subprocess.run(['coredumpctl', 'info', str(pid)], check=True,
|
||||||
|
stdout=subprocess.PIPE).stdout
|
||||||
output = output.decode('utf-8')
|
output = output.decode('utf-8')
|
||||||
for line in output.split('\n'):
|
for line in output.split('\n'):
|
||||||
if not line.strip():
|
if not line.strip():
|
||||||
@ -117,12 +118,12 @@ def dump_infos_gdb(parsed):
|
|||||||
"""Dump all needed infos for the given crash using gdb."""
|
"""Dump all needed infos for the given crash using gdb."""
|
||||||
with tempfile.TemporaryDirectory() as tempdir:
|
with tempfile.TemporaryDirectory() as tempdir:
|
||||||
coredump = os.path.join(tempdir, 'dump')
|
coredump = os.path.join(tempdir, 'dump')
|
||||||
subprocess.check_call(['coredumpctl', 'dump', '-o', coredump,
|
subprocess.run(['coredumpctl', 'dump', '-o', coredump,
|
||||||
str(parsed.pid)])
|
str(parsed.pid)], check=True)
|
||||||
subprocess.check_call(['gdb', parsed.exe, coredump,
|
subprocess.run(['gdb', parsed.exe, coredump,
|
||||||
'-ex', 'info threads',
|
'-ex', 'info threads',
|
||||||
'-ex', 'thread apply all bt full',
|
'-ex', 'thread apply all bt full',
|
||||||
'-ex', 'quit'])
|
'-ex', 'quit'], check=True)
|
||||||
|
|
||||||
|
|
||||||
def dump_infos(parsed):
|
def dump_infos(parsed):
|
||||||
@ -143,7 +144,7 @@ def check_prerequisites():
|
|||||||
"""Check if coredumpctl/gdb are installed."""
|
"""Check if coredumpctl/gdb are installed."""
|
||||||
for binary in ['coredumpctl', 'gdb']:
|
for binary in ['coredumpctl', 'gdb']:
|
||||||
try:
|
try:
|
||||||
subprocess.check_call([binary, '--version'])
|
subprocess.run([binary, '--version'], check=True)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
print("{} is needed to run this script!".format(binary),
|
print("{} is needed to run this script!".format(binary),
|
||||||
file=sys.stderr)
|
file=sys.stderr)
|
||||||
@ -158,7 +159,8 @@ def main():
|
|||||||
action='store_true')
|
action='store_true')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
coredumps = subprocess.check_output(['coredumpctl', 'list'])
|
coredumps = subprocess.run(['coredumpctl', 'list'], check=True,
|
||||||
|
stdout=subprocess.PIPE).stdout
|
||||||
lines = coredumps.decode('utf-8').split('\n')
|
lines = coredumps.decode('utf-8').split('\n')
|
||||||
for line in lines[1:]:
|
for line in lines[1:]:
|
||||||
if not line.strip():
|
if not line.strip():
|
||||||
|
@ -62,7 +62,8 @@ def check_git():
|
|||||||
print()
|
print()
|
||||||
return False
|
return False
|
||||||
untracked = []
|
untracked = []
|
||||||
gitst = subprocess.check_output(['git', 'status', '--porcelain'])
|
gitst = subprocess.run(['git', 'status', '--porcelain'], check=True,
|
||||||
|
stdout=subprocess.PIPE).stdout
|
||||||
gitst = gitst.decode('UTF-8').strip()
|
gitst = gitst.decode('UTF-8').strip()
|
||||||
for line in gitst.splitlines():
|
for line in gitst.splitlines():
|
||||||
s, name = line.split(maxsplit=1)
|
s, name = line.split(maxsplit=1)
|
||||||
|
@ -116,9 +116,11 @@ def main():
|
|||||||
|
|
||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
pip_bin = os.path.join(tmpdir, 'bin', 'pip')
|
pip_bin = os.path.join(tmpdir, 'bin', 'pip')
|
||||||
subprocess.check_call(['virtualenv', tmpdir])
|
subprocess.run(['virtualenv', tmpdir], check=True)
|
||||||
subprocess.check_call([pip_bin, 'install', '-r', filename])
|
subprocess.run([pip_bin, 'install', '-r', filename], check=True)
|
||||||
reqs = subprocess.check_output([pip_bin, 'freeze']).decode('utf-8')
|
reqs = subprocess.run([pip_bin, 'freeze'], check=True,
|
||||||
|
stdout=subprocess.PIPE
|
||||||
|
).stdout.decode('utf-8')
|
||||||
|
|
||||||
with open(filename, 'r', encoding='utf-8') as f:
|
with open(filename, 'r', encoding='utf-8') as f:
|
||||||
comments = read_comments(f)
|
comments = read_comments(f)
|
||||||
|
@ -76,14 +76,15 @@ def main():
|
|||||||
pass
|
pass
|
||||||
elif args.profile_tool == 'gprof2dot':
|
elif args.profile_tool == 'gprof2dot':
|
||||||
# yep, shell=True. I know what I'm doing.
|
# yep, shell=True. I know what I'm doing.
|
||||||
subprocess.call('gprof2dot -f pstats {} | dot -Tpng | feh -F -'.format(
|
subprocess.run(
|
||||||
|
'gprof2dot -f pstats {} | dot -Tpng | feh -F -'.format(
|
||||||
shlex.quote(profilefile)), shell=True)
|
shlex.quote(profilefile)), shell=True)
|
||||||
elif args.profile_tool == 'kcachegrind':
|
elif args.profile_tool == 'kcachegrind':
|
||||||
callgraphfile = os.path.join(tempdir, 'callgraph')
|
callgraphfile = os.path.join(tempdir, 'callgraph')
|
||||||
subprocess.call(['pyprof2calltree', '-k', '-i', profilefile,
|
subprocess.run(['pyprof2calltree', '-k', '-i', profilefile,
|
||||||
'-o', callgraphfile])
|
'-o', callgraphfile])
|
||||||
elif args.profile_tool == 'snakeviz':
|
elif args.profile_tool == 'snakeviz':
|
||||||
subprocess.call(['snakeviz', profilefile])
|
subprocess.run(['snakeviz', profilefile])
|
||||||
|
|
||||||
shutil.rmtree(tempdir)
|
shutil.rmtree(tempdir)
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ def main():
|
|||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
env['PYTHONPATH'] = os.pathsep.join(pythonpath)
|
env['PYTHONPATH'] = os.pathsep.join(pythonpath)
|
||||||
|
|
||||||
ret = subprocess.call(['pylint'] + args, env=env)
|
ret = subprocess.run(['pylint'] + args, env=env).returncode
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,22 +92,22 @@ def main():
|
|||||||
utils.print_bold("==== {} ====".format(page))
|
utils.print_bold("==== {} ====".format(page))
|
||||||
if test_harfbuzz:
|
if test_harfbuzz:
|
||||||
print("With system harfbuzz:")
|
print("With system harfbuzz:")
|
||||||
ret = subprocess.call([sys.executable, '-c', SCRIPT, page])
|
ret = subprocess.run([sys.executable, '-c', SCRIPT, page]).returncode
|
||||||
print_ret(ret)
|
print_ret(ret)
|
||||||
retvals.append(ret)
|
retvals.append(ret)
|
||||||
if test_harfbuzz:
|
if test_harfbuzz:
|
||||||
print("With QT_HARFBUZZ=old:")
|
print("With QT_HARFBUZZ=old:")
|
||||||
env = dict(os.environ)
|
env = dict(os.environ)
|
||||||
env['QT_HARFBUZZ'] = 'old'
|
env['QT_HARFBUZZ'] = 'old'
|
||||||
ret = subprocess.call([sys.executable, '-c', SCRIPT, page],
|
ret = subprocess.run([sys.executable, '-c', SCRIPT, page],
|
||||||
env=env)
|
env=env).returncode
|
||||||
print_ret(ret)
|
print_ret(ret)
|
||||||
retvals.append(ret)
|
retvals.append(ret)
|
||||||
print("With QT_HARFBUZZ=new:")
|
print("With QT_HARFBUZZ=new:")
|
||||||
env = dict(os.environ)
|
env = dict(os.environ)
|
||||||
env['QT_HARFBUZZ'] = 'new'
|
env['QT_HARFBUZZ'] = 'new'
|
||||||
ret = subprocess.call([sys.executable, '-c', SCRIPT, page],
|
ret = subprocess.run([sys.executable, '-c', SCRIPT, page],
|
||||||
env=env)
|
env=env).returncode
|
||||||
print_ret(ret)
|
print_ret(ret)
|
||||||
retvals.append(ret)
|
retvals.append(ret)
|
||||||
if all(r == 0 for r in retvals):
|
if all(r == 0 for r in retvals):
|
||||||
|
@ -529,9 +529,9 @@ def regenerate_cheatsheet():
|
|||||||
]
|
]
|
||||||
|
|
||||||
for filename, x, y in files:
|
for filename, x, y in files:
|
||||||
subprocess.check_call(['inkscape', '-e', filename, '-b', 'white',
|
subprocess.run(['inkscape', '-e', filename, '-b', 'white',
|
||||||
'-w', str(x), '-h', str(y),
|
'-w', str(x), '-h', str(y),
|
||||||
'misc/cheatsheet.svg'])
|
'misc/cheatsheet.svg'], check=True)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -46,12 +46,14 @@ def run_py(executable, *code):
|
|||||||
f.write('\n'.join(code))
|
f.write('\n'.join(code))
|
||||||
cmd = [executable, filename]
|
cmd = [executable, filename]
|
||||||
try:
|
try:
|
||||||
ret = subprocess.check_output(cmd, universal_newlines=True)
|
ret = subprocess.run(cmd, universal_newlines=True, check=True,
|
||||||
|
stdout=subprocess.PIPE).stdout
|
||||||
finally:
|
finally:
|
||||||
os.remove(filename)
|
os.remove(filename)
|
||||||
else:
|
else:
|
||||||
cmd = [executable, '-c', '\n'.join(code)]
|
cmd = [executable, '-c', '\n'.join(code)]
|
||||||
ret = subprocess.check_output(cmd, universal_newlines=True)
|
ret = subprocess.run(cmd, universal_newlines=True, check=True,
|
||||||
|
stdout=subprocess.PIPE).stdout
|
||||||
return ret.rstrip()
|
return ret.rstrip()
|
||||||
|
|
||||||
|
|
||||||
|
@ -51,12 +51,14 @@ def _git_str():
|
|||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
# https://stackoverflow.com/questions/21017300/21017394#21017394
|
# https://stackoverflow.com/questions/21017300/21017394#21017394
|
||||||
commit_hash = subprocess.check_output(
|
commit_hash = subprocess.run(
|
||||||
['git', 'describe', '--match=NeVeRmAtCh', '--always', '--dirty'],
|
['git', 'describe', '--match=NeVeRmAtCh', '--always', '--dirty'],
|
||||||
cwd=BASEDIR).decode('UTF-8').strip()
|
cwd=BASEDIR, check=True,
|
||||||
date = subprocess.check_output(
|
stdout=subprocess.PIPE).stdout.decode('UTF-8').strip()
|
||||||
|
date = subprocess.run(
|
||||||
['git', 'show', '-s', '--format=%ci', 'HEAD'],
|
['git', 'show', '-s', '--format=%ci', 'HEAD'],
|
||||||
cwd=BASEDIR).decode('UTF-8').strip()
|
cwd=BASEDIR, check=True,
|
||||||
|
stdout=subprocess.PIPE).stdout.decode('UTF-8').strip()
|
||||||
return '{} ({})'.format(commit_hash, date)
|
return '{} ({})'.format(commit_hash, date)
|
||||||
except (subprocess.CalledProcessError, OSError):
|
except (subprocess.CalledProcessError, OSError):
|
||||||
return None
|
return None
|
||||||
|
@ -47,10 +47,10 @@ def update_documentation():
|
|||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
subprocess.call(['asciidoc'], stdout=subprocess.DEVNULL,
|
subprocess.run(['asciidoc'], stdout=subprocess.DEVNULL,
|
||||||
stderr=subprocess.DEVNULL)
|
stderr=subprocess.DEVNULL)
|
||||||
except OSError:
|
except OSError:
|
||||||
pytest.skip("Docs outdated and asciidoc unavailable!")
|
pytest.skip("Docs outdated and asciidoc unavailable!")
|
||||||
|
|
||||||
update_script = os.path.join(script_path, 'asciidoc2html.py')
|
update_script = os.path.join(script_path, 'asciidoc2html.py')
|
||||||
subprocess.call([sys.executable, update_script])
|
subprocess.run([sys.executable, update_script])
|
||||||
|
@ -259,14 +259,13 @@ def test_command_on_start(request, quteproc_new):
|
|||||||
|
|
||||||
def test_launching_with_python2():
|
def test_launching_with_python2():
|
||||||
try:
|
try:
|
||||||
proc = subprocess.Popen(['python2', '-m', 'qutebrowser',
|
proc = subprocess.run(['python2', '-m', 'qutebrowser',
|
||||||
'--no-err-windows'], stderr=subprocess.PIPE)
|
'--no-err-windows'], stderr=subprocess.PIPE)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
pytest.skip("python2 not found")
|
pytest.skip("python2 not found")
|
||||||
_stdout, stderr = proc.communicate()
|
|
||||||
assert proc.returncode == 1
|
assert proc.returncode == 1
|
||||||
error = "At least Python 3.5 is required to run qutebrowser"
|
error = "At least Python 3.5 is required to run qutebrowser"
|
||||||
assert stderr.decode('ascii').startswith(error)
|
assert proc.stderr.decode('ascii').startswith(error)
|
||||||
|
|
||||||
|
|
||||||
def test_initial_private_browsing(request, quteproc_new):
|
def test_initial_private_browsing(request, quteproc_new):
|
||||||
|
@ -60,8 +60,9 @@ class TestSet:
|
|||||||
@pytest.mark.parametrize('option, old_value, inp, new_value', [
|
@pytest.mark.parametrize('option, old_value, inp, new_value', [
|
||||||
('url.auto_search', 'naive', 'dns', 'dns'),
|
('url.auto_search', 'naive', 'dns', 'dns'),
|
||||||
# https://github.com/qutebrowser/qutebrowser/issues/2962
|
# https://github.com/qutebrowser/qutebrowser/issues/2962
|
||||||
('editor.command', ['gvim', '-f', '{}'], '[emacs, "{}"]',
|
('editor.command',
|
||||||
['emacs', '{}']),
|
['gvim', '-f', '{file}', '-c', 'normal {line}G{column0}l'],
|
||||||
|
'[emacs, "{}"]', ['emacs', '{}']),
|
||||||
])
|
])
|
||||||
def test_set_simple(self, monkeypatch, commands, config_stub,
|
def test_set_simple(self, monkeypatch, commands, config_stub,
|
||||||
temp, option, old_value, inp, new_value):
|
temp, option, old_value, inp, new_value):
|
||||||
|
@ -1815,9 +1815,12 @@ class TestShellCommand:
|
|||||||
|
|
||||||
@pytest.mark.parametrize('kwargs, val, expected', [
|
@pytest.mark.parametrize('kwargs, val, expected', [
|
||||||
({}, '[foobar]', ['foobar']),
|
({}, '[foobar]', ['foobar']),
|
||||||
({'placeholder': '{}'}, '[foo, "{}", bar]', ['foo', '{}', 'bar']),
|
({'placeholder': True}, '[foo, "{}", bar]', ['foo', '{}', 'bar']),
|
||||||
({'placeholder': '{}'}, '["foo{}bar"]', ['foo{}bar']),
|
({'placeholder': True}, '["foo{}bar"]', ['foo{}bar']),
|
||||||
({'placeholder': '{}'}, '[foo, "bar {}"]', ['foo', 'bar {}']),
|
({'placeholder': True}, '[foo, "bar {}"]', ['foo', 'bar {}']),
|
||||||
|
({'placeholder': True}, '[f, "{file}", b]', ['f', '{file}', 'b']),
|
||||||
|
({'placeholder': True}, '["f{file}b"]', ['f{file}b']),
|
||||||
|
({'placeholder': True}, '[f, "b {file}"]', ['f', 'b {file}']),
|
||||||
])
|
])
|
||||||
def test_valid(self, klass, kwargs, val, expected):
|
def test_valid(self, klass, kwargs, val, expected):
|
||||||
cmd = klass(**kwargs)
|
cmd = klass(**kwargs)
|
||||||
@ -1825,8 +1828,15 @@ class TestShellCommand:
|
|||||||
assert cmd.to_py(expected) == expected
|
assert cmd.to_py(expected) == expected
|
||||||
|
|
||||||
@pytest.mark.parametrize('kwargs, val', [
|
@pytest.mark.parametrize('kwargs, val', [
|
||||||
({'placeholder': '{}'}, '[foo, bar]'),
|
({'placeholder': True}, '[foo, bar]'),
|
||||||
({'placeholder': '{}'}, '[foo, "{", "}", bar'),
|
({'placeholder': True}, '[foo, "{", "}", bar'),
|
||||||
|
({'placeholder': True}, '[foo, bar]'),
|
||||||
|
({'placeholder': True}, '[foo, "{fi", "le}", bar'),
|
||||||
|
|
||||||
|
# Like valid ones but with wrong placeholder
|
||||||
|
({'placeholder': True}, '[f, "{wrong}", b]'),
|
||||||
|
({'placeholder': True}, '["f{wrong}b"]'),
|
||||||
|
({'placeholder': True}, '[f, "b {wrong}"]'),
|
||||||
])
|
])
|
||||||
def test_from_str_invalid(self, klass, kwargs, val):
|
def test_from_str_invalid(self, klass, kwargs, val):
|
||||||
with pytest.raises(configexc.ValidationError):
|
with pytest.raises(configexc.ValidationError):
|
||||||
|
@ -36,15 +36,14 @@ TEXT = (r"At least Python 3.5 is required to run qutebrowser, but it's "
|
|||||||
def test_python2():
|
def test_python2():
|
||||||
"""Run checkpyver with python 2."""
|
"""Run checkpyver with python 2."""
|
||||||
try:
|
try:
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.run(
|
||||||
['python2', checkpyver.__file__, '--no-err-windows'],
|
['python2', checkpyver.__file__, '--no-err-windows'],
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE)
|
stderr=subprocess.PIPE)
|
||||||
stdout, stderr = proc.communicate()
|
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
pytest.skip("python2 not found")
|
pytest.skip("python2 not found")
|
||||||
assert not stdout
|
assert not proc.stdout
|
||||||
stderr = stderr.decode('utf-8')
|
stderr = proc.stderr.decode('utf-8')
|
||||||
assert re.match(TEXT, stderr), stderr
|
assert re.match(TEXT, stderr), stderr
|
||||||
assert proc.returncode == 1
|
assert proc.returncode == 1
|
||||||
|
|
||||||
|
@ -177,3 +177,18 @@ def test_modify(qtbot, editor, initial_text, edited_text):
|
|||||||
editor._proc.finished.emit(0, QProcess.NormalExit)
|
editor._proc.finished.emit(0, QProcess.NormalExit)
|
||||||
|
|
||||||
assert blocker.args == [edited_text]
|
assert blocker.args == [edited_text]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('text, caret_position, result', [
|
||||||
|
('', 0, (1, 1)),
|
||||||
|
('a', 0, (1, 1)),
|
||||||
|
('a\nb', 1, (1, 2)),
|
||||||
|
('a\nb', 2, (2, 1)),
|
||||||
|
('a\nb', 3, (2, 2)),
|
||||||
|
('a\nbb\nccc', 4, (2, 3)),
|
||||||
|
('a\nbb\nccc', 5, (3, 1)),
|
||||||
|
('a\nbb\nccc', 8, (3, 4)),
|
||||||
|
])
|
||||||
|
def test_calculation(editor, text, caret_position, result):
|
||||||
|
"""Test calculation for line and column given text and caret_position."""
|
||||||
|
assert editor._calc_line_and_column(text, caret_position) == result
|
||||||
|
@ -555,8 +555,9 @@ def test_no_qapplication(qapp, tmpdir):
|
|||||||
pyfile = tmpdir / 'sub.py'
|
pyfile = tmpdir / 'sub.py'
|
||||||
pyfile.write_text(textwrap.dedent(sub_code), encoding='ascii')
|
pyfile.write_text(textwrap.dedent(sub_code), encoding='ascii')
|
||||||
|
|
||||||
output = subprocess.check_output([sys.executable, str(pyfile)] + sys.path,
|
output = subprocess.run([sys.executable, str(pyfile)] + sys.path,
|
||||||
universal_newlines=True)
|
universal_newlines=True,
|
||||||
|
check=True, stdout=subprocess.PIPE).stdout
|
||||||
sub_locations = json.loads(output)
|
sub_locations = json.loads(output)
|
||||||
|
|
||||||
standarddir._init_dirs()
|
standarddir._init_dirs()
|
||||||
|
@ -299,8 +299,8 @@ class TestGitStr:
|
|||||||
def _has_git():
|
def _has_git():
|
||||||
"""Check if git is installed."""
|
"""Check if git is installed."""
|
||||||
try:
|
try:
|
||||||
subprocess.check_call(['git', '--version'], stdout=subprocess.DEVNULL,
|
subprocess.run(['git', '--version'], stdout=subprocess.DEVNULL,
|
||||||
stderr=subprocess.DEVNULL)
|
stderr=subprocess.DEVNULL, check=True)
|
||||||
except (OSError, subprocess.CalledProcessError):
|
except (OSError, subprocess.CalledProcessError):
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
@ -337,12 +337,13 @@ class TestGitStrSubprocess:
|
|||||||
# If we don't call this with shell=True it might fail under
|
# If we don't call this with shell=True it might fail under
|
||||||
# some environments on Windows...
|
# some environments on Windows...
|
||||||
# http://bugs.python.org/issue24493
|
# http://bugs.python.org/issue24493
|
||||||
subprocess.check_call(
|
subprocess.run(
|
||||||
'git -C "{}" {}'.format(tmpdir, ' '.join(args)),
|
'git -C "{}" {}'.format(tmpdir, ' '.join(args)),
|
||||||
env=env, shell=True)
|
env=env, check=True, shell=True)
|
||||||
else:
|
else:
|
||||||
subprocess.check_call(
|
subprocess.run(
|
||||||
['git', '-C', str(tmpdir)] + list(args), env=env)
|
['git', '-C', str(tmpdir)] + list(args),
|
||||||
|
check=True, env=env)
|
||||||
|
|
||||||
(tmpdir / 'file').write_text("Hello World!", encoding='utf-8')
|
(tmpdir / 'file').write_text("Hello World!", encoding='utf-8')
|
||||||
_git('init')
|
_git('init')
|
||||||
@ -368,14 +369,14 @@ class TestGitStrSubprocess:
|
|||||||
subprocess.CalledProcessError(1, 'foobar')
|
subprocess.CalledProcessError(1, 'foobar')
|
||||||
])
|
])
|
||||||
def test_exception(self, exc, mocker, tmpdir):
|
def test_exception(self, exc, mocker, tmpdir):
|
||||||
"""Test with subprocess.check_output raising an exception.
|
"""Test with subprocess.run raising an exception.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
exc: The exception to raise.
|
exc: The exception to raise.
|
||||||
"""
|
"""
|
||||||
m = mocker.patch('qutebrowser.utils.version.os')
|
m = mocker.patch('qutebrowser.utils.version.os')
|
||||||
m.path.isdir.return_value = True
|
m.path.isdir.return_value = True
|
||||||
mocker.patch('qutebrowser.utils.version.subprocess.check_output',
|
mocker.patch('qutebrowser.utils.version.subprocess.run',
|
||||||
side_effect=exc)
|
side_effect=exc)
|
||||||
ret = version._git_str_subprocess(str(tmpdir))
|
ret = version._git_str_subprocess(str(tmpdir))
|
||||||
assert ret is None
|
assert ret is None
|
||||||
|
Loading…
Reference in New Issue
Block a user