Skip to content

Commit

Permalink
Validate namedtuples as tuples
Browse files Browse the repository at this point in the history
namedtuples can't be initialized with a tuple. Detect that datatype and
initialize it with *args notation.

Resolves alecthomas#230
  • Loading branch information
dangitall committed Oct 9, 2016
1 parent 99fb7bd commit cfc8536
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 1 deletion.
10 changes: 9 additions & 1 deletion voluptuous/schema_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ def iteritems(d):
REMOVE_EXTRA = 2 # extra keys not in schema will be excluded from output


def _isnamedtuple(obj):
return isinstance(obj, tuple) and hasattr(obj, '_fields')


class Undefined(object):
def __nonzero__(self):
return False
Expand Down Expand Up @@ -557,7 +561,11 @@ def validate_sequence(path, data):
errors.append(invalid)
if errors:
raise er.MultipleInvalid(errors)
return type(data)(out)

if _isnamedtuple(data):
return type(data)(*out)
else:
return type(data)(out)

return validate_sequence

Expand Down
12 changes: 12 additions & 0 deletions voluptuous/tests/tests.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import copy
import collections
from nose.tools import assert_equal, assert_raises, assert_true

from voluptuous import (
Expand Down Expand Up @@ -699,3 +700,14 @@ def test_number_validation_with_valid_precision_scale_yield_decimal_false():
schema = Schema({"number" : Number(precision=6, scale=2, yield_decimal=False)})
out_ = schema({"number": '1234.00'})
assert_equal(out_.get("number"), '1234.00')


def test_named_tuples_validate_as_tuples():
NT = collections.namedtuple('NT', ['a', 'b'])
nt = NT(1, 2)
t = (1, 2)

Schema((int, int))(nt)
Schema((int, int))(t)
Schema(NT(int, int))(nt)
Schema(NT(int, int))(t)

0 comments on commit cfc8536

Please sign in to comment.