Following the discussion about investigating a plugin architecture for modflowapi packages I've done a little bit of research into how python plugins work and created a simple example to dynamically search for and load plugins in an existing python package. In essence, this would allow user developed modflowapi packages to be installed seperately, but be discoverable and useable by flopy.
The first step is to create a standardized entry point naming convention for the existing python package (i.e. flopy). This could be something like flopy.plugin or flopy.package.plugin. The entry point name will be used to search the python installations to see if they include this "entry point".
After that we can create a module, such as plugins.py in this example, that programatically search entry points and then import them into the existing software package when plugins.py is imported. For this code example I use test_plugins.plugin for the entry point:
import sys
if sys.version_info < (3, 10):
from importlib_metadata import entry_points
else:
from importlib.metadata import entry_points
this_module = sys.modules[__name__]
eps = entry_points(group="test_plugins.plugin")
installed_plugins = {}
for ep in eps:
_x = ep.load()
setattr(this_module, ep.name, _x())
installed_plugins[ep.name] = _x()
Once this script exists, a plugin developer can create code as a seperate installable python package for distribution, wrap it with a simple function, add an [options.entry_points] record to their setup.cfg file, and specify that it is a test_plugins.plugin entry point. Example plugin code and setup.cfg entry.
class FancyHelloWord():
def __init__(self):
self.str = "@@!! Hello World !!@@"
def display(self):
print(self.str)
def plugin():
return FancyHelloWord
Hey @jlarsen-usgs, this looks very promising to me. Maybe the next step is for you and @spaulins-usgs to start exploring an implementation of the AG package as a flopy plugin?
Hello,
Following the discussion about investigating a plugin architecture for modflowapi packages I've done a little bit of research into how python plugins work and created a simple example to dynamically search for and load plugins in an existing python package. In essence, this would allow user developed modflowapi packages to be installed seperately, but be discoverable and useable by
flopy
.The first step is to create a standardized entry point naming convention for the existing python package (i.e.
flopy
). This could be something likeflopy.plugin
orflopy.package.plugin
. The entry point name will be used to search the python installations to see if they include this "entry point".After that we can create a module, such as
plugins.py
in this example, that programatically search entry points and then import them into the existing software package whenplugins.py
is imported. For this code example I usetest_plugins.plugin
for the entry point:Once this script exists, a plugin developer can create code as a seperate installable python package for distribution, wrap it with a simple function, add an
[options.entry_points]
record to their setup.cfg file, and specify that it is atest_plugins.plugin
entry point. Example plugin code and setup.cfg entry.Finally, the user will be able to call the new plugin features from the
plugins.py
module in the existing software. Example:I put together a full working example with instructions that can be found at https://github.com/jlarsen-usgs/plugin_example.git
Any thoughts or ideas on this @langevin-usgs @jdhughes-usgs @spaulins-usgs? Feel free to mention others that would be interested in this discussion.