= 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 [http://peak.telecommunity.com/DevCenter/PythonEggs Python eggs] that really makes plugin development fun. This tutorial shows how to make an egg, successfully load an egg in Trac and in advanced topics how to serve templates and static content from an egg. You should be familiar with [trac:TracDev/ComponentArchitecture component architecture] and [trac:TracDev/PluginDevelopment plugin development]. This plugin is based on 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. Then you need of course Trac 0.9. Currently, it means source checkout from Subversion repository. Instructions for getting it done are located at [trac:TracDownload#LatestDevelopmentSourceCode1 TracDownload] page. == Directories == To develop a plugin you need to create few directories to keep things together. So let's create following directories: {{{ ./helloworld-plugin/ ./helloworld-plugin/helloworld/ ./helloworld-plugin/TracHelloworld.egg-info/ }}} == Main plugin == First step is to generate main module for this plugin. We will construct simple plugin that will display "Hello world!" on screen when accessed through /helloworld URL. Plugin also provides "Hello" button that is by default rendered on far right in 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 class UserbaseModule(Component): implements(INavigationContributor, IRequestHandler) # INavigationContributor methods def get_active_navigation_item(self, req): return 'helloworld' def get_navigation_items(self, req): yield 'mainnav', 'helloworld', 'Hello' \ % escape(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) req.send_header('Content-Type', 'text/plain') req.end_headers() req.write('Hello world!') }}} == Make it as a module == Since this is not enough, we need to make our simple plugin as a module. To do so, you simply create that magic ''_''____''_init_''____''_.py'' into ''./helloworld-plugin/helloworld/'': {{{ #!python # Helloworld module from helloworld import * }}} == Make it as an egg == Now it's time to make it as an egg. For that we need a chicken called ''setup.py'' that is created into ''./helloworld-plugin/'': {{{ #!python from setuptools import setup PACKAGE = 'TracHelloworld' VERSION = '0.1' setup(name=PACKAGE, version=VERSION, packages=['helloworld']) }}} To make egg loadable in Trac we need to create one file more. in ''./helloworld-plugin/!TracHelloworld.egg-info/'' create file ''trac_plugin.txt'': {{{ helloworld }}} == First deployment == Now you could try to build your first plugin. Run command {{{python setup.py bdist_egg}}} in directory where you created it. If everthing went OK you should have small .egg file in ''./dist'' directory. Copy this ''.egg'' file to ''/[your trac env]/plugins'' directory. If you're using mod_python you have to restart Apache. Now you should see ''Hello'' link at far right in main navigation bar when accessing your site. Click it. == Aftermath == Now you have successfully created your first egg. You can continue now reading [wiki:EggCookingTutorial/AdvancedEggCooking EggCookingTutorial/AdvancedEggCooking] to really integrate plugin into Trac layout.