diff --git a/AUTHORS.rst b/AUTHORS.rst index 6b44851..a98c02b 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -37,6 +37,7 @@ Code contributions: - Jesper Schlegel (jesperschlegel) - J vanBemmel (jbemmel) - m-janicki +- Guo Jiarui (Jerry-val) Suggestions and bug reporting: diff --git a/CHANGES.rst b/CHANGES.rst index c4a347d..5ac7fbc 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,6 +1,11 @@ Changelog ========= +Unreleased +---------- + +* Fixing #300 CamelCase keys in dotted and indexed lookups with camel_killer_box (thanks to Guo Jiarui) + Version 7.4.1 ------------- diff --git a/box/box.py b/box/box.py index 8252643..2652611 100644 --- a/box/box.py +++ b/box/box.py @@ -620,6 +620,8 @@ def __getitem__(self, item, _ignore_default=False): if self._box_config["default_box"] and not _ignore_default: return self.__get_default(item) raise BoxKeyError(str(item)) from _exception_cause(err) + if first_item not in self.keys() and self._box_config["camel_killer_box"]: + first_item = _camel_killer(first_item) if first_item in self.keys(): if hasattr(self[first_item], "__getitem__"): return self[first_item][children] diff --git a/test/test_box.py b/test/test_box.py index e5c56e0..4d05376 100644 --- a/test/test_box.py +++ b/test/test_box.py @@ -539,6 +539,47 @@ def test_default_and_camel_killer_box(self): assert isinstance(killer_default_box.does_not_exist, Box) assert isinstance(killer_default_box["does_not_exist"], Box) + @pytest.mark.parametrize("default_box", [False, True]) + @pytest.mark.parametrize("conversion_box", [False, True]) + def test_camel_killer_box_dotted_lookup(self, default_box, conversion_box): + bx = Box( + {"someKey": [{"innerKey": "value"}], "otherKey": {"innerKey": "value"}}, + camel_killer_box=True, + box_dots=True, + default_box=default_box, + conversion_box=conversion_box, + ) + + for key in ( + "some_key[0].inner_key", + "some_key[0].innerKey", + "someKey[0].innerKey", + "SomeKey[0].InnerKey", + "other_key.inner_key", + "otherKey.innerKey", + "OtherKey.InnerKey", + ): + assert bx[key] == "value" + assert bx.to_dict() == {"some_key": [{"inner_key": "value"}], "other_key": {"inner_key": "value"}} + + @pytest.mark.parametrize("camel_killer_box, box_dots", [(False, True), (True, False)]) + def test_camel_killer_box_dotted_lookup_disabled(self, camel_killer_box, box_dots): + bx = Box({"some_key": {"inner_key": "value"}}, camel_killer_box=camel_killer_box, box_dots=box_dots) + + with pytest.raises(BoxKeyError): + bx["someKey.innerKey"] + assert bx.to_dict() == {"some_key": {"inner_key": "value"}} + + def test_camel_killer_box_dotted_lookup_exact_key(self): + bx = Box({"someKey": {"innerKey": "converted"}}, camel_killer_box=True, box_dots=True) + bx.update({"someKey": {"innerKey": "exact"}}) + + assert bx["someKey.innerKey"] == "exact" + assert bx["some_key.innerKey"] == "converted" + + bx.update({"someKey.innerKey": "literal"}) + assert bx["someKey.innerKey"] == "literal" + def test_box_modify_tuples(self): bx = Box(extended_test_dict, modify_tuples_box=True) assert bx.tuples_galore[0].item == 3