Config files
The primary documentation for the config parser is in the
tranche documentation.
Here, we include some specific details relevant to using the
tranche.Tranche in polaris.
Here, we provide the polaris.config.PolarisConfigParser that has
almost the same functionality but also ensures that certain relative paths are
converted automatically to absolute paths. PolarisConfigParser also has
attributes for a filepath where the config file will be written out and a
list of symlinks that will point to filepath. It also has a
polaris.config.PolarisConfigParser.setup() method that can be
overridden to add config options (e.g. algorithmically from other config
options) as part of setting up polaris tasks and steps. These features are
included to accommodate sharing config options across shared steps and/or
multiple tasks.
The tranche.Tranche.add_from_package() method can
be used to add the contents of a config file within a package to the config
options. Examples of this can be found in many tasks as well as in the
polaris.setup module. Here is a typical example from
polaris.tasks.ocean.inertial_gravity_wave.InertialGravityWave:
from polaris import Task
class InertialGravityWave(Task):
def __init__(self, component):
name = 'inertial_gravity_wave'
subdir = f'planar/{name}'
super().__init__(component=component, name=name, subdir=subdir)
...
self.config.add_from_package(
'polaris.tasks.ocean.inertial_gravity_wave',
'inertial_gravity_wave.cfg')
The first and second arguments are the name of a package containing the config
file and the name of the config file itself, respectively. You can see that
the file is in the path polaris/ocean/tasks/baroclinic_channel
(replacing the . in the module name with /). In this case, we know
that the config file should always exist, so we would like the code to raise
an exception (exception=True) if the file is not found. This is the
default behavior. In some cases, you would like the code to add the config
options if the config file exists and do nothing if it does not. In this
example from polaris.setup.setup_task(), there may not be a config
file for the particular machine we’re on, and that’s fine:
from polaris.config import PolarisConfigParser
def _get_basic_config(config_file, machine, component_path, component):
config = PolarisConfigParser()
if machine is not None:
config.add_from_package('mache.machines', f'{machine}.cfg',
exception=False)
If there isn’t a config file for this machine, nothing will happen.
The MpasConfigParser class also includes methods for adding a user
config file and other config files by file name, but these are largely intended
for use by the framework rather than individual tasks.
Other methods for the MpasConfigParser are similar to those for
configparser.ConfigParser. In addition to get(),
getinteger(), getfloat() and getboolean() methods, this class
implements tranche.Tranche.getlist(), which
can be used to parse a config value separated by spaces and/or commas into
a list of strings, floats, integers, booleans, etc. Other useful methods
are tranche.Tranche.getexpression(), which can
be used to get python dictionaries, lists, and tuples, and
tranche.Tranche.getnumpy(), which also suppports a small set
of functions (range(), numpy.linspace(),
numpy.arange(), and numpy.array())
Comments in config files
One of the main advantages of
tranche.Trancheoverconfigparser.ConfigParseris that it keeps track of comments that are associated with config sections and options.Comments must begin with the
#character. They must be placed before the config section or option in question (preferably without blank lines between). The comments can be any number of lines long.