Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added validation for default values #324

Merged
merged 1 commit into from
Feb 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
## [Unreleased]

- [#280](https://github.com/alecthomas/voluptuous/pull/280): Making
`IsDir()`, `IsFile()` and `PathExists()` consistent between different python versions.
`IsDir()`, `IsFile()` and `PathExists()` consistent between different python versions.
- [#279](https://github.com/alecthomas/voluptuous/pull/279):
Treat Python 2 old-style classes like types when validating.
- [324](https://github.com/alecthomas/voluptuous/pull/324):
Default values MUST now pass validation just as any regular value.

## [0.10.5]

Expand Down
33 changes: 19 additions & 14 deletions voluptuous/schema_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,11 +334,25 @@ def _compile_mapping(self, schema, invalid_msg=None):

def validate_mapping(path, iterable, out):
required_keys = all_required_keys.copy()
# keeps track of all default keys that haven't been filled
default_keys = all_default_keys.copy()

# Build a map of all provided key-value pairs.
# The type(out) is used to retain ordering in case a ordered
# map type is provided as input.
key_value_map = type(out)()
for key, value in iterable:
key_value_map[key] = value

# Insert default values for non-existing keys.
for key in all_default_keys:
if not isinstance(key.default, Undefined) and \
key.schema not in key_value_map:
# A default value has been specified for this missing
# key, insert it.
key_value_map[key.schema] = key.default()

error = None
errors = []
for key, value in iterable:
for key, value in key_value_map.items():
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure this line is what's causing the test failure. key_value_map is not an OrderedDict so it fails the ordering guarantee.

key_path = path + [key]
remove_key = False

Expand Down Expand Up @@ -388,12 +402,10 @@ def validate_mapping(path, iterable, out):
required_keys.discard(skey)
break

# Key and value okay, mark any Required() fields as found.
# Key and value okay, mark as found in case it was
# a Required() field.
required_keys.discard(skey)

# No need for a default if it was filled
default_keys.discard(skey)

break
else:
if remove_key:
Expand All @@ -405,13 +417,6 @@ def validate_mapping(path, iterable, out):
errors.append(er.Invalid('extra keys not allowed', key_path))
# else REMOVE_EXTRA: ignore the key so it's removed from output

# set defaults for any that can have defaults
for key in default_keys:
if not isinstance(key.default, Undefined): # if the user provides a default with the node
out[key.schema] = key.default()
if key in required_keys:
required_keys.discard(key)

# for any required keys left that weren't found and don't have defaults:
for key in required_keys:
msg = key.msg if hasattr(key, 'msg') and key.msg else 'required key not provided'
Expand Down