Repository: alecthomas/voluptuous

Issue:
NamedTuples do not validate as tuples or named tuples
```
from collections import namedtuple

NT = namedtuple('NT', ['a', 'b'])

nt = NT(1, 2)
t = (1, 2)

Schema((int, int))(nt)    # => Invalid
Schema((int, int))(t)     # => Valid
Schema(NT(int, int))(nt)  # => Invalid
Schema(NT(int, int))(t)   # => Valid
````

Given that `NT(1, 2) == (1, 2) => True` I'd expect all of the above cases to return as valid.

Discussion:

Patch:
diff --git a/voluptuous/schema_builder.py b/voluptuous/schema_builder.py
index 053d951..9e4b622 100644
--- a/voluptuous/schema_builder.py
+++ b/voluptuous/schema_builder.py
@@ -106,6 +106,10 @@ ALLOW_EXTRA = 1  # extra keys not in schema will be included in output
 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
@@ -557,7 +561,11 @@ class Schema(object):
                     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
 


Test patch:
diff --git a/voluptuous/tests/tests.py b/voluptuous/tests/tests.py
index 8759b13..7ddd092 100644
--- a/voluptuous/tests/tests.py
+++ b/voluptuous/tests/tests.py
@@ -1,4 +1,5 @@
 import copy
+import collections
 from nose.tools import assert_equal, assert_raises, assert_true
 
 from voluptuous import (
@@ -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)