altendky / pyqt-tools

Qt tools including PyQt Designer and QML plugins
Other
249 stars 39 forks source link

Decide on a path forward for the project #110

Open CAM-Gerlach opened 1 year ago

CAM-Gerlach commented 1 year ago

Hi @altendky ,

It appears this project remains very popular and useful to users thanks to your work, but it appears to not been maintained in some time. Due to its dependencies being hard-pinned down to specific PyQt versions that don't have pre-built binary wheels available for modern Pythons, users have now become unable to easily build and install it, and in PyQt6's case, given only <= 6.1.0 is supported, are versions not widely supported by current Qt-based software.

The status quo, with mass user confusion and frustration trying and failing to install the package, clearly isn't good for anyone involved, and I might suggest a number of options to deal with it, depending on what you prefer to do as maintainer:

Thanks!

altendky commented 1 year ago

I certainly have neglected this suite of packages. I hate that it has happened but I switched jobs and no longer work with Qt. Combined with this always having been a painful project to maintain... here we are. :[ A couple times I have tried to come back and resurrect it and each time I've run into some annoying boiler plate issues that were not quickly resolved. I still wish I would get back, but the evidence so far doesn't encourage optimism.

If I do, I will probably start with reducing the supported matrix as much as possible to simplify the CI and build needs. The number of jobs spread across four layers of projects (pyqt-tools uses pyqt-plugins uses qt-tools uses qt-applications) is... big. I had been supporting many Python versions and many Qt versions across all platforms. I would expect to drop supporting older Qt versions, maybe just latest Qt5 and Qt6, or maybe even drop Qt5 entirely. Given the size of the qt-applications releases, there was also complexity around properly building new python and platform support for existing releases to avoid re-releasing the same data for already supported platforms and Python versions under a new version.

Note the four layers of this project created to isolate the slow builds of the Qt application package and the PyQt plugins from the pure python Qt tools and PyQt tools layers. The separation also allows for isolation of releases of wrapper features from including duplicates of the big Qt applications files. Note that at one point we were in the top 40 packages on PyPI for disk usage...

https://github.com/altendky/pyqt-tools https://github.com/altendky/pyqt-plugins https://github.com/altendky/qt-tools https://github.com/altendky/qt-applications

If other developers are interested in maintenance, I would have the normal author hesitation to give up control... :| but I do fully support having more folks involved and sharing access to reduce the bus factor primarily around PyPI. I already setup https;//github.com/python-qt-tools for the PyQt stubs projects and the tools projects here could certainly move there as well. I would suggest that potential other maintainers would start with comments here about what they imagine would be helpful, depending on the significance discussion may be appropriate first, and then PRs to implement the idea. I expect that a few PRs from a contributor would make sense before handing out write access to the project, but maybe I'm wrong and you can form an argument for another approach.

You have already proposed a few possible changes here, which is inline with my suggestion in the previous paragraph.

Update the Readme to state the project is no longer maintained, and archived the project

I think a PR describing the state of the project in the readme is a great idea. It could say 'unmaintained', or 'unmaintained with discussions around fixing that situation', or...

Do the above, but direct users to a specific maintained fork and or other options/distribution channels

Is there a maintained fork? I haven't been looking around. :|

Due to its dependencies being hard-pinned down to specific PyQt versions that don't have pre-built binary wheels available for modern Pythons

I think the issue might be less the upstream pinned versions and more the lack of builds of pyqtX-plugins and qtX-applications for more recent versions? Or did the build process get setup well enough that folks are able to build those reasonably themselves.

This doesn't fix the situation, but do note that the PyQt and Qt versions uses can be set when building via environment variables. This is how CI does it.

https://github.com/altendky/pyqt-tools/blob/2583303f213bcb69f5f16716a2563301481d1530/.github/workflows/ci.yml#L131-L133

    env:
      QT_VERSION: ${{ matrix.qt.qt_version }}
      PYQT_VERSION: ${{ matrix.qt.pyqt_version }}

https://github.com/altendky/pyqt-plugins/blob/8138b740346f475181a94729832a6095e0ac1d24/.github/workflows/ci.yml#L180-L182

    env:
      QT_VERSION: ${{ matrix.qt.qt_version }}
      PYQT_VERSION: ${{ matrix.qt.pyqt_version }}

https://github.com/altendky/qt-tools/blob/e81ea193a28a060875bba18b0a2f23c5506e0822/.github/workflows/ci.yml#L275-L276

    env:
      QT_VERSION: ${{ matrix.qt.env }}

https://github.com/altendky/qt-applications/blob/3605008783a71f8ccfd61c32e55fab74108eaad9/.github/workflows/ci.yml#L135-L136

    env:
      QT_VERSION: ${{ matrix.qt.env }}

Though yeah, there's a little more to go with that like the pluginloader.X.Y.Z.patch files in pyqt-plugins. I just apply the existing patch to the new code from the PyQt codebase and create a new clean patch after any needed fixup. But, the env var does drive both the dependencies on other packages in this suite and against PyQt itself.

https://github.com/altendky/pyqt-tools/blob/2583303f213bcb69f5f16716a2563301481d1530/setup.py#L90-L95

Welp, there's a first pass anyways at 1) acknowledging the badness of the present situation, 2) agreeing with your interest in having other folks involved, and 3) laying out some of the reasons, hassles, and mechanisms around supporting this and keeping it updated.

CAM-Gerlach commented 1 year ago

Wow, thanks for such a detailed, thoughtful and comprehensive response! And hope it didn't take up too much of your time.

Just for some context, the reason I brought this up was that we had users asking about it on the Python Discourse, and I'd looked into it a bit further, particularly since I'm one of the maintainers of QtPy. However, unfortunately I am not a user this package myself nor am I actually a Qt expert (nor do I really use it much outside the context of Spyder)—I just help maintain things where I can (and something like this lies pretty far outside the realm of my expertise, just to be clear). The reason I reached out was mostly because I recognized your name from interacting with you previously as a QtPy contributor (and we were eventually able to merge your PR, BTW, I just had to take some time off myself for other reasons and came back to it later), and figured I'd send you a ping on this on behalf of the various users asking.

The number of jobs spread across four layers of projects (pyqt-tools uses pyqt-plugins uses qt-tools uses qt-applications) is... big.

Yeah, it's definitely tough for sure. Even just with QtPy, which itself is pure-Python, it's a lot with 2 major Qt versions (5, 6) x 3 Qt minor versions (5.9, 5.12, 5.15 + 6.2, 6.3, 6.4) x 2 bindings (PyQt, PySide) x 2 Python versions (3.7, 3.11) x 3 platforms (Mac, Linux, Windows). It's still not perfect but I've refactored and simplified our CI scripts and workflows to keep most of the matrix stuff in one place in the declarative config; you're welcome to steal any of that you like in case it is helpful.

If other developers are interested in maintenance, I would have the normal author hesitation to give up control... :| but I do fully support having more folks involved and sharing access to reduce the bus factor primarily around PyPI.

You're probably familiar with it, but especially as its changed a lot lately and gained a lot of new features, GitHub branch protection can really help reduce risk and put your mind more at ease when giving others write access; it's pretty powerful these days and heavily customizable. In fact, on the core Python org, we were able to use to to develop a way to safely give core triagers the missing GitHub-level permissions of the Write role, without actually giving them the ability to push, commit, merge to or otherwise modify the actual cpython, etc. repository (not that this is something you'd want to do here, but just an example). Of course, you need an org to get the most out of it, which is one reason why moving this to one might be a good idea.

I expect that a few PRs from a contributor would make sense before handing out write access to the project

Yup, that definitely seems reasonable to me. However, to my surprise, despite the project having several hundred stars, it doesn't look like you have any here—whereas QtPy only has a few times more and we've had many dozens of community contributors step up to help (including you!), many with multiple complex PRs over a sustained period of time. I figure maybe because QtPy occupies a somewhat different niche in the space, and is generally used directly mostly by the comparatively more experienced FOSS folks, as opposed to individual users, but its still a bit surprising.

You could consider putting out a public call to your community, and maybe also reaching out to other trusted maintainers from the Qt-related Conda-Forge projects, PySide, QtPy, and Qt dev channels. However, ultimately this is really on the shoulders of your user community who benefits from your hard and thankless work here.

Is there a maintained fork? I haven't been looking around. :|

Surprisingly, there doesn't appear to be any fork at all that has had any independent activity on it... :|

I think the issue might be less the upstream pinned versions and more the lack of builds of pyqtX-plugins and qtX-applications for more recent versions?

Yeah, I'd of course defer to your expertise on that; the upstream pinning is only the proximate cause of the immediate (and I presume necessary for stable operation).

Or did the build process get setup well enough that folks are able to build those reasonably themselves.

It seems like a saw some successes browsing the many Stack Overflow threads about this, but I only skimmed them and its unclear how much they had to modify things.

altendky commented 1 year ago

Alrighty, I might start an exploration. Anyone interested could follow along. Plan is one last release covering Qt5. Only latest of each of Qt 5 and 6. Python 3.8+. This is a complete change of approach from trying to help everyone on any version. Just trying to reduce scope and build times so there's at least a little less resistance against maintenance. Not sure about macOS M1/ARM since I remember something about needing another PyPI exception since the universal wheel was even bigger, but I haven't found notes about that yet. I'll start with just version update level stuff. If that goes well then maybe we'll worry about some of the reported issues.

Don't get too excited, this may quickly become nothing more than a refresher on why I didn't finish this effort last time I started. But, any questions from people interested in learning are welcome.

https://github.com/altendky/qt-applications/pull/23 https://github.com/altendky/qt-tools/pull/11 https://github.com/altendky/pyqt-plugins/pull/19 altendky/pyqt-tools#111

altendky commented 1 year ago

Oh yeah, and not having runners for macOS ARM. Though I could check on those services that do or maybe cross build. Both of which introduce additional complexity.

altendky commented 1 year ago

In case anyone has experience with this. Consistently with Qt 6.5 on Windows. Qt 5.15.2 on Windows and other platforms with Qt 6 are fine. Sometimes it's the directory and sometimes a file inside. Maybe running out of disk space and getting a silly message for it?

https://github.com/altendky/qt-applications/actions/runs/4502286775/jobs/7923893654?pr=23#step:9:1459

      ----<==== Execute Copy Actions ====>----
  attempt (1/5): PermissionError: [Errno 13] Permission denied: 'D:\\a\\qt-applications\\qt-applications\\build\\qt_applications-4_deh1y_\\qt\\6.5.0\\msvc2019_64'
  attempt (2/5): PermissionError: [Errno 13] Permission denied: 'D:\\a\\qt-applications\\qt-applications\\build\\qt_applications-4_deh1y_\\qt\\6.5.0\\msvc2019_64'
  attempt (3/5): PermissionError: [Errno 13] Permission denied: 'D:\\a\\qt-applications\\qt-applications\\build\\qt_applications-4_deh1y_\\qt\\6.5.0\\msvc2019_64'
  attempt (4/5): PermissionError: [Errno 13] Permission denied: 'D:\\a\\qt-applications\\qt-applications\\build\\qt_applications-4_deh1y_\\qt\\6.5.0\\msvc2019_64'
  attempt (5/5): PermissionError: [Errno 13] Permission denied: 'D:\\a\\qt-applications\\qt-applications\\build\\qt_applications-4_deh1y_\\qt\\6.5.0\\msvc2019_64'
  error: [Errno 13] Permission denied: 'D:\\a\\qt-applications\\qt-applications\\build\\qt_applications-4_deh1y_\\qt\\6.5.0\\msvc2019_64'
altendky commented 1 year ago

I'm copying a directory. Not sure why only here or only a problem here, but...

altendky commented 1 year ago

So, another useful note is that I would guess that a lot of people would be ok with just the qt-tools layer (which depends on and uses qt-applications). That gets you Designer etc. What it doesn't get is the plugins built in pyqt-plugins. That's fine if you aren't making custom Python widgets that you want to use inside Designer. Or... some QML plugin stuff too. Anyways, this is relevant since it removes the dependence on a specific PyQt version. I mean yeah, you want a vaguely related version of Designer, but it doesn't have to match exactly with the Qt version used by the PyQt you are using.

But hopefully... we get lucky and future maintenance of these projects is a bit easier and it just keeps up.

CAM-Gerlach commented 1 year ago

In case anyone has experience with this. Consistently with Qt 6.5 on Windows. Qt 5.15.2 on Windows and other platforms with Qt 6 are fine. Sometimes it's the directory and sometimes a file inside. Maybe running out of disk space and getting a silly message for it?

Not an expert, but one reason you'll see this is if copyfile is trying to copy a path it expects to be a file, but is actually a directory instead. It tries to open the source directory as a file, but its actually a folder, and fails with this error. Not totally sure why your build infra might be trying to do that, but based on the output it looks like that is what might be happening, as a first guess. If it was out of space, usually you'd see No space left on device or something similar and a different error code (at least, IIRC).

Other reasons for this are Windows' very aggressive and sometimes unpredictable file locking whenever anything holds a handle to a file (or didn't close it properly), or something went wrong with setting the permissions for the file. But it seems the first is the most likely from what I can see...not sure though.

altendky commented 1 year ago

Thanks for the pointers. I'm thinking that the reporting from windeployqt has changed and my parsing is picking up the directory now. For the moment anyways I just added an exclusion of directories from the parsed list. Enough to move forward, something to research and tidy up later when someone has nothing better to do. (ha! :]) Anyways, I got up to pyqt-plugins test failures last night.

altendky commented 1 year ago

Looks like two issues at this point.

On macOS with Python 3.8-3.10 (3.11 passes) there's some library search path issue. https://github.com/altendky/pyqt-plugins/actions/runs/4516468364/jobs/7954837439#step:14:807 qt.core.library: "libpython3.10.dylib" cannot load: Cannot load library libpython3.10.dylib: (dlopen(libpython3.10.dylib, 0x0009): tried: '/Users/runner/work/pyqt-plugins/pyqt-plugins/.tox/py310-qt6/lib/python3.10/site-packages/qt6_applications/Qt/lib/QtCore.framework/Versions/A/../../../libpython3.10.dylib' (no such file), '/Users/runner/work/pyqt-plugins/pyqt-plugins/.tox/py310-qt6/lib/python3.10/site-packages/qt6_applications/Qt/bin/../lib/libpython3.10.dylib' (no such file), 'libpython3.10.dylib' (no such file), '/usr/local/lib/libpython3.10.dylib' (no such file), '/usr/lib/libpython3.10.dylib' (no such file), '/Users/runner/work/pyqt-plugins/pyqt-plugins/libpython3.10.dylib' (no such file))

On Windows 3.11 Qt 5 (not 3.8-3.10 nor Qt 6 on 3.11) there's some goofy thing with the QML paths or something. https://github.com/altendky/pyqt-plugins/actions/runs/4516468364/jobs/7954838476#step:14:109 file:///D:/a/pyqt-plugins/pyqt-plugins/.tox/py311-qt5/Lib/site-packages/pyqt5_plugins/examples/qmldir:-1 plugin cannot be loaded for module "D:.a.pyqt-plugins.pyqt-plugins..py311-qt5.Lib.site-packages.pyqt5_plugins.examples": Module namespace 'examples' does not match import URI 'D:.a.pyqt-plugins.pyqt-plugins..py311-qt5.Lib.site-packages.pyqt5_plugins.examples'

Or, there are at least those two things. :] I haven't looked into them yet.

