예제 #1
0
 def test_str_schema(self):
     """simple schema for an item with type"""
     schema = {"type": str}
     data1 = "foo"
     err1 = ["foo"]
     err2 = {"foo": "bar"}
     self.assertEqual(validate(data1, schema), None)
     self.assertEqual(validate(err1, schema),
                      "Invalid type <class 'list'>, expected <class 'str'>")
     self.assertEqual(validate(err2, schema),
                      "Invalid type <class 'dict'>, expected <class 'str'>")
예제 #2
0
 def test_schema_with_check(self):
     """test a schema with a check function"""
     def checker(data):
         if data > 42:
             return "Data should not be greater than 42"
     schema = {"type": int, "check": checker}
     data1 = 12
     err1 = 32.434
     err2 = "meme"
     err3 = 434234
     self.assertEqual(validate(data1, schema), None)
     self.assertEqual(validate(err1, schema),
                      "Invalid type <class 'float'>, expected <class 'int'>")
     self.assertEqual(validate(err2, schema),
                      "'>' not supported between instances of 'str' and 'int'")
     self.assertEqual(validate(err3, schema),
                      "Data should not be greater than 42")
예제 #3
0
 def test_list_schema(self):
     """a list schema should apply its subschema to all of its items"""
     def checker(data):
         if data > 42:
             raise Exception("Data should not be greater than 42")
     inner_schema = {"type": int, "check": checker}
     schema = {
         "items": inner_schema
     }
     all_good = list(range(10, 20))
     one_bad = [0, 50, 25]
     two_bad = [0.0, 10, "meme"]
     self.assertEqual(validate(all_good, schema), None)
     self.assertEqual(validate(one_bad, schema), {1: "Data should not be greater than 42"})
     self.assertEqual(validate(two_bad, schema), {
         0: "Invalid type <class 'float'>, expected <class 'int'>",
         2: "'>' not supported between instances of 'str' and 'int'"
     })
예제 #4
0
    def test_dict_schema(self):
        """a dict schema should apply itself to underlying values as necessary"""
        def checker(amt):
            if amt < 100:
                raise Exception("Must be greater than 100")
        schema = {
            "properties": {
                "name": {
                    "type": str,
                    "required": False
                },
                "weight": {
                    "check": checker
                }
            }
        }
        all_good = {"name": "jim", "weight": 120}
        self.assertEqual(validate(all_good, schema), None)

        no_name_but_good = {"weight": 3203}
        self.assertEqual(validate(no_name_but_good, schema), None)

        bad_name = {"name": 1000, "weight": 120}
        self.assertEqual(validate(bad_name, schema), {
            "name": "Invalid type <class 'int'>, expected <class 'str'>"
        })

        missing_weight = {"name": "jim"}
        self.assertEqual(validate(missing_weight, schema), {
            "weight": "Missing required field"
        })

        bad_weight = {"weight": 90}
        self.assertEqual(validate(bad_weight, schema), {
            "weight": "Must be greater than 100"
        })

        bad_weight_type = {"weight": "meme"}
        self.assertEqual(validate(bad_weight_type, schema), {
            "weight": "'<' not supported between instances of 'str' and 'int'"
        })

        unused_field = {"weight": 3213, "whoops": 37}
        self.assertEqual(validate(unused_field, schema), {
            "whoops": "Unused field"
        })

        everything_wrong = {"weight": 90, "name": ["hi"], "extra": "whoops"}
        self.assertEqual(validate(everything_wrong, schema), {
            "extra": "Unused field",
            "weight": "Must be greater than 100",
            "name": "Invalid type <class 'list'>, expected <class 'str'>"
        })
예제 #5
0
 def test_recursive_matcher(self):
     """test that matcher can work recursively"""
     def check_int(value):
         if int(value) != 3:
             raise Exception("Value should be 3")
     int_like = {"check": check_int}
     schema = {
         "match": type,
         "choices": {
             int: int_like,
             float: int_like,
             str: int_like
         }
     }
     # allow schema to recursively accept lists of itself
     schema["choices"][list] = { "items": schema }
     self.assertEqual(validate([], schema), None)
     self.assertEqual(validate(3, schema), None)
     self.assertEqual(validate([3, "3", 3.0], schema), None)
     self.assertEqual(validate([3, "3", 3.0, [3, 3, [3, 3]]], schema), None)
     self.assertEqual(validate([3, "3", 3.0, [3, 7]], schema), {
         3: {1: "Value should be 3"}
     })
