Edgewall Software

Changes between Version 69 and Version 70 of TracDev/PluginDevelopment


Ignore:
Timestamp:
Mar 16, 2015, 4:10:28 PM (9 years ago)
Author:
figaro
Comment:

Cosmetic changes

Legend:

Unmodified
Added
Removed
Modified
  • TracDev/PluginDevelopment

    v69 v70  
    1 = Writing Plugins for Trac =
     1= Writing Plugins for Trac
     2
    23[[PageOutline]]
    34
    45Starting 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.
    56
    6 == Writing the plugin code ==
     7== Writing the plugin code
    78
    89To 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:
     
    3738}}}
    3839
    39 == Extension points ==
     40== Extension points
     41
    4042The 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.
    4143
    42 == Component member variables ==
     44== Component member variables
    4345
    4446Every [wiki:TracDev/ComponentArchitecture component] that gets instantiated through the Trac environment gets three extra member variables for convenience:
     
    5254Storing 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.
    5355
    54 == Single file plugins ==
     56== Single file plugins
    5557
    5658Plugins 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.
    5759
    58 == Packaging plugins ==
     60== Packaging plugins
    5961
    6062TracPlugins 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.
     
    7981This 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.
    8082
    81 == !Internationalization/Localization of plugins ==
     83== !Internationalization/Localization of plugins
     84
    8285'' relevant since trac-0.12 introduced i18n/l10n support for Trac utilizing Babel''
    8386
    8487See the [wiki:CookBook/PluginL10N plugin i18n/l10n cookbook page] for details.
    8588
    86 == Plugin deployment ==
     89== Plugin deployment
    8790
    8891A plugin can either be deployed globally, or only for a specific environment. Global deployment is done by installing the plugin:
    8992{{{
    90 $ cd /path/to/pluginsource
    91 $ python setup.py install
     93#!sh
     94cd /path/to/pluginsource
     95python setup.py install
    9296}}}
    9397
    9498To deploy a plugin only to a specific Trac environment, copy the egg file into the `plugins` directory of that environment:
    9599{{{
    96 $ cd /path/to/pluginsource
    97 $ python setup.py bdist_egg
    98 $ cp dist/*.egg /path/to/projenv/plugins
     100#!sh
     101cd /path/to/pluginsource
     102python setup.py bdist_egg
     103cp dist/*.egg /path/to/projenv/plugins
    99104}}}
    100105
    101106During 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:
    102107{{{
    103 $ cd /path/to/pluginsource
    104 $ python setup.py develop --multi-version --exclude-scripts --install-dir /path/to/projenv/plugins
     108#!sh
     109cd /path/to/pluginsource
     110python setup.py develop --multi-version --exclude-scripts --install-dir /path/to/projenv/plugins
    105111}}}
    106112
    107113or the short version:
    108114{{{
    109 $ python setup.py develop -mxd /path/to/projenv/plugins
     115#!sh
     116python setup.py develop -mxd /path/to/projenv/plugins
    110117}}}
    111118
     
    116123A tutorial to build your own plugins is available [http://trac-hacks.org/wiki/EggCookingTutorial here].
    117124
    118 == Disabling built-in components ==
     125== Disabling built-in components
    119126
    120127Sometimes 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.
     
    124131For example, to disable the built-in Wiki macro `RecentChanges`, you'd include the following in [wiki:TracIni trac.ini]:
    125132{{{
     133#!ini
    126134[components]
    127135trac.wiki.macros.RecentChangesMacro = disabled
    128136}}}
    129137
    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):
     138You can also use a wildcard at the end of a name, so you could even disable the complete Wiki module:
    131139{{{
     140#!ini
    132141[components]
    133142trac.wiki.* = disabled
    134143}}}
    135144
    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:
     145Wiki formatting will still work in the remaining modules, of course.
     146
     147== Debugging
     148
     149The logging API is a very good debugging tool. For example, use this code when you want to view the value of a variable:
    138150
    139151{{{
    140152#!python
    141   env.log.debug("*** Hey, varname is %r ***", varname)
     153env.log.debug("*** Hey, varname is %r ***", varname)
    142154}}}
    143155where `env` is the `Environment` instance.
     
    146158{{{
    147159#!python
    148   self.log.debug("Hey, varname is %r", varname)
     160self.log.debug("Hey, varname is %r", varname)
    149161}}}
     162
    150163This 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.
    151164