Cement defines an Extension Interface, as well as the default CementExtensionHandler that implements the interface. Its purpose is to manage loading framework extensions and making them usable by the application. Extensions are similar to Application Plugins, but at the framework level (application agnostic).
The following options under
App.Meta modify extension handling:
A handler class that implements the Extension Interface. This can be a string (label of a registered handler), an uninstantiated class, or an instantiated class object. Default:
A list of additional framework extensions to load. Will be merged together with
In general, extensions are only loaded and accessed by the framework. That said the extension handler can be used to access information about loaded extensions, as well as manually load extensions if necessary.
from cement import Appwith App('myapp') as app:# list loaded extensionsapp.ext.list()# load an extensionapp.ext.load_extension('myapp.ext.myextension')# load a list of extensionsapp.ext.load_extensions(['myapp.ext.ext1','myapp.ext.ext2'])
The extension system is a mechanism for dynamically loading code to extend the functionality of the framework. In general, this includes the registration of interfaces, handlers, and/or hooks but can include controllers, command-line options, or anything else.
The preferred method of creating an extension would be via the included developer tools:
$ cement generate extension /path/to/myapp/ext
This would produce something like the following:
myapp/ext/ext_myextension.pyfrom cement import minimal_loggerLOG = minimal_logger(__name__)def myextension_pre_run_hook(app):# do something with appLOG.debug('Inside myextension_pre_run_hook!')def load(app):# do something to extend cementapp.hook.register('pre_run', myextension_pre_run_hook)
You will notice that extensions are essentially the same as application plugins. The difference is found both in when/how the code is loaded, as well as the purpose of that code.
Extensions are loaded when
App.setup() is called on an application. Cement automatically loads all extensions listed under the application's
App.Meta.extensions meta options.
To load the above example into our application, we just add it to the list of
App.Meta.extensions. Let's assume the extension code lives in
from cement import Appclass MyApp(App):class Meta:label = 'myapp'extensions = 'myapp.ext.ext_myextension'
Some use cases may require that end-users be able to modify what framework extensions are loaded depending on the needs of the application, while most extensions are defined by the developer to support key features.
The following example demonstrates an application loading extensions defined via the
extensions setting under the application's configuration settings.
myapp.pyfrom cement import Appwith App('myapp') as app:app.run()for e in app.extension.list():print(e)
~/.myapp.conf[myapp]exensions = json, yaml, myapp.ext.ext_myextension
$ python myapp.pycement.ext.ext_dummycement.ext.ext_smtpcement.ext.ext_plugincement.ext.ext_configparsercement.ext.ext_loggingcement.ext.ext_argparsecement.ext.ext_jsoncement.ext.ext_yamlmyapp.ext.ext_myextension