20
20
_types ,
21
21
validators ,
22
22
)
23
- from jsonschema .compat import PY3
23
+ from jsonschema .compat import PY3 , pathname2url
24
24
from jsonschema .tests .compat import mock
25
25
26
26
27
- if PY3 :
28
- from urllib .request import pathname2url
29
- else :
30
- from urllib import pathname2url
31
-
32
-
33
27
def startswith (validator , startswith , instance , schema ):
34
28
if not instance .startswith (startswith ):
35
29
yield ValidationError (u"Whoops!" )
36
30
37
31
38
- class TestCreateAndExtend (TestCase ):
32
+ class TestCreateAndExtend (SynchronousTestCase ):
39
33
def setUp (self ):
40
34
self .addCleanup (
41
35
self .assertEqual ,
@@ -53,14 +47,23 @@ def setUp(self):
53
47
)
54
48
55
49
def test_attrs (self ):
56
- self .assertEqual (self .Validator .VALIDATORS , self .validators )
57
- self .assertEqual (self .Validator .META_SCHEMA , self .meta_schema )
58
- self .assertEqual (self .Validator .TYPE_CHECKER , self .type_checker )
50
+ self .assertEqual (
51
+ (
52
+ self .Validator .VALIDATORS ,
53
+ self .Validator .META_SCHEMA ,
54
+ self .Validator .TYPE_CHECKER ,
55
+ ), (
56
+ self .validators ,
57
+ self .meta_schema ,
58
+ self .type_checker ,
59
+ ),
60
+ )
59
61
60
62
# Default types should still be set to the old default if not provided
61
63
expected_types = {u"array" , u"boolean" , u"integer" , u"null" , u"number" ,
62
64
u"object" , u"string" }
63
65
self .assertEqual (set (self .Validator .DEFAULT_TYPES ), expected_types )
66
+ self .assertEqual (len (self .flushWarnings ()), 1 )
64
67
65
68
def test_init (self ):
66
69
schema = {u"startswith" : u"foo" }
@@ -132,15 +135,19 @@ def test_extend(self):
132
135
(
133
136
Extended .VALIDATORS ,
134
137
Extended .META_SCHEMA ,
135
- Extended .DEFAULT_TYPES ,
136
138
Extended .TYPE_CHECKER ,
137
139
self .Validator .VALIDATORS ,
140
+
141
+ Extended .DEFAULT_TYPES ,
142
+ self .flushWarnings ()[0 ]["message" ],
138
143
), (
139
144
dict (original , new = new ),
140
145
self .Validator .META_SCHEMA ,
141
- self .Validator .DEFAULT_TYPES ,
142
146
self .Validator .TYPE_CHECKER ,
143
147
original ,
148
+
149
+ self .Validator .DEFAULT_TYPES ,
150
+ self .flushWarnings ()[0 ]["message" ],
144
151
),
145
152
)
146
153
@@ -922,7 +929,7 @@ def test_valid_instances_are_valid(self):
922
929
)
923
930
924
931
def test_invalid_instances_are_not_valid (self ):
925
- errors = iter ([mock . Mock ( )])
932
+ errors = iter ([ValidationError ( "An error!" )])
926
933
927
934
with mock .patch .object (
928
935
self .validator , "iter_errors" , return_value = errors ,
@@ -979,17 +986,25 @@ def test_string_a_bytestring_is_a_string(self):
979
986
self .Validator ({"type" : "string" }).validate (b"foo" )
980
987
981
988
def test_it_can_validate_with_decimals (self ):
982
- schema = {"type" : "number" }
983
- validator = self .Validator (
984
- schema , types = {"number" : (int , float , Decimal )}
989
+ schema = {"items" : {"type" : "number" }}
990
+ Validator = validators .extend (
991
+ self .Validator ,
992
+ type_checker = self .Validator .TYPE_CHECKER .redefine (
993
+ "number" ,
994
+ lambda checker , thing : isinstance (
995
+ thing , (int , float , Decimal ),
996
+ ) and not isinstance (thing , bool ),
997
+ )
985
998
)
986
999
987
- for valid in [ 1 , 1.1 , Decimal ( 1 ) / Decimal ( 8 )]:
988
- validator . validate ( valid )
1000
+ validator = Validator ( schema )
1001
+ validator . validate ([ 1 , 1.1 , Decimal ( 1 ) / Decimal ( 8 )] )
989
1002
990
- for invalid in ["foo" , {}, [], True , None ]:
991
- with self .assertRaises (ValidationError ):
992
- validator .validate (invalid )
1003
+ invalid = ["foo" , {}, [], True , None ]
1004
+ self .assertEqual (
1005
+ [error .instance for error in validator .iter_errors (invalid )],
1006
+ invalid ,
1007
+ )
993
1008
994
1009
def test_it_returns_true_for_formats_it_does_not_know_about (self ):
995
1010
validator = self .Validator (
@@ -1025,6 +1040,35 @@ def check(value):
1025
1040
# Make sure original cause is attached
1026
1041
self .assertIs (cm .exception .cause , bad )
1027
1042
1043
+ def test_non_string_custom_type (self ):
1044
+ non_string_type = object ()
1045
+ schema = {"type" : [non_string_type ]}
1046
+ Crazy = validators .extend (
1047
+ self .Validator ,
1048
+ type_checker = self .Validator .TYPE_CHECKER .redefine (
1049
+ non_string_type ,
1050
+ lambda checker , thing : isinstance (thing , int ),
1051
+ )
1052
+ )
1053
+ Crazy (schema ).validate (15 )
1054
+
1055
+ def test_it_properly_formats_tuples_in_errors (self ):
1056
+ """
1057
+ A tuple instance properly formats validation errors for uniqueItems.
1058
+
1059
+ See https://github.com/Julian/jsonschema/pull/224
1060
+ """
1061
+ TupleValidator = validators .extend (
1062
+ self .Validator ,
1063
+ type_checker = self .Validator .TYPE_CHECKER .redefine (
1064
+ "array" ,
1065
+ lambda checker , thing : isinstance (thing , tuple ),
1066
+ )
1067
+ )
1068
+ with self .assertRaises (ValidationError ) as e :
1069
+ TupleValidator ({"uniqueItems" : True }).validate ((1 , 1 ))
1070
+ self .assertIn ("(1, 1) has non-unique elements" , str (e .exception ))
1071
+
1028
1072
1029
1073
class AntiDraft6LeakMixin (object ):
1030
1074
"""
@@ -1083,11 +1127,6 @@ def test_is_type_does_not_evade_bool_if_it_is_being_tested(self):
1083
1127
self .assertTrue (self .validator .is_type (True , "boolean" ))
1084
1128
self .assertTrue (self .validator .is_valid (True , {"type" : "any" }))
1085
1129
1086
- def test_non_string_custom_types (self ):
1087
- schema = {'type' : [None ]}
1088
- cls = self .Validator (schema , types = {None : type (None )})
1089
- cls .validate (None , schema )
1090
-
1091
1130
1092
1131
class TestDraft4Validator (AntiDraft6LeakMixin , ValidatorTestMixin , TestCase ):
1093
1132
Validator = validators .Draft4Validator
@@ -1097,6 +1136,10 @@ class TestDraft6Validator(ValidatorTestMixin, TestCase):
1097
1136
Validator = validators .Draft6Validator
1098
1137
1099
1138
1139
+ class TestDraft7Validator (ValidatorTestMixin , TestCase ):
1140
+ Validator = validators .Draft7Validator
1141
+
1142
+
1100
1143
class TestBuiltinFormats (TestCase ):
1101
1144
"""
1102
1145
The built-in (specification-defined) formats do not raise type errors.
@@ -1490,35 +1533,6 @@ def test_helpful_error_message_on_failed_pop_scope(self):
1490
1533
self .assertIn ("Failed to pop the scope" , str (exc .exception ))
1491
1534
1492
1535
1493
- class UniqueTupleItemsMixin (object ):
1494
- """
1495
- A tuple instance properly formats validation errors for uniqueItems.
1496
-
1497
- See https://github.com/Julian/jsonschema/pull/224
1498
- """
1499
-
1500
- def test_it_properly_formats_an_error_message (self ):
1501
- validator = self .Validator (
1502
- schema = {"uniqueItems" : True },
1503
- types = {"array" : (tuple ,)},
1504
- )
1505
- with self .assertRaises (ValidationError ) as e :
1506
- validator .validate ((1 , 1 ))
1507
- self .assertIn ("(1, 1) has non-unique elements" , str (e .exception ))
1508
-
1509
-
1510
- class TestDraft6UniqueTupleItems (UniqueTupleItemsMixin , TestCase ):
1511
- Validator = validators .Draft6Validator
1512
-
1513
-
1514
- class TestDraft4UniqueTupleItems (UniqueTupleItemsMixin , TestCase ):
1515
- Validator = validators .Draft4Validator
1516
-
1517
-
1518
- class TestDraft3UniqueTupleItems (UniqueTupleItemsMixin , TestCase ):
1519
- Validator = validators .Draft3Validator
1520
-
1521
-
1522
1536
def sorted_errors (errors ):
1523
1537
def key (error ):
1524
1538
return (
0 commit comments