16 | | * ''tbw'' |
| 16 | A ''template plugin'' can be a Python module or a Python package. The name of the module/package becomes the plugin name. |
| 17 | |
| 18 | It must expose a function {{{setup()}}}: |
| 19 | - {{{setup()}}} takes no arguments, and returns nothing |
| 20 | - {{{setup()}}} will be called during ''every'' request cycle (so minimize the load!) |
| 21 | - {{{setup()}}} will be called immediately before the controller is executed |
| 22 | |
| 23 | {{{ |
| 24 | # Example plugin |
| 25 | |
| 26 | __version__ = "0.0.0" |
| 27 | |
| 28 | def setup(): |
| 29 | |
| 30 | # The plugin can access and alter deployment settings |
| 31 | settings = current.deployment_settings |
| 32 | }}} |
| 33 | |
| 34 | The plugin module/package can additionally define a {{{__version__}}} string, which becomes accessible via current.session: |
| 35 | |
| 36 | {{{ |
| 37 | # The session holds the registry of current plugins |
| 38 | registry = current.session.s3.plugins |
| 39 | |
| 40 | # The registry is a dict of tuples {plugin_name: (version, status)} |
| 41 | plugin_info = registry.get(plugin_name) |
| 42 | |
| 43 | # - version is the __version__ string defined by the plugin or "unknown" |
| 44 | # - status is True if the plugin's setup function was successful, otherwise False |
| 45 | if plugin_info: |
| 46 | version, status = plugin_info |
| 47 | else: |
| 48 | # Plugin has not been loaded yet |
| 49 | version, status = None, None |
| 50 | }}} |
| 51 | |
| 52 | '''Notes:''' |
| 53 | |
| 54 | - plugins '''should''' raise an exception in case of unrecoverable errors during setup, in order to deactivate themselves |
| 55 | - plugins are responsible to log all their errors themselves, using {{{current.log}}} |
| 56 | - plugins '''must not''' redirect (HTTP 30x) unconditionally (that would give an indefinite redirection loop) |
| 57 | - there is no particular order in which plugins are run - plugins with conflicts should auto-detect each other (via registry), log the problem, and then raise an exception during setup in order to deactivate themselves |
| 58 | - a plugin with {{{status=False}}} will not automatically be reloaded. Reloading can be enforced by restarting the server thread, by calling {{{PluginLoader.load(plugin_name, force=True)}}}, or by setting the registry entry to None: |
| 59 | |
| 60 | {{{ |
| 61 | # Enforce immediate reload of a plugin |
| 62 | from plugins import PluginLoader |
| 63 | PluginLoader.load(plugin_name, force=True) |
| 64 | |
| 65 | # Setting the registry entry to None triggers a reload in the next request cycle |
| 66 | registry = current.session.s3.plugins |
| 67 | registry[plugin_name] = None |
| 68 | }}} |
| 69 | |
| 70 | It is also possible to reload all plugins: |
| 71 | |
| 72 | {{{ |
| 73 | # Re-run plugin detection and run all setups: |
| 74 | from plugins import PluginLoader |
| 75 | PluginLoader.setup_all(reload_all=True) |
| 76 | |
| 77 | # Re-run plugin detection, but without running setups: |
| 78 | from plugins import PluginLoader |
| 79 | PluginLoader.detect(reset_all=True) |
| 80 | }}} |