feat: constants support

This commit is contained in:
Divyansh Singh 2023-03-24 02:39:37 +05:30
parent 9bec029b4f
commit 6f300b0079
3 changed files with 38 additions and 3 deletions

View file

@ -81,7 +81,8 @@ class Include_constructor(ruamel.yaml.SafeConstructor):
def load_configuration(filename): def load_configuration(filename):
''' '''
Load the given configuration file and return its contents as a data structure of nested dicts Load the given configuration file and return its contents as a data structure of nested dicts
and lists. and lists. Also, replace any "{constant}" strings with the value of the "constant" key in the
"constants" section of the configuration file.
Raise ruamel.yaml.error.YAMLError if something goes wrong parsing the YAML, or RecursionError Raise ruamel.yaml.error.YAMLError if something goes wrong parsing the YAML, or RecursionError
if there are too many recursive includes. if there are too many recursive includes.
@ -98,7 +99,15 @@ def load_configuration(filename):
yaml = ruamel.yaml.YAML(typ='safe') yaml = ruamel.yaml.YAML(typ='safe')
yaml.Constructor = Include_constructor_with_include_directory yaml.Constructor = Include_constructor_with_include_directory
return yaml.load(open(filename)) with open(filename) as f:
file_contents = f.read()
config = yaml.load(file_contents)
if config and 'constants' in config:
for key, value in config['constants'].items():
file_contents = file_contents.replace(f'{{{key}}}', str(value))
config = yaml.load(file_contents)
del config['constants']
return config
DELETED_NODE = object() DELETED_NODE = object()

View file

@ -3,6 +3,17 @@ required:
- location - location
additionalProperties: false additionalProperties: false
properties: properties:
constants:
type: object
description: |
Constants to use in the configuration file. All occurences of the
constant name within culy braces will be replaced with the value.
For example, if you have a constant named "hostname" with the value
"myhostname", then the string "{hostname}" will be replaced with
"myhostname" in the configuration file.
example:
hostname: myhostname
prefix: myprefix
location: location:
type: object type: object
description: | description: |

View file

@ -10,8 +10,23 @@ from borgmatic.config import load as module
def test_load_configuration_parses_contents(): def test_load_configuration_parses_contents():
builtins = flexmock(sys.modules['builtins']) builtins = flexmock(sys.modules['builtins'])
builtins.should_receive('open').with_args('config.yaml').and_return('key: value') config_file = io.StringIO('key: value')
config_file.name = 'config.yaml'
builtins.should_receive('open').with_args('config.yaml').and_return(config_file)
assert module.load_configuration('config.yaml') == {'key': 'value'}
def test_load_configuration_replaces_constants():
builtins = flexmock(sys.modules['builtins'])
config_file = io.StringIO(
'''
constants:
key: value
key: {key}
'''
)
config_file.name = 'config.yaml'
builtins.should_receive('open').with_args('config.yaml').and_return(config_file)
assert module.load_configuration('config.yaml') == {'key': 'value'} assert module.load_configuration('config.yaml') == {'key': 'value'}