Changes between Version 69 and Version 70 of TracDev/PluginDevelopment
- Timestamp:
- Mar 16, 2015, 4:10:28 PM (9 years ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
TracDev/PluginDevelopment
v69 v70 1 = Writing Plugins for Trac = 1 = Writing Plugins for Trac 2 2 3 [[PageOutline]] 3 4 4 5 Starting with version [milestone:0.9 0.9], you can develop plugins for Trac that extend the builtin functionality. The plugin functionality is based on the [wiki:TracDev/ComponentArchitecture component architecture], so please read that document before continuing here. For more information, not covered here, see TracDev. 5 6 6 == Writing the plugin code ==7 == Writing the plugin code 7 8 8 9 To extend Trac with a custom plugin, you need to implement a ''component''. For example, to add a new web module to Trac (i.e. a component that handles HTTP requests and extends the navigation bar), you'd start with something like the following code: … … 37 38 }}} 38 39 39 == Extension points == 40 == Extension points 41 40 42 The above example implements two of Trac's many [wiki:TracDev/PluginDevelopment/ExtensionPoints extension point interfaces]. Look at the extension point specific pages (like [wiki:TracDev/PluginDevelopment/ExtensionPoints/trac.web.chrome.INavigationContributor]) for an overview, or the API documentation to see what exactly you're expected to return. 41 43 42 == Component member variables ==44 == Component member variables 43 45 44 46 Every [wiki:TracDev/ComponentArchitecture component] that gets instantiated through the Trac environment gets three extra member variables for convenience: … … 52 54 Storing any other objects as instance variables of your component is probably a bad idea: remember that a component is only instantiated once for a given environment; unless your plugin is used in a CGI deployment of Trac, that means that the same component instance will get invoked for multiple HTTP requests; if the server is multi-threaded, this will even happen concurrently. 53 55 54 == Single file plugins ==56 == Single file plugins 55 57 56 58 Plugins that consist of a single `.py` file can be dropped directly into either the project's or the shared `plugins` directory. More complex plugins require some packaging. 57 59 58 == Packaging plugins ==60 == Packaging plugins 59 61 60 62 TracPlugins are packaged as [http://peak.telecommunity.com/DevCenter/PythonEggs Python Eggs]. You can use [https://pythonhosted.org/setuptools/setuptools.html setuptools] to make a `setup.py` script that will produce a Python egg for your plugin. … … 79 81 This assumes that the `HelloWorldPlugin` example above is defined in the module `helloworld.py` in the `myplugs` package. The entry point ''name'' (in this example “helloworld”) is required by the Python egg runtime, but not currently used by Trac. In most cases, you can simply use the qualified module name there. 80 82 81 == !Internationalization/Localization of plugins == 83 == !Internationalization/Localization of plugins 84 82 85 '' relevant since trac-0.12 introduced i18n/l10n support for Trac utilizing Babel'' 83 86 84 87 See the [wiki:CookBook/PluginL10N plugin i18n/l10n cookbook page] for details. 85 88 86 == Plugin deployment ==89 == Plugin deployment 87 90 88 91 A plugin can either be deployed globally, or only for a specific environment. Global deployment is done by installing the plugin: 89 92 {{{ 90 $ cd /path/to/pluginsource 91 $ python setup.py install 93 #!sh 94 cd /path/to/pluginsource 95 python setup.py install 92 96 }}} 93 97 94 98 To deploy a plugin only to a specific Trac environment, copy the egg file into the `plugins` directory of that environment: 95 99 {{{ 96 $ cd /path/to/pluginsource 97 $ python setup.py bdist_egg 98 $ cp dist/*.egg /path/to/projenv/plugins 100 #!sh 101 cd /path/to/pluginsource 102 python setup.py bdist_egg 103 cp dist/*.egg /path/to/projenv/plugins 99 104 }}} 100 105 101 106 During development of a plugin, it is inconvenient to have to install it in either of the ways described above. Instead, you should use the setuptools `develop` command: 102 107 {{{ 103 $ cd /path/to/pluginsource 104 $ python setup.py develop --multi-version --exclude-scripts --install-dir /path/to/projenv/plugins 108 #!sh 109 cd /path/to/pluginsource 110 python setup.py develop --multi-version --exclude-scripts --install-dir /path/to/projenv/plugins 105 111 }}} 106 112 107 113 or the short version: 108 114 {{{ 109 $ python setup.py develop -mxd /path/to/projenv/plugins 115 #!sh 116 python setup.py develop -mxd /path/to/projenv/plugins 110 117 }}} 111 118 … … 116 123 A tutorial to build your own plugins is available [http://trac-hacks.org/wiki/EggCookingTutorial here]. 117 124 118 == Disabling built-in components ==125 == Disabling built-in components 119 126 120 127 Sometimes you might want to write a plugin that completely replaces a built-in component, for example to develop an advanced variant of an existing module. Trac uses a list of default component to load, as specified in the `default_components` list in [source:/trunk/trac/db_default.py#latest trac.db_default]. These built-in components are always loaded, and might therefore conflict with your replacement plugin. … … 124 131 For example, to disable the built-in Wiki macro `RecentChanges`, you'd include the following in [wiki:TracIni trac.ini]: 125 132 {{{ 133 #!ini 126 134 [components] 127 135 trac.wiki.macros.RecentChangesMacro = disabled 128 136 }}} 129 137 130 You can also use a wildcard at the end of a name, so you could even disable the complete Wiki module (although wiki formatting will still work in the remaining modules, of course):138 You can also use a wildcard at the end of a name, so you could even disable the complete Wiki module: 131 139 {{{ 140 #!ini 132 141 [components] 133 142 trac.wiki.* = disabled 134 143 }}} 135 144 136 == Debugging == 137 The logging API is a very good debugging tool. Simply use this code when you want to view value of a variable: 145 Wiki formatting will still work in the remaining modules, of course. 146 147 == Debugging 148 149 The logging API is a very good debugging tool. For example, use this code when you want to view the value of a variable: 138 150 139 151 {{{ 140 152 #!python 141 153 env.log.debug("*** Hey, varname is %r ***", varname) 142 154 }}} 143 155 where `env` is the `Environment` instance. … … 146 158 {{{ 147 159 #!python 148 160 self.log.debug("Hey, varname is %r", varname) 149 161 }}} 162 150 163 This will implicitly use the `self.env` Environment, but your component name will now be used for the $module (see TracLogging#LogFormat). This makes it easier to identify the relevant debug lines. 151 164