altendky commented 1 year ago

macOS fixed. I was using LD_LIBRRARY_PATH instead of DYLD_LIBRARY_PATH... I'm not sure how some of these things were working before but... ok.

altendky commented 1 year ago

pluginloader.cpp has changed slightly around this. Though that alone doesn't explain only Python 3.11 having issues. I don't even know the present expected state of PyQt5 around Python 3.11.

PyQt5 5.15.9 https://doc.qt.io/qt-5/qlibraryinfo.html#location

// Register the plugin's types.
void PyQt5QmlPlugin::registerTypes(const char *uri)
{
    // Construct the import path that the engine will have used by default.
    // Unfortunately we won't know about any directories added by qmlscene's -I
    // flag.
    QStringList import_path;

    import_path << QCoreApplication::applicationDirPath();

    const char *env_path = getenv("QML2_IMPORT_PATH");

    if (env_path)
    {
#if defined(Q_OS_WIN)
        QLatin1Char sep(';');
#else
        QLatin1Char sep(':');
#endif

        QStringList env_dirs = QString::fromLatin1(env_path).split(sep, QString::SkipEmptyParts);

        foreach (QString dir_name, env_dirs)
            import_path << QDir(dir_name).canonicalPath();
    }

    import_path << QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath);

PyQt6 6.4.2 https://doc.qt.io/qt-6/qlibraryinfo.html#path

