Commit Graph

373 Commits

Author SHA1 Message Date
toofar 00daefff7e Add test to ensure `set_model(None)` cleans up
We want to make sure that the selection model gets deleted when clearing
the model, since we are switching from doing that directly to having it
happen indirectly based off of signals we don't manage.

Hopefully this doesn't end up to be flaky. I think we are depending on
this happening in two different Qt even loop runs (`model.deleteLater()`
in the first one then `selmod.deleteLater()` gets called from the
`model.deleted` signal).

I tried using `qtbot.wait_signals()` with a list but it segfaulted in
some cleanup method. Perhaps is doesn't handle the deleted signal well?

Alternately we could maybe just wait for the selmodel one and check
`sip.isdelted(model)` to check the model is gone too.
2024-06-09 18:16:01 +12:00
toofar f6e9295c50 remove unneeded QTimer imports 2024-05-25 09:34:01 +12:00
Florian Bruhin 6d99dff10b Merge branch 'update-dependencies' 2024-05-24 21:53:08 +02:00
Florian Bruhin 72d7e2327b Update for new pylint/astroid releases
- Add a couple new "raise utils.Unreachable" to avoid
  possibly-used-before-assignment issues.
- Simplify an "if" for the same reason
- Remove an unneeded "return"
- Use "NoReturn" to prepare for pylint knowing about it in the future:
  https://github.com/pylint-dev/pylint/issues/9674
- Add some ignores for used-before-assignment false-positives
- Ignore new undefined-variable messages for Qt wrapers
- Ignore a new no-member warning for KeySequence:
  https://github.com/pylint-dev/astroid/issues/2448#issuecomment-2130124755
2024-05-24 21:46:04 +02:00
toofar 117cb15b8d Handle selection model being None when clearing selection
Change `CompletionView.on_clear_completion_selection()` to call the Qt
selection model getter, instead of our one. Since it can be called when the
selection model has already been cleared and our one asserts that there
is a selection model to return.

Back in the distant past there was a change to handle the completion widget's
selection model being None when the `on_clear_completion_selection()` slot was
called: https://github.com/qutebrowser/qutebrowser/commit/88b522fa167e2f97b

More recently a common getter for the selection model was added so we could
have a single place to apply type narrowing to the returned object from the Qt
getter (the type hints had been updated to be wrapped in `Optional`): https://github.com/qutebrowser/qutebrowser/commit/92dea988c01e745#diff-1559d42e246323bea35fa064d54d48c990999aaf4c732b09ccd448f994da74cf

It seems this is one place where it does, and already did, handle that
optional. So it didn't need to change to use the new getter. This is called
from the `Command.on_mode_left` signal, not sure why the selection model is
None here. Perhaps it already gets cleared by the effects of the `hide_cmd`
signal that gets fired earlier, or perhaps even from the `self.hide()` on the
line before. Anyway, this was working for several years and seems harmless
enough.
2024-05-19 14:29:31 +12:00
Florian Bruhin ee9aecda46 listcategory: Fix O(n^2) performance if no match
With the change in #7955, if the regex did not match, it ended up retrying the
lookahead at every position of the string (expected), but then *also* repeated
that process for every position in the string. Thus, a non-matching pattern
ended up in O(n^2) performance (with n = length of URL).

Instead, anchor the pattern at the beginning of the string. This doesn't change
behaviour as we use .* at the beginning of every lookahead anyways, but it means
we end up with O(n) instead of O(n^2) performance.

Co-authored-by: toofar <toofar@spalge.com>
2024-01-12 18:53:22 +01:00
Florian Bruhin f8df682b90 Reapply "Merge pull request #7955 from arza-zara/search_any_order"
This reverts commit 45d483479a.
2024-01-12 18:53:22 +01:00
Florian Bruhin 45d483479a Revert "Merge pull request #7955 from arza-zara/search_any_order"
This reverts commit fe1faa14b9, reversing
changes made to 04af4c657d.

