diff --git a/Makefile b/Makefile index ab0f16e..e6e77ec 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ venv: $(VENV)/bin/activate # Format the codebase using Black format: venv - @ '$(VENV)/bin/black' setup.py app + @ '$(VENV)/bin/black' setup.py app/*.py app/**/*.py .PHONY: format # Remove any temporary files diff --git a/app/exceptions.py b/app/exceptions.py deleted file mode 100644 index 1ebfe95..0000000 --- a/app/exceptions.py +++ /dev/null @@ -1,36 +0,0 @@ -"""Common exceptions raised by the program.""" -from typing import Union, List - - -class InvalidKeyError(Exception): - """Thrown when a config file contains an invalid key.""" - - def __init__(self, keys: Union[str, List[str]]): - """Create a new InvalidKeyError object with the given key. - - Args: - keys: the invalid key(s) - """ - if type(keys) == str: - keys = [keys] - - self.message = "Invalid key(s): {}".format(", ".join(keys)) - - super().__init__() - - -class MissingKeyError(Exception): - """Thrown when a required key is missing from a config.""" - - def __init__(self, keys: Union[str, List[str]]): - """Create a new MissingKeyError object with the given key. - - Args: - keys: the invalid key(s) - """ - if type(keys) == str: - keys = [keys] - - self.message = "Missing key(s): {}".format(", ".join(keys)) - - super().__init__() diff --git a/app/skeleton.py b/app/skeleton.py index c12bd45..b6e871a 100644 --- a/app/skeleton.py +++ b/app/skeleton.py @@ -1,6 +1,33 @@ """Handles merging with the skeleton config.""" from typing import Dict -from .exceptions import InvalidKeyError, MissingKeyError + + +class InvalidKeyError(Exception): + """Thrown when a config file contains an invalid key.""" + + def __init__(self, key: str): + """Create a new InvalidKeyError object with the given key. + + Args: + key: the invalid key + """ + self.message = "Invalid key: {}".format(key) + + super().__init__(key) + + +class MissingKeyError(Exception): + """Thrown when a required key is missing from a config.""" + + def __init__(self, key: str): + """Create a new MissingKeyError object with the given key. + + Args: + key: the invalid key + """ + self.message = "Missing key: {}".format(key) + + super().__init__(key) def merge(*dicts: [Dict]) -> Dict: @@ -66,10 +93,10 @@ def merge_with_skeleton(data: Dict, skel: Dict) -> Dict: * Split info less complex functions """ # First, check for illegal keys - invalid_keys = list(filter(lambda k: k not in skel, data)) + key = next(key not in skel for key in data) - if invalid_keys: - raise InvalidKeyError(invalid_keys) + if key: + raise InvalidKeyError(key) # Then, check the default values for key, value in skel.items(): diff --git a/renovate.json b/renovate.json index 9775346..dca187a 100644 --- a/renovate.json +++ b/renovate.json @@ -1,3 +1,10 @@ { - "$schema": "https://docs.renovatebot.com/renovate-schema.json" + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "packageRules": [ + { + "matchUpdateTypes": ["minor", "patch", "pin", "digest"], + "automerge": true, + "automergeType": "branch" + } + ] } diff --git a/tests/test_dict_merge.py b/tests/test_dict_merge.py deleted file mode 100644 index 2da81bf..0000000 --- a/tests/test_dict_merge.py +++ /dev/null @@ -1,69 +0,0 @@ -"""Tests for the skeleton module.""" -from app.skeleton import merge - - -def test_merge_empty(): - """Test correct response for an empty merge.""" - assert merge() == {} - - -def test_merge_single(): - """Test merge command with a single input.""" - assert merge({}) == {} - - dic = {"test": "value", "test2": "value2"} - - assert merge(dic) == dic - - -def test_merge_double_no_overlap(): - """Test merge command with two non-overlapping inputs.""" - d1 = {"test": "value", "test2": "value2"} - d2 = {"test3": "value3"} - d_res = {"test": "value", "test2": "value2", "test3": "value3"} - - assert merge(d1, d2) == d_res - - -def test_merge_double_overlap(): - """Test merge command with two overlapping inputs.""" - d1 = {"test": "value", "test2": "value2"} - d2 = {"test2": "value3"} - d_res = {"test": "value", "test2": "value3"} - - assert merge(d1, d2) == d_res - - -def test_merge_triple_no_overlap(): - """Test merge command with three non-overlapping inputs. - - This test tells us that the recursion works. - """ - d1 = {"test": "value", "test2": "value2"} - d2 = {"test3": "value3"} - d3 = {"test4": "value4"} - d_res = { - "test": "value", - "test2": "value2", - "test3": "value3", - "test4": "value4", - } - - assert merge(d1, d2, d3) == d_res - - -def test_merge_triple_overlap(): - """Test merge command with three overlapping inputs. - - This test tells us that the recursion works. - """ - d1 = {"test": "value", "test2": "value2"} - d2 = {"test3": "value3"} - d3 = {"test2": "value4"} - d_res = { - "test": "value", - "test2": "value4", - "test3": "value3", - } - - assert merge(d1, d2, d3) == d_res diff --git a/tests/test_skeleton.py b/tests/test_skeleton.py index 6cebba6..2da81bf 100644 --- a/tests/test_skeleton.py +++ b/tests/test_skeleton.py @@ -1,70 +1,69 @@ -"""Tests wether the skeleton merge works.""" -from app.skeleton import merge_with_skeleton, MissingKeyError, InvalidKeyError -from app.exceptions import InvalidKeyError, MissingKeyError -import pytest +"""Tests for the skeleton module.""" +from app.skeleton import merge -def test_single_invalid_key(): - """Tests wether an InvalidKeyError is correctly thrown for a single key.""" - data = { - "test": 1, - "test2": "test" - } - skel = { - "test": None, +def test_merge_empty(): + """Test correct response for an empty merge.""" + assert merge() == {} + + +def test_merge_single(): + """Test merge command with a single input.""" + assert merge({}) == {} + + dic = {"test": "value", "test2": "value2"} + + assert merge(dic) == dic + + +def test_merge_double_no_overlap(): + """Test merge command with two non-overlapping inputs.""" + d1 = {"test": "value", "test2": "value2"} + d2 = {"test3": "value3"} + d_res = {"test": "value", "test2": "value2", "test3": "value3"} + + assert merge(d1, d2) == d_res + + +def test_merge_double_overlap(): + """Test merge command with two overlapping inputs.""" + d1 = {"test": "value", "test2": "value2"} + d2 = {"test2": "value3"} + d_res = {"test": "value", "test2": "value3"} + + assert merge(d1, d2) == d_res + + +def test_merge_triple_no_overlap(): + """Test merge command with three non-overlapping inputs. + + This test tells us that the recursion works. + """ + d1 = {"test": "value", "test2": "value2"} + d2 = {"test3": "value3"} + d3 = {"test4": "value4"} + d_res = { + "test": "value", + "test2": "value2", + "test3": "value3", + "test4": "value4", } - with pytest.raises(InvalidKeyError) as e_info: - merge_with_skeleton(data, skel) - - assert e_info.value.message == "Invalid key(s): test2" + assert merge(d1, d2, d3) == d_res -def test_multiple_invalid_keys(): - """Tests wether an InvalidKeyError is thrown for multiple keys.""" - data = { - "test": 1, - "test2": "test", - "test3": "test", - } - skel = { - "test": None, +def test_merge_triple_overlap(): + """Test merge command with three overlapping inputs. + + This test tells us that the recursion works. + """ + d1 = {"test": "value", "test2": "value2"} + d2 = {"test3": "value3"} + d3 = {"test2": "value4"} + d_res = { + "test": "value", + "test2": "value4", + "test3": "value3", } - with pytest.raises(InvalidKeyError) as e_info: - merge_with_skeleton(data, skel) - - assert e_info.value.message == "Invalid key(s): test2, test3" - - -def test_single_missing_key(): - """Tests wether a MissingKeyError is correctly thrown for a single key.""" - data = { - "test": 1, - } - skel = { - "test": None, - "test2": None, - } - - with pytest.raises(MissingKeyError) as e_info: - merge_with_skeleton(data, skel) - - assert e_info.value.message == "Missing key(s): test2" - - -def test_multiple_missing_keys(): - """Tests wether a MissingKeyError is correctly thrown for multiple keys.""" - data = { - "test": 1, - } - skel = { - "test": None, - "test2": None, - "test3": None, - } - - with pytest.raises(MissingKeyError) as e_info: - merge_with_skeleton(data, skel) - - assert e_info.value.message == "Missing key(s): test2, test3" + assert merge(d1, d2, d3) == d_res