-
Notifications
You must be signed in to change notification settings - Fork 27
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
Add PluginManifest.properties for cross-plugin configuration #149
Conversation
This prevents collision with Talley's configuration :)
for more information, see https://pre-commit.ci
Codecov Report
@@ Coverage Diff @@
## main #149 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 26 26
Lines 1717 1728 +11
=========================================
+ Hits 1717 1728 +11
Continue to review full report at Codecov.
|
just for the sake of completeness, can you show an concrete plugin manifest using |
Sure, my plan was to append napari-imagej's name: napari-imagej
display_name: napari-imagej
properties:
jvm_classpath:
- 'io.scif:scifio:0.43.1'
contributions:
commands:
- id: napari-imagej.func
python_name: napari_imagej.widget:ImageJWidget
title: Run ImageJ2 commands
widgets:
- command: napari-imagej.func
display_name: ImageJ2 then, in my plugin, I can call: import logging
import imagej
from scyjava import config, jimport
from napari.plugins import plugin_manager
# -- LOGGER CONFIG -- #
_logger = logging.getLogger(__name__)
_logger.setLevel(logging.DEBUG) # TEMP
# -- IMAGEJ CONFIG -- #
# TEMP: Avoid issues caused by https://github.com/imagej/pyimagej/issues/160
config.add_repositories(
{"scijava.public": "https://maven.scijava.org/content/groups/public"}
)
config.add_option(f"-Dimagej.dir={os.getcwd()}") # TEMP
for endpoint in plugin_manager.properties("jvm_classpath"):
config.endpoints.append(endpoint)
_logger.debug("Completed JVM Configuration") Any other plugin that uses the JVM would then initialize the JVM in a similar way, using for endpoint in plugin_manager.properties("jvm_classpath"):
config.endpoints.append(endpoint) just like I did above. In this way, all plugins would initialize the JVM with the JARs needed by all files. Of course, scyjava would then be responsible for ensuring that the JAR list is valid. Is this what you were looking for @tlambert03? |
yeah, thanks. need to have a think on it. busy this week. will have a look next week and curious to hear @Carreau's thoughts too |
Sure thing. It's a significant addition so I think it warrants serious review/consideration. Happy to work with you guys to revise. |
I don't think we need it because we have a default (empty) map
for more information, see https://pre-commit.ci
Bumping for visibility |
Hi @gselzer, thanks for your patience, and thanks so much for taking a crack at this PR. We chatted about this at the plugin dev meeting yesterday. In short, I'm not sure that a new "properties" field is the best approach here. The biggest issue here was the open-endedness of Because this case of a shared global singleton is unlikely to have too many other similar cases in the near future, we're inclined to just provide you with a for endpoint in plugin_manager.properties("jvm_classpath"):
config.endpoints.append(endpoint) still seems to have the issue of "whoever gets to the JVM first wins", (though it at least provides a place for everyone to share their needs). As a side question, why can't we use If having a |
Fair point. I figured that its open-endedness was a benefit, but yes, you are right that maybe the use cases do not warrant the scope of this solution.
That...is a fantastic question. Maybe I misunderstood something @ctrueden said about adding classes after JVM startup. The following works on my machine, after downloading a standalone JAR like parsington: (scyjava) : gselzer@gselzer-OptiPlex-5090 ~/code/scijava/scyjava (master) [scyjava] »
python # 0 {2022-04-21 9:11:25}
Python 3.10.4 | packaged by conda-forge | (main, Mar 24 2022, 17:39:04) [GCC 10.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import scyjava
>>> scyjava.start_jvm()
>>> scyjava.config.add_classpath('/home/gselzer/Downloads/parsington-3.0.0.jar')
>>> scyjava.jimport('org.scijava.parsington.eval.Evaluator')
<java class 'org.scijava.parsington.eval.Evaluator'>
>>>
Note that I think the problem is that I am starting to wonder why we need napari's help on this myself 😆 @ctrueden why can't we just add more options (namely endpoint support/dependency resolution) to |
Dynamic classpath extension is something that @hanslovsky and I spent some time trying to do via custom class loaders back in the pyjnius days, but we weren't able to get it working due to a bug/limitation in pyjnius. Since JPype 1.2.0 (December 2020-11-29), the
But ImageJ has its own custom class loader for its plugins, and I am not sure how these two things would interact in different scenarios (the two major ones being a local ImageJ2/Fiji installation, and a jgo-based one with Maven coordinates). If we determine that JPype's
So TL;DR using custom class loaders solves some problems and introduces others. The Fiji strategy until now has been to eschew custom class loaders in favor of creating a sane unified environment accessible from the system class loader whenever possible. Doing it differently for pyimagej et al. would be a major strategic change, although not unprecedented for us. |
This PR introduces the contribution point
properties
, designed to allow plugins to contribute to global state before any individual plugin starts up.This work is motivated by the napari-imagej plugin, which runs the JVM under the hood. This plugin depends on a set of JARs to run; if another plugin were to start the JVM before napari-imagej would, napari-imagej would not be able to add its JARs to the classpath and would thus be unrunnable.
By declaring all JARs as properties in this new contribution point, JVM-using plugins can install all jars needed by all discoverable plugins, allowing all to run.
@tlambert03 pointed out that there is already a
configuration
contribution point, however it is my impression thatconfiguration
andproperties
are designed to do different things:configuration
is designed to solve user-selected plugin-specific configuration behavior at plugin startup. In other words, the value solved byconfiguration
is not known at napari startup.properties
is designed to solve developer-selected global configuration behavior during napari startup. In other words, the value solved byproperties
is known at napari startup.If I am wrong on this, I am happy to work towards a solution that combines the two.
I'd love to hear all opinions from @tlambert03 and the napari team more broadly. As long as we can solve the problem of #136 without becoming a burden on the user, I am happy to make any changes.
This PR closes #136.