def load_config( conf_files: t.Union[t.Iterable[str], str, None] = None) -> t.Dict: """ Load configuration. Load configuration from all found conf files. The default configuration is loaded followed by a system-wide location, user-location, and then any files specified in the ``conf_files`` parameter. Toplevel keys in later files will overwrite earlier those same keys in earlier files. :arg conf_files: An iterable of conf_files to load configuration information from. :returns: A dict containing the configuration. """ flog = mlog.fields(func='load_config') flog.debug('Enter') if isinstance(conf_files, str): conf_files = (conf_files, ) elif conf_files is None: conf_files = () user_config_file = os.path.expanduser(USER_CONFIG_FILE) available_files = find_config_files( itertools.chain((SYSTEM_CONFIG_FILE, user_config_file), conf_files)) includes = list(available_files) flog.debug('loading config files') # Perky has some bugs that prevent this simple way from working: # https://github.com/ansible-community/antsibull/pull/118 # cfg = {'includes': includes} # cfg = perky.includes(cfg, recursive=True) # Workaround for above bug. Note that includes specified in the config files will not work # but we can just add that as a new feature when perky gets it working. cfg = {} for filename in includes: new_cfg = perky.load(filename) cfg.update(new_cfg) flog.debug('validating configuration') # Note: We parse the object but discard the model because we want to validate the config but let # the context handle all setting of defaults ConfigModel.parse_obj(cfg) flog.fields(config=cfg).debug('Leave') return cfg
def read_config(filename: str) -> ConfigModel: """ Parse a config file and return the data from it. :arg filename: The filename of the config file to parse. :returns: A ConfigModel model containing the config data. """ flog = mlog.fields(func='read_config') flog.debug('Enter') filename = os.path.abspath(filename) flog.fields(filename=filename).info('loading config file') raw_config_data = perky.load(filename) flog.debug('Validatinging the config file data') # Note: We parse the object but discard the model because we want to validate the config but let # the context handle all setting of defaults ConfigModel.parse_obj(raw_config_data) flog.debug('Leave') return raw_config_data
def test_perky_include_nested(self): with perky.pushd("include_nested"): root = perky.load("main.pky", pragmas={'include': perky.pragma_include()}) self.assertEqual( root, { 'a': '1', 'b': { 'ba': '1', 'bb': '2', 'bc': '3', 'bd': '4', 'nested_dict': { 'x': '3', 'y': '2', 'z': ['1', '2', '3', '4'] }, 'nested_list': ['a', 'b', 'c'], }, 'c': '3', 'd': '4' })
def test_perky_include_path(self): with perky.pushd("include_path"): root = perky.load( "dir1/main.pky", pragmas={'include': perky.pragma_include(['dir1', 'dir2'])}) self.assertEqual(root, dict(zip("abc", "345")))
def test_perky_include_dict(self): with perky.pushd("include_dict"): root = perky.load("main.pky", pragmas={'include': perky.pragma_include()}) self.assertEqual(root, dict(zip("abcd", "1234")))
def test_perky_include_list(self): with perky.pushd("include_list"): root = perky.load("main.pky", root=[], pragmas={'include': perky.pragma_include()}) self.assertEqual(root, list("abcd"))
def test_read_file(self): test_input = perky.load("test_input.txt", encoding="utf-8") self.assertIsNotNone(self, test_input)