-
-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Turning Plugin Management into Actual Package Management #179
Comments
First, I should state this is really an AMAZING analysis !!! Probably one of the most thoroughful QEP ever. Could I just ask that you extend a bit the TL;DR section to highlight a bit more about the interaction with pip and conda (mostly from things mentioned in https://github.com/qgist/pluginmanager-qep/blob/master/QEP.md#step-2-adding-support-for-python-package-managers), which is the main motivation for this rework. This will make this QEP even better I'm not sure if given this proposal, QGIS would be able to install new QGIS plugins from pip or conda, or if he would find already installed QGIS plugins installed previously through them ? Tiny detail regarding discovery of QGIS plugins from pip / conda: you mention scanning through the packages to find those with metadata.txt. I was wondering if for example having a dummy "qgis-base-plugin" package that pip/conda QGIS plugin packages would be required to depend on wouldn't make the discovery faster if there's some centralized file somewhere with the chain of dependencies (one advantage I can think of having this base package however would be the abiility to uninstall all packaged QGIS plugins by removing it) But I haven't looked at the implementation details of pip/conda, so perhaps the scan approach and find metadata.txt is the best one. |
Do you want this information simply added from the long version to the TL;DR - or does the actual long version leave any open questions for you?
QGIS would be able to install new QGIS plugins from PyPI (through
Sort of a "reverse dependency lookup" - i.e. "Which Python packages depend on the qgis-base-plugin package?" Both |
yes. As it appears otherwise close to the end of the long version, given reader fatigue, it is a bit hard to extract the high level overview of how QGIS would interact exactly with pip/conda.
Sounds good |
Wow !!! It was a great read !! Thanks for the proposal :-) I also had in mind working on adding pip support to QGIS, but certainly with less ambitions than you. Also from a recent small contribution to the plugin manager, I can only agree that the code really deserves a rewrite. A few suggestions for the QEP : 1/ 2/ I think the alternative/unfavorable sections should mention the somewhat opposite strategy suggested on the ML thread (moving more towards C++ and keeping the python part to a minimum). It's not clear to me what goals of this QEP would be harder to achieve with that other approach ? And a few questions/suggestions on the proposal itself : 1/ About backwards compatibility: there will be a lot of things to take into account for a rewrite from scratch (metadata.txt VS setup.py, qgis plugin repository VS pipy/conda repos, etc.). Handling all this legacy logic will make it hard to have a clean implementation and it may also become confusing for plugin developers (will they have to create both setup.py and metadata.txt ?). 2/ It's not exactly clear to me from reading the QEP what the intention is in terms of repositories. Would QGIS-Django stay the central repository for QGIS plugins (and thus expose a custom python package index, mirroring plugins.xml) ? Or would pypi become the central repo ? I think we want to keep one central repository at all costs (as there's no such thing as multiple central repositories :-) ). Multiple repositories should only be used for enterprise/dev setups, not for distributing plugins to the public. 3/ Would packages be installed in a virtualenv ? Is it doable to have one virtualenv per user profile ? 4/ Maybe C++ plugins could be managed completely independently, so that the new implementation wouldn't have to take care of this. Basically it means the described C++ fallback manager wouldn't be a fallback, but just the regular C++ manager. It could be moved into QGIS settings instead, any maybe even rebranded as "extensions" to avoid confusion with python plugins (I'm not really sure of this, as I never installed/enabled/disabled a C++ plugin, but it seems you can't do much with C++ plugins in the manager anyways, and the move is towards killing them). 5/ Would the new plugin manager be a python plugin itself ? 6/ I'm not sure I like the idea of an alternative installer for Windows. If this works ends up in having QGIS being fully installable via pip or conda, that's a nice bonus, but I wouldn't advertise this as an installation method to the general public, it's already confusing enough now with just two ways to install. Many thanks again for the great work ! I'll be following this with great interest ;-) |
Nice description, thanks! A couple of things which come immediately to mind
This sounds quite costly to do -- would it happen on every startup? We've already got an issue with sloooow QGIS startup speeds caused by all the Python imports happening when Processing is initialiased, and I'd be concerned that this approach may make things much worse 😱 |
Hi, Nice analysis !
I cannot agree more, this part is a total hack and rely on deprecated api. This is one of the most fragile part of the python plugin support in Qgis, and will blow up at some point in the future. Worst, the unloading hack is not able in removing all plugins declarations, especially declarations in other namespaces. So, unloading plugin is merely a false promise since many side effects are potentially left behind. Anyway, I have considered the question since sometime now, and I have never found a satisfactory |
There is no need for this, Python has an extension auto-discovery mecanism using setup.py |
This would be a desirable feature but you'll have to run a Python interpreter for each environment. |
Done - I added a new section to TL;DR. I hope it covers all desired aspects. |
They can, if they want to ship the plugin as a wheel, but the do not have to. It all depends on their desire to have (a) Python package dependencies and (b) binary extensions in the plugin. If (a) or (b) can be answered with a "yes", they will very likely need a
A user can choose on a per-plugin basis - depending on whether or not a certain plugin is available through multiple distribution channels.
Yes, if using
I can add this information, yes. In a nutshell: The pluginmanager will heavily interact with Python plugins, e.g. for import (loading), detailed error handling or introspection, see proof of concept implementation for instance. While the proposal suggests to implement a sub-process layer around
It's doable :) It's just a question of cleanly separating the pieces.
Yep. It really requires some good documentation on plugin-writing. It's already complicated and the documentation has "gaps" and inconsistencies, mildly put. When I wrote my first plugins, I ended up reading QGIS source code (for the first time). As far as
That's an option and it's up to you. You will have to support older versions of QGIS. So adding those features on a repository level will probably make the repository implementation much more complex. It's code is not as bad as the QGIS plugin installer code, but it would certainly require a re-write in a few places. From my perspective, the easier solution is to offer a "second" repository at qgis.org and use software like warehouse for it. warehouse is driving pypi.org. warehouse is not the only open source Python package repository implementation in existence.
QGIS-Django would stay the central repo.
No. pypi.org could be used by plugin authors, but the QGIS pluginmanager could be configured to not use / search it by default. If a user wants to install plugins from pypi.org, it must be added manually as a repository.
Agreed.
That's an idea worth exploring. warehouse (as well as the anaconda cloud) does support queries like this.
Virtual environments are a topic on its own. Exploring related issues and ideas would result in another QEP of similar proportions ;) Bottom line: This proposal assumes that there is a working Python configuration in place, whether system-wide or within a virtual environment. It is assumed that QGIS is started inside this pre-existing configuration / environment. Independently, it is theoretically possible to make QGIS manage virtual environments and connect them to profiles. This would actually allow to cleanup some really wilde manipulations of
I would not kill them or the C++ plugin infrastructure in general (in my personal opinion). It has its legitimate use-cases. I'd also prefer to not manage C++ plugins somewhere else. At least from my perspective, having two places inside QGIS for managing "plugins" only adds confusion.
I have considered this options. It can be done like this, yes, but there is a major problem: The proposed pluginmanager should handle plugin loading. It can not load itself. I also do not want to leave plugin loading to the old QGIS Python infrastructure. Bottom line: Some changes to QGIS core are required either way. I could in theory imagine a scenario where the pluginmanager remains a separate project and can be updated independently of QGIS - while QGIS core looks for it and initializes it if present.
Yes and no. Both current ways have serious limitations. Laying the foundation for a potential third way does not hurt. One day, this third way can proof to be better and replace the two existing distribution methods. Or it does not - who knows. |
Agreed. I am more than happy to change the text and use a better term. Any suggestion?
Well, allow me to use the term "legacy" here ... For the legacy packaging approach, nothing really changes. Those xml-files could still be used. For
O.k., I did not know that people relied on
Makes sense, agreed.
It would simplify things, yes, but it would also sort of limit the C++ plugin infrastructure even further. I think it's worth keeping it around - see my earlier reply to Olivier Dalang.
A task queue, I assume (?). Sure, this can be done. The pluginmanager could prepare "transactions" and then leave their execution to
I have noticed that, yes. My proof of concept actually uses
I came across related discussions and thought about solving it. (a) Python's scandir is really fast. Even in a worst-case scenario, the proposed approach is not as bad as it sounds. The only bottlenecks I can think of are really slow spinning disks and congested network shares - but both of them would blow up the current QGIS infrastructure as well. (b) There is no need to import certain things (which causes the current slowdowns on startup) if you use some of the magic provided by ast and inspect. I would handle actual imports as lazy as possible, which should speed up the QGIS loading times considerably. I have played with the proposed solution. I'd be happy to implement a simple benchmark plugin for tests, which could be used in actual, complex deployments for gaining some useful numbers. How about that? |
Yes, indeed. But this would require a cleanup of the Python thread initialization code in QGIS core. It's a good idea but a little bit beyond the scope of this proposal.
It's an interesting idea but also a technology that is horribly bad documented. My thinking is that looking for |
I understand the point and I agree that setup.py has never been very well documented - it is somewhat a little better since old distutils api is now deprecated - but it is still the reference for packaging python and should not be put aside. Global scanning may have really unwanted side effects as it will scan everything even if not related to qgis. |
You're right, yep.
Agreed. Though, I'd not perform a truly "global" scan. This is how
I have used some "pseudo-environment variables" in this list for simplicity. Anyway, after killing the redundancies in here, I only need to scan the first level of those folders - for folders containing two specific files inside their root, |
In this context, I think that |
@s-m-e I gave this another thought. I very much adhere to the main goal, but find the proposed approach too risky. I particularly fear having multiple repos/backend will end up being very confusing both for users (which backend should I install a plugin from) and plugin developers (so, is it metadata.txt or setup.py, the QGIS plugin repo or Pypi, etc), and even in terms of logic (for example I don't understand the implication of the sentence I think we should drop the idea of having pip/conda installable QGIS plugins as a first step. I don't think we have enough real-word use cases to justify this. If a plugin really provides an API to be used by other plugins, it can most probably be factored out of a QGIS plugin and become a regular python library. And for other cases, it's not clear how changing the package management improves other cross-plugin dependency issues (e.g. nondeterministic loading order). Instead, I suggest to focus on making external libraries installable, which is where this proposal's value lies IMO (besides cleaning up the code base). We'd stick to the good old qgis plugins repo as the one and only repository for QGIS plugin. And then it's just about allowing to control the python environment being used. It's still just one environment, optionally a conda environment, and ideally one per user profile. Going this way is less ambitious, but also less risky. It basically comes down to supporting Maybe I underestimate the use case for pip/conda installable python plugins. If that's the case, I'd love to hear more of real world examples where this would improve cross plugin dependency issues. I'd also like to hear more about what conda packages you're thinking of (as we could start even smaller, without conda, as pip already covers many libraries including stuff like tensorflow, and other notoriously annoying libraries to install with pip on windows such as scipy or numpy are already covered by the OSGeo4w installer). |
Thanks. TL;DR: Given the feedback that I have seen (including your latest reply), I am under the impression that there are a significant number of misconceptions about Python packaging as well as "Python environments" and the implications of this proposal. Without writing too many more words (I just wrote 1.5k words in an attempt to reply to you at the required level of detail), how about organizing a (virtual) session for discussing this proposal? Short "presentation" / summary plus Q&A or similar. It would allow to actually talk through individual aspects one by one. We could then publish / link a full recording and a written (short) summary here. |
@rouault @dmarteau @nyalldawson @olivierdalang Thanks for your feedback. Following up on the above comment, I would like to organize a small online Q&A plus discussion session for actually talking about this proposal. I have created a survey for finding a suitable time sometimes next week (first week of June 2020). All proposed times are Central European Summer Time (CEST). I'd greatly appreciate your feedback. |
My thoughts so far:
Based on the thoughts above, it seems safer and easier to target a single packaging system and only support installation of wheels. Independent from that could be modernization of python plugin support code and python plugin installer - I agree those are not the most shiny pieces of code that we are proud of, and I am one of those responsible for that mess :-) That code survived with relatively few changes since its introduction somewhere around 2007 - we were all Python beginners at that point... |
@wonder-sk said:
Martin is not guilty! It was just a tiny piece of mess I enlarged into the current spaghetti monster... |
For me, the idea of getting the plugins with pip and discover them with an entry point is technically attractive but I agree @wonder-sk and @olivierdalang that probably not a good idea for QGIS desktop, then +1 for the proposition of @olivierdalang. Perhaps it can be a good idea to have this kind of mechanism for QGIS server where we actually don't have any tool to install a plugin. |
Just some brief feedback about the decision of the PSC to not accept this proposal (for now): we all agree that the Python plugin installer situation should be improved, but from the discussion here, we thought that there is no consensus among core devs yet. Once this consensus is reached we can rediscuss supporting this proposal. |
Short summary of thoughts:
More notes about this comment by @wonder-sk
These was where I ended up last time I thought about this. The biggest opportunity of that would be consistent dependencies across all platforms (got qgis 3.10.6 using the downloadable installer made from conda? you'll always have exactly the same gdal version). Also, it will be easier to collaboratively manage packages compared to the current osgeo4w situation.
thanks for the clarification PSC 👍 |
Ouch, yeah... I would NOT want the main QGIS packaging to be dependent on something like conda. Homebrew has just burnt me too much to see that as a good thing! I can only see the horror in this situation as our ltr builds suddenly break mid-cycle because someone completely unaware of qgis has decided to drop the qt WebKit package because it was causing issue with some completely unrelated desktop app..! 😱 While osgeo4w does have its downsides, at least we are in direct control of what happens on it and can make packaging decisions in the best interest of qgis. |
proposal has not been marked as eligible |
I know the conversation here has gone a bit cold, so I just wanted to add a couple of thoughts on this proposal. I did join for the second half of the discussion call that was held and I think my feeling along with others is that this QEP (whilst beautifully written) is a bit overwhelming. There are many concepts to grasp and points of potential contention. I know we need a good roadmap for python in QGIS and there are other things potentially interacting with python like native Qt6 python API instead of SIP that will be coming up on the radar. What I want to suggest is to treat this as a 'meta QEP' and that you break out small components of your plan and implement them in a piecemeal fashion. I think it will be easier to discuss and agree one thing e.g. adding pip or virtualenv etc. and then add that and then moving on to the next thing after that. I guess the concern with my proposal in the last sentence is that the concerns are so intermeshed that it is going to prove difficult to do that, but if you could find a first low hanging fruit that moves us one step forward to python Nirvana that would be great.... |
@timlinux Thanks for your reply.
Yeah, sorry for that. I have been working on a revised version of the QEP, mostly addressing the raised concerns. I did not yet have the time to get it polished for release.
I agree. I am not entirely sure how to break it into smaller pieces because most of the touched components are heavily interwoven. So an overall roadmap which addresses interactions between the touched components is indeed required. However, I do not think that I am in a position to start it.
With all due respect, some of the raised concerns are valid from a pure technical perspective, some are not. It's a wild, intermeshed mix which makes it difficult to address them in a short and concise manner. Talking about "adding" I am not intending to lecture (and/or offend) people - I am merely offering to educate, so we can eventually have a (more) educated discussion about the subject matter. This is what I am proposing as a next step. I am open to debate. I am also be willing to offer a crash course, online, maybe a couple of hours or a day, about the relevant technologies - if there was actual interest. How does this sound?
Let me think of that. There are a few options. |
QEP:
... and ...
How about a unified & tested library for meta data handling for starters? As a by-product, plugin authors could be provided with an offline verification tool for their plugins (prior to uploading them and trouble-shooting them based on feedback from QGIS Django). It's needed either way and probably one of the least controversial aspects of this QEP. |
Has there been any progress and/or discussion of this since summer 2020? Can anything be expected for the near or medium-term future? (Asking because I'm quite unsure how (and when) to best proceed with NixOS/nixpkgs#59842.) |
@das-g As the author of this QEP, I am still interested in pushing this topic but it certainly wont happen near-term. It got a little silent as I got side-tracked and the discussion here was ultimately not going anywhere, but I am soon going revive my efforts in a somewhat different form. |
QGIS Enhancement: Turning Plugin Management into Actual Package Management
Abstract
QGIS Python plugins can not explicitly depend on regular Python packages. Although QGIS Python plugins can depend on other QGIS Python plugins, introduced in QGIS 3.8, this mechanism is far away from mature. Code quality, design and maintainability of the entire current plugin management system within QGIS, based on a detailed analysis of version 3.12, are questionable at best. This document proposes (a) to re-implement the existing plugin management system with all of its features, (b) to clean up the cross-plugin dependency design and (c) to add support for both the
conda
and thepip
Python package managers for managing QGIS Python plugins - effectively adding support for dependencies between QGIS Python plugins and regular Python packages. These proposed changes are fully backward compatible and do not introduce adverse performance characteristics.TL;DR
Although not overly complicated from a pure technical point of view, this QEP is an unusual long one. Certain gaps in QGIS' relationship to the Python ecosystem make QGIS fall far behind its true potential. This document proposes to close the gaps. However, figuring out an actually good, sustainable solution - not just any solution - is not trivial. It requires a thorough analysis of (1) the problem, (2) the current codebase, (3) all possible options forward and (4) potential pitfalls. Unfortunately, the topic of Python modules and packaging is also paved with common misconceptions. This QEP has therefore intentionally been developed in great detail in a separate GitHub repository. The following table of contents provides direct links to the individual chapters of the QEP within the separate repository. Once the discussion ends, a final version of this QEP might replace this "TL;DR" section.
Interaction between traditional QGIS plugins and
conda
/pip
The described approach does not introduce any changes to the QGIS "legacy" Python plugin "package" format. It is therefore perfectly feasible to distribute a QGIS Python plugin in multiple formats, e.g. in the legacy format and as a conda package, while maintaining the entire project in a simple directory tree within a git repository or similar.
Because the support for
conda
andpip
should not replace the existing "legacy" QGIS plugin "package" format, all three distribution paths are supposed to coexist. It is proposed to design the newpluginmanager
module in a modular way, containing one "backend" each forconda
,pip
and the "legacy" QGIS Python plugin "package" format. Each backend is on its own responsible for installing & uninstalling QGIS Python plugins as well as handling their dependencies. Dependencies can intentionally not be handled across multiple backends, which would blow up the complexity of the implementation beyond a manageable point. Thepluginmanager
will only handle direct conflicts between the different backends and prohibit broken installations by exploiting dry-run capabilities of all involved tools. If a plugin is available from multiple backends (and/or in multiple versions), a user will be asked to choose a backend (and a version) for installation.QGIS already supports package repositories. The concept will simply be extended by allowing
conda
andpip
repositories with configuration options specific to those backends. In the case ofconda
, different conda repositories within a QGIS configuration could refer to different conda package channels. In the case ofpip
, different pip repositories could refer to specific package sources.Table of Contents
The text was updated successfully, but these errors were encountered: