TurboGears provides a bunch of hook points and ways to extend the framework behavior
to write extensions. Most of the needs can usually be satisfied by relying on
tg.ApplicationConfigurator
, Configuration Milestones and Hooks.
TurboGears extensions are identified by the tgext.*
package name, since
version 2.3.2 the devtools provide a command to quickly create a new TurboGears
extension which can be both used by itself or plugged through tgext.pluggable
.
To quickstart the extension run:
$ gearbox tgext -n myextension -a "My Name" -e "my@email.com"
This will create a tgext.myextension
directory which a simple sample extension
inside. To tune the author, description, license of your extension have a look
at the tgext
command options using gearbox help tgext
.
If you created the tgext.myextension
using the tgext
command you can
quickly turn it on by editing your application config/app_cfg.py
and appending
at the end the following lines:
import tgext.myextension
tgext.myextension.plugme(base_config)
of through the pluggable application interface if tgext.pluggable
is available:
from tgext.pluggable import plug
plug(base_config, 'tgext.myextension')
By enabling the autogenerated extension and starting gearbox serve
again,
you will notice that it just provides a bunch of logging hooks and not much more:
17:52:30,019 INFO [tgext.myextension] Setting up tgext.myextension extension...
17:52:30,023 INFO [tgext.myextension] >>> Public files path is /home/USER/myapp/myapp/public
17:52:30,023 INFO [tgext.myextension] + Application Running!
17:52:30,040 INFO [gearbox] Starting server in PID 22484.
Starting HTTP server on http://0.0.0.0:8080
17:52:30,740 INFO [tgext.myextension] Serving: /
The sample extension created by the tgext
command provides its actual setup
inside the __init__.py
file. This file showcases some of the extension
points provided by TurboGears.
If you actually created tgext.myextension
you should get a
tgext.myextension/tgext/myextension/__init__.py
file with the following content:
from tg import config
from tg import hooks
from tg.configuration import milestones
import logging
log = logging.getLogger('tgext.myextension')
# This is the entry point of your extension, will be called
# both when the user plugs the extension manually or through tgext.pluggable
# What you write here has the same effect as writing it into app_cfg.py
# So it is possible to plug other extensions you depend on.
def plugme(configurator, options=None):
if options is None:
options = {}
log.info('Setting up tgext.myextension extension...')
milestones.config_ready.register(SetupExtension(configurator))
return dict(appid='tgext.myextension')
# Most of your extension initialization should probably happen here,
# where it's granted that .ini configuration file has already been loaded
# in tg.config but you can still register hooks or other milestones.
class SetupExtension(object):
def __init__(self, configurator):
self.configurator = configurator
def __call__(self):
log.info('>>> Plugin files path is %s' % config['paths']['static_files'])
hooks.register('startup', self.on_startup)
def echo_wrapper_factory(handler, config):
def echo_wrapper(controller, environ, context):
log.info('Serving: %s' % context.request.path)
return handler(controller, environ, context)
return echo_wrapper
# Application Wrappers are much like easier WSGI Middleware
# that get a TurboGears context and return a Response object.
self.configurator.register_application_wrapper(echo_wrapper_factory)
def on_startup(self):
log.info('+ Application Running!')
The core parts of the previous example are:
- plugme function, this is the function used to turn on your extension.
will be automatically called by
tgext.pluggable
when the extension is enabled using the pluggable application interface or by the user itself when manually enabling your extension. Inside this method the application configurator object is available and the options the user specified for the extension, but not application configuration as it has not been loaded yet.
- SetupExtension.__call__, this is a callable that is registered
by the plugme function for the
config_read
milestone so that it is executed when the .ini configuration has been loaded and merged with the options declared through the application configurator in config/app_cfg.py.Here you can register additional milestones, functions or access and modify the application configurator through the
self.configurator
object.
- SetupExtension.on_startup This is a sample hook registered on
application startup by
SetupExtension.__call__
that says hello when the application has started. Have at look at Hooks for a complete list of available hooks.
If your extension needs to expose models and controllers you probably want to have a look at Pluggable Applications which are meant to create reusable turbogears applications that can be plugged inside other applications to extend their features.
TurboGears 2.1.4 introduced support for pluggable applications using tgext.pluggable.
tgext.pluggable
is now the official supported way in TurboGears to create pluggable
reusable applications.
Currently only SQLAlchemy based applications are supported as pluggable applications.
Official documentation for tgext.pluggable
can be found at: http://pypi.python.org/pypi/tgext.pluggable
Pluggable applications can define their own:
- controllers, which will be automatically mounted when the application is purged.
- models, which will be available inside and outside of the plugged application.
- helpers, which can be automatically exposed in
h
object in application template.- bootstrap, which will be executed when setup-app is called.
- statics, which will be available at their own private path.
In your application config/app_cfg.py import plug
from tgext.pluggable
and
call it for each pluggable application you want to enable.
The plugged package must be installed in your environment.
from tgext.pluggable import plug
plug(base_config, 'package_name')
tgext.pluggable
provides a quickstart-pluggable command
to create a new pluggable applications:
$ gearbox quickstart-pluggable plugtest
...
The quickstarted application will provide an example on how to use models, helpers, bootstrap, controllers and statics.