예제 #6
0
 def test_empty_schema(self):
     """empty schema should validate anything"""
     schema = {}
     data = {"foo": "bar", 42: "meaning of life"}
     self.assertEqual(validate(data, schema), None)
예제 #7
0
 def test_matcher(self):
     """schemas should match using the 'match' and 'choices' fields"""
     def check_int(value):
         if int(value) != 3:
             raise Exception("Value should be 3")
     int_like = {"check": check_int}
     list_of_int = {"items": int_like}
     schema = {
         "match": type,
         "choices": {
             int: int_like,
             float: int_like,
             str: int_like,
             list: list_of_int,
         }
     }
     # check for a simple integer
     self.assertEqual(validate(3, schema), None)
     # check for a float
     self.assertEqual(validate(3.0, schema), None)
     # check for a string
     self.assertEqual(validate("3", schema), None)
     # check for a list
     self.assertEqual(validate([], schema), None)
     self.assertEqual(validate(["3", 3.0, 3, 3], schema), None)
     # bad integer
     self.assertEqual(validate(4, schema), "Value should be 3")
     # bad float
     self.assertEqual(validate(4.2, schema), "Value should be 3")
     # bad string
     self.assertEqual(validate("5", schema), "Value should be 3")
     # cannot parse string
     self.assertEqual(validate("ab", schema), "invalid literal for int() with base 10: 'ab'")
     # cannot handle a dict value
     self.assertEqual(validate({3: "3"}, schema),
         "Has value '<class 'dict'>', expected one of [<class 'int'>, <class 'float'>, <class 'str'>, <class 'list'>]"
     )
     self.assertEqual(validate(["ab", 3, 3, 4, "3"], schema), {
         0: "invalid literal for int() with base 10: 'ab'",
         3: "Value should be 3"
     })
예제 #8
0
   def test_recursive(self):
       """test if schemas can apply themselves recursively"""
       father = {
           "required": False,
           "properties": {
               "name": {
                   "type": str
               }
           }
       }
       son_schema = {"required": False, "type": list, "items": father}
       father["properties"]["sons"] = son_schema
       no_kids = {"name": "Bill"}
       one_kid = {"name": "Bill", "sons": [{"name": "Jeff"}]}
       two_kid = {"name": "Bill", "sons": [{"name": "Jeff"}, {"name": "Jim"}]}
       self.assertEqual(validate(no_kids, father), None)
       self.assertEqual(validate(one_kid, father), None)
       self.assertEqual(validate(two_kid, father), None)
       nameless_kid = {"name": "Bill", "sons": [{}]}
       self.assertEqual(validate(nameless_kid, father), {
           "sons": {0: {"name": "Missing required field"}}
       })
       bad_types = {"name": 32, "sons": "Bill"}
       self.assertEqual(validate(bad_types, father), {
           "name": "Invalid type <class 'int'>, expected <class 'str'>",
           "sons": "Invalid type <class 'str'>, expected <class 'list'>"
       })
       grandsons = {
           "name": "Grandpa",
           "sons": [
               {
                   "name": "Junior",
                   "sons": [
                       {
                           "name": "Little Billy"
                       },
                       {
                           "name": "Andrew"
                       }
                   ]
               },
               {
                   "name": "Uncle William",
                   "sons": [
                       "Matt"
                   ]
               }
           ]
       }
       self.assertEqual(validate(grandsons, father), None)
       bad_grandpa = {
           "name": "Grandpa",
           "sons": [
               {
                   "name": "Junior",
                   "sons": [
                       {
                           "name": 2
                       },
                       {
                           "name": "Little One",
                           "last name": "Juniorivich"
                       }
                   ]
               },
               {
               }
           ]
       }
       error = validate(bad_grandpa, father)
       self.assertEqual(error, {
           "sons": {
               0: {
                   "sons": {
                       0: {
                           "name": "Invalid type <class 'int'>, expected <class 'str'>"
                       },
                       1: {
                           "last name": "Unused field"
                       }
                   }
               },
               1: {
                   "name": "Missing required field"
               }
           }
       })
       formatted = '''At key 'sons':
 At index '0':
   At key 'sons':
     At index '0':
       At key 'name':
         With '2': Invalid type <class 'int'>, expected <class 'str'>
     At index '1':
       At key 'last name':
         With 'Juniorivich': Unused field
 At index '1':
   At key 'name':
     Missing required field'''
       self.assertEqual(format_error(bad_grandpa, error), formatted)