diff --git a/schema.py b/schema.py index f4f5460..0788117 100644 --- a/schema.py +++ b/schema.py @@ -114,7 +114,8 @@ def validate(self, data): data = Schema(dict, error=e).validate(data) new = type(data)() # new - is a dict of the validated values x = None - coverage = set() # matched schema keys + matched_schema_keys = set() + matched_input_keys = set() # for each key and value find a schema entry matching them, if any sorted_skeys = sorted(s, key=priority) for key, value in data.items(): @@ -133,7 +134,8 @@ def validate(self, data): x = _x raise else: - coverage.add(skey) + matched_schema_keys.add(skey) + matched_input_keys.add(key) valid = True break if valid: @@ -143,12 +145,12 @@ def validate(self, data): raise SchemaError(['Invalid value for key %r' % key] + x.autos, [e] + x.errors) required = set(k for k in s if type(k) is not Optional) - if not required.issubset(coverage): - missing_keys = required - coverage + if not required.issubset(matched_schema_keys): + missing_keys = required - matched_schema_keys s_missing_keys = ", ".join(repr(k) for k in missing_keys) raise SchemaError('Missing keys: ' + s_missing_keys, e) if len(new) != len(data): - wrong_keys = set(data.keys()) - set(new.keys()) + wrong_keys = set(data.keys()) - matched_input_keys s_wrong_keys = ', '.join(repr(k) for k in sorted(wrong_keys, key=repr)) raise SchemaError('Wrong keys %s in %r' % (s_wrong_keys, data), @@ -156,7 +158,7 @@ def validate(self, data): # Apply default-having optionals that haven't been used: defaults = set(k for k in s if type(k) is Optional and - hasattr(k, 'default')) - coverage + hasattr(k, 'default')) - matched_schema_keys for default in defaults: new[default.key] = default.default diff --git a/test_schema.py b/test_schema.py index e124fc9..0e42379 100644 --- a/test_schema.py +++ b/test_schema.py @@ -415,3 +415,16 @@ def test_issue_83_iterable_validation_return_type(): data = TestSetType(["test", "strings"]) s = Schema(set([str])) assert isinstance(s.validate(data), TestSetType) + + +def test_issue_80_wrong_keys_exception(): + s = Schema({And(str, Use(str.lower), 'id'): int}) + data = {'Id': 10, 'Name': 'me'} + with SE: + try: + s.validate(data) + except SchemaError as e: + msg = e.args[0] + assert msg.count("'Id'") == 1 + assert msg.count("'Name'") == 2 + raise