Have simple to install plugins that can provide multiple services in one plugin.
It should be possible to add feature sets by dropping in EGG files; a single EGG should be able to provide all types of plugins, and additional pages for the underlay as well (help text, templates, etc.).
This will make it easier to install or remove macro-action plugins or themes. Lot of plugins need a combination of macro and action. Some of these plugins are marketed in separate markets, which make it even harder to find what you need. Even if you package all the stuff together, the user has to copy multiple files to install or remove a feature. Themes have similar problem when you have to copy the theme module into your plugin directory, and the theme htdocs into prefix/share/moin/htdocs.
An alternative can be some kind of package manager that install and remove files in multiple locations from one plugin package, like PackageInstaller, or simpler tool that works like distutils.
Problems
Services are hidden
The provided services are hidden in the EGG, you lose the simple way to add or remove features from the system. In the current system you can look into the plugin dir and you know what is installed, because service is plugin is a file.
This may be a user interface problem. From the user point of view, he has one plugin called Foo, from moin point of view, it has plugins.foo.Foo macro, plugins.foo.foo action and HelpOnFoo page.
Plugin conflicts
Two plugin can try to provide a service with the same name. Which one will win? How the user can know about the conflict?
Resolution when two plugins offer services with the same name could be performed by using the plugin that appears first in sys.path, and a warning should be logged.
- Those warnings are evil, they fill your logs behind your back, and the real problem may be hidden for long time.
Another possibility would be to completely reject the plugins from an EGG if any of the plugins conflicts with an already loaded plugin; there's various policy issues to consider here, I suspect.
- This is much better, specially if you can disable a service in a plugin. The metadata-driven approach below would support this. The plugin would provide exactly what the metadata describes; disable a specific service using an alternate metadata configuration for that plugin that simply doesn't list that service.
It might be a good idea for EGG-based plugins to provide a metadata file that describes what is exported, making it easier for an installer to see what each provides. Since each service is implemented as a single callable recognized by a magic name in a module, the metadata file could easily be used to make things simpler for a Python developer, allowing avoidance of the currently enforced module structure as well. For example, the metadata could be a simple mapping of names to callables for each type of service:
<macros> SomethingSimple mypkg.moin.SomethingSimple SomethingMystical mypkg.moin.SomethingMystical </macros> <themes> MagicalWorld mypkg.moin.MagicalWorldTheme </themes>
This would also allow the structure of the Python code for a plugin to be completely independent of the MoinMoin structure. For example, a single module or package could be used to provide a set of related services, and additional support modules could be kept without them appearing to be potential sources for services.
Separating plugin metadata from the implementation like this would allow conflict resolution policy to be handled more sanely, especially since we'd end up with recognizable sets of services, instead of having services that implicitly rely on each other. In other words, we could choose to either use or ignore an entire plugin, and not decide separately for each service.
It may be that an installation could provide alternate metadata files alongside the EGG files to allow the installation to hide particular services (by removing them from the metadata) or renaming them. That seems like a secondary aspect, not likely to be needed right away.
Something like this could affect the solution for the next issue ("CGI related problems") as well.
CGI related problems
The current system can do a simple directory listing to detect the installed services or pages, and you have to do this for any request. Loading all plugins for each request just to see what is installed might be too expensive.
(I've not dug into this aspect of the MoinMoin code yet, but this gives me the impression that MoinMoin might not want the plugin packages to be multi-placeful (have __path__ contain multiple paths); I need to look into this. -- FredDrake)
Solution
This will probably require a disk cache that have to be invalidated each time you add or remove a plugin, for example, have all plugins in the same directory and check the mtime of the directory. MoinMoin would need to be able to store the cache outside the plugin directories themselves, since an installation may well want to configure the plugin directories to be read-only by the process running MoinMoin.
Different kinds of files
Plugin may have different kinds of files: code, images, css, wiki pages. Some are served directly by the web server, and need to be in a special directory, and some are accessed by other code.
- How can we make sure that the web server will have access only to certain files in a plugin?
Another possibility would be to have MoinMoin serve the static content from EGG plugins; some (configurable) page name could be reserved for this, so if the wiki is at /mywiki/, the EGG-based resources could be served from /mywiki/resources/eggname/resourcepath, where eggname is the name of the EGG without the version information or .egg extension, and resourcepath is the path to the resource within the EGG. (We'd want to drop the version information from the eggname to avoid exposing incidental changes in the URL-space.)
- This is not static serving any more. Opening a file with moin long running process and serving the data is about 100 times slower then static serving using Apache. With CGI the difference can be much higher. On the other hand static files are usually cached by clients for long periods, so the cost might not be that big. Correct, of course. For heavily trafficed sites, real static serving is likely still important, especially for theme plugins.
Perhaps the right way to do this isn't to hide the installation structure so much, though the version numbers from EGGs should still be hidden. The current approach has a single static collection of documents served at /wiki/ and provided with MoinMoin. This could change so that the current static tree is still served as /wiki/, and farm-specific and wiki-specific trees are also exposed. There would need to be some install/uninstall tool for plugins (whether EGG or something else) that adds the static files from the plugin to an appropriate tree, and generated pages would need to use the right URL to those pages. That could be accomplished with a helper function: resourceUrl(pluginName, relativePath), returning a relative URL that should be used in the page (usually something like /wiki/modern/style.css for MoinMoin-provided resources, /wikifarm/sometheme/style.css for plugins installed for a farm, and /mywikidata/mytheme/style.css for a wiki-specific plugin).
Discussion
I really like this feature request! -- ThiloPfennig 2006-12-07 00:02:43 Maybe something for 1.7 release?