diff options
27 files changed, 253 insertions, 79 deletions
diff --git a/.github/workflows/bleeding.yml b/.github/workflows/bleeding.yml index 766f535d7..435141e56 100644 --- a/.github/workflows/bleeding.yml +++ b/.github/workflows/bleeding.yml @@ -58,7 +58,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: 3.9 + python-version: "3.10" - name: Get asciidoc uses: actions/checkout@v2 with: diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc index f86b84622..36861b802 100644 --- a/doc/changelog.asciidoc +++ b/doc/changelog.asciidoc @@ -24,6 +24,21 @@ Changed - Improved message if a spawned process wasn't found and a Flatpak container is in use. +- The `:tab-move` command now takes `start` and `end` as `index` to move a tab + to the first/last position. +- Tests now automatically pick the backend (QtWebKit/QtWebEngine) based on + what's available. The `QUTE_BDD_WEBENGINE` environment variable and + `--qute-bdd-webengine` argument got replaced by `QUTE_TESTS_BACKEND` and + `--qute-backend` respectively, which can be set to either `webengine` or + `webkit`. +- Using `:tab-give` or `:tab-take` on the last tab in a window now always + closes that window, no matter what `tabs.last_close` is set to. + +Added +~~~~~ + +- New `input.match_counts` option which allows to turn off count matching for + more emacs-like bindings. [[v2.4.1]] v2.4.1 (unreleased) @@ -36,6 +51,7 @@ Fixed binaries (in certain rare environments). - Speculative fix for a qutebrowser crash when the notification daemon crashes while showing the notification. +- Fix crash when using `:screenshot` with an invalid `--rect` argument. [[v2.4.0]] v2.4.0 (2021-10-21) diff --git a/doc/help/commands.asciidoc b/doc/help/commands.asciidoc index 8c11e15cc..442c136a7 100644 --- a/doc/help/commands.asciidoc +++ b/doc/help/commands.asciidoc @@ -1431,6 +1431,7 @@ If neither is given, move it to the first position. ==== positional arguments * +'index'+: `+` or `-` to move relative to the current tab by count, or a default of 1 space. A tab index to move to that index. + `start` and `end` to move to the start and the end. ==== count diff --git a/doc/help/settings.asciidoc b/doc/help/settings.asciidoc index 60c229078..4ca5c2517 100644 --- a/doc/help/settings.asciidoc +++ b/doc/help/settings.asciidoc @@ -269,6 +269,7 @@ |<<input.insert_mode.leave_on_load,input.insert_mode.leave_on_load>>|Leave insert mode when starting a new page load. |<<input.insert_mode.plugins,input.insert_mode.plugins>>|Switch to insert mode when clicking flash and other plugins. |<<input.links_included_in_focus_chain,input.links_included_in_focus_chain>>|Include hyperlinks in the keyboard focus chain when tabbing. +|<<input.match_counts,input.match_counts>>|Interpret number prefixes as counts for bindings. |<<input.media_keys,input.media_keys>>|Whether the underlying Chromium should handle media keys. |<<input.mouse.back_forward_buttons,input.mouse.back_forward_buttons>>|Enable back and forward buttons on the mouse. |<<input.mouse.rocker_gestures,input.mouse.rocker_gestures>>|Enable Opera-like mouse rocker gestures. @@ -3557,6 +3558,15 @@ Type: <<types,Bool>> Default: +pass:[true]+ +[[input.match_counts]] +=== input.match_counts +Interpret number prefixes as counts for bindings. +This enables for vi-like bindings that can be prefixed with a number to indicate a count. Disabling it allows for emacs-like bindings where number keys are passed through (according to `input.forward_unbound_keys`) instead. + +Type: <<types,Bool>> + +Default: +pass:[true]+ + [[input.media_keys]] === input.media_keys Whether the underlying Chromium should handle media keys. diff --git a/misc/requirements/requirements-check-manifest.txt b/misc/requirements/requirements-check-manifest.txt index 21843c4ae..c61218ba3 100644 --- a/misc/requirements/requirements-check-manifest.txt +++ b/misc/requirements/requirements-check-manifest.txt @@ -2,8 +2,8 @@ build==0.7.0 check-manifest==0.47 -packaging==21.2 +packaging==21.3 pep517==0.12.0 -pyparsing==2.4.7 +pyparsing==3.0.6 toml==0.10.2 tomli==1.2.2 diff --git a/misc/requirements/requirements-dev.txt b/misc/requirements/requirements-dev.txt index 34234a50b..0dd45cebc 100644 --- a/misc/requirements/requirements-dev.txt +++ b/misc/requirements/requirements-dev.txt @@ -3,18 +3,18 @@ bump2version==1.0.1 certifi==2021.10.8 cffi==1.15.0 -charset-normalizer==2.0.7 -cryptography==35.0.0 +charset-normalizer==2.0.8 +cryptography==36.0.0 Deprecated==1.2.13 github3.py==3.0.0 hunter==3.3.8 idna==3.3 jwcrypto==1.0 manhole==1.8.0 -packaging==21.2 +packaging==21.3 pycparser==2.21 Pympler==0.9 -pyparsing==2.4.7 +pyparsing==3.0.6 PyQt-builder==1.12.2 python-dateutil==2.8.2 requests==2.26.0 diff --git a/misc/requirements/requirements-flake8.txt b/misc/requirements/requirements-flake8.txt index 08b75e2bf..1d1f5eebc 100644 --- a/misc/requirements/requirements-flake8.txt +++ b/misc/requirements/requirements-flake8.txt @@ -2,7 +2,7 @@ attrs==21.2.0 flake8==4.0.1 -flake8-bugbear==21.9.2 +flake8-bugbear==21.11.28 flake8-builtins==1.5.3 flake8-comprehensions==3.7.0 flake8-copyright==0.2.2 @@ -21,4 +21,4 @@ pycodestyle==2.8.0 pydocstyle==6.1.1 pyflakes==2.4.0 six==1.16.0 -snowballstemmer==2.1.0 +snowballstemmer==2.2.0 diff --git a/misc/requirements/requirements-mypy.txt b/misc/requirements/requirements-mypy.txt index 4d5f08e49..ce64972b3 100644 --- a/misc/requirements/requirements-mypy.txt +++ b/misc/requirements/requirements-mypy.txt @@ -2,10 +2,10 @@ chardet==4.0.0 diff-cover==6.4.2 -importlib-metadata==4.8.1 +importlib-metadata==4.8.2 importlib-resources==5.4.0 inflect==5.3.0 -Jinja2==3.0.2 +Jinja2==3.0.3 jinja2-pluralize==0.3.0 lxml==4.6.4 MarkupSafe==2.0.1 @@ -16,6 +16,6 @@ Pygments==2.10.0 PyQt5-stubs==5.15.2.0 toml==0.10.2 types-dataclasses==0.6.1 -types-PyYAML==6.0.0 -typing-extensions==3.10.0.2 +types-PyYAML==6.0.1 +typing_extensions==4.0.0 zipp==3.6.0 diff --git a/misc/requirements/requirements-pyinstaller.txt b/misc/requirements/requirements-pyinstaller.txt index 8d5567e67..9a53c11cd 100644 --- a/misc/requirements/requirements-pyinstaller.txt +++ b/misc/requirements/requirements-pyinstaller.txt @@ -1,5 +1,5 @@ # This file is automatically generated by scripts/dev/recompile_requirements.py altgraph==0.17.2 -pyinstaller==4.6 +pyinstaller==4.7 pyinstaller-hooks-contrib==2021.3 diff --git a/misc/requirements/requirements-pylint.txt b/misc/requirements/requirements-pylint.txt index afb692789..c26af6406 100644 --- a/misc/requirements/requirements-pylint.txt +++ b/misc/requirements/requirements-pylint.txt @@ -3,8 +3,8 @@ astroid==2.3.3 # rq.filter: < 2.4 certifi==2021.10.8 cffi==1.15.0 -charset-normalizer==2.0.7 -cryptography==35.0.0 +charset-normalizer==2.0.8 +cryptography==36.0.0 Deprecated==1.2.13 future==0.18.2 github3.py==3.0.0 diff --git a/misc/requirements/requirements-pyroma.txt b/misc/requirements/requirements-pyroma.txt index 8849014be..a76402053 100644 --- a/misc/requirements/requirements-pyroma.txt +++ b/misc/requirements/requirements-pyroma.txt @@ -1,8 +1,8 @@ # This file is automatically generated by scripts/dev/recompile_requirements.py certifi==2021.10.8 -charset-normalizer==2.0.7 -docutils==0.18 +charset-normalizer==2.0.8 +docutils==0.18.1 idna==3.3 Pygments==2.10.0 pyroma==3.2 diff --git a/misc/requirements/requirements-sphinx.txt b/misc/requirements/requirements-sphinx.txt index 86553bb4c..b7f013853 100644 --- a/misc/requirements/requirements-sphinx.txt +++ b/misc/requirements/requirements-sphinx.txt @@ -3,19 +3,19 @@ alabaster==0.7.12 Babel==2.9.1 certifi==2021.10.8 -charset-normalizer==2.0.7 +charset-normalizer==2.0.8 docutils==0.17.1 idna==3.3 -imagesize==1.2.0 -Jinja2==3.0.2 +imagesize==1.3.0 +Jinja2==3.0.3 MarkupSafe==2.0.1 -packaging==21.2 +packaging==21.3 Pygments==2.10.0 -pyparsing==2.4.7 +pyparsing==3.0.6 pytz==2021.3 requests==2.26.0 -snowballstemmer==2.1.0 -Sphinx==4.2.0 +snowballstemmer==2.2.0 +Sphinx==4.3.1 sphinxcontrib-applehelp==1.0.2 sphinxcontrib-devhelp==1.0.2 sphinxcontrib-htmlhelp==2.0.0 diff --git a/misc/requirements/requirements-tests.txt b/misc/requirements/requirements-tests.txt index a3a48adea..b15a23c08 100644 --- a/misc/requirements/requirements-tests.txt +++ b/misc/requirements/requirements-tests.txt @@ -3,28 +3,28 @@ attrs==21.2.0 beautifulsoup4==4.10.0 certifi==2021.10.8 -charset-normalizer==2.0.7 +charset-normalizer==2.0.8 cheroot==8.5.2 click==8.0.3 -coverage==6.1.1 +coverage==6.2 EasyProcess==0.3 execnet==1.9.0 -filelock==3.3.2 +filelock==3.4.0 Flask==2.0.2 glob2==0.7 hunter==3.3.8 -hypothesis==6.24.2 +hypothesis==6.28.1 icdiff==2.0.4 idna==3.3 iniconfig==1.1.1 itsdangerous==2.0.1 jaraco.functools==3.4.0 -# Jinja2==3.0.2 -Mako==1.1.5 +# Jinja2==3.0.3 +Mako==1.1.6 manhole==1.8.0 # MarkupSafe==2.0.1 -more-itertools==8.10.0 -packaging==21.2 +more-itertools==8.12.0 +packaging==21.3 parse==1.19.0 parse-type==0.5.2 pluggy==1.0.0 @@ -32,7 +32,7 @@ pprintpp==0.4.0 py==1.11.0 py-cpuinfo==8.0.0 Pygments==2.10.0 -pyparsing==2.4.7 +pyparsing==3.0.6 pytest==6.2.5 pytest-bdd==4.1.0 pytest-benchmark==3.4.1 @@ -51,7 +51,7 @@ requests==2.26.0 requests-file==1.5.1 six==1.16.0 sortedcontainers==2.4.0 -soupsieve==2.3 +soupsieve==2.3.1 tldextract==3.1.2 toml==0.10.2 tomli==1.2.2 diff --git a/misc/requirements/requirements-tox.txt b/misc/requirements/requirements-tox.txt index a069ca44b..a2a57808b 100644 --- a/misc/requirements/requirements-tox.txt +++ b/misc/requirements/requirements-tox.txt @@ -1,15 +1,15 @@ # This file is automatically generated by scripts/dev/recompile_requirements.py -backports.entry-points-selectable==1.1.0 +backports.entry-points-selectable==1.1.1 distlib==0.3.3 -filelock==3.3.2 -packaging==21.2 +filelock==3.4.0 +packaging==21.3 pip==21.3.1 platformdirs==2.4.0 pluggy==1.0.0 py==1.11.0 -pyparsing==2.4.7 -setuptools==58.5.3 +pyparsing==3.0.6 +setuptools==59.4.0 six==1.16.0 toml==0.10.2 tox==3.24.4 diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index f3438aaa8..796bb2eb3 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -451,7 +451,7 @@ class CommandDispatcher: self._open(tab.url(), tab=True) if not keep: - tabbed_browser.close_tab(tab, add_undo=False) + tabbed_browser.close_tab(tab, add_undo=False, transfer=True) @cmdutils.register(instance='command-dispatcher', scope='window') @cmdutils.argument('win_id', completion=miscmodels.window) @@ -500,7 +500,8 @@ class CommandDispatcher: tabbed_browser.tabopen(self._current_url()) if not keep: self._tabbed_browser.close_tab(self._current_widget(), - add_undo=False) + add_undo=False, + transfer=True) def _back_forward(self, tab, bg, window, count, forward, index=None): """Helper function for :back/:forward.""" @@ -1004,11 +1005,10 @@ class CommandDispatcher: raise cmdutils.CommandError("There's no tab with index {}!".format( index)) - @cmdutils.register(instance='command-dispatcher', scope='window') - @cmdutils.argument('index', choices=['+', '-']) - @cmdutils.argument('count', value=cmdutils.Value.count) - def tab_move(self, index: Union[str, int] = None, - count: int = None) -> None: + @cmdutils.register(instance="command-dispatcher", scope="window") + @cmdutils.argument("index", choices=["+", "-", "start", "end"]) + @cmdutils.argument("count", value=cmdutils.Value.count) + def tab_move(self, index: Union[str, int] = None, count: int = None) -> None: """Move the current tab according to the argument and [count]. If neither is given, move it to the first position. @@ -1017,24 +1017,29 @@ class CommandDispatcher: index: `+` or `-` to move relative to the current tab by count, or a default of 1 space. A tab index to move to that index. + `start` and `end` to move to the start and the end. count: If moving relatively: Offset. If moving absolutely: New position (default: 0). This overrides the index argument, if given. """ - if index in ['+', '-']: + if index in ["+", "-"]: # relative moving new_idx = self._current_index() delta = 1 if count is None else count - if index == '-': + if index == "-": new_idx -= delta - elif index == '+': # pragma: no branch + elif index == "+": # pragma: no branch new_idx += delta if config.val.tabs.wrap: new_idx %= self._count() else: # absolute moving - if count is not None: + if index == "start": + new_idx = 0 + elif index == "end": + new_idx = self._count() - 1 + elif count is not None: new_idx = count - 1 elif index is not None: assert isinstance(index, int) diff --git a/qutebrowser/components/misccommands.py b/qutebrowser/components/misccommands.py index 120806bfe..8eaae045f 100644 --- a/qutebrowser/components/misccommands.py +++ b/qutebrowser/components/misccommands.py @@ -183,7 +183,10 @@ def screenshot( raise cmdutils.CommandError( f"File {filename} already exists (use --force to overwrite)") - qrect = None if rect is None else utils.parse_rect(rect) + try: + qrect = None if rect is None else utils.parse_rect(rect) + except ValueError as e: + raise cmdutils.CommandError(str(e)) pic = tab.grab_pixmap(qrect) if pic is None: diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml index e034fe8f5..3c5dc6f2f 100644 --- a/qutebrowser/config/configdata.yml +++ b/qutebrowser/config/configdata.yml @@ -1794,6 +1794,17 @@ input.media_keys: On Linux, disabling this also disables Chromium's MPRIS integration. +input.match_counts: + default: true + type: Bool + desc: >- + Interpret number prefixes as counts for bindings. + + This enables for vi-like bindings that can be prefixed with a number to + indicate a count. + Disabling it allows for emacs-like bindings where number keys are passed + through (according to `input.forward_unbound_keys`) instead. + ## keyhint keyhint.blacklist: diff --git a/qutebrowser/keyinput/basekeyparser.py b/qutebrowser/keyinput/basekeyparser.py index 7e688dab1..4db1d5d76 100644 --- a/qutebrowser/keyinput/basekeyparser.py +++ b/qutebrowser/keyinput/basekeyparser.py @@ -254,6 +254,9 @@ class BaseKeyParser(QObject): def _match_count(self, sequence: keyutils.KeySequence, dry_run: bool) -> bool: """Try to match a key as count.""" + if not config.val.input.match_counts: + return False + txt = str(sequence[-1]) # To account for sequences changed above. if (txt in string.digits and self._supports_count and not (not self._count and txt == '0')): diff --git a/qutebrowser/mainwindow/tabbedbrowser.py b/qutebrowser/mainwindow/tabbedbrowser.py index e081284ee..8c6ac2424 100644 --- a/qutebrowser/mainwindow/tabbedbrowser.py +++ b/qutebrowser/mainwindow/tabbedbrowser.py @@ -406,15 +406,16 @@ class TabbedBrowser(QWidget): else: yes_action() - def close_tab(self, tab, *, add_undo=True, new_undo=True): + def close_tab(self, tab, *, add_undo=True, new_undo=True, transfer=False): """Close a tab. Args: tab: The QWebView to be closed. add_undo: Whether the tab close can be undone. new_undo: Whether the undo entry should be a new item in the stack. + transfer: Whether the tab is closing because it is moving to a new window. """ - if config.val.tabs.tabs_are_windows: + if config.val.tabs.tabs_are_windows or transfer: last_close = 'close' else: last_close = config.val.tabs.last_close diff --git a/requirements.txt b/requirements.txt index 0805ad6cc..e088ca805 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,11 +3,11 @@ adblock==0.5.0 colorama==0.4.4 dataclasses==0.6 ; python_version<"3.7" -importlib-metadata==4.8.1 ; python_version<"3.8" +importlib-metadata==4.8.2 ; python_version<"3.8" importlib-resources==5.4.0 ; python_version<"3.9" -Jinja2==3.0.2 +Jinja2==3.0.3 MarkupSafe==2.0.1 Pygments==2.10.0 PyYAML==6.0 -typing-extensions==3.10.0.2 +typing_extensions==4.0.0 ; python_version<"3.8" zipp==3.6.0 diff --git a/scripts/dev/recompile_requirements.py b/scripts/dev/recompile_requirements.py index ed5473971..1b9759eb8 100644 --- a/scripts/dev/recompile_requirements.py +++ b/scripts/dev/recompile_requirements.py @@ -155,11 +155,11 @@ CHANGELOG_URLS = { 'cheroot': 'https://cheroot.cherrypy.org/en/latest/history.html', 'certifi': 'https://ccadb-public.secure.force.com/mozilla/IncludedCACertificateReport', 'chardet': 'https://github.com/chardet/chardet/releases', - 'charset-normalizer': 'https://github.com/Ousret/charset_normalizer/commits/master', + 'charset-normalizer': 'https://github.com/Ousret/charset_normalizer/blob/master/CHANGELOG.md', 'idna': 'https://github.com/kjd/idna/blob/master/HISTORY.rst', 'tldextract': 'https://github.com/john-kurkowski/tldextract/blob/master/CHANGELOG.md', 'backports.entry-points-selectable': 'https://github.com/jaraco/backports.entry_points_selectable/blob/main/CHANGES.rst', - 'typing-extensions': 'https://github.com/python/typing/commits/master/typing_extensions', + 'typing_extensions': 'https://github.com/python/typing/commits/master/typing_extensions', 'diff-cover': 'https://github.com/Bachmann1234/diff_cover/blob/master/CHANGELOG', 'pytest-icdiff': 'https://github.com/hjwp/pytest-icdiff/blob/master/HISTORY.rst', 'icdiff': 'https://github.com/jeffkaufman/icdiff/blob/master/ChangeLog', diff --git a/tests/conftest.py b/tests/conftest.py index 40631af34..26cc04345 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -214,20 +214,74 @@ def pytest_addoption(parser): help="Delay between qutebrowser commands.") parser.addoption('--qute-profile-subprocs', action='store_true', default=False, help="Run cProfile for subprocesses.") - parser.addoption('--qute-bdd-webengine', action='store_true', - help='Use QtWebEngine for BDD tests') + parser.addoption('--qute-backend', action='store', + choices=['webkit', 'webengine'], help='Set backend for BDD tests') def pytest_configure(config): - webengine_arg = config.getoption('--qute-bdd-webengine') - webengine_env = os.environ.get('QUTE_BDD_WEBENGINE', 'false') - config.webengine = webengine_arg or webengine_env == 'true' - # Fail early if QtWebEngine is not available - if config.webengine: - import PyQt5.QtWebEngineWidgets + backend = _select_backend(config) + config.webengine = backend == 'webengine' + earlyinit.configure_pyqt() +def _select_backend(config): + """Select the backend for running tests. + + The backend is auto-selected in the following manner: + 1. Use QtWebKit if available + 2. Otherwise use QtWebEngine as a fallback + + Auto-selection is overridden by either passing a backend via + `--qute-backend=<backend>` or setting the environment variable + `QUTE_TESTS_BACKEND=<backend>`. + + Args: + config: pytest config + + Raises: + ImportError if the selected backend is not available. + + Returns: + The selected backend as a string (e.g. 'webkit'). + """ + backend_arg = config.getoption('--qute-backend') + backend_env = os.environ.get('QUTE_TESTS_BACKEND') + + backend = backend_arg or backend_env or _auto_select_backend() + + # Fail early if selected backend is not available + if backend == 'webkit': + import PyQt5.QtWebKitWidgets + elif backend == 'webengine': + import PyQt5.QtWebEngineWidgets + else: + raise utils.Unreachable(backend) + + return backend + + +def _auto_select_backend(): + try: + # Try to use QtWebKit as the default backend + import PyQt5.QtWebKitWidgets + return 'webkit' + except ImportError: + # Try to use QtWebEngine as a fallback and fail early + # if that's also not available + import PyQt5.QtWebEngineWidgets + return 'webengine' + + +def pytest_report_header(config): + if config.webengine: + backend_version = version.qtwebengine_versions(avoid_init=True) + else: + backend_version = version.qWebKitVersion() + + return f'backend: {backend_version}' + + @pytest.fixture(scope='session', autouse=True) def check_display(request): if utils.is_linux and not os.environ.get('DISPLAY', ''): diff --git a/tests/end2end/conftest.py b/tests/end2end/conftest.py index a4a089cea..16170d460 100644 --- a/tests/end2end/conftest.py +++ b/tests/end2end/conftest.py @@ -165,7 +165,7 @@ if not getattr(sys, 'frozen', False): def pytest_collection_modifyitems(config, items): - """Apply @qtwebengine_* markers; skip unittests with QUTE_BDD_WEBENGINE.""" + """Apply @qtwebengine_* markers.""" # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-75884 # (note this isn't actually fixed properly before Qt 5.15) header_bug_fixed = qtutils.version_check('5.15', compiled=False) diff --git a/tests/end2end/features/tabs.feature b/tests/end2end/features/tabs.feature index c9d983755..3715d5765 100644 --- a/tests/end2end/features/tabs.feature +++ b/tests/end2end/features/tabs.feature @@ -633,6 +633,27 @@ Feature: Tab management - data/numbers/1.txt (active) - data/numbers/3.txt + Scenario: :tab-move with absolute position + When I open data/numbers/1.txt + And I open data/numbers/2.txt in a new tab + And I open data/numbers/3.txt in a new tab + And I run :tab-focus 1 + And I run :tab-move end + Then the following tabs should be open: + - data/numbers/2.txt + - data/numbers/3.txt + - data/numbers/1.txt (active) + + Scenario: :tab-move with absolute position + When I open data/numbers/1.txt + And I open data/numbers/2.txt in a new tab + And I open data/numbers/3.txt in a new tab + And I run :tab-move start + Then the following tabs should be open: + - data/numbers/3.txt (active) + - data/numbers/1.txt + - data/numbers/2.txt + Scenario: Make sure :tab-move retains metadata When I open data/title.html And I open data/hello.txt in a new tab @@ -1349,6 +1370,25 @@ Feature: Tab management And I run :tab-take 0/1 Then the error "Can't take tabs when using windows as tabs" should be shown + @windows_skip + Scenario: Close the last tab of a window when taken by another window + Given I have a fresh instance + When I open data/numbers/1.txt + And I run :tab-only + And I open data/numbers/2.txt in a new window + And I set tabs.last_close to ignore + And I run :tab-take 1/1 + And I wait until data/numbers/2.txt is loaded + Then the session should look like: + windows: + - tabs: + - history: + - url: about:blank + - url: http://localhost:*/data/numbers/1.txt + - active: true + history: + - url: http://localhost:*/data/numbers/2.txt + # :tab-give @xfail_norun # Needs qutewm @@ -1406,6 +1446,24 @@ Feature: Tab management And I run :tab-give 0 Then the error "Can't give tabs when using windows as tabs" should be shown + @windows_skip + Scenario: Close the last tab of a window when given to another window + Given I have a fresh instance + When I open data/numbers/1.txt + And I run :tab-only + And I open data/numbers/2.txt in a new window + And I set tabs.last_close to ignore + And I run :tab-give 1 + And I wait until data/numbers/1.txt is loaded + Then the session should look like: + windows: + - tabs: + - active: true + history: + - url: http://localhost:*/data/numbers/2.txt + - history: + - url: http://localhost:*/data/numbers/1.txt + # Other Scenario: Using :tab-next after closing last tab (#1448) diff --git a/tests/unit/keyinput/test_basekeyparser.py b/tests/unit/keyinput/test_basekeyparser.py index 30ee36301..84068bf47 100644 --- a/tests/unit/keyinput/test_basekeyparser.py +++ b/tests/unit/keyinput/test_basekeyparser.py @@ -346,3 +346,14 @@ def test_clear_keystring_empty(qtbot, keyparser): keyparser._sequence = keyseq('') with qtbot.assert_not_emitted(keyparser.keystring_updated): keyparser.clear_keystring() + + +def test_respect_config_when_matching_counts(keyparser, config_stub): + """Don't match counts if disabled in the config.""" + config_stub.val.input.match_counts = False + + info = keyutils.KeyInfo(Qt.Key_1, Qt.NoModifier) + keyparser.handle(info.to_event()) + + assert not keyparser._sequence + assert not keyparser._count diff --git a/tests/unit/utils/test_version.py b/tests/unit/utils/test_version.py index 6c57cb3d3..1ffbe3c09 100644 --- a/tests/unit/utils/test_version.py +++ b/tests/unit/utils/test_version.py @@ -484,17 +484,20 @@ class TestGitStrSubprocess: @needs_git def test_real_git(self, git_repo): """Test with a real git repository.""" - branch_name = subprocess.run( - ['git', 'config', 'init.defaultBranch'], - check=False, - stdout=subprocess.PIPE, - encoding='utf-8', - ).stdout.strip() - if not branch_name: - branch_name = 'master' + def _get_git_setting(name, default): + return subprocess.run( + ['git', 'config', '--default', default, name], + check=True, + stdout=subprocess.PIPE, + encoding='utf-8', + ).stdout.strip() ret = version._git_str_subprocess(str(git_repo)) - assert ret == f'6e4b65a on {branch_name} (1970-01-01 01:00:00 +0100)' + branch_name = _get_git_setting('init.defaultBranch', 'master') + abbrev_length = int(_get_git_setting('core.abbrev', '7')) + expected_sha = '6e4b65a529c0ab78fb370c1527d5809f7436b8f3'[:abbrev_length] + + assert ret == f'{expected_sha} on {branch_name} (1970-01-01 01:00:00 +0100)' def test_missing_dir(self, tmp_path): """Test with a directory which doesn't exist.""" @@ -13,7 +13,6 @@ minversion = 3.15 setenv = PYTEST_QT_API=pyqt5 pyqt{,512,513,514,515,5150}: LINK_PYQT_SKIP=true - pyqt{,512,513,514,515,5150}: QUTE_BDD_WEBENGINE=true cov: PYTEST_ADDOPTS=--cov --cov-report xml --cov-report=html --cov-report= passenv = PYTHON DISPLAY XAUTHORITY HOME USERNAME USER CI XDG_* QUTE_* DOCKER QT_QUICK_BACKEND PY_COLORS DBUS_SESSION_BUS_ADDRESS basepython = @@ -42,7 +41,6 @@ commands = basepython = {env:PYTHON:python3} setenv = PYTEST_QT_API=pyqt5 - QUTE_BDD_WEBENGINE=true pip_pre = true deps = -r{toxinidir}/misc/requirements/requirements-tests-bleeding.txt commands_pre = pip install --index-url https://www.riverbankcomputing.com/pypi/simple/ --pre --upgrade PyQt5 PyQtWebEngine |