Hi all, sorry for my lengthy email last week - but this issue is still spinning in my head and blocking progress in my test-bed plugin installer re-implementation.
PR#9619 actually has two interesting comments ... https://github.com/qgis/QGIS/pull/9619#issuecomment-476499538 https://github.com/qgis/QGIS/pull/9619#issuecomment-476550817 ... in terms of use-cases for inter-plugin dependencies, their current limitations and their (potential) correct use. The second comment is interesting in terms of how one plugin should correctly expose a "stable" API to other plugins: By injecting code into `qgis.plugins` *at runtime* and exposing something like for instance `qgis.plugins.QuickWkt`. The idea is interesting but it essentially suffers from what I described: The absolutely non-deterministic loading sequence. So it is not an actual, reliable solution at the moment - unless the plugin requiring this API does some serious checking prior to accessing its desired API and calls into the mostly undocumented API of `qgis.utils` as a fallback solution. How should a plugin author handle this at the moment (with QGIS 3.8 to 3.12)? Best regards, Sebastian Am 23.04.20 um 20:46 schrieb Sebastian M. Ernst: > Hi all, > > working my way through the current plugin (dependency) installer > mechanism, I have a few questions. > > Bottom line: What kind of assumptions can a plugin safely make about its > dependencies and their initialization (from QGIS' perspective)? > > Imagine two plugins: "PluginA" and "PluginB". PluginA depends on > PluginB, i.e. if a user was installing PluginA, current QGIS would ask > him to install PluginB as well. > > Now the plugin system in QGIS does three things actually: > > - Installing and uninstalling plugins > - Loading (i.e. importing, in Python terms) and unloading plugins > - Starting and stopping (`initGui` + friends and `unload`) > > In comparison, typical package managers usually do not care about the > loading and starting part. This is because usually a package installer > does run outside of the scope of the stuff that is using the packages. > > So if a user was installing PluginA in QGIS, the following sequence > would be triggered: > > - Install PluginA > - Find dependencies of PluginA: PluginB > - Install PluginB > - Load PluginB > - Start PluginB > - Load PluginA > - Start PluginA > > PluginB would be loaded (imported) and started before PluginA. Depending > on the use-case, this can make a lot of sense. Unfortunately, if a user > was restarting QGIS, the loading and starting sequence would depend on > (as it appears) the order of plugin folders on the filesystem which can > be more or less "random". So here, PluginA can not rely on PluginB to > have been loaded and/or started in advance at the moment. > > This leads to many potential problems, some of which were discussed here > (Nyall's comment being the most interesting one for me): > > https://github.com/qgis/QGIS-Enhancement-Proposals/issues/132#issuecomment-460136324 > > So the question now is: How is PluginA supposed to interact with PluginB? > > Thanks to the way `sys.path` is configured in QGIS, PluginA could easily > run `import PluginB` and it would actually work. QGIS has a modified > `builtins.__import__` method which would even track this import. This > would sort of allow to treat PluginB as a "normal" Python package and be > equivalent to `qgis.utils.loadPlugin("PliginB")`, for better or for worse. > > A possible alternative is that PluginA requires PluginB to initialize > itself through `classFactory` (or `serverClassFactory`). PluginA's best > (and probably safest) option then would be to run > `qgis.utils.startPlugin("PluginB")` (or `startProcessingPlugin` / > `startServerPlugin`). PluginA could now basically access the instance of > PluginB's class through `qgis.utils.plugins["PluginB"]` (or > `server_plugins`). > > All of the above is fragile in many ways and - as far as I can tell - > more or less undocumented. How much of the described API in `qgis.utils` > is supposed to be available to "the public", i.e. to plugins? > > As far as I can see, only one plugin (for QGIS 3.8 or later) in the > plugin repository actually uses inter-plugin dependencies (properly), so > there are not many examples of how things should look like. QEP 132 also > is not really detailed about the exact behavior and assumptions a > plugin's author can make. Fortunately, the current lack of "downstream" > users and the lack of "established" documentation opens the option to > "fix" the system without breaking too much stuff if desired. > > Final questions: > > - How is the *current* plugin-dependency system supposed to be used / > not supposed to be used from your perspective? > - How do you envision an actual plugin-dependency system to work (with > respect to interactions between plugins)? > - Does it make sense to care about plugin dependencies when QGIS is > loading and starting plugins (so dependencies are loaded & started first)? > > Best regards, > Sebastian > _______________________________________________ > QGIS-Developer mailing list > [email protected] > List info: https://lists.osgeo.org/mailman/listinfo/qgis-developer > Unsubscribe: https://lists.osgeo.org/mailman/listinfo/qgis-developer > _______________________________________________ QGIS-Developer mailing list [email protected] List info: https://lists.osgeo.org/mailman/listinfo/qgis-developer Unsubscribe: https://lists.osgeo.org/mailman/listinfo/qgis-developer
