Age | Commit message (Collapse) | Author |
|
It seems the rename script losses the alias when you re-run it. Probably
gets confused, lets see if it ignores it when the other module is
aliased.
|
|
No need to import webengine early in early init because we are doing
that in qt.py anyway.
Missed a conditional import in conftest that needed to change to a None
check.
Found by running the rewrite script again to see how idempotent it is.
|
|
Not sure why this is needed now, possibly we are importing more stuff
now?
The `-y` was added because I don't know how it is working without it but
it doesn't see to with https://github.com/nektos/act
|
|
|
|
|
|
|
|
It seems it does lower the number of errors!
Still lots of errors that appear to be from the PyQt5 path though (eg
complaining that webenginecore doesn't have QWebEngineDownloadRequest
because we copied that over for qt5)
I'm starting to think just making our own copy of the stub files might
actually be a better option, despite it probably being hard to make work
with everyone's local setup (eg their IDEs).
|
|
The comment changes in qt.py might have to change once we figure out the
best way to run mypy (eg with PyQt5 and 6 at the same time or one at a
time? If one at a time how to properly make mypy ignore stuff like
AttributeErrors?).
I had to comment all the PyQt5 stuff in qt.py to get mypy to run with
just PyQt6 without casting everything to Any. Presumably it's possibly
to nudge mypy into type narrowing or whatever but I couldn't figure out
a way to make it work.
There are still lots of mypy errors, the most common ones are:
* complaining about webkit not having type anymore (since I was running
it with just PyQt6 installed
* <somesignal> has no attribute "connect"
* no override for method with "bytes" as an arg (they expect QByteArray)
* complaining that a Qt module doesn't have an attribute when the
attribute access is inside a 'except AttributeError' block or a 'if
hasattr():' block
* a few places complaining about unexpected types being passed to
functions, mainly that is _EnumValueType in
qutebrowser/utils/debug.py, it seems `simplewrapper` is now treated
differently? Maybe we are getting real types now?
|
|
|
|
|
|
|
|
I have both backends available in my test environment and use
QUTE_TESTS_BACKEND to pick a backend.
Since moving to qutebrowser/qt.py as a file instead of modules some
error cases show up as AttributeErrors at import time instead of ImportErrors.
In particular when you import a qutebrowser module like
webenginequtescheme and the webengine stuff in qt.py is None we get
errors like
AttributeError: 'NoneType' object has no attribute 'QWebEngineUrlSchemeHandler'
when we import the qutebrowser module.
This is a way for me to make sure those errors show up for me even when
I have both backends available.
|
|
|
|
Leftover from 62515fecf0a64f ref #7091
|
|
Updated on master in https://github.com/qutebrowser/qutebrowser/pull/7272
Maybe this would be better handled with a rebase instead.
|
|
I only had the old way save in my bash history and this one was only
mentioned in the changelog.
Also changed the heading above the new entry to be title case, which
seems to be more consistent with the other headinfs in the file.
Also remove the one remaining mention of `QUTE_BDD_WEBENGINE` since it
does nothing anymore.
|
|
Webengine tests weren't getting skipped if webengine was importable but webkit
was selected.
This made it so you couldn't run cleanly with QUTE_TESTS_BACKEND=webkit in an
environment with both webkit and webengine installed.
Adds qtwebkit_skip and qtwebengine_skip markers, which duplicate names used in
the BDD tests.
Refactors various webengine tests that were failing in this setup to act
consistently in both cases.
1. pytestmark = [pytest.mark.qtwebkit_skip]
2. QtWebEngineCore = testutils.qt_module_skip("webenginecore")
(1) skips the module based on the selected backend. (2) skips it if the needed
module isn't available. Possibly they could be folded into one.
When you have both backends available the qt_module_skip method won't skip
the test, and since I changed import from qt.py to be None instead of raising
an ImportError pytest.importorskip also won't skip based off of imports
(AttributeErrors end up getting raised, which are a bit to generic to skip
based off).
So for that case imports have additionally been moved down been below the
skips. Generally using pytest.importorskip in case I have to rewrite imports
agin, because in that case it'll move them back up to the top...
Relates to: 1d01d5faf115 Adapt unittests for re-writing PyQt imports
Where I moved some import skips down. Which works fine for first order imports
like `from qutebrowser.qt import webengine`, which just import None, but for
things like `from qutebrowser.browser import webenginesettings` that ends up
raising AttributeError. So this moves them back down.
|
|
|
|
|
|
My fork has Webengine stubs included too. All autogenerated with no
specific codemods or anything yet. Ref https://github.com/python-qt-tools/PyQt6-stubs/issues/6
Switching to just PyQt6 instead of both 5 and 6 installed at the moment
because ... it causes about half as many mypy errors. There are a lot of
places like:
if gettatt(...):
# pyqt6
...
else:
# pyqt5
...
that mypy has no idea about. I'm not sure the best way to guide it at
this point. Even once I figure that out I'm not sure that doing one run
with both 5+6 is the way to go, we might want to split mypy into two
runs.
|
|
|
|
|
|
Make the module be passed as attributes for qutebrowser.qt, not full modules
names.
Remove redundant importlib call, the skipping methods should already do this.
Add lowlevel log line ignore (software rendering on AMD).
|
|
Firstly switch importorskip out for our own version that'll check
if a module is None in qutebrowser.qt.
Then a bunch of misc changes to get tests working:
* change some ImportError checks in tests to look for None
* some places that did importorskip when import qutebrowser modules, and
then used the response, have been changed to first check the Qt module
and then import the qutebrowser module. This is because some
qutebrowser modules might throw AttributeErrors now that some Qt
modules they depend on are None (probably type hints? I forget).
* change a few stubs.ImportFake()s for the same reason
* in test_ipc.py save the original enums to the mocked qlocal socket,
for equality checks in the code, otherwise they were being returned as
specced magick mocks
Swapping out importorskip was done like:
git grep -l pytest.importorskip tests/ | xargs sed -i -e 's/pytest.importorskip/testutils.qt_module_skip/'
git grep -l "qt_module_skip('qutebrowser.qt" tests/ | xargs sed -i -e "s/qt_module_skip('qutebrowser.qt./qt_module_skip('/"
git grep -l 'qt_module_skip("qutebrowser.qt' tests/ | xargs sed -i -e 's/qt_module_skip("qutebrowser.qt./qt_module_skip("/
Then manually changing a few back that weren't Qt related.
|
|
Now that we are importing the PyQt modules and then accessing stuff as
attributes on them the mocks in the tests should be done the same way.
This was done manually, I didn't even try to automate it.
Cherry picked from 81e802faaf08 on the Qt5 only branch.
|
|
|
|
Since we are no doing "from qt import sql" instead of using qt.sql in
the code the submodule names are clashing with other names in the code
now. pylint told me about these ones.
|
|
We have differences in names between 5 and 6. Mostly we use the wrapper
machinery with conditional in a few special places which need to know
the details. So we could probably get away with just having Qt6
installed (since we are preferring Qt6 locations for things already).
But webkit isn't in Qt6 so we need Qt5 if we are keeping that anyway.
|
|
See #7128 for discussion. Mypy doesn't see to follow wildcard imports
like those used in /qt/gui.py etc. Importing the Qt modules as
attributes seems to work better for that. It does mean we can't import
stuff from Qt modules though. We have to import the module and then
reference the things in it as attributes.
The _Machinery class and renaming at the bottom of the file are quick
hacks to make it compatible with the qts-like approach. Mostly this
qt.py file is copied from a PyQt5-only version and it could use a little
refactoring in it's current state.
|
|
adjust indent of trailing lines because the leading ones got longer when
re-writing imports in the big qt import reference rewrite commit
|
|
The LibCST rename tool got a bit confused by imports done in `if
TYPE_CHECKING:` blocks. For ones that were used it moved them out of
those blocks. For ones that were only used in string type hints it half
changed the imports and didn't updated the strings.
A couple of instances were fixed in previous commits. These are the last
few that mypy could see.
Addressed manually. These fixers based on LibCST
https://github.com/python-qt-tools/PyQt6-stubs/tree/main/fixes look like
they could be useful. But they don't have any documentations of tests or
anything. So it's much faster to fix these manually then to try to
understand what all that is doing, if any of it is useful for us,
extract it, test it etc.
|
|
These require a bit of special casing due to how they handle imports.
|
|
Imports in TYPE_CHECKING conditions are not consistently handled, possibly when
they are only used in string types.
Not sure what happened with the duplicates in the logging modules.
Found by grepping 'Qt and "Qt
|
|
Some test imports that didn't have the things there were importing used
got dropped by the rename tool. This restores them.
Found by searching in the diff for eg `import qutebrowser.qt$` and
`import qutebrowser.qt `
Relates to #995
|
|
Fixups for commit Qt import rewrite commit "Re-write PyQt references to always include the module"
Imports not at the top of the file were mostly moved up there. Where
they were inside a try/except block they were replaced with `pass`
(why!).
In a previous version of this commit it was based on a branch were we
were doing things like:
if module and module.attribute is not None:
do_thing()
elif hasattr(module, 'attribute'):
do_thing()
else:
cant_do_thing()
But on this branch we are doing it like:
try:
import module.attribute
do_thing()
except ImportError:
cant_do_thing()
They may have been some stuff that came over from the earlier version of
this commit (1378c09aa5de) that hasn't been migrated over. I'll get
back to it when I know what direction we are going with the qt wrapper.
Because different approaches require different handling of this (for
example if you just do import QtCore in the wrapper and then refer to
stuff as QtCore.attribute in the code you won't get any ImportErrors)
This has not currently been well tested. We might have to move some of
the conditional checks into qt.py.
I identified these pieces of code by looking for `^+ * pass$` in the
diff of the big rewrite commit.
|
|
Still some manual fixes to make, see #995 and linked PRs.
This was done like:
date ; for mod in core dbus gui network printsupport qml sql webengine webenginecore webenginewidgets webkit webkitwidgets widgets test opengl; do
echo "renaming $mod"
python3 -m libcst.tool codemod rename_pyqt.RenameCommand qutebrowser/ tests --old_name=qutebrowser.qt.$mod.* --new_name=qutebrowser.qt:$mod.* --no-format
done ; date
Where the list of modules was obtained from the current
pyqt5/pqyt6/pyside2 import wrapper machinery. That list of modules to
include can also be obtained using semgrep like so (it might miss out
the QtTest module for some reason):
semgrep --lang=py -e 'from qutebrowser.qt.$SUBMODULE import ($IMPORTEES)' -o findings.json --json qutebrowser scripts/ tests/
and then
with open("findings.json") as f: data=json.load(f)
results = data['results']
submodules = sorted(set(r['extra']['metavars']['$SUBMODULE']['abstract_content'] for r in results))
for m in submodules: print(m
|
|
|
|
(From my LibCST fork e6b990836204b)
The rename codemod currently has a few variables cached on `self` which
are used to transfer information between different visitor methods.
For example one of the nodes being visited inside an import from
statement might cause the import to be skipped in `leave_Import` using
`self.bypass_import`.
Or in the test case below relevant seen imports are cached in
`self.scheduled_removals` so they can be given special attention in
`leave_Module`.
The lifecycles don't work out though as the transforms that codemods run
ass are only initialised once for a whole run. So stuff can leak between
modules. There is probably a better place for them, but this works for
now. I'm not sure if this is reproducable outside of this wildcard
rename support.
Here is an example:
1. Have a folder with two test files
==> context_test/1.py <==
from a.b import c
c.x.foo
==> context_test/2.py <==
from a.b.g import d
d.bar
2. Rename something from the first file
python3 -m libcst.tool codemod rename.RenameCommand context_test/ -j 1 --old_name=a.b.c.* --new_name=a.b:c.* --no-format ; head -n-0 context_test/*
3. Observe a removed import from the first file leaks into the second
==> context_test/1.py <==
from a.b import c
c.x.foo
==> context_test/2.py <==
from a.b.g import d
from a.b import c
d.bar
|
|
When the target rename was something like "a.b.c" and the file happened
to do a simple "import a" it would fail with `CSTValidationError:
Cannot have empty name identifier.` when trying to construct a new
import alias. Because the result of gen_replacement_module() in this
case was an empty string. Which is apparently used for "no replacement
required", which is accurate in this case.
This is a bandaid, the problem is more likely to be that the
`old_name.startswith(import_alias_full_name+'.')` conditional is too
simplistic.
|
|
Fix this https://github.com/Instagram/LibCST/pull/675#issue-1198913564
And supports wildcard renaming. So that we don't have to run it for
every attribute of every PyQt module we import. Just for every PyQt
module we import. (We can change it to hardcode them since this copy is
just in this repo!)
|
|
It works! With lots of printf debugging!
Now that I've gone through and made it work I need to go back and try to
understand it and think about all the cases I haven't tested and might
have broken.
This is my minimal example:
before:
from qutebrowser.qt.QtCore import (QUrl,
QPoint)
from qutebrowser.qt.QtGui import QIcon
foo = QUrl("about:blank")
bar = QPoint()
qux = QIcon()
after:
from qutebrowser.qt import QtCore, QtGui
foo = QtCore.QUrl("about:blank")
bar = QtCore.QPoint()
qux = QtGui.QIcon()
I've already ran into one case that I didn't cover with that:
from qutebrowser.qt.QtCore import Qt
foo = Qt.Key_Enter
|
|
Copies the upstream rename codemod because it has shown pretty good
results but I want to change it to support wildcards. For example:
python -m libcst.tool codemod rename.RenameCommand qutebrowser/browser/browsertab.py --old_name=qutebrowser.qt.QtCore.pyqtSignal --new_name=qutebrowser.qt:QtCore.pyqtSignal --no-format
With the vanilla codemod correctly handles the pyqtSignal import and all
the references but I don't want to have to run it for every Qt type. I
would like to be able to specify names like:
--old_name=qutebrowser.qt.QtCore.* --new_name=qutebrowser.qt:QtCore.*
|
|
This avoids the temptation of creating a Qt.Key() manually, which needs
to be checked for ValueError with PyQt 6.2 due to its handling of unknown enum
values.
This is exactly what happened in RegisterKeyParser, which caused such a
ValueError:
https://github.com/qutebrowser/qutebrowser/issues/7047#issuecomment-1163288560
Closes #7047
|
|
processId() got introduced in Qt 5.3
FIXME: pick to master?
|
|
|
|
See #7278
|
|
|
|
|
|
|
|
|