Extending CementApp¶
CementApp provides a convenient extend
mechanism that allows plugins,
extensions, or the app itself to add objects/functions to the global
application object. For example, a plugin might extend the CementApp with an
api
member allowing developers to call app.api.get(...)
. The
application itself does not provide app.api
however the plugin does. As
plugins are often third party, it is not possible for the plugin developer to
simply sub-class the CementApp and add the functionality because the CementApp
is already instantiated by the time plugins are loaded.
Take the following for example:
myapp.py
from cement.core.foundation import CementApp
with CementApp('myapp') as app:
app.run()
The above is a very simple Cement application, which obviously doesn’t do much. That said, we can add a plugin that extends the application to add an API client object, for example, pretty easily. Note the following is an arbitrary and non-functional example using dRest:
/etc/myapp/plugins.d/api.conf
[api]
enable_plugin = true
endpoint = https://example.com/api/v1
user = john.doe
password = XXXXXXXXXXXX
/var/lib/myapp/plugins/api.py
import drest
from cement.core import hook
def extend_api_object(app):
# get api info from this plugins configuration
endpoint = app.config.get('api', 'endpoint')
user = app.config.get('api', 'user')
password = app.config.get('api', 'password')
# create an api object and authenticate
my_api_client = drest.API(endpoint)
my_api_client.auth(username, password)
# extend the global app object with an ``api`` member
app.extend('api', my_api_client)
def load(app):
hook.register('pre_run', extend_api_object)
In the above plugin, we simply created a dRest API client within a
pre_run
hook and then extended the global app
with it. The developer
can now reference app.api
anywhere that the global app
object is
accessible.
Our application code could now look like:
myapp.py
from cement.core.foundation import CementApp
with CementApp('myapp') as app:
app.run()
# use the api object that the plugin provides
app.api.get(...)