The CheckPlatform macro will prompt the user user to use the 32bit installer
if they are on a 32bit system. But we don't provide a 32bit installer anymore.
This commit changes the OS version check for Qt5 builds to be based on checking
version numbers ourselves too, so that we can have our own error message.
Also moves the Qt5 conditionals to be compile time ones.
We dropped 32bit support in #7804 and as a result removed the arch
suffix from the binary that pyinstaller produces. This commit removes it
form the lookup path in the installer too.
Note that we are leaving the arch string in the installer itself for
now. Mostly because it'll be removed as part of a later change when the
installer itself is refreshed. But it might also be useful to clarify in
the installer names what the arch is? Maybe, that reasoning might not
fit with the previous change to remove the arch strings.
The Qt docs for 6.5 say that the minimum supported version is Windows 10
1809.
Experimentally it seems qutebrowser and it's dependencies work fine on a
version as early 1607.
There should be no change in OS version requirements for the Qt5 build,
although we've dropped 32 bit support already and in a future version of
the installer we may bring the minimum OS version support in line with
the Qt6 requirements for simplicity too.
Added a new QT5 version into the NSIS scripts so we can do the different
version check per installer build. It just uses the python bool
serialization format so should always be "True" or "False", but I've
added a fallback anyway for consistency.
I don't want to deal with having to review development changes of
pyinstaller every week. So pin to one commit for now that we can
actually test. I'm subscribed to release notifications on github so I'll
manually change this back to point to the pyinstaller pypi package ones
it does.
Not that we are looking up resources via importlib_resources for
pyinstaller builds too we need to change where the data files are
installed to to match what importlib_resources is expecting.
There was a comment in the previous resource lookup special case
complaining about the data files being at the top level so it seems this
is a change for the better anyhow.
Observed paths:
requested file: qutebrowser.app/Contents/Frameworks/qutebrowser/config/configdata.yml
actual file : qutebrowser.app/Contents/Frameworks/config/configdata.yml
PyInstaller has [recently][symlinks] landed a change that should restore
the webengine sandbox on macOS builds. With a bit more testing we are
hoping that we can go ahead releasing builds based on that
in-development PyInstaller codebase even before they've made a release.
This commit pins our pyinstaller dependency to be the latest commit on
their develop branch.
[symlinks]: https://github.com/pyinstaller/pyinstaller/pull/7619
reuse annotate --license="GPL-3.0-or-later" --style python \
misc/nsis/uninstall_pages.nsh \
misc/nsis/install.nsh \
misc/nsis/uninstall.nsh
And fixing qutebrowser.nsi manually as that uses iso-8859-1 and the reuse tool
doesn't like that apparently.
These tests were failing on webkit due to cookies not getting set (they
made a change recently to fix a security issue around cookies and must
have messed something up)
tests/end2end/test_invocations.py::test_cookies_store
tests/end2end/features/test_private_bdd.py::test_make_sure_private_data_is_not_cleared_when_closing_a_private_window_but_another_remains
Pin Flask and Werkzeug for py3.7
They've removed compatibility upstream.
Added example to readme file because I had to go dig for one in the
commit history.
Add blinker to changelog URLs as it's a required dependency of Flask
now.
The previous way of obtaining the Bang's URL was using the
response's body, using the url atrribute of a meta tag. The way
this was handled was a bit problematic: some URLs were of the format
/l/?uddg=<URL>&<some-other-query-arguments>, while others (such as google)
is simply <URL>. This could have been fixed by using an if-else, but I
preferred another approach. Lite DuckDuckGo sends a 303 response when
using Bangs, instead of a 200 response which makes the redirect. The
location header of the 303 response is the search engine's URL, so it's
easy to implement this function, working for both afformentioned URL
templates.
Looks like the upstream bug is fixed now.
I didn't run recompile-requirements because it requires py3.7 for the
pylint file and I don't have that. The robot will run overnight anyway
(and pick up a new pylint release)
ref: 085a7956eb
The changes in requirements-mypy.txt would get overwritten on the next
dependency update. Also, it looks like we don't actually need PyQt6 (or
the PyQt6 stubs) available for checking PyQt 5 code if all Qt 6 imports
are appropriately gated by conditionals mypy knows about.
Follow-up to c1738ca550.
Would be nice to have a bare `mypy` env which ran both the more specific ones
in sequence but I don't know how to do that.
Not sure if there is a way to pull the CONSTANTS_ARGS stuff out to a non-env
parameter and pass it into commands but I couldn't figure out a way. So via
the environment it is.
TODO: compare PyQt6 as-is with the WIP PyQt6-Stub
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).
Fix qute-bitwarden userscript URL matching for multi level subdomains
The qute-bitwarden userscript is not able to autofill for a multi-level subdomain URLs (e.g. `http://my.sub.domain.local/`).
qute-bitwarden exits with status code 2 and returns the following on stderr:
```
No pass candidates for URL 'http://my.sub.domain.local/' found!
```
Joining the extracted subdomain and domain with a `.` solves the issue.
The PyQt resources system is gone in 6.2 and deprecated before that. This
should be the last usage of it.
Switches icons to be read with `utils.resources.read_file_binary()` in
`notification.py` (fallback desktop notification icon) and `app.py` (icon for
the desktop window).
importlib only loads resources under a package, so the icons are moved under
the `qutebrowser/` directory.
Closes: #6062
Then regenerate the relevant files.
Also drop dataclasses from requirements files.
TODO: should we drop the dataclasses-types requirement for mypy too?
I am making the yt-dl program used in the `cast` userscript
configurable, via a pattern borrowed from some of the other
userscripts here (e.g. `password_fill` and `kodi`): we look for an
optional "cast_rc" file in the qutebrowser config directory and source
it if it exists.
(Technically this allows for overriding any variables used in `cast`,
but this is in line with how the pattern works in the other scripts
already.)
If the config file is not found, we default to yt-dlp, and if that
doesn't exist then youtube-dl. If after all this no program is
available, we emit an error message
(note, the error messaging function as currently written in the cast script
seems broken and doesn't display the full error message, but fixing this
existing bug is outside of the scope of this change. May be good for a
followup).
I recognize there's some danger of breakage for some users by switching
the default to yt-dlp, but I think it's reasonable to assume that almost
everybody who has yt-dlp installed would prefer it to be used anyway.
Those who don't will experience no difference.
The `cast` userscript hasn't worked for me in a while, because it attempts to launch youtube-dl which has been replaced by yt-dlp for some time. Switching this one command gets `cast` working for me.
I wonder how many else will fail.
Also it would be nice if the compiled requirements files said where the
requirements come from, as in what they are dependencies of, if
anything. Like pip-compile does.
Hopefully that works. This was confusing. Grepping for 3.6 to see how
other places pin it there were a bunch of normal pins in .txt files and
then some comment-but-actually-instruction comments in the -raw files.
There is a readme in the requirements folder but it just says what
instructions are allowed. Not why you would want to add them, seems to
very high cognitive load setup.
Trying to run the recompile_requirements.py script it did some stuff
then quit because it couldn't find python3.7. Yeah I don't have that
installed. It doesn't try to use pyenv or anything, just runs venv
expecting you have everything installed?
Turns out you take the name of the requirements file you added the
instructions to (eq requirements-test.txt-raw -> test) and run it with
that as argument. The requirements file you modify should be the highest
level one that mentions the requirement you want to pin.
Anyway I edited the qutebrowser.text-raw one because that seems like the
main one and it mentions MarkupSafe (because of jinja2?) and ran
`scripts/dev/recompile_requirements qutebrowser` in my existing venv.
Lets see what the CI thinks.
Also got lots of `pkg_resources==0.0.0` in a bunch of requirements files
which seems problematic.