Merge branch 'knaggita-issue52'
This commit is contained in:
commit
60001ec8b1
@ -39,6 +39,8 @@ Added
|
|||||||
to focus the previous/next category in the completion (bound to `<Ctrl-Tab>`
|
to focus the previous/next category in the completion (bound to `<Ctrl-Tab>`
|
||||||
and `<Ctrl-Shift-Tab>` by default).
|
and `<Ctrl-Shift-Tab>` by default).
|
||||||
- New `:click-element` command to fake a click on a element.
|
- New `:click-element` command to fake a click on a element.
|
||||||
|
- New `:debug-log-filter` command to change console log filtering on-the-fly.
|
||||||
|
- New `:debug-log-level` command to change the console loglevel on-the-fly.
|
||||||
|
|
||||||
Changed
|
Changed
|
||||||
~~~~~~~
|
~~~~~~~
|
||||||
|
@ -199,6 +199,7 @@ Contributors, sorted by the number of commits in descending order:
|
|||||||
* Brian Jackson
|
* Brian Jackson
|
||||||
* sbinix
|
* sbinix
|
||||||
* neeasade
|
* neeasade
|
||||||
|
* knaggita
|
||||||
* jnphilipp
|
* jnphilipp
|
||||||
* Tobias Patzl
|
* Tobias Patzl
|
||||||
* Stefan Tatschner
|
* Stefan Tatschner
|
||||||
@ -224,7 +225,6 @@ Contributors, sorted by the number of commits in descending order:
|
|||||||
* zwarag
|
* zwarag
|
||||||
* xd1le
|
* xd1le
|
||||||
* oniondreams
|
* oniondreams
|
||||||
* knaggita
|
|
||||||
* issue
|
* issue
|
||||||
* haxwithaxe
|
* haxwithaxe
|
||||||
* evan
|
* evan
|
||||||
|
@ -1449,6 +1449,8 @@ These commands are mainly intended for debugging. They are hidden if qutebrowser
|
|||||||
|<<debug-crash,debug-crash>>|Crash for debugging purposes.
|
|<<debug-crash,debug-crash>>|Crash for debugging purposes.
|
||||||
|<<debug-dump-page,debug-dump-page>>|Dump the current page's content to a file.
|
|<<debug-dump-page,debug-dump-page>>|Dump the current page's content to a file.
|
||||||
|<<debug-log-capacity,debug-log-capacity>>|Change the number of log lines to be stored in RAM.
|
|<<debug-log-capacity,debug-log-capacity>>|Change the number of log lines to be stored in RAM.
|
||||||
|
|<<debug-log-filter,debug-log-filter>>|Change the log filter for console logging.
|
||||||
|
|<<debug-log-level,debug-log-level>>|Change the log level for console logging.
|
||||||
|<<debug-pyeval,debug-pyeval>>|Evaluate a python string and display the results as a web page.
|
|<<debug-pyeval,debug-pyeval>>|Evaluate a python string and display the results as a web page.
|
||||||
|<<debug-set-fake-clipboard,debug-set-fake-clipboard>>|Put data into the fake clipboard and enable logging, used for tests.
|
|<<debug-set-fake-clipboard,debug-set-fake-clipboard>>|Put data into the fake clipboard and enable logging, used for tests.
|
||||||
|<<debug-trace,debug-trace>>|Trace executed code via hunter.
|
|<<debug-trace,debug-trace>>|Trace executed code via hunter.
|
||||||
@ -1500,6 +1502,24 @@ Change the number of log lines to be stored in RAM.
|
|||||||
==== positional arguments
|
==== positional arguments
|
||||||
* +'capacity'+: Number of lines for the log.
|
* +'capacity'+: Number of lines for the log.
|
||||||
|
|
||||||
|
[[debug-log-filter]]
|
||||||
|
=== debug-log-filter
|
||||||
|
Syntax: +:debug-log-filter 'filters'+
|
||||||
|
|
||||||
|
Change the log filter for console logging.
|
||||||
|
|
||||||
|
==== positional arguments
|
||||||
|
* +'filters'+: A comma separated list of logger names.
|
||||||
|
|
||||||
|
[[debug-log-level]]
|
||||||
|
=== debug-log-level
|
||||||
|
Syntax: +:debug-log-level 'level'+
|
||||||
|
|
||||||
|
Change the log level for console logging.
|
||||||
|
|
||||||
|
==== positional arguments
|
||||||
|
* +'level'+: The log level to set.
|
||||||
|
|
||||||
[[debug-pyeval]]
|
[[debug-pyeval]]
|
||||||
=== debug-pyeval
|
=== debug-pyeval
|
||||||
Syntax: +:debug-pyeval [*--quiet*] 's'+
|
Syntax: +:debug-pyeval [*--quiet*] 's'+
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
import functools
|
import functools
|
||||||
import types
|
import types
|
||||||
import traceback
|
import traceback
|
||||||
|
import logging
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import hunter
|
import hunter
|
||||||
@ -249,6 +250,34 @@ def log_capacity(capacity: int):
|
|||||||
log.ram_handler.change_log_capacity(capacity)
|
log.ram_handler.change_log_capacity(capacity)
|
||||||
|
|
||||||
|
|
||||||
|
@cmdutils.register(debug=True)
|
||||||
|
@cmdutils.argument('level', choices=sorted(
|
||||||
|
(level.lower() for level in log.LOG_LEVELS),
|
||||||
|
key=lambda e: log.LOG_LEVELS[e.upper()]))
|
||||||
|
def debug_log_level(level: str):
|
||||||
|
"""Change the log level for console logging.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
level: The log level to set.
|
||||||
|
"""
|
||||||
|
log.console_handler.setLevel(log.LOG_LEVELS[level.upper()])
|
||||||
|
|
||||||
|
|
||||||
|
@cmdutils.register(debug=True)
|
||||||
|
def debug_log_filter(filters: str):
|
||||||
|
"""Change the log filter for console logging.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
filters: A comma separated list of logger names.
|
||||||
|
"""
|
||||||
|
if set(filters.split(',')).issubset(log.LOGGER_NAMES):
|
||||||
|
log.console_filter.names = filters.split(',')
|
||||||
|
else:
|
||||||
|
raise cmdexc.CommandError("filters: Invalid value {} - expected one "
|
||||||
|
"of: {}".format(filters,
|
||||||
|
', '.join(log.LOGGER_NAMES)))
|
||||||
|
|
||||||
|
|
||||||
@cmdutils.register()
|
@cmdutils.register()
|
||||||
@cmdutils.argument('current_win_id', win_id=True)
|
@cmdutils.argument('current_win_id', win_id=True)
|
||||||
def window_only(current_win_id):
|
def window_only(current_win_id):
|
||||||
|
@ -87,6 +87,15 @@ LOG_LEVELS = {
|
|||||||
'CRITICAL': logging.CRITICAL,
|
'CRITICAL': logging.CRITICAL,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOGGER_NAMES = [
|
||||||
|
'statusbar', 'completion', 'init', 'url',
|
||||||
|
'destroy', 'modes', 'webview', 'misc',
|
||||||
|
'mouse', 'procs', 'hints', 'keyboard',
|
||||||
|
'commands', 'signals', 'downloads',
|
||||||
|
'js', 'qt', 'rfc6266', 'ipc', 'shlexer',
|
||||||
|
'save', 'message', 'config', 'sessions'
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def vdebug(self, msg, *args, **kwargs):
|
def vdebug(self, msg, *args, **kwargs):
|
||||||
"""Log with a VDEBUG level.
|
"""Log with a VDEBUG level.
|
||||||
@ -131,6 +140,8 @@ sessions = logging.getLogger('sessions')
|
|||||||
|
|
||||||
|
|
||||||
ram_handler = None
|
ram_handler = None
|
||||||
|
console_handler = None
|
||||||
|
console_filter = None
|
||||||
|
|
||||||
|
|
||||||
def stub(suffix=''):
|
def stub(suffix=''):
|
||||||
@ -149,6 +160,7 @@ class CriticalQtWarning(Exception):
|
|||||||
|
|
||||||
def init_log(args):
|
def init_log(args):
|
||||||
"""Init loggers based on the argparse namespace passed."""
|
"""Init loggers based on the argparse namespace passed."""
|
||||||
|
global console
|
||||||
level = args.loglevel.upper()
|
level = args.loglevel.upper()
|
||||||
try:
|
try:
|
||||||
numeric_level = getattr(logging, level)
|
numeric_level = getattr(logging, level)
|
||||||
@ -161,9 +173,11 @@ def init_log(args):
|
|||||||
console, ram = _init_handlers(numeric_level, args.color, args.force_color,
|
console, ram = _init_handlers(numeric_level, args.color, args.force_color,
|
||||||
args.json_logging, args.loglines)
|
args.json_logging, args.loglines)
|
||||||
root = logging.getLogger()
|
root = logging.getLogger()
|
||||||
|
global console_filter
|
||||||
if console is not None:
|
if console is not None:
|
||||||
if args.logfilter is not None:
|
if args.logfilter is not None:
|
||||||
console.addFilter(LogFilter(args.logfilter.split(',')))
|
console_filter = LogFilter(args.logfilter.split(','))
|
||||||
|
console.addFilter(console_filter)
|
||||||
root.addHandler(console)
|
root.addHandler(console)
|
||||||
if ram is not None:
|
if ram is not None:
|
||||||
root.addHandler(ram)
|
root.addHandler(ram)
|
||||||
@ -175,6 +189,10 @@ def init_log(args):
|
|||||||
_log_inited = True
|
_log_inited = True
|
||||||
|
|
||||||
|
|
||||||
|
def change(filters):
|
||||||
|
console.addFilter(LogFilter(filters.split(',')))
|
||||||
|
|
||||||
|
|
||||||
def _init_py_warnings():
|
def _init_py_warnings():
|
||||||
"""Initialize Python warning handling."""
|
"""Initialize Python warning handling."""
|
||||||
warnings.simplefilter('default')
|
warnings.simplefilter('default')
|
||||||
@ -210,6 +228,7 @@ def _init_handlers(level, color, force_color, json_logging, ram_capacity):
|
|||||||
json_logging: Output log lines in JSON (this disables all colors).
|
json_logging: Output log lines in JSON (this disables all colors).
|
||||||
"""
|
"""
|
||||||
global ram_handler
|
global ram_handler
|
||||||
|
global console_handler
|
||||||
console_fmt, ram_fmt, html_fmt, use_colorama = _init_formatters(
|
console_fmt, ram_fmt, html_fmt, use_colorama = _init_formatters(
|
||||||
level, color, force_color, json_logging)
|
level, color, force_color, json_logging)
|
||||||
|
|
||||||
@ -448,16 +467,16 @@ class LogFilter(logging.Filter):
|
|||||||
|
|
||||||
def __init__(self, names):
|
def __init__(self, names):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._names = names
|
self.names = names
|
||||||
|
|
||||||
def filter(self, record):
|
def filter(self, record):
|
||||||
"""Determine if the specified record is to be logged."""
|
"""Determine if the specified record is to be logged."""
|
||||||
if self._names is None:
|
if self.names is None:
|
||||||
return True
|
return True
|
||||||
if record.levelno > logging.DEBUG:
|
if record.levelno > logging.DEBUG:
|
||||||
# More important than DEBUG, so we won't filter at all
|
# More important than DEBUG, so we won't filter at all
|
||||||
return True
|
return True
|
||||||
for name in self._names:
|
for name in self.names:
|
||||||
if record.name == name:
|
if record.name == name:
|
||||||
return True
|
return True
|
||||||
elif not record.name.startswith(name):
|
elif not record.name.startswith(name):
|
||||||
|
@ -471,10 +471,26 @@ Feature: Various utility commands.
|
|||||||
Then the page should contain the plaintext "newstuff"
|
Then the page should contain the plaintext "newstuff"
|
||||||
And the page should not contain the plaintext "oldstuff"
|
And the page should not contain the plaintext "oldstuff"
|
||||||
|
|
||||||
|
Scenario: Using :debug-log-capacity with negative capacity
|
||||||
|
When I run :debug-log-capacity -1
|
||||||
|
Then the error "Can't set a negative log capacity!" should be shown
|
||||||
|
|
||||||
|
# :debug-log-level / :debug-log-filter
|
||||||
|
# Other :debug-log-{level,filter} features are tested in
|
||||||
|
# unit/utils/test_log.py as using them would break end2end tests.
|
||||||
|
|
||||||
|
Scenario: Using debug-log-level with invalid level
|
||||||
|
When I run :debug-log-level hello
|
||||||
|
Then the error "level: Invalid value hello - expected one of: vdebug, debug, info, warning, error, critical" should be shown
|
||||||
|
|
||||||
|
Scenario: Using debug-log-filter with invalid filter
|
||||||
|
When I run :debug-log-filter blah
|
||||||
|
Then the error "filters: Invalid value blah - expected one of: statusbar, *" should be shown
|
||||||
|
|
||||||
## https://github.com/The-Compiler/qutebrowser/issues/1523
|
## https://github.com/The-Compiler/qutebrowser/issues/1523
|
||||||
|
|
||||||
Scenario: Completing a single option argument
|
Scenario: Completing a single option argument
|
||||||
When I run :set-cmd-text -s :--
|
When I run :set-cmd-text -s :--
|
||||||
Then no crash should happen
|
Then no crash should happen
|
||||||
|
|
||||||
## https://github.com/The-Compiler/qutebrowser/issues/1386
|
## https://github.com/The-Compiler/qutebrowser/issues/1386
|
||||||
|
@ -29,6 +29,7 @@ import pytest
|
|||||||
import pytest_catchlog
|
import pytest_catchlog
|
||||||
|
|
||||||
from qutebrowser.utils import log
|
from qutebrowser.utils import log
|
||||||
|
from qutebrowser.misc import utilcmds
|
||||||
|
|
||||||
|
|
||||||
@pytest.yield_fixture(autouse=True)
|
@pytest.yield_fixture(autouse=True)
|
||||||
@ -167,6 +168,19 @@ class TestLogFilter:
|
|||||||
record = self._make_record(logger, "bacon", level=logging.INFO)
|
record = self._make_record(logger, "bacon", level=logging.INFO)
|
||||||
assert logfilter.filter(record)
|
assert logfilter.filter(record)
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('category, logged_before, logged_after', [
|
||||||
|
('init', True, False), ('url', False, True), ('js', False, True)])
|
||||||
|
def test_debug_log_filter_cmd(self, monkeypatch, logger, category,
|
||||||
|
logged_before, logged_after):
|
||||||
|
logfilter = log.LogFilter(["init"])
|
||||||
|
monkeypatch.setattr(log, 'console_filter', logfilter)
|
||||||
|
|
||||||
|
record = self._make_record(logger, category)
|
||||||
|
|
||||||
|
assert logfilter.filter(record) == logged_before
|
||||||
|
utilcmds.debug_log_filter('url,js')
|
||||||
|
assert logfilter.filter(record) == logged_after
|
||||||
|
|
||||||
|
|
||||||
class TestRAMHandler:
|
class TestRAMHandler:
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user