// Register the plugin's types.
void PyQt6QmlPlugin::registerTypes(const char *uri)
{

<snip>

        QStringList env_dirs = QString::fromLatin1(env_path).split(sep, Qt::SkipEmptyParts);

<snip>

    import_path << QLibraryInfo::path(QLibraryInfo::Qml2ImportsPath);
CAM-Gerlach commented 1 year ago

Though that alone doesn't explain only Python 3.11 having issues. I don't even know the present expected state of PyQt5 around Python 3.11.

FWIW, at least in our QtPy CI matrix, PyQt5 5.15, PySide2 5.15 (conda only), PyQt6 6.4 and PySide6 6.4 all work on Python 3.11, while the PySide2 5.15 PyPI wheel isn't built for it (the PyQt5 wheel is built with the CPython stable ABI), and PyQt5/PySide2 5.12 and PySide6 <= 6.2-6.3, and I believe PyQt6 <= 6.2, are confirmed not to work.

altendky commented 1 year ago

Thanks for sharing that reference. I posted to the maillist just in case I get lucky and someone has time and knowledge to help out. https://www.riverbankcomputing.com/pipermail/pyqt/2023-March/045225.html

For the sake of not getting stuck, I'll just xfail the failing QML tests for PyQt5 on Windows for Python 3.11. If we resolve this even after release, it is easy enough to push another release at this level. qt-applications is the one I don't want to roll lots of releases of given the size and the three layers above it that need tested against it.

altendky commented 1 year ago

One of the reasons to not move this out of my user org is that I have a pro account and so have double the concurrency (last I checked) of orgs. I could make the python-qt-tools org pro, but that would cost a lost more since that's per user cost in the org. Not saying it can't be moved, just noting one of the factors. With the smaller matrix right now it's not such a big deal. Though with things working I might expand it a bit again if more versions also work.

altendky commented 1 year ago

One of the issues around (not) pinning is that we have both the underlying Qt/PyQt library version and the 'tools' version. Or, well, three if you take Qt and PyQt separately. Or four if you count PyQtX-QtX separately... Anyways, how would I describe a dependency on pyqt-plugins for use with PyQt6 6.3.1 and Qt 6.3.2 that is at least version 2.2 of all these wrapper projects here? pyqt6-plugins==6.3.1.2.2 would be a way to describe it, but if we do >=6.3 then we can get, for example 6.3.1.2.1 that isn't what we want and >=6.3.1.2.2 still allows 6.4.2.2.1 (a made up future possibility) Given the single sequence of version segments, you run into a problem controlling the two aspects.

Anyone have any commentary or thoughts about handling this better?

One option is to just leave the regular dependencies unpinned, allowing people to get entirely the wrong combinations if they want, and then provide an extra so if you ask for pyqt6-tools[pinned] then it will give you the existing super strict constraints. That offers the flexibility, but is kind of backwards since it leaves people by default getting a mess of inconsistent versions if they do pyqt6-tools==6.3.1.2.2 to go with their PyQt 6.3.1 install.

CAM-Gerlach commented 1 year ago

Hmm, this is indeed a tricky situation. After some followup investigation, seems the fundamental issue is that the source distribution of the package can (at least theoretically) be built with a range of supported versions of PyQt, and don't necessarily need the PyQt version pinned, while the binary wheels are necessarily built with a specific Qt/PyQt version and thus are specific to that version, and (I presume) must be used with PyQt also pinned to that specific version. See this active Packaging Discourse thread for discussion of this specific use case.

As a further complicating factor, as a result of this, two separately-varying version sequences are encoded into the package version, which then results in the above situation where it comes very complicated to impose separate constraints on both the actual pyqt-tools version in the source tree (and applicable to the sdist), and the underlying Qt/binding version it is actually built with (in the wheels).

It's a complex issue without an obvious an easy solution, for sure, with two separate though related parts: handling the differing dependency specs between the sdists and wheels, and handling the two different versions between your wrapper package and the underlying bindings.

For the dependency specs, since you're already accepting the cost of using a dynamic setup.py instead of a declarative, standardized pyproject.toml for your packaging metadata and configuration, you could just dynamically set the either the compatible version bounds or the exact pin of the PyQt dependency on whether a wheel or a sdist is being built. This means that pip will try to install the exact versions with the wheel by default, as it does now, but users can request installation of the sdist to build against a wider range of compatible PyQt versions, instead of having to do everything manually.

For the versions, ultimately you probably want to decouple the two distinct versions (PyQt and your wrappers) in some form. Probably the easiest immediate solution is to only encode the version of your bindings in the public version identifier. This is the easiest immediate solution to implement, and allows flexibly or precisely specifying the compatible desired "tools" version separately from the PyQt version, as either you or the user specify them separately for PyQt and the -tools, etc. packages.

There are no real downsides to this with the sdist, though it means for the wheels, each tools release will only be available against one PyQt version at a time per tools version; you could build against a newer one for the same tools version by releasing a new .post release, though only the latest .post release will be considered by the pip solver (AFAIK) unless a user explicitly specifies a particular post release.

To avoid the latter issue, you could potentially split out the binary requirement to a separate package that only gets installed with the wheels, but I'm not sure there's an easy way to do that—I'd have to think about it more.

I recommend asking about this further in the Packaging Discourse category to get some expert feedback and possible better ideas.

altendky commented 1 year ago

Hum, so I don't think I'm actually going to take on the version scheme change this time. I don't want to hazard getting stuck and not releasing. Also, I don't think that another release with the existing scheme is likely to make the situation much worse. The biggest opportunity is that there exists no release for the higher 6 versions. But, I would probably Oh well.

I don't think I've thought about this as much as you in the general context, seemingly, but I think that publishing an sdist with the present versioning scheme would probably be more confusing than helpful. You ~should be able to~ can almost do stuff like (for theoretical future versions that have not been published) PYQT_VERSION=6.5.0 QT_VERSION=6.5.2 venv/bin/pip install git+https://github.com/altendky/qt-applications@v2.2 to locally build the present latest release of qt-applications. Then likewise do the same for each next layer. Not beautiful, but a path none the less. Almost. The big hook here is that pyqt-plugins expects a specific patch file for the PyQt version requested. That could be adjusted to take a guess from the existing options in hopes that it is close enough to apply. I do almost this CI when developing except that I additionally leverage this bit of dynamic code.

https://github.com/altendky/pyqt-tools/blob/2583303f213bcb69f5f16716a2563301481d1530/setup.py#L34-L46

And yes, this dynamic code in setup.py is... a thing. It used to be that these projects didn't follow any Python patterns to build so the sdist didn't make a lot of sense. The build process installed various things globally and in general was a mess and made a mess. When I updated to the build_py extensions and the PEP517 local backends, users building became a lot more plausible. Also, the project got closer to being 'compliant'. But yes, there are still plenty of steps to take to improve this situation.

As to separating out the binary packages, that was part of the point of the four layers. The two binary layers are pyqt-plugins and qt-applications. The pyqt-tools and qt-tools are the pure python wrappers around those. The primary use case I had imagined in terms of version constraints was that a user was working with PyQt 5.14.2 and wanted the latest tools that matched. Presently they can pyqt-tools~=5.14.2.0 to get that. That's why I made the PyQt version 'primary'. But... Back to the split binary packages, maybe you meant a different thing when you said "split out the binary requirement to a separate package"?

altendky commented 1 year ago

And... releases are out. Now to see if they work.

Thanks for your interest, time, and insights around this @CAM-Gerlach. Let's hope I can keep the workload lower and still more responsive in the future. And maybe a user will jump in and give the next needed update a try.

FYI, I'll be closing out most of the install related issues with the note below. I also entered several new tickets about issues I ignored or noticed in the past few days.

Hey all, this is a common note I'm adding to several issues.

I apologize for the hassle you have all dealt with around this project. I don't work with Qt anymore and every time I've come back to this I have run into various problems trying to get it going again. This time I made it through the five days of work to get the release out (fingers crossed that it actually works). It would be great to get some community involvement around updating and debugging whatever issues come up. Maybe the next Python, Qt, or PyQt release will provide an opportunity for someone to offer that. Maybe I'll find time to continue cleaning this up so it's a bit more maintainable. If interested, there's been some discussion about the project at https://github.com/altendky/pyqt-tools/issues/110.

In an effort to make it easier to monitor issues around the latest release I am closing this issue. Discussion can continue if still applicable, but I want to make it easier to move forward. If there are issues with the new releases, please open new issues.

Things to be aware of that may ease some cases:

  • If you just want the Qt applications, you can directly use qt-tools which provides helpers around qt-applications. This skips the PyQt specific layers. You won't have access to the plugins, such as for showing custom PyQt Designer widget plugins in Designer, but you also won't have the hassle of needing a version matching your PyQt version. At least not quite as closely.
  • If I once again fail to maintain this, or you just want a specific version I didn't include, you can set environment variables to select the versions when building. PYQT_VERSION=6.5.0 QT_VERSION=6.5.2 venv/bin/pip install git+https://github.com/altendky/qt-applications@v2.3 for example would try to build and install qt-applications v2.3 including (a theoretical future) PyQt version 6.5.0 and Qt 6.5.2. I'm sure there are corners around this, but it would be relevant.