For my setup with 310 quickmarks and 94 bookmarks, this makes qutebrowser hang
for around a minute on every keypress.
2024-01-11 17:30:27 +01:00
toofar fe1faa14b9 Merge pull request #7955 from arza-zara/search_any_order
A few more completions will now match search terms in any order:
`:quickmark-*`, `:bookmark-*`, `:tab-take` and `:tab-select` (for the quick
and bookmark categories).
2023-12-21 12:28:22 +13:00
arza 6671dbf2b4 Search ListCategory in any order of search terms 2023-10-07 11:02:26 +03:00
Florian Bruhin 3eb826f664 reuse: Update remaining copyright texts
git ls-files | \
    xargs sed -Ei 's/Copyright [0-9]{4}(-[0-9]{4}) ([^<]*)<([^>]*)>/SPDX-FileCopyrightText: \2<\3>/'
2023-07-23 12:52:01 +02:00
Florian Bruhin b2aaba6043 reuse: Adjust most license headers
git ls-files | xargs grep -l "is free software"  | xargs reuse annotate --license="GPL-3.0-or-later" --skip-unrecognised
2023-07-23 12:11:07 +02:00
Philipp Albrecht d9e8b638bf Remove vim modelines
We're deprecating vim modelines in favor of `.editorconfig`.

Removing vim modelines could be done using two one-liners. Most of the vim modelines
were followed by an empty line, so this one-liner took care of these ones:

```sh
rg '^# vim: .+\n\n' -l | xargs sed -i '/^# vim: /,+1d'
```

Then some of the vim modelines were followed by a pylint configuration line, so running
this one-liner afterwards took care of that:

```sh
rg '^# vim:' -l | xargs sed -i '/^# vim: /d'
```
2023-06-30 11:03:06 +02:00
Florian Bruhin b4d32e04f4 Merge branch 'master' into qt6-v2 2022-12-13 09:05:32 +01:00
Florian Bruhin f396c6fe67 tests: Make sure we close history database connections
With pytest main, pytest now reuses temporary directories...
2022-12-06 17:06:56 +01:00
Kian-Meng Ang d77b0fb8a3 Fix typos
Found via `codespell -S *.js -L
technik,gir,nam,ans,wih,wil,ro,nowe,te,datas,qutie,ned,fo,clude,alph,crashers,nd,wasn,cros,ue,possition`

Co-authored-by: Marcel Schilling <marcel.schilling@uni-luebeck.de>
2022-11-19 13:03:39 +08:00
Florian Bruhin 51f1420ef5 qt 6: Comprehensive core moves
According to docs, even for stuff we don't use so far
2022-08-23 18:31:41 +02:00
Florian Bruhin d387b1a108 tests: Adjust most imports 2022-08-23 18:31:40 +02:00
Florian Bruhin 0877fb0d78 Run scripts/dev/rewrite_enums.py 2022-08-23 18:31:38 +02:00
Florian Bruhin d47cfd99d7 Run scripts/dev/rewrite_qt_imports.sh 2022-08-23 18:09:11 +02:00
Florian Bruhin 7932d44dab Fix lint 2022-04-25 17:57:57 +02:00
Florian Bruhin a20bb67a87 mypy: Upgrade to PyQt5-stubs 5.15.6.0
For some unknown reason, those new stubs cause a *lot* of things now to be
checked by mypy which formerly probably got skipped due to Any being implied
somewhere.

The stubs themselves mainly improved, with a couple of regressions too.

In total, there were some 337 (!) new mypy errors. This commit fixes almost all
of them, and the next commit improves a fix to get things down to 0 errors
again.

Overview of the changes:

==== qutebrowser/app.py

- Drop type ignore due to improved stubs.

==== qutebrowser/browser/browsertab.py

