Jump to >

Writing Features

Features are very small and easy to write. They’re subclasses of Feature, which are typically placed in a features.py file in the app defining the feature.

Let’s start with a basic example:

# myapp/features.py

from djblets.features import Feature, FeatureLevel


class MyFeature(Feature):
    feature_id = 'myproject.myfeature'
    name = 'My Feature'
    summary = 'This feature does some neat things.'
    level = FeatureLevel.EXPERIMENTAL


my_feature = MyFeature()

Each feature must have a unique ID. This ID is how you look up a feature dynamically and is used when specifying which features are enabled (through a feature checker).

Features should also have a name and a summary. These aren’t used directly by the Djblets Features code, but applications may want to use these to show a human-readable list of possible features.

You’ll also want to instantiate your feature subclass, but just once. We recommend instantiating it in the same file in which it’s defined, as a top-level variable. At this point, the feature will be registered with the feature registry, allowing the feature to be used and its enable state computed.

Stability Levels

A feature has a stability level, which indicates whether it’s enabled by default, or even whether it can be enabled at all.

The built-in stability levels are defined in FeatureLevel, and include:

UNAVAILABLE:
The feature is unavailable for use, and can’t be enabled through a feature checker. Useful when shipping code that you don’t want used at all yet by anybody else, and you just want to selectively enable in your own tree or in a development branch.
EXPERIMENTAL:
The feature is experimental and disabled by default, but can be enabled through the feature checker.
BETA:
The feature is in beta. It will be disabled by default if settings.DEBUG is False, but can be enabled through the feature checker. If settings.DEBUG is True, it will be enabled.
STABLE:
The feature is always enabled.

The meaning of these levels can be changed in the feature checker by overriding min_enabled_level().

You can set the stability level of your feature through the Feature.level attribute:

from djblets.features import FeatureLevel


class MyFeature(Feature):
    level = FeatureLevel.BETA

Feature Initialization/Shutdown

If you need to perform some logic surrounding the initialization of a feature, such as registering signal handlers, then you can do so by defining a initialize() method:

class MyFeature(Feature):
    ...

    def initialize(self):
        # Your code goes here.

Similarly, you can handle feature shutdown through a shutdown() method. This is only ever called if the application unregisters the feature, which not all applications will do, but if yours does, this would be a good place to put shutdown logic.

class MyFeature(Feature):
    ...

    def shutdown(self):
        # Your code goes here.

Not all features are going to need these capabilities, but they’re there if you do need them.