# Modules Almost all of the front end's functionality is contained in small, separate modules that reside in the directory tree beneath `/modules/installed`. Some are installed by default, some are required for operation, and some are entirely optional. ## Installing and Loading Modules Eventually, the goal is for module to be separate Debian package so installation is as simple as `aptitude install freedombox-foo`. As an intermediate step, we'll start scripting module installation. But until then, we can install them manually. Modules are installed by copying them into the tree beneath the `/modules/installed` directory. They are activated by linking their .py files into the modules directory. (Freedom Box will not load modules unless they are symlinks.) If the module provides other resources, they can be linked from wherever in the working tree they need to be. So if a module provides a template, that template can be linked from `/templates`. Modules can be organized into subdirectories beneath the installed directory. As an initial matter, I've made separate directories for each major tab. Modules that extend the functionality of the Freedom Box code base (as opposed to being user-visible interface modules under specific major tabs) go in `modules/installed/lib`. This convention can be adjusted or ignored as needed. In fact, modules can be installed anywhere in the file system as long as the symlinks are in `/modules`. The names of the symlinks in the `modules` directory can be arbitrary, and if a name is already taken, (e.g. if `router/info.py` and `apps/info.p`y both exist), append a counter to the end (e.g. link `info.py` to `router/info.py` and `info1.py` to `apps/info.py`). If a module cannot be imported for any reason (e.g. it's a dead symlink), freedombox.py will log an error but will otherwise just keep going. TODO: automatically prune dead links to clear out old module installs. This is something the install scripts should do. ## Pluggable Module Structure Plugin interfaces are contained in `plugin_mount.py`. Each interface is a metaclass. Classes that implement a given interface should inherit the metaclass and then provide the indicated properties. New metaclasses can be created to make new classes of plugins. Any place that might be affected by arbitrary addition of modules should have its own metaclass. ### FromPlugin Each form displayed in the interface should inherit from FormPlugin. This will allow the system to display multiple forms on the page in the correct order. Forms will likely also want to inherit from PagePlugin because after the user clicks submit, the plugin usually displays a responsive message or an error (along with the form to fill out again). ## Coding Practices for Modules All the [coding practices for hacking on the front end](#hacking_code_practices) also apply to modules. In addition, I try to stick to the other practices listed in this section. * Every module should `from gettext import gettext as _` and wrap displayed strings with _().