wiki:EggCookingTutorial/BasicEggCooking

Version 34 (modified by rjollos, 13 months ago) (diff)

Removed Tagit macro.

Egg cooking

Since Trac 0.9 it has been possible to write plugins for Trac to extend Trac functionality. Even better, you can deploy plugins as Python eggs, which really makes plugin development fun and easy.

This tutorial shows how to make and load an egg in Trac. In the advanced parts you'll learn how to serve templates and static content from an egg.

You should be familiar with component architecture and plugin development. This plugin is based on the example in the plugin development article. Here we extend it a bit further.

Required items

First you need setuptools. For instructions and files see EasyInstall page.

You also need Trac. Download it from the TracDownload page.

Directories

To develop a plugin you need to create a few directories to keep things together.

So let's create following directories:

./helloworld-plugin/
./helloworld-plugin/helloworld/

Main plugin

The first step is to generate the main module for this plugin. We will construct a simple plugin that will display "Hello world!" on the screen when accessed through the /helloworld URL. The plugin also provides a "Hello" button that is, by default, rendered on the far right in the main navigation bar.

So create helloworld.py in ./helloworld-plugin/helloworld/:

# Helloworld plugin

from trac.core import *
from trac.web.chrome import INavigationContributor
from trac.web.main import IRequestHandler
from trac.util import escape, Markup

class HelloWorldPlugin(Component):
    implements(INavigationContributor, IRequestHandler)

    # INavigationContributor methods
    def get_active_navigation_item(self, req):
        return 'helloworld'

    def get_navigation_items(self, req):
        yield 'mainnav', 'helloworld', Markup('<a href="%s">Hello</a>' % (
                self.env.href.helloworld() ) )

    # IRequestHandler methods
    def match_request(self, req):
        return req.path_info == '/helloworld'

    def process_request(self, req):
        req.send_response(200)
        abuffer = 'Hello world!'
        req.send_header('Content-Type', 'text/plain')
        req.send_header('Content-length', str(len(abuffer)))
        req.end_headers()
        req.write(abuffer)

To help understand how that works, read the INavigationContributor and IRequestHandler interface specifications.

Make it a module

To make the plugin a module, you simply create an __init__.py in ./helloworld-plugin/helloworld/:

# Helloworld module
from helloworld import *

Make it an egg

Now it's time to make it an egg. For that we need a chicken called setup.py in ./helloworld-plugin/:

from setuptools import setup

PACKAGE = 'TracHelloworld'
VERSION = '0.1'

setup(name=PACKAGE,
      version=VERSION,
      packages=['helloworld'],
      entry_points={'trac.plugins': '%s = helloworld' % PACKAGE},
)

You will also have to add special egg metadata to cater to Trac's plugin loader. First create the directory ./helloworld-plugin/TracHelloworld.egg-info, where the name of the .egg-info file corresponds to PACKAGE.

Put the following text in a file named trac_plugin.txt in ./helloworld-plugin/TracHelloworld.egg-info:

helloworld

First deployment

Now try to build the plugin. Run the command python setup.py bdist_egg in the directory where you created it. If everything went OK, you should have a .egg file in ./dist directory.

Copy this .egg file to /[your trac env]/plugins directory. Restart the trac server. If you're using mod_python you have to restart Apache.

Now you should see Hello link at far right in the main navigation bar when accessing your site. Click it.

Aftermath

Now that you have successfully created your first egg, you can continue by reading EggCookingTutorial/AdvancedEggCooking to learn how to use templates in your plugins, and make its output look like other Trac pages.

Attachments (2)

Download all attachments as: .zip