Edgewall Software

Version 16 (modified by Ryan J Ollos, 5 years ago) ( diff )

Document some discussion in #8172.

Extension Point : IEnvironmentSetupParticipant


The IEnvironmentSetupParticipant will be called during both the creation of a new environment (trac-admin <env-dir> initenv) and on upgrade of an existing environment (trac-admin <env-dir> upgrade).


Responsibilities of the interface are to both participate in the creation of a new environment and during upgrade of an existing environment. This includes adding information to the database schema, such as table declarations and so on. Some implementations, see below, might also opt in for adding default data to the newly created database, or to set up the folder where the environment will be created in.

On environment upgrade, the responsibilities of the participant are to non-destructively migrate existing user data to a newer database schema, provided that the data model has changed at the SQL level, and of course to migrate the environment's folder structure and content to meet the requirements of the participant.


Implementing the interface follows the standard guidelines found in TracDev/ComponentArchitecture and of course TracDev/PluginDevelopment.


The following example basically does nothing more than logging to the standard log file during either trac-admin <env-dir> initenv or trac-admin <env-dir> upgrade.

from trac.core import implements, Component
from trac.env import IEnvironmentSetupParticipant

class SampleEnvironmentSetupParticipant(Component):


    # IEnvironmentSetupParticipant methods

    def environment_created(self):
        self.log.debug("creating environment for sample plugin.")

    def environment_needs_upgrade(self):
        self.log.debug("the existing environment requires an upgrade for sample plugin.")
        return True

    def upgrade_environment(self):
        self.log.debug("upgrading existing environment for sample plugin.")

DB upgrades

A more realistic use case would be a plugin that maintains its own database tables and provides scripts for automatically upgrading the database schema.

The DatabaseManager class provides several methods that can be used to run these scripts. (Since Trac 1.1.5, see #8172)

An entire example plugin would consists of the following files and directories:

  • example/
    • upgrades
      • __init__.py (empty)
      • db2.py
        def do_upgrade(env, ver, cursor):
            pass # Change the database schema here
    • __init__.py (empty)
    • core.py
      from trac.core import *
      from trac.env import *
      from trac.db.api import DatabaseManager
      from trac.db.schema import Table, Column
      PLUGIN_NAME = 'ExamplePlugin'
          Table('table1', key='name')[
            ('name', 'value'),
              (('name1', 'value1'),
               ('name2', 'value2'))),)
      class ExamplePlugin(Component):
          # IEnvironmentSetupParticipant methods
          def environment_created(self):
              # Same work is done for environment created and
              # upgraded, in almost all use-cases.
          def environment_needs_upgrade(self):
              dbm = DatabaseManager(self.env)
              return dbm.needs_upgrade(PLUGIN_VERSION, PLUGIN_NAME)
          def upgrade_environment(self):
              dbm = DatabaseManager(self.env)
              if dbm.get_database_version(PLUGIN_NAME) == 0:
                  dbm.set_database_version(PLUGIN_VERSION, PLUGIN_NAME)
                  dbm.upgrade(PLUGIN_VERSION, PLUGIN_NAME, 'example.upgrades')
  • setup.py
    #!/usr/bin/env python
    from setuptools import setup
    setup(name = 'example', version = '1.0',
          packages = ['example', 'example.upgrades'],
          entry_points = {'trac.plugins': ['example.core = example.core']})

Available Implementations

  • trac.env.EnvironmentSetup
    This is the setup participant that will initialize the trac database and also the sample configuration provided with each trac instance, providing sane initial defaults for use with both an existing environment and a newly created one. For the creation of a new environment it uses the default db structure. and on upgrade it will use a db upgrade path defined in the individual db*.py modules therein. The version number of the trac database schema is available from the system table, the key to look for is database_version. The value of this system property will be updated on environment upgrade. In addition to that, trac will also keep track of the initial database version that was installed when first creating the environment. The key to look for in the system table is initial_database_version.

Additional Information and References

  • Preventing data corruption on upgrade
    For the IEnvironmentSetupParticipant there is currently talk about a best practice to always commit changes to the database when upgrading using a migration path, so that on error during the migration, the existing data will not be corrupted. This basically involves atomic changes to the database, so that either all or none of the changes being applied will be committed. This also includes incrementally updating the system property database_version, e.g. for each update available the version will be incremented by one. For your plugins this basically means that you should not try to upgrade the database and your data model schema thereof in just a single transaction, but allow the system to fail, and if it does, gracefully provide the user with the chance of reverting back to the original state. As of now, prior to each update to the database, a copy of the existing database will be created, at least for SQLite based backends. When using PostgreSQL or other supported backends, this will require extra effort by the user in order to be able to revert to a working version of the database before the failed upgrade attempt.
  • On upgrade the existing help pages in the wiki will not be updated
    This is currently not being addressed by trac's default environment setup participant, as it is implemented in a different component. However, there is a proposed new help system that would externalize all help pages to static resources in the filesystem. Note: in order to also upgrade existing wiki pages that will be installed by the system by default, you will have to run trac-admin <env-dir> wiki upgrade.
  • comment:19:ticket:10779 and following discuss that IEnvironmentSetupParticipants are not ordered. Also they should be carefully written not to expect a particular version of the database schema, components or other code that is not guaranteed to be compatible with the upgrade.

  • environment_created is only called for a plugin if the plugin is enabled at the time the environment is created. To have a plugin enabled at the time the environment is created the --inherit (comment:42:ticket:8172) or --config (since 1.2) argument must be used to specify a configuration with the plugin enabled.

API History

Note: See TracWiki for help on using the wiki.