Commits

Jean-Tiare Le Bigot committed 5a00de8

100% coverage Yeeeeeeeah \!

  • Participants
  • Parent commits 7ac07e3

Comments (0)

Files changed (3)

tests/functional/test_schema.py

 
 import unittest
 
+MSG = "custom msg"
+
 class TestSchema(unittest.TestCase):
-    def test_init(self): pass
+    def test_dict(self):
+        from voluptuous import Schema, InvalidList, Coerce, Required
+
+        validate = Schema({'one': 'two', 'three': 'four'})
+
+        # invalid dictionary value
+        self.assertRaisesRegexp(InvalidList, 'not a valid value', validate, {'one': 'three'})
+        # invalid key
+        self.assertRaisesRegexp(InvalidList, 'extra key', validate, {'two': 'three'})
+
+        # validate int type
+        validate = Schema({'one': 'two', 'three': 'four', int: str})
+        self.assertEqual({10: 'twenty'}, validate({10: 'twenty'}))
+        self.assertRaisesRegexp(InvalidList, 'extra key', validate, {'10': 'twenty'})
+
+        # validate with type coercion
+        validate = Schema({'one': 'two', 'three': 'four', Coerce(int): str})
+        self.assertEqual({10: 'twenty'}, validate({'10': 'twenty'}))
+
+        # test required key with defaults
+        validate = Schema({Required(1,default='toto'):str})
+        self.assertEqual({1: 'toto'}, validate({}))
+
+    def test_list(self):
+        from voluptuous import Schema, InvalidList
+
+        self.assertEqual([1,2,3], Schema([1,2,3,4,5,6])([1,2,3]))
+        self.assertEqual([1,2,3], Schema([int])([1,2,3]))
+
+        # extra entry
+        self.assertRaisesRegexp(InvalidList, "value", Schema([1,2,3,4,5,6]), [0,1,2,3])
+
+
+    def test_msg(self):
+        from voluptuous import Schema, InvalidList, Msg
+
+        # custom message for direct descendants errors
+        validate = Schema(Msg(['one', 'two', int], MSG))
+        self.assertRaisesRegexp(InvalidList, MSG, validate, ['three'])
+
+        # regular message for indirect descendants
+        validate = Schema(Msg([['one', 'two', int]], MSG))
+        self.assertRaisesRegexp(InvalidList, "invalid", validate, [['three']])
+
+    def test_any_all(self):
+        from voluptuous import Schema, Any, All, InvalidList, Coerce
+
+        validate = Schema(Any('true', 'false', All(Any(int, bool), Coerce(bool))))
+        self.assertTrue(validate('true'))
+        self.assertTrue(validate(1))
+        self.assertRaisesRegexp(InvalidList, "valid", validate, "toto")
+
+        validate = Schema(Any({int: {int:str}}, bool))
+        self.assertRaises(InvalidList, validate, {1:{"2":"titi"}})
+

tests/unit/test_validators.py

 # -*- coding: utf-8 -*-
 
-import unittest
+import unittest, mock
 
 MSG = "custom msg"
 
         self.assertRaisesRegexp(Invalid, MSG, Boolean(MSG), "toto")
         self.assertRaisesRegexp(Invalid, "expected", Boolean(), "toto")
 
+    @mock.patch('__builtin__.bool')
+    def test_boolean_error(self, m_bool):
+        from voluptuous import Boolean, Invalid
+
+        m_bool.side_effect = ValueError
+        self.assertRaisesRegexp(Invalid, "expected", Boolean(), None)
+
     def test_match(self):
         from voluptuous import Match, Invalid
 

voluptuous/voluptuous.py

             raise InvalidList([e])
 
     def _validate_dict(self, path, schema, data):
-        """Validate a dictionary.
+        """Validates ``data`` dictionnary. If the schema is empty and extra keys
+        are explicitely allowed, ``data`` is returned immediately.
 
