Skip to content

Commit b4614b0

Browse files
committed
Renamed and expanded the use of user-defined exceptions for corner cases
1 parent 1233570 commit b4614b0

File tree

5 files changed

+80
-19
lines changed

5 files changed

+80
-19
lines changed

jsonsubschema/_canonicalization.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -301,8 +301,7 @@ def rewrite_enum(d):
301301

302302
# Unsupported cases of rewriting enums
303303
elif t == 'array' or t == 'object':
304-
raise UnexpectedCanonicalization(
305-
msg='Rewriting the following enum is not supported.', tau=t, schema=d)
304+
raise UnsupportedEnumCanonicalization(tau=t, schema=d)
306305

307306

308307
def simplify_schema_and_embed_checkers(s):

jsonsubschema/_checkers.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -1450,7 +1450,12 @@ def neg(s):
14501450
# if s.__getattr__(k) != default:
14511451
# break
14521452
# else:
1453-
return None
1453+
if s.keys() & definitions.JtypesToKeywords['object']:
1454+
raise UnsupportedNegatedObject(schema=s)
1455+
else:
1456+
return boolToConstructor.get("anyOf")(
1457+
{"anyOf": get_default_types_except("object")})
1458+
14541459

14551460

14561461
def JSONanyOfFactory(s):

jsonsubschema/exceptions.py

+30-6
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,19 @@
44
'''
55

66

7-
class _Error(Exception):
7+
class _UnsupportedCase(Exception):
88
pass
99

1010

11-
class UnsupportedRecursiveRef(_Error):
11+
class _CanonicalizationError(_UnsupportedCase):
12+
pass
13+
14+
15+
class _SubtypeCheckError(_UnsupportedCase):
16+
pass
17+
18+
19+
class UnsupportedRecursiveRef(_CanonicalizationError):
1220
def __init__(self, schema, which_side):
1321
self.schema = schema
1422
self.which_side = which_side
@@ -17,16 +25,32 @@ def __str__(self):
1725
return f'Recursive schemas are not supported. {self.which_side} is recursive.'
1826

1927

20-
class UnexpectedCanonicalization(_Error):
28+
class UnsupportedEnumCanonicalization(_CanonicalizationError):
2129

22-
def __init__(self, msg, tau, schema):
23-
self.msg = msg
30+
def __init__(self, tau, schema):
2431
self.tau = tau
2532
self.schema = schema
2633

2734
def __str__(self):
28-
return '{}\n"type": {} \n"schema": {}'.format(self.msg, self.tau, self.schema)
35+
return f'Canonicalizing an enum schema of type {self.tau} is not supported.'
36+
2937

38+
class UnsupportedNegatedObject(_SubtypeCheckError):
39+
40+
def __init__(self, schema):
41+
self.schema = schema
42+
43+
def __str__(self):
44+
return f'Object negation at {self.schema} is not supported.'
45+
46+
47+
class UnsupportedNegatedArray(_SubtypeCheckError):
48+
49+
def __init__(self, schema):
50+
self.schema = schema
51+
52+
def __str__(self):
53+
return f'Array negation at {self.schema} is not supported.'
3054

3155
# class UnsupportedSchemaType(_Error):
3256
# '''

test/test_enum.py

+10-8
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import unittest
77

88
from jsonsubschema import isSubschema
9-
from jsonsubschema.exceptions import UnexpectedCanonicalization
9+
from jsonsubschema.exceptions import UnsupportedEnumCanonicalization
1010

1111

1212
class TestEnum(unittest.TestCase):
@@ -91,10 +91,11 @@ def test_array(self):
9191
s2 = {'type': 'array'}
9292

9393
with self.subTest():
94-
self.assertRaises(UnexpectedCanonicalization, isSubschema, s1, s2)
94+
self.assertRaises(UnsupportedEnumCanonicalization,
95+
isSubschema, s1, s2)
9596

96-
with self.subTest(): # To test prining the exception msg
97-
with self.assertRaises(UnexpectedCanonicalization) as ctxt:
97+
with self.subTest(): # To test prining the exception msg
98+
with self.assertRaises(UnsupportedEnumCanonicalization) as ctxt:
9899
isSubschema(s2, s1)
99100
print(ctxt.exception)
100101

@@ -103,9 +104,10 @@ def test_object(self):
103104
s2 = {'type': 'object'}
104105

105106
with self.subTest():
106-
self.assertRaises(UnexpectedCanonicalization, isSubschema, s1, s2)
107+
self.assertRaises(UnsupportedEnumCanonicalization,
108+
isSubschema, s1, s2)
107109

108-
with self.subTest(): # To test prining the exception msg
109-
with self.assertRaises(UnexpectedCanonicalization) as ctxt:
110+
with self.subTest(): # To test prining the exception msg
111+
with self.assertRaises(UnsupportedEnumCanonicalization) as ctxt:
110112
isSubschema(s2, s1)
111-
print(ctxt.exception)
113+
print(ctxt.exception)

test/test_refs.py

+33-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import unittest
77

88
from jsonsubschema import isSubschema
9+
from jsonsubschema.exceptions import UnsupportedRecursiveRef
910

1011

1112
class TestSimpleRefs(unittest.TestCase):
@@ -89,7 +90,7 @@ def test_1(self):
8990
with self.subTest():
9091
self.assertFalse(isSubschema(s2, s4))
9192

92-
@unittest.skip("Unsupported recursive/circular $ref")
93+
@unittest.skip("Recursive schema; fails due to jsonschema failure case, not us")
9394
def test_2(self):
9495
s1 = {"definitions": {"S": {"anyOf": [{"enum": [None]},
9596
{"allOf": [{"items": [{"$ref": "#/definitions/S"},
@@ -110,4 +111,34 @@ def test_2(self):
110111
s2 = {"enum": [None]}
111112

112113
with self.subTest():
113-
self.assertTrue(isSubschema(s2, s1))
114+
with self.assertRaises(UnsupportedRecursiveRef) as ctxt:
115+
isSubschema(s2, s1)
116+
print(ctxt.exception)
117+
118+
def test_3(self):
119+
s1 = {
120+
"definitions": {
121+
"person": {
122+
"type": "object",
123+
"properties": {
124+
"name": {"type": "string"},
125+
"children": {
126+
"type": "array",
127+
"items": {"$ref": "#/definitions/person"},
128+
"default": []
129+
}
130+
}
131+
}
132+
},
133+
"type": "object",
134+
"properties": {
135+
"person": {"$ref": "#/definitions/person"}
136+
}
137+
}
138+
139+
s2 = {"enum": [None]}
140+
141+
with self.subTest():
142+
with self.assertRaises(UnsupportedRecursiveRef) as ctxt:
143+
isSubschema(s2, s1)
144+
print(ctxt.exception)

0 commit comments

Comments
 (0)