Rose Configuration API
CLI
The rose config command provides a command line tool for reading, processing and dumping files written in the Rose Configuration Format:
$ echo -e "
> [foo]
> bar=baz
> " > rose.conf
$ rose config foo --file rose.conf
bar=baz
For more information see the rose config command line reference.
Python
Rose provides a Python API for loading, processing, editing and dumping Rose
configurations via the metomi.rose.config
module located within the
Rose Python library.
Simple INI-style configuration data model, loader and dumper.
- Synopsis:
>>> # Create a config file. >>> with open('config.conf', 'w+') as config_file: ... _ = config_file.write(''' ... [foo] ... bar=Bar ... !baz=Baz ... ''')
>>> # Load in a config file. >>> try: ... config_node = load('config.conf') ... except ConfigSyntaxError: ... # Handle exception. ... pass
>>> # Retrieve config settings. >>> config_node.get(['foo', 'bar']) {'value': 'Bar', 'state': '', 'comments': []}
>>> # Set new config settings. >>> _ = config_node.set(['foo', 'new'], 'New')
>>> # Overwrite existing config settings. >>> _ = config_node.set(['foo', 'baz'], state=ConfigNode.STATE_NORMAL, ... value='NewBaz')
>>> # Write out config to a file. >>> dump(config_node, sys.stdout) [foo] bar=Bar baz=NewBaz new=New
- Classes:
metomi.rose.config.ConfigNode
([value, ...])Represent a node in a configuration file.
Represent differences between two ConfigNode instances.
metomi.rose.config.ConfigDumper
([char_assign])Dumper of a ConfigNode object in Rose INI format.
Loader of an INI format configuration into a ConfigNode object.
- Functions:
metomi.rose.config.load
(source[, root])Shorthand for
ConfigLoader.load()
.metomi.rose.config.dump
(root[, target, ...])Shorthand for
ConfigDumper.dump()
.- Limitations:
The loader does not handle trailing comments.
- What about the standard library ConfigParser? Well, it is problematic:
The comment character and style is hard-coded.
The assignment character is hard-coded.
A duplicated section header causes an exception to be raised.
Option keys are transformed to lower case by default.
It is far too complicated and confusing.
- exception metomi.rose.config.ConfigDecodeError(path, unicode_decode_err)[source]
Exception that should be raised when loading a configuration file that is not encoded in a UTF-8 compatible charset.
- Parameters:
path (str) – Path to the config file
unicode_decode_err (UnicodeDecodeError) – The original exception raised when doing bytes.decode()
- class metomi.rose.config.ConfigDumper(char_assign='=')[source]
Dumper of a ConfigNode object in Rose INI format.
Examples
>>> config_node = ConfigNode() >>> _ = config_node.set(keys=['foo', 'bar'], value='Bar') >>> _ = config_node.set(keys=['foo', 'baz'], value='Baz', ... comments=['Currently ignored!'], ... state=ConfigNode.STATE_USER_IGNORED) >>> dumper = ConfigDumper() >>> dumper(config_node, sys.stdout) [foo] bar=Bar #Currently ignored! !baz=Baz
- dump(root, target=<_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>, sort_sections=None, sort_option_items=None, env_escape_ok=False, concat_mode=False)[source]
Format a ConfigNode object and write result to target.
- Parameters:
root (ConfigNode) – The root config node.
target (object) – An open file handle or a string containing a file path. If not specified, the result is written to sys.stdout.
sort_sections (Callable) – An optional argument that should be a function for sorting a list of section keys.
sort_option_items (Callable) – An optional argument that should be a function for sorting a list of option (key, value) tuples in string values.
env_escape_ok (bool) – An optional argument to indicate that $NAME and ${NAME} syntax in values should be escaped.
concat_mode (bool) – Switch on concatenation mode. If True, add [] before root level options.
- class metomi.rose.config.ConfigLoader(char_assign='=', char_comment='#', allow_sections=True)[source]
Loader of an INI format configuration into a ConfigNode object.
Example
>>> with open('config.conf', 'w+') as config_file: ... _ = config_file.write(''' ... [foo] ... !bar=Bar ... baz=Baz ... ''') >>> loader = ConfigLoader() >>> try: ... config_node = loader.load('config.conf') ... except ConfigSyntaxError: ... raise # Handle exception. >>> config_node.get(keys=['foo', 'bar']) {'value': 'Bar', 'state': '!', 'comments': []}
- static can_miss_opt_conf_key(key)[source]
Return KEY if key is a string like “(KEY)”, None otherwise.
- load(source, node=None, default_comments=None)[source]
Read a source configuration file.
- Parameters:
source (str) – An open file handle, a string for a file path or a list of [SECTION]KEY=VALUE items.
node (ConfigNode) – A ConfigNode object if specified, otherwise created.
- Returns:
A new ConfigNode object.
- Return type:
Examples
>>> # Create example config file. >>> with open('config.conf', 'w+') as config_file: ... _ = config_file.write(''' ... [foo] ... # Some comment ... !bar=Bar ... ''')
>>> # Load config file. >>> loader = ConfigLoader() >>> try: ... config_node = loader.load('config.conf') ... except ConfigSyntaxError: ... raise # Handle exception. >>> config_node.get(keys=['foo', 'bar']) {'value': 'Bar', 'state': '!', 'comments': [' Some comment']}
- load_with_opts(source, node=None, more_keys=None, used_keys=None, return_config_map=False, mark_opt_confs=False, defines=None)[source]
Read a source configuration file with optional configurations.
- Parameters:
source (str) – A file path.
node (ConfigNode) – A ConfigNode object if specified, otherwise one is created.
more_keys (list) – A list of additional optional configuration names. If source is “rose-${TYPE}.conf”, the file of each name should be “opt/rose-${TYPE}-${NAME}.conf”.
used_keys (list) – If defined, it should be a list for this method to append to. The key of each successfully loaded optional configuration will be appended to the list (unless the key is already in the list). Missing optional configurations that are specified in more_keys will not raise an error. If not defined, any missing optional configuration will trigger an OSError.
mark_opt_configs (bool) – if True, add comments above any settings which have been loaded from an optional config.
return_config_map (bool) – If True, construct and return a dict (config_map) containing config names vs their uncombined nodes. Optional configurations use their opt keys as keys, and the main configuration uses ‘None’.
defines (list) – A list of [SECTION]KEY=VALUE overrides.
- Returns:
- node or (node, config_map):
node - The loaded configuration as a ConfigNode.
config_map - A dictionary containing opt_conf_key: ConfigNode pairs. Only returned if return_config_map is True.
- Return type:
Examples
>>> # Write config file. >>> with open('config.conf', 'w+') as config_file: ... _ = config_file.write(''' ... [foo] ... bar=Bar ... ''') >>> # Write optional config file (foo). >>> os.mkdir('opt') >>> with open('opt/config-foo.conf', 'w+') as opt_config_file: ... _ = opt_config_file.write(''' ... [foo] ... bar=Baz ... ''')
>>> loader = ConfigLoader() >>> config_node, config_map = loader.load_with_opts( ... 'config.conf', more_keys=['foo'], return_config_map=True) >>> config_node.get_value(keys=['foo', 'bar']) 'Baz'
>>> original_config_node = config_map[None] >>> original_config_node.get_value(keys=['foo', 'bar']) 'Bar'
>>> optional_config_node = config_map['foo'] >>> optional_config_node.get_value(keys=['foo', 'bar']) 'Baz'
- class metomi.rose.config.ConfigNode(value=None, state='', comments=None)[source]
Represent a node in a configuration file.
- Nodes are stored hierarchically, for instance the following config
[foo] bar = Bar
When loaded by ConfigNode.load(file) would result in three levels of ConfigNodes, the first representing “root” (i.e. the top level of the config), one representing the config section “foo” and one representing the setting “bar”.
Examples
>>> # Create a new ConfigNode. >>> config_node = ConfigNode()
>>> # Add sub-nodes. >>> _ = config_node.set(keys=['foo', 'bar'], value='Bar') >>> _ = config_node.set(keys=['foo', 'baz'], value='Baz') >>> config_node {'value': {'foo': {'value': {'bar': {'value': 'Bar', 'state': '', 'comments': []}, 'baz': {'value': 'Baz', 'state': '', 'comments': []}}, 'state': '', 'comments': []}}, 'state': '', 'comments': []}
>>> # Set the state of a node. >>> _ = config_node.set(keys=['foo', 'bar'], ... state=ConfigNode.STATE_USER_IGNORED)
>>> # Get the value of the node at a position. >>> config_node.get_value(keys=['foo', 'baz']) 'Baz'
>>> # Walk over the hierarchical structure of a node. >>> [keys for keys, sub_node in config_node.walk()] [['foo'], ['foo', 'baz'], ['foo', 'bar']]
>>> # Walk over the config skipping ignored sections. >>> [keys for keys, sub_node in config_node.walk(no_ignore=True)] [['foo'], ['foo', 'baz']]
>>> # Add two ConfigNode instances to create a new "merged" node. >>> another_config_node = ConfigNode() >>> _ = another_config_node.set(keys=['new'], value='New') >>> new_config_node = config_node + another_config_node >>> [keys for keys, sub_node in new_config_node.walk()] [['', 'new'], ['foo'], ['foo', 'baz'], ['foo', 'bar']]
- STATE_NORMAL = ''
The default state of a ConfigNode.
- STATE_SYST_IGNORED = '!!'
ConfigNode state if a metadata opperation has logically ignored the config.
- STATE_USER_IGNORED = '!'
ConfigNode state if it has been specifically ignored in the config.
- add(config_diff)[source]
Apply a ConfigNodeDiff object to self.
- Parameters:
config_diff (ConfigNodeDiff) – A diff to apply to this ConfigNode.
Examples
>>> # Create ConfigNode >>> config_node = ConfigNode() >>> _ = config_node.set(keys=['foo', 'bar'], value='Bar') >>> [keys for keys, sub_node in config_node.walk()] [['foo'], ['foo', 'bar']]
>>> # Create ConfigNodeDiff >>> config_node_diff = ConfigNodeDiff() >>> config_node_diff.set_added_setting(keys=['foo', 'baz'], ... data='Baz')
>>> # Apply ConfigNodeDiff to ConfigNode >>> config_node.add(config_node_diff) >>> [keys for keys, sub_node in config_node.walk()] [['foo'], ['foo', 'baz'], ['foo', 'bar']]
- get(keys=None, no_ignore=False)[source]
Return a node at the position of keys, if any.
- Parameters:
- Returns:
The config node located at the position of keys or None.
- Return type:
Examples
>>> # Create ConfigNode. >>> config_node = ConfigNode() >>> _ = config_node.set(['foo', 'bar'], 'Bar') >>> _ = config_node.set(['foo', 'baz'], 'Baz', ... state=ConfigNode.STATE_USER_IGNORED)
>>> # A ConfigNode containing sub-nodes. >>> config_node.get(keys=['foo']) {'value': {'bar': {'value': 'Bar', 'state': '', 'comments': []}, 'baz': {'value': 'Baz', 'state': '!', 'comments': []}}, 'state': '', 'comments': []}
>>> # A bottom level sub-node. >>> config_node.get(keys=['foo', 'bar']) {'value': 'Bar', 'state': '', 'comments': []}
>>> # Skip ignored nodes. >>> print(config_node.get(keys=['foo', 'baz'], no_ignore=True)) None
- get_filter(no_ignore)[source]
Return this ConfigNode unless no_ignore and node is ignored.
- Parameters:
no_ignore (bool) – If True only return this node if it is not ignored.
- Returns:
This ConfigNode unless no_ignore and node is ignored.
- Return type:
Examples
>>> config_node = ConfigNode(value=42) >>> config_node.get_filter(False) {'value': 42, 'state': '', 'comments': []} >>> config_node.get_filter(True) {'value': 42, 'state': '', 'comments': []}
>>> config_node = ConfigNode(value=42, ... state=ConfigNode.STATE_USER_IGNORED) >>> config_node.get_filter(False) {'value': 42, 'state': '!', 'comments': []} >>> print(config_node.get_filter(True)) None
- get_value(keys=None, default=None)[source]
Return the value of a normal node at the position of keys, if any.
If the node does not exist or is ignored, return None.
- Parameters:
- Returns:
The value of this ConfigNode at the position of keys or default if not set.
- Return type:
Examples
>>> # Create ConfigNode. >>> config_node = ConfigNode(value=42) >>> _ = config_node.set(['foo'], 'foo') >>> _ = config_node.set(['foo', 'bar'], 'Bar')
>>> # Get value without specifying keys returns the value of the >>> # root ConfigNode (which in this case is a dict of its >>> # sub-nodes). >>> config_node.get_value() {'foo': {'value': {'bar': {'value': 'Bar', 'state': '', 'comments': []}}, 'state': '', 'comments': []}}
>>> # Intermediate level ConfigNode. >>> config_node.get_value(keys=['foo']) {'bar': {'value': 'Bar', 'state': '', 'comments': []}}
>>> # Bottom level ConfigNode. >>> config_node.get_value(keys=['foo', 'bar']) 'Bar'
>>> # If there is no node located at the position of keys or if >>> # that node is unset then the default value is returned. >>> config_node.get_value(keys=['foo', 'bar', 'baz'], ... default=True) True
- set(keys=None, value=None, state=None, comments=None)[source]
Set node properties at the position of keys, if any.
- Parameters:
keys (list) – A list defining a hierarchy of node.value ‘keys’. If an entry in keys is the null string, it is skipped.
value (object) – The node.value property to set at this position.
state (str) – The node.state property to set at this position. If None, the node.state property is unchanged.
comments (str) – The node.comments property to set at this position. If None, the node.comments property is unchanged.
- Returns:
This config node.
- Return type:
Examples
>>> # Create ConfigNode. >>> config_node = ConfigNode() >>> config_node {'value': {}, 'state': '', 'comments': []}
>>> # Add a sub-node at the position 'foo' with the comment 'Info'. >>> config_node.set(keys=['foo'], comments='Info') ... {'value': {'foo': {'value': {}, 'state': '', 'comments': 'Info'}}, 'state': '', 'comments': []}
>>> # Set the value for the sub-node at the position >>> # 'foo' to 'Foo'. >>> config_node.set(keys=['foo'], value='Foo') ... {'value': {'foo': {'value': 'Foo', 'state': '', 'comments': 'Info'}}, 'state': '', 'comments': []}
>>> # Set the value of the ConfigNode to True, this overwrites all >>> # sub-nodes! >>> config_node.set(keys=[''], value=True) {'value': True, 'state': '', 'comments': []}
- unset(keys=None)[source]
Remove a node at the position of keys, if any.
- Parameters:
keys (list) – A list defining a hierarchy of node.value ‘keys’. If an entry in keys is the null string, it is skipped.
- Returns:
The ConfigNode instance that was removed, else None.
- Return type:
Examples
>>> # Create ConfigNode. >>> config_node = ConfigNode() >>> _ = config_node.set(keys=['foo'], value='Foo')
>>> # Unset without providing any keys does nothing. >>> print(config_node.unset()) None
>>> # Unset with invalid keys does nothing. >>> print(config_node.unset(keys=['bar'])) None
>>> # Unset with valid keys removes the node from the node. >>> config_node.unset(keys=['foo']) {'value': 'Foo', 'state': '', 'comments': []}
>>> config_node {'value': {}, 'state': '', 'comments': []}
- walk(keys=None, no_ignore=False)[source]
Return all keylist - sub-node pairs below keys.
- Parameters:
- Yields:
- tuple - (keys, sub_node)
keys (list) - A list defining a hierarchy of node.value ‘keys’. If a sub-node is at the top level, and does not contain any node children, a null string will be prepended to the returned keylist.
sub_node (ConfigNode) - The config node at the position of keys.
Examples
>>> config_node = ConfigNode() >>> _ = config_node.set(['foo', 'bar'], 'Bar') >>> _ = config_node.set(['foo', 'baz'], 'Baz', ... state=ConfigNode.STATE_USER_IGNORED)
>>> # Walk over the full hierarchy. >>> [keys for keys, sub_node in config_node.walk()] [['foo'], ['foo', 'baz'], ['foo', 'bar']]
>>> # Walk over one branch of the hierarchy >>> [keys for keys, sub_node in config_node.walk(keys=['foo'])] [['foo', 'baz'], ['foo', 'bar']]
>>> # Skip over ignored nodes. >>> [keys for keys, sub_node in config_node.walk(no_ignore=True)] [['foo'], ['foo', 'bar']]
>>> # Invalid/non-existent keys. >>> [keys for keys, sub_node in config_node.walk( ... keys=['elephant'])] []
- class metomi.rose.config.ConfigNodeDiff[source]
Represent differences between two ConfigNode instances.
Examples
>>> # Create a new ConfigNodeDiff. >>> config_node_diff = ConfigNodeDiff() >>> config_node_diff.set_added_setting(keys=['bar'], ... data=('Bar', None, None,))
>>> # Create a new ConfigNode. >>> config_node = ConfigNode() >>> _ = config_node.set(keys=['baz'], value='Baz')
>>> # Apply the diff to the node. >>> config_node.add(config_node_diff) >>> [(keys, sub_node.get_value()) for keys, sub_node in ... config_node.walk()] [(['', 'bar'], 'Bar'), (['', 'baz'], 'Baz')]
>>> # Create a ConfigNodeDiff by comparing two ConfigNodes. >>> another_config_node = ConfigNode() >>> _ = another_config_node.set(keys=['bar'], value='NewBar') >>> _ = another_config_node.set(keys=['new'], value='New') >>> config_node_diff = ConfigNodeDiff() >>> config_node_diff.set_from_configs(config_node, ... another_config_node) >>> config_node_diff.get_added() [(('', 'new'), ('New', '', []))] >>> config_node_diff.get_removed() [(('', 'baz'), ('Baz', '', []))] >>> config_node_diff.get_modified() [(('', 'bar'), (('Bar', '', []), ('NewBar', '', [])))]
>>> # Inverse a ConfigNodeDiff. >>> reversed_diff = config_node_diff.get_reversed() >>> reversed_diff.get_added() [(('', 'baz'), ('Baz', '', []))]
- delete_removed()[source]
Deletes all ‘removed’ keys from this ConfigNodeDiff.
Examples
>>> config_node_diff = ConfigNodeDiff() >>> config_node_diff.set_removed_setting(['foo'], ... ('foo', None, None)) >>> config_node_diff.delete_removed() >>> config_node_diff.get_removed() []
- get_added()[source]
Return a list of tuples of added keys with their data.
The data is a tuple of value, state, comments, where value is set to None for sections.
- Returns:
- A list of the form [(keys, data), …]
keys - The position of an added setting.
data - Tuple of the form (value, state, comments) of the properties of the added setting.
- Return type:
Examples
>>> config_node_diff = ConfigNodeDiff() >>> config_node_diff.set_added_setting(['foo'], ... ('Foo', None, None)) >>> config_node_diff.get_added() [(('foo',), ('Foo', None, None))]
- get_all_keys()[source]
Return all keys affected by this ConfigNodeDiff.
- Returns:
A list containing any keys affected by this diff as tuples, e.g. (‘foo’, ‘bar’).
- Return type:
Examples
>>> config_node_diff = ConfigNodeDiff() >>> config_node_diff.set_added_setting(['foo'],('foo', None, None)) >>> config_node_diff.set_removed_setting(['bar'], ... ('bar', None, None)) >>> config_node_diff.get_all_keys() [('bar',), ('foo',)]
- get_as_opt_config()[source]
Return a ConfigNode such that main + new_node = main + diff.
Add all the added settings, add all the modified settings, add all the removed settings as user-ignored.
- Returns:
A new ConfigNode instance.
- Return type:
Example
>>> config_node_diff = ConfigNodeDiff() >>> config_node_diff.set_added_setting(['foo'], ... ('Foo', None, None,)) >>> config_node_diff.set_removed_setting(['bar'], ... ('Bar', None, None,)) >>> config_node = config_node_diff.get_as_opt_config() >>> list(config_node.walk()) [(['', 'bar'], {'value': 'Bar', 'state': '!', 'comments': []}), (['', 'foo'], {'value': 'Foo', 'state': '', 'comments': []})]
- get_modified()[source]
Return a dict of altered keys with before and after data.
The data is a list of two tuples (before and after) of value, state, comments, where value is set to None for sections.
- Returns:
- A list of the form [(keys, data), …]:
keys - The position of an added setting.
data - Tuple of the form (value, state, comments) for the properties of the setting before the modification.
old_data - The same tuple as data but representing the properties of the setting after the modification.
- Return type:
Examples
>>> config_node_diff = ConfigNodeDiff() >>> config_node_diff.set_modified_setting( ... ['foo'], ('Foo', None, None), ('New Foo', None, None)) >>> config_node_diff.get_modified() [(('foo',), (('Foo', None, None), ('New Foo', None, None)))]
- get_removed()[source]
Return a dict of removed keys with their data.
The data is a tuple of value, state, comments, where value is set to None for sections.
- Returns:
- A list of the form
[(keys, data), ...]
: keys - The position of an added setting.
data - Tuple of the form (value, state, comments) of the properties of the removed setting.
- A list of the form
- Return type:
Examples
>>> config_node_diff = ConfigNodeDiff() >>> config_node_diff.set_removed_setting(keys=['foo'], ... data=('foo', None, None)) >>> config_node_diff.get_removed() [(('foo',), ('foo', None, None))]
- get_reversed()[source]
Return an inverse (add->remove, etc) copy of this ConfigNodeDiff.
- Returns:
A new ConfigNodeDiff instance.
- Return type:
Examples
>>> # Create ConfigNodeDiff instance. >>> config_node_diff = ConfigNodeDiff() >>> config_node_diff.set_added_setting(['foo'],('foo', None, None)) >>> config_node_diff.set_removed_setting(['bar'], ... ('bar', None, None))
>>> # Generate reversed diff. >>> reversed_diff = config_node_diff.get_reversed() >>> reversed_diff.get_added() [(('bar',), ('bar', None, None))] >>> reversed_diff.get_removed() [(('foo',), ('foo', None, None))]
- set_added_setting(keys, data)[source]
Set a config setting to be “added” in this ConfigNodeDiff.
- Parameters:
Examples
>>> config_node_diff = ConfigNodeDiff() >>> config_node_diff.set_added_setting(['foo'], ... ('Foo', None, None,)) >>> config_node_diff.set_added_setting( ... ['bar'], ... ('Bar', ConfigNode.STATE_USER_IGNORED, 'Some Info',))
>>> config_node = ConfigNode() >>> config_node.add(config_node_diff)
>>> list(config_node.walk()) [(['', 'foo'], {'value': 'Foo', 'state': '', 'comments': []}), (['', 'bar'], {'value': 'Bar', 'state': '!', 'comments': 'Some Info'})]
- set_from_configs(config_node_1, config_node_2)[source]
Create diff data from two ConfigNode instances.
- Parameters:
config_node_1 (ConfigNode) – The node for which to base the diff off of.
config_node_2 (ConfigNode) – The “new” node the changes of which this diff will “apply”.
Example
>>> # Create two ConfigNode instances to compare. >>> config_node_1 = ConfigNode() >>> _ = config_node_1.set(keys=['foo']) >>> config_node_2 = ConfigNode() >>> _ = config_node_2.set(keys=['bar'])
>>> # Create a ConfigNodeDiff instance. >>> config_node_diff = ConfigNodeDiff() >>> config_node_diff.set_from_configs(config_node_1, config_node_2) >>> config_node_diff.get_added() [(('bar',), (None, '', []))] >>> config_node_diff.get_removed() [(('foo',), (None, '', []))]
- set_modified_setting(keys, old_data, data)[source]
Set a config setting to be “modified” in this ConfigNodeDiff.
If a property in both the old_data and data (new data) are both set to None then no change will be made to any pre-existing value.
- Parameters:
Examples
>>> # Create a ConfigNodeDiff. >>> config_node_diff = ConfigNodeDiff() >>> config_node_diff.set_modified_setting( ... ['foo'], ('Foo', None, None), ('New Foo', None, None))
>>> # Create a ConfigNode. >>> config_node = ConfigNode() >>> _ = config_node.set(keys=['foo'], value='Foo', ... comments='Some Info')
>>> # Apply the ConfigNodeDiff to the ConfigNode >>> config_node.add(config_node_diff) >>> config_node.get(keys=['foo']) {'value': 'New Foo', 'state': '', 'comments': 'Some Info'}
- set_removed_setting(keys, data)[source]
Set a config setting to be “removed” in this ConfigNodeDiff.
- Parameters:
Example
>>> # Create a ConfigNodeDiff. >>> config_node_diff = ConfigNodeDiff() >>> config_node_diff.set_removed_setting(['foo'], ('X', 'Y', 'Z'))
>>> # Create a ConfigNode. >>> config_node = ConfigNode() >>> _ = config_node.set(keys=['foo'], value='Foo', ... comments='Some Info')
>>> # Apply the ConfigNodeDiff to the ConfigNode >>> config_node.add(config_node_diff) >>> print(config_node.get(keys=['foo'])) None
- exception metomi.rose.config.ConfigSyntaxError(code, file_name, line_num, col_num, line)[source]
Exception raised for syntax error loading a configuration file.
- exc.code
Error code. Can be one of: ConfigSyntaxError.BAD_CHAR (bad characters in a name) ConfigSyntaxError.BAD_SYNTAX (general syntax error)
- exc.file_name
The name of the file that triggers the error.
- exc.line_num
The line number (from 1) in the file with the error.
- exc.col_num
The column number (from 0) in the line with the error.
- exc.line
The content of the line that contains the error.
Examples
>>> with open('config.conf', 'w+') as config_file: ... _ = config_file.write('[foo][foo]') >>> loader = ConfigLoader() >>> try: ... loader.load('config.conf') ... except ConfigSyntaxError as exc: ... print('Error (%s) in file "%s" at %s:%s' % ( ... exc.code, exc.file_name, exc.line_num, exc.col_num)) ... Error (BAD_CHAR) in file "..." at 1:5
- metomi.rose.config.dump(root, target=<_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>, sort_sections=None, sort_option_items=None, env_escape_ok=False)[source]
Shorthand for
ConfigDumper.dump()
.
- metomi.rose.config.load(source, root=None)[source]
Shorthand for
ConfigLoader.load()
.