diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c89e077..33eabea 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,7 +4,7 @@ ChangeLog 8.2 (unreleased) ---------------- -- Nothing changed yet. +- Use recursive update on grocker config 8.1 (2024-02-23) diff --git a/src/grocker/helpers.py b/src/grocker/helpers.py index a6126a5..45c42df 100644 --- a/src/grocker/helpers.py +++ b/src/grocker/helpers.py @@ -21,6 +21,16 @@ import importlib_resources as resources # type: ignore +def deep_update(initial_mapping, updating_mapping): + updated_mapping = initial_mapping.copy() + for k, v in updating_mapping.items(): + if k in updated_mapping and isinstance(updated_mapping[k], dict) and isinstance(v, dict): + updated_mapping[k] = deep_update(updated_mapping[k], v) + else: + updated_mapping[k] = v + return updated_mapping + + def copy_resources(package, destination): os.makedirs(destination, exist_ok=True) diff --git a/src/grocker/utils.py b/src/grocker/utils.py index 3671785..b313a4a 100644 --- a/src/grocker/utils.py +++ b/src/grocker/utils.py @@ -108,11 +108,9 @@ def parse_config(config_paths, **kwargs): for config_path in config_paths: project_config = helpers.load_yaml(config_path) - config.update(project_config or {}) + config = helpers.deep_update(config, project_config or {}) - config.update({k: v for k, v in kwargs.items() if v}) - - return config + return helpers.deep_update(config, {k: v for k, v in kwargs.items() if v}) class GrockerRequirement: diff --git a/tests/test_config.py b/tests/test_config.py index 0b5c4dd..29e9957 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -8,6 +8,8 @@ import textwrap import unittest +import yaml + import grocker.builders as grocker_builders import grocker.utils as grocker_utils @@ -25,7 +27,7 @@ def mkchtmpdir(): def write_file(directory, name, content): with open(os.path.join(directory, name), 'w') as fp: - fp.write(textwrap.dedent(content)) + fp.write(yaml.dump(yaml.safe_load(content))) class ConfigTestCase(unittest.TestCase): @@ -37,11 +39,14 @@ class ConfigTestCase(unittest.TestCase): first_config_content = """ file: first.yml - dependencies: first.yml + dependencies: + run: first.yml """[1:-1] second_config_content = """ file: second.yml + dependencies: + build: second.yml runtime: second.yml """[1:-1] @@ -54,7 +59,8 @@ def test_parse_config(self): config = grocker_utils.parse_config(['first.yml', 'second.yml']) self.assertNotIn('not_used_key', config) # .grocker.yml is not read self.assertIn('entrypoint_name', config) # grocker internal config is read - self.assertEqual(config.get('dependencies'), 'first.yml') # from first.yml + self.assertEqual(config.get('dependencies').get('run'), 'first.yml') # from first.yml + self.assertEqual(config.get('dependencies').get('build'), 'second.yml') # from second.yml self.assertEqual(config.get('runtime'), 'second.yml') # from second.yml self.assertEqual(config.get('file'), 'second.yml') # from second.yml