diff --git a/voluptuous/schema_builder.py b/voluptuous/schema_builder.py index cdeb514..da20737 100644 --- a/voluptuous/schema_builder.py +++ b/voluptuous/schema_builder.py @@ -364,11 +364,13 @@ def validate_mapping(path, iterable, out): continue elif self.extra == ALLOW_EXTRA: out[key] = value + elif self.extra == REMOVE_EXTRA: + # ignore the key so it's removed from output + continue elif error: errors.append(error) - elif self.extra != REMOVE_EXTRA: + else: errors.append(er.Invalid('extra keys not allowed', key_path)) - # else REMOVE_EXTRA: ignore the key so it's removed from output # for any required keys left that weren't found and don't have defaults: for key in required_keys: diff --git a/voluptuous/tests/tests.py b/voluptuous/tests/tests.py index 77110d8..8d1b792 100644 --- a/voluptuous/tests/tests.py +++ b/voluptuous/tests/tests.py @@ -8,7 +8,7 @@ import pytest from voluptuous import ( - ALLOW_EXTRA, PREVENT_EXTRA, All, AllInvalid, Any, Clamp, Coerce, Contains, + ALLOW_EXTRA, PREVENT_EXTRA, REMOVE_EXTRA, All, AllInvalid, Any, Clamp, Coerce, Contains, ContainsInvalid, Date, Datetime, Email, EmailInvalid, Equal, ExactSequence, Exclusive, Extra, FqdnUrl, In, Inclusive, InInvalid, Invalid, IsDir, IsFile, Length, Literal, LiteralInvalid, Marker, Match, MatchInvalid, Maybe, MultipleInvalid, NotIn, @@ -1704,7 +1704,7 @@ def as_int(a): assert str(ctx.value.errors[1]) == "expecting a number @ data['four']" -def test_key3(): +def test_any_with_extra_allow(): schema = Schema( { Any("name", "area"): str, @@ -1712,7 +1712,32 @@ def test_key3(): }, extra=ALLOW_EXTRA, ) - schema( + + result = schema( + { + "name": "one", + "domain": "two", + "additional_key": "extra", + } + ) + + assert result == { + "name": "one", + "domain": "two", + "additional_key": "extra", + } + + +def test_any_with_extra_remove(): + schema = Schema( + { + Any("name", "area"): str, + "domain": str, + }, + extra=REMOVE_EXTRA, + ) + + result = schema( { "name": "one", "domain": "two", @@ -1720,6 +1745,54 @@ def test_key3(): } ) + assert result == { + "name": "one", + "domain": "two", + } + + +def test_any_with_extra_prevent(): + schema = Schema( + { + Any("name", "area"): str, + "domain": str, + }, + extra=PREVENT_EXTRA, + ) + + with pytest.raises(MultipleInvalid) as ctx: + schema( + { + "name": "one", + "domain": "two", + "additional_key": "extra", + } + ) + + assert len(ctx.value.errors) == 1 + assert str(ctx.value.errors[0]) == "not a valid value @ data['additional_key']" + + +def test_any_with_extra_none(): + schema = Schema( + { + Any("name", "area"): str, + "domain": str, + }, + ) + + with pytest.raises(MultipleInvalid) as ctx: + schema( + { + "name": "one", + "domain": "two", + "additional_key": "extra", + } + ) + + assert len(ctx.value.errors) == 1 + assert str(ctx.value.errors[0]) == "not a valid value @ data['additional_key']" + def test_coerce_enum(): """Test Coerce Enum"""