[[TOC(heading=Egg Cooking Tutorial, EggCookingTutorial/BasicEggCooking, EggCookingTutorial/AdvancedEggCooking, EggCookingTutorial/AdvancedEggCooking2, EggCookingTutorial/publish)]] = Egg cooking 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 Trac's [trac:TracDev/ComponentArchitecture component architecture] and [trac:TracDev/PluginDevelopment 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 [http://peak.telecommunity.com/DevCenter/EasyInstall#installing-easy-install EasyInstall] page. You also need a running version of '''Trac'''. Download it from the [trac:TracDownload] page. == Directories To develop a plugin you need to create a few directories to keep things together. So let's create the following directories: {{{#!sh ./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/'': {{{#!python # 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('Hello' % ( 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 [http://projects.edgewall.com/trac/browser/branches/0.9-stable/trac/web/chrome.py#L53 INavigationContributor] and [http://projects.edgewall.com/trac/browser/branches/0.9-stable/trac/web/api.py#L224 IRequestHandler] interface specifications. == Make it a module To make the plugin a module, you simply create an ''_''____''_init_''____''_.py'' in ''./helloworld-plugin/helloworld/'': {{{#!python # 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/'': {{{#!python 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 [http://peak.telecommunity.com/DevCenter/EggFormats#project-metadata 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 [wiki:EggCookingTutorial/AdvancedEggCooking] to learn how to use templates in your plugins, and make its output look like other Trac pages.