- Specify the type of _widget members more closely than just QWidget.
  This is debatable: I suppose the abstract stuff shouldn't need to know
  anything about the concrete backends at all. But it seems like we cut some
  corners when initially implementing things, and put some code in browsertab.py
  just because the APIs of both backends happened to be compatible. Perhaps
  something to reconsider once we drop QtWebKit and hopefully implement a dummy
  backend.

- Add an additional assertion in AbstractAction.run_string. This is already
  covered by the isinstance(member, self.action_base) above it, but that's too
  dynamic for mypy to understand.

- Fix the return type of AbstractScroller.pos_px, which is a QPoint (with x
  and y components), not a single int.

- Fix the return type of AbstractScroller.pos_perc, which is a Tuple (with x
  and y components), not a single int.

- Fix the argument types of AbstractScroller.to_perc, as it's possible to pass
  fractional percentages too.

- Specify the type for AbstractHistoryPrivate._history. See above (_widget) re
  this being debatable.

- Fix the return type of AbstractTabPrivate.event_target(), which can be None
  (see #3888).

- Fix the return type of AbstractTabPrivate.run_js_sync, which is Any (the JS
  return value), not None.

- Fix the argument type for AbstractTabPrivate.toggle_inspector: position can
  be None to use the last used position.

- Declare the type of sub-objects of AbstractTab.

- Fix the return value of AbstractTab.icon(), which is the QIcon, not None.

==== qutebrowser/browser/commands.py

- Make sure the active window is a MainWindow (with a .win_id attribute).

==== qutebrowser/browser/downloadview.py

- Add _model() which makes sure that self.model() is a DownloadModel, not None
  or any other model. This is needed because other methods access a variety of
  custom attributes on it, e.g. last_index().

==== qutebrowser/browser/greasemonkey.py

- Add an ignore for AbstractDownload.requested_url which we patch onto the
  downloads. Probably would be nicer to add it as a proper attribute which always
  gets set by the DownloadManager.

==== qutebrowser/browser/hints.py

- Remove type ignores for QUrl.toString().
- Add a new type ignore for combining different URL flags (which works, but is
  not exactly type safe... still probably a regression in the stubs).
- Make sure the things we get back from self._get_keyparser are what we actually
  expect. Probably should introduce a TypedDict (and/or overloads for
  _get_keyparser with typing.Literal) to teach mypy about the exact return value.
  See #7098.
  This is needed because we access Hint/NormalKeyParser-specific attributes such
  as .set_inhibited_timout() or .update_bindings().

==== qutebrowser/browser/inspector.py

- Similar changes than in browsertab.py to make some types where we share API
  (e.g. .setPage()) more concrete. Didn't work out unfortunately, see next
  commit.

==== qutebrowser/browser/network/pac.py

- Remove now unneeded type ignore for signal.

==== qutebrowser/browser/qtnetworkdownloads.py

- Make sure that downloads is a qtnetworkdownloads.DownloadItem (rather than an
  AbstractDownload), so that we can call ._uses_nam() on it.

==== qutebrowser/browser/qutescheme.py

- Remove now unneeded type ignore for QUrl flags.

==== qutebrowser/browser/urlmarks.py

- Specify the type of UrlMarkManager._lineparser, as those only get initialized
  in _init_lineparser of subclasses, so mypy doesn't know it's supposed to exist.

==== qutebrowser/browser/webelem.py

- New casts to turn single KeyboardModifier (enum) entries into
  KeyboardModifiers (flags). Might not be needed anymore with Qt 6.
- With that, casting the final value is now unneeded.

==== qutebrowser/browser/webengine/notification.py

- Remove now unneeded type ignore for signal.
- Make sure the self.sender() we get in HerbeNotificationAdapter._on_finished()
  is a QProcess, not just any QObject.

==== qutebrowser/browser/webengine/webenginedownloads.py

- Remove now unneeded type ignores for signals.

==== qutebrowser/browser/webengine/webengineelem.py

- Specify the type of WebEngineElement._tab.
- Remove now unneeded type ignore for mixed flags.

==== qutebrowser/browser/webengine/webengineinspector.py

- See changes to inspector.py and next commit.
- Remove now unneeded type ignore for signal.

==== qutebrowser/browser/webengine/webenginequtescheme.py

- Remove now unneeded type ignore for mixed flags.

==== qutebrowser/browser/webengine/webenginesettings.py

- Ignore access of .setter attribute which we patch onto QWebEngineProfile.
  Would be nice to have a subclass or wrapper-class instead.

==== qutebrowser/browser/webengine/webenginetab.py

- Specified the type of _widget members more closely than just QWidget.
  See browsertab.py changes for details.
- Remove some now-unneeded type ignores for creating FindFlags.
- Specify more concrete types for WebEngineTab members where we actually need to
  access WebEngine-specific attributes.
- Make sure the page we get is our custom WebEnginePage subclass, not just any
  QWebEnginePage. This is needed because we access custom attributes on it.

==== qutebrowser/browser/webengine/webview.py

- Make sure the page we get is our custom WebEnginePage subclass, not just any
  QWebEnginePage. This is needed because we access custom attributes on it.

==== qutebrowser/browser/webkit/network/networkreply.py

- Remove now unneeded type ignores for signals.

==== qutebrowser/browser/webkit/webkitinspector.py

- See changes to inspector.py and next commit.

==== qutebrowser/browser/webkit/webkittab.py

- Specify the type of _widget members more closely than just QWidget.
  See browsertab.py changes for details.
- Add a type ignore for WebKitAction because our workaround needs to
  treat them as ints (which is allowed by PyQt, even if not type-safe).
- Add new ignores for findText calls: The text is a QString and can be None; the
  flags are valid despite mypy thinking they aren't (stubs regression?).
- Specify the type for WebKitHistoryPrivate._history, because we access
  WebKit-specific attributes. See above (_widget) re this being debatable.
- Make mypy aware that .currentFrame() and .frameAt() can return None (stubs
  regression?).
- Make sure the .page() and .page().networkAccessManager() are our subclasses
  rather than the more generic QtWebKit objects, as we use custom attributes.
- Add new type ignores for signals (stubs regression!)

==== qutebrowser/browser/webkit/webpage.py

- Make sure the .networkAccessManager() is our subclass rather than the more
  generic QtWebKit object, as we use custom attributes.
- Replace a cast by a type ignore. The cast didn't work anymore.

==== qutebrowser/browser/webkit/webview.py

- Make sure the .page() is our subclass rather than the more generic QtWebKit
  object, as we use custom attributes.

==== qutebrowser/commands/userscripts.py

- Remove now unneeded type ignore for signal.

==== qutebrowser/completion/completer.py

- Add a new _completion() getter (which ensures it actually gets the completion
  view) rather than accessing the .parent() directly (which could be any QObject).

==== qutebrowser/completion/completiondelegate.py

- Make sure self.parent() is a CompletionView (no helper method as there is only
  one instance).
- Remove a now-unneeded type ignore for adding QSizes.

==== qutebrowser/completion/completionwidget.py

- Add a ._model() getter which ensures that we get a CompletionModel (with
  custom attributes) rather than Qt's .model() which can be any QAbstractItemModel
  (or None).
- Removed a now-unneeded type ignore for OR-ing flags.

==== qutebrowser/completion/models/completionmodel.py

- Remove now unneeded type ignores for signals.
- Ignore a complaint about .set_pattern() not being defined. Completion
  categories don't share any common parent class, so it would be good to introduce
  a typing.Protocol for this. See #7098.

==== qutebrowser/components/misccommands.py

- Removed a now-unneeded type ignore for OR-ing flags.

==== qutebrowser/components/readlinecommands.py

- Make sure QApplication.instance() is a QApplication (and not just a
  QCoreApplication). This includes the former "not None" check.

==== qutebrowser/components/scrollcommands.py

- Add basic annotation for "funcs" dict. Could have a callable protocol to
  specify it needs a count kwarg, see #7098.

==== qutebrowser/config/stylesheet.py

- Correctly specify that stylesheet apply to QWidgets, not any QObject.
- Ignore an attr-defined for obj.STYLESHEET. Perhaps could somehow teach mypy
  about this with overloads and protocols (stylesheet for set_register being None
  => STYLESHEET needs to be defined, otherwise anything goes), but perhaps not
  worth the troble. See #7098.

==== qutebrowser/keyinput/keyutils.py

- Remove some now-unneeded type ignores and add a cast for using a single enum
  value as flags. Might need to look at this again with Qt 6 support.

==== qutebrowser/keyinput/modeman.py

- Add a FIXME for using a TypedDict, see comments for hints.py above.

==== qutebrowser/mainwindow/mainwindow.py

- Remove now-unneeded type ignores for calling with OR-ed flags.
- Improve where we cast from WindowType to WindowFlags, no int needed
- Use new .tab_bar() getter, see below.

==== qutebrowser/mainwindow/prompt.py

- Remove now-unneeded type ignores for calling with OR-ed flags.

==== qutebrowser/mainwindow/statusbar/bar.py

- Adjust type ignores around @pyqtProperty. The fact one is still needed seems
  like a stub regression.

==== qutebrowser/mainwindow/statusbar/command.py

- Fix type for setText() override (from QLineEdit): text can be None
  (QString in C++).

==== qutebrowser/mainwindow/statusbar/url.py

- Adjust type ignores around @pyqtProperty. The fact one is still needed seems
  like a stub regression.

==== qutebrowser/mainwindow/tabbedbrowser.py

- Specify that TabDeque manages browser tabs, not any QWidgets. It accesses
  AbstractTab-specific attributes.
- Make sure that the .tabBar() we get is a tabwidget.TabBar, as we access
  .maybe_hide.
- Fix the annotations for stored marks: Scroll positions are a QPoint, not int.
- Add _current_tab() and _tab_by_idx() wrappers for .currentWidget() and
  .widget(), which ensures that the return values are valid AbstractTabs (or None
  for _tab_by_idx). This is needed because we access AbstractTab-specific
  attributes.
- For some places, where the tab can be None, continue using .currentTab() but
  add asserts.
- Remove some now-unneeded [unreachable] ignores, as mypy knows about the None
  possibility now.

==== qutebrowser/mainwindow/tabwidget.py

- Add new tab_bar() and _tab_by_idx() helpers which check that the .tabBar() and
  .widget() are of type TabBar and AbstractTab, respectively.
- Add additional assertions where we expect ._tab_by_idx() to never be None.
- Remove dead code in get_tab_fields for handling a None y scroll position. I
  was unable to find any place in the code where this could be set to None.
- Remove some now-unneeded type ignores and casts, as mypy now knows that
  _type_by_idx() could be None.
- Work around a strange instance where mypy complains about not being able to
  find the type of TabBar.drag_in_progress from TabWidget._toggle_visibility,
  despite it clearly being shown as a bool *inside* that class without any
  annotation.
- Add a ._tab_widget() getter in TabBar which ensures that the .parent() is in
  fact a TabWidget.

==== qutebrowser/misc/crashsignal.py

- Remove now unneeded type ignores for signals.

==== qutebrowser/misc/editor.py

- Remove now unneeded type ignores for signals.

==== qutebrowser/misc/ipc.py

- Remove now unneeded type ignores for signals.
- Add new type ignores for .error() which is both a signal and a getter
  (stub regression?). Won't be relevant for Qt 6 anymore, as the signal was
  renamed to errorOccurred in 5.15.

==== qutebrowser/misc/objects.py

- Make sure mypy knows that objects.app is our custom Application (with custom
  attributes) rather than any QApplication.

==== qutebrowser/utils/objreg.py

- Ignore attr-defined for .win_id attributes. Maybe could add a typing.Protocol,
  but ideally, the whole objreg stuff should die one day anyways.

==== tests/unit/completion/test_completer.py

- Make CompletionWidgetStub inherit from CompletionView so that it passes the
  new isinstance() asserts in completer.py (see above).
2022-04-25 17:23:16 +02:00
Florian Bruhin 2dc11c128a Update docs/changelog 2022-01-29 11:38:14 +01:00
mohite-abhi ef87b5df72 Add tests for tab focus completion delete 2022-01-25 04:22:50 +05:30
Florian Bruhin f4714a9300 Use flake8-pytest-style 2022-01-04 10:30:24 +01:00
Florian Bruhin 26d308d95d pylint: Enable docparams checker 2021-12-03 13:36:20 +01:00
Florian Bruhin 676c9db2fe Handle and test more file path corner cases 2021-07-13 16:23:40 +02:00
lufte 03b8a26645 The database of a table shouldn't be private 2021-07-02 22:18:12 -03:00
lufte b75d23e0b1 Fix histcategory unit tests 2021-07-02 21:48:34 -03:00
Florian Bruhin c09e1439f1 Clean up successful process data after 1h 2021-03-23 12:53:23 +01:00
Florian Bruhin ea60bcfc2a Sort :process completion manually 2021-03-23 12:53:23 +01:00
Florian Bruhin d9caaffa14 Add a test for :process completion 2021-03-23 12:53:23 +01:00
Lembrun 28f4c40bc7 Changed pathlib.Path.expanduser to pathlib.Path.home 2021-03-11 19:17:39 +01:00
Lembrun e21c4a0664 Changed joinpath to / 2021-03-11 08:20:39 +01:00
Lembrun c346afcc9e Merge branch 'master' into pathlib-/unit/completion 2021-03-09 22:41:55 +01:00
Lembrun 38311a69a8 Replaced os.path by the pathlib equivalent 2021-03-03 12:59:17 +01:00
Florian Bruhin 9909bf0b11 Fix lint 2021-03-02 18:23:50 +01:00
Florian Bruhin 2cbbbe54c6 tests: Disallow NUL for filesystem tests
From what I can see, there's no way for an user to enter a NUL byte.

Closes #6223
2021-03-02 17:54:32 +01:00
Lembrun e8b05af233 Qtbot methods changed to snake case,snake case check added 2021-02-26 22:07:08 +01:00
Florian Bruhin 217711f200 tests: Fix ~ completion test on Windows 2021-01-27 19:48:52 +01:00
Florian Bruhin 1a4fff1a42 doc: Switch URLs to https 2021-01-26 15:19:01 +01:00
Florian Bruhin 222f1f19a1 Bump copyright years
Closes #6015
2021-01-20 20:06:19 +01:00
Florian Bruhin fd6790fe8c Rename :buffer to :tab-select
See #6022
2021-01-20 18:00:38 +01:00
Florian Bruhin 6fd2077b6c Improve tests for filesystem completion 2021-01-20 10:30:25 +01:00
Florian Bruhin 88cd06c0b7 Minor reformat 2021-01-20 09:50:32 +01:00
Andrew MacFie a0cc57d0fd Add some tests 2021-01-19 18:07:39 -05:00
Andrew MacFie 51343a432b Add filesystem completion to default 2021-01-19 14:07:35 -05:00
Florian Bruhin efa8916faa Merge remote-tracking branch 'origin/pr/5992' 2020-12-30 13:51:39 +01:00
Ryan Roden-Corrent ba1bbd555c
Correct import order (pylint). 2020-12-29 07:35:44 -05:00
Ryan Roden-Corrent faa4d51930
Trim long patterns rather than clearing them.
Fixes #5973.
2020-12-28 18:20:26 -05:00