python/mach/docs/settings.rst
author Andrew Halberstadt <ahalberstadt@mozilla.com>
Wed, 23 Mar 2016 17:49:15 -0400
changeset 330688 b552927e1a1fe9f916811236eb30352be72eaaaf
parent 330687 99146ae25db725f0a1b37b624ec47fea07366e03
child 330690 355e8bb48aeeef736df7ca21351f7e87caf90668
permissions -rw-r--r--
Bug 1255450 - [mach] Simplify managing of locale documentation for settings, r=gps This adds a |mach settings locale-gen| subcommand to automatically generate locale specific documentation for settings. It also refactors |mach settings-create| to |mach settings| and moves |mach settings| to |mach settings -l|. Finally it performs some misc cleanup mostly related to locales. MozReview-Commit-ID: 1VWLcb9ehAH

.. _mach_settings:

========
Settings
========

Mach can read settings in from a set of configuration files. These
configuration files are either named ``mach.ini`` or ``.machrc`` and
are specified by the bootstrap script. In mozilla-central, these files
can live in ``~/.mozbuild`` and/or ``topsrcdir``.

Settings can be specified anywhere, and used both by mach core or
individual commands.


Defining Settings
=================

Settings need to be explicitly defined, along with their type,
otherwise mach will throw when loading the configuration files.

To define settings, use the :func:`~decorators.SettingsProvider`
decorator in an existing mach command module. E.g:

.. code-block:: python

    from mach.decorators import SettingsProvider

    @SettingsProvider
    class ArbitraryClassName(object):
        config_settings = [
            ('foo.bar', 'string'),
            ('foo.baz', 'int', 0, set([0,1,2])),
        ]

``@SettingsProvider``'s must specify a variable called ``config_settings``
that returns a list of tuples. Alternatively, it can specify a function
called ``config_settings`` that returns a list of tuples.

Each tuple is of the form:

.. code-block:: python

    ('<section>.<option>', '<type>', default, extra)

``type`` is a string and can be one of:
string, boolean, int, pos_int, path

``default`` is optional, and provides a default value in case none was
specified by any of the configuration files.

``extra`` is also optional and is a dict containing additional key/value
pairs to add to the setting's metadata. The following keys may be specified
in the ``extra`` dict:
    * ``choices`` - A set of allowed values for the setting.

Wildcards
---------

Sometimes a section should allow arbitrarily defined options from the user, such
as the ``alias`` section mentioned above. To define a section like this, use ``*``
as the option name. For example:

.. parsed-literal::

    ('foo.*', 'string')

This allows configuration files like this:

.. parsed-literal::

    [foo]
    arbitrary1 = some string
    arbitrary2 = some other string


Documenting Settings
====================

All settings must at least be documented in the en_US locale. Otherwise,
running ``mach settings`` will raise. Mach uses gettext to perform localization.

A handy command exists to generate the localization files:

.. parsed-literal::

    mach settings locale-gen <section>

You'll be prompted to add documentation for all options in section with the
en_US locale. To add documentation in another locale, pass in ``--locale``.


Accessing Settings
==================

Now that the settings are defined and documented, they're accessible from
individual mach commands if the command receives a context in its constructor.
For example:

.. code-block:: python

    from mach.decorators import (
        Command,
        CommandProvider,
        SettingsProvider,
    )

    @SettingsProvider
    class ExampleSettings(object):
        config_settings = [
            ('a.b', 'string', 'default'),
            ('foo.bar', 'string'),
            ('foo.baz', 'int', 0, {'choices': set([0,1,2])}),
        ]

    @CommandProvider
    class Commands(object):
        def __init__(self, context):
            self.settings = context.settings

        @Command('command', category='misc',
                 description='Prints a setting')
        def command(self):
            print(self.settings.a.b)
            for option in self.settings.foo:
                print(self.settings.foo[option])