Skip to content

Commit

Permalink
Always evaluate {} as {}
Browse files Browse the repository at this point in the history
If you want a dict with any content, use 'dict', not
Schema({}, extra=ALLOW_EXTRA).
  • Loading branch information
Tuukka Mustonen committed Sep 24, 2016
1 parent 79d7ed8 commit 381b610
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 1 deletion.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,25 @@ token `extra` as a key:

```

However, an empty dict (`{}`) is treated as is. If you want to specify a list that can
contain anything, specify it as `dict`:

```pycon
>>> schema = Schema({}, extra=ALLOW_EXTRA) # don't do this
>>> schema({'extra': 1})
Traceback (most recent call last):
...
MultipleInvalid: not a valid value
>>> schema({})
{}
>>> schema = Schema(dict) # do this instead
>>> schema({})
{}
>>> schema({'extra': 1})
{'extra': 1}

```

#### Required dictionary keys

By default, keys in the schema are not required to be in the data:
Expand Down
2 changes: 1 addition & 1 deletion voluptuous/schema_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ def _compile(self, schema):
return lambda _, v: v
if isinstance(schema, Object):
return self._compile_object(schema)
if isinstance(schema, collections.Mapping):
if isinstance(schema, collections.Mapping) and len(schema):
return self._compile_dict(schema)
elif isinstance(schema, list) and len(schema):
return self._compile_list(schema)
Expand Down
34 changes: 34 additions & 0 deletions voluptuous/tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,40 @@ def test_empty_list_as_exact():
s([])


def test_empty_dict_as_exact():
# {} always evaluates as {}
s = Schema({})
assert_raises(Invalid, s, {'extra': 1})
s = Schema({}, extra=ALLOW_EXTRA) # this should not be used
assert_raises(Invalid, s, {'extra': 1})

# {...} evaluates as Schema({...})
s = Schema({'foo': int})
assert_raises(Invalid, s, {'foo': 1, 'extra': 1})
s = Schema({'foo': int}, extra=ALLOW_EXTRA)
s({'foo': 1, 'extra': 1})

# dict matches {} or {...}
s = Schema(dict)
s({'extra': 1})
s({})
s = Schema(dict, extra=PREVENT_EXTRA)
s({'extra': 1})
s({})

# nested {} evaluate as {}
s = Schema({
'inner': {}
}, extra=ALLOW_EXTRA)
assert_raises(Invalid, s, {'inner': {'extra': 1}})
s({})
s = Schema({
'inner': Schema({}, extra=ALLOW_EXTRA)
})
assert_raises(Invalid, s, {'inner': {'extra': 1}})
s({})


def test_schema_decorator_match_with_args():
@validate(int)
def fn(arg):
Expand Down

0 comments on commit 381b610

Please sign in to comment.