-        A dictionary schema can contain a set of values, or at most one
-        validator function/type.
-
-        A dictionary schema will only validate a dictionary:
-
-            >>> validate = Schema({})
-            >>> validate([])
-            Traceback (most recent call last):
-            ...
-            InvalidList: expected a dictionary
-
-        An invalid dictionary value:
-
-            >>> validate = Schema({'one': 'two', 'three': 'four'})
-            >>> validate({'one': 'three'})
-            Traceback (most recent call last):
-            ...
-            InvalidList: not a valid value for dictionary value @ data['one']
-
-        An invalid key:
-
-            >>> validate({'two': 'three'})
-            Traceback (most recent call last):
-            ...
-            InvalidList: extra keys not allowed @ data['two']
-
-        Validation function, in this case the "int" type:
-
-            >>> validate = Schema({'one': 'two', 'three': 'four', int: str})
-
-        Valid integer input:
-
-            >>> validate({10: 'twenty'})
-            {10: 'twenty'}
-
-        By default, a "type" in the schema (in this case "int") will be used
-        purely to validate that the corresponding value is of that type. It
-        will not coerce the value:
-
-            >>> validate({'10': 'twenty'})
-            Traceback (most recent call last):
-            ...
-            InvalidList: extra keys not allowed @ data['10']
-
-        Wrap them in the Coerce() function to achieve this:
-
-            >>> validate = Schema({'one': 'two', 'three': 'four',
-            ...                    Coerce(int): str})
-            >>> validate({'10': 'twenty'})
-            {10: 'twenty'}
-
-        (This is to avoid unexpected surprises.)
+        This handles the ``Required``, ``Optional`` and ``Extra`` markers.
+        It has also support for default values if provided in ``default``
+        attribute
         """
         # Empty schema when extra allowed, allow any data list.
         if (not schema and self.extra):
                         new_key = self.validate(key_path, skey, key)
                         break  # Match found !
                     except Invalid, e:
-                        if len(e.path) > len(key_path):
-                            raise
                         error = e
             # No matching rule ?
             else:
                     out[key] = value
                 else:
                     errors.append(Invalid('extra keys not allowed', key_path))
-                continue  # Next key
+                # go to next key
+                continue  # pragma: no coverage (coverage bug...)
 
             # Second, validate data against the rule we just found
             try:
         # Check that all required keys are supplied or have default values
         for key in required_keys:
             if getattr(key, 'default', None) is not None:
-                out[key] = key.default
+                out[key.schema] = key.default
             else:
                 errors.append(Invalid('required key not provided', path + [key]))
 
             else:
                 errors.append(Invalid('invalid list value', index_path))
 
-        # handle errors an return
+        # handle errors and return
         if errors:
             raise InvalidList(errors)
 
 
 def Msg(schema, msg):
     """Report a user-friendly message if a schema fails to validate.
-
-    >>> validate = Schema(
-    ...   Msg(['one', 'two', int],
-    ...       'should be one of "one", "two" or an integer'))
-    >>> validate(['three'])
-    Traceback (most recent call last):
-    ...
-    InvalidList: should be one of "one", "two" or an integer
-
-    Messages are only applied to invalid direct descendants of the schema:
-
-    >>> validate = Schema(Msg([['one', 'two', int]], 'not okay!'))
-    >>> validate([['three']])
-    Traceback (most recent call last):
-    ...
-    InvalidList: invalid list value @ data[0][0]
+    Messages are only applied to invalid direct descendants of the schema.
     """
     schema = Schema(schema)
     def f(v):
 
     :param msg: Message to deliver to user if validation fails.
     :returns: Return value of the first validator that passes.
-
-    >>> validate = Schema(Any('true', 'false',
-    ...                       All(Any(int, bool), Coerce(bool))))
-    >>> validate('true')
-    'true'
-    >>> validate(1)
-    True
-    >>> validate('moo')
-    Traceback (most recent call last):
-    ...
-    InvalidList: no valid value found
     """
     msg = kwargs.pop('msg', None)
     schemas = [Schema(val) for val in validators]
             except Invalid, e:
                 if len(e.path) > 1:
                     raise
-                pass
+                pass  # pragma: no coverage (still and again a coverage bug)
         else:
             raise Invalid(msg or 'no valid value found')
     return f