Skip to content

Commit

Permalink
More tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mwatts15 committed Jul 20, 2019
1 parent a59a4f4 commit d7f32b0
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 40 deletions.
95 changes: 55 additions & 40 deletions PyOpenWorm/json_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ class Creator(object):
'''
Creates objects based on a JSON schema augmented with type annotations as would be
produced by :py:class:`TypeCreator`
Currently, only annotations for JSON objects are supported. In the future, conversions
for all types (arrays, numbers, ints, strings) may be supported.
'''

def __init__(self, schema):
Expand Down Expand Up @@ -169,53 +172,65 @@ def _create(self, instance, schema=None, ident=None):
elif isinstance(instance, dict):
if sType == 'object':
pow_type = schema.get('_pow_type')
if pow_type:
pt_args = dict()
for k, v in instance.items():
props = schema.get('properties', {})

# If patprops doesn't have anything, then we pick it up with
# additionalProperties
patprops = schema.get('patternProperties', {})

# additionalProperties doesn't have any keys to check, so we
# can just pass true down to the next level
addprops = schema.get('additionalProperties', True)

if props:
sub_schema = props.get(k)
if sub_schema:
with self._pushing(k):
pt_args[k] = self._create(v, sub_schema)
continue

if patprops:
found = False
for p in patprops:
if re.match(p, k):
with self._pushing(k):
pt_args[k] = self._create(v, patprops[p])
found = True
break
if found:
continue

if addprops:
if not pow_type:
# If an object isn't annotated, we treat as an error -- alternatives
# like returning None or just 'instance' could both be surprising and
# not annotating an object is most likely a mistake in a TypeCreator
# sub-class.
raise AssignmentValidationException(sType, instance)

pt_args = dict()
for k, v in instance.items():
props = schema.get('properties', {})

# If patprops doesn't have anything, then we pick it up with
# additionalProperties
patprops = schema.get('patternProperties', {})

# additionalProperties doesn't have any keys to check, so we
# can just pass true down to the next level
addprops = schema.get('additionalProperties', True)

if props:
sub_schema = props.get(k)
if sub_schema:
with self._pushing(k):
pt_args[k] = self._create(v, addprops)
pt_args[k] = self._create(v, sub_schema)
continue

raise AssignmentValidationException(sType, instance, k, v)
if patprops:
found = False
for p in patprops:
if re.match(p, k):
with self._pushing(k):
pt_args[k] = self._create(v, patprops[p])
found = True
break
if found:
continue

res = self.make_instance(pow_type)
for k, v in pt_args.items():
self.assign(res, k, v)
return res
else:
return None
if addprops:
with self._pushing(k):
pt_args[k] = self._create(v, addprops)
continue

raise AssignmentValidationException(sType, instance, k, v)

# res must be treated as a black-box since sub-classes have total freedom
# as far as what substitution they want to make
res = self.make_instance(pow_type)
for k, v in pt_args.items():
self.assign(res, k, v)
return res
else:
raise AssignmentValidationException(sType, instance)

def assign(self, obj, name, value):
raise NotImplementedError()

def make_instance(self, pow_type):
raise NotImplementedError()


class TypeCreator(object):
'''
Expand Down
61 changes: 61 additions & 0 deletions tests/JSONSchemaCreatorTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,64 @@ def test_items(self):

with self.assertRaises(AssignmentValidationException):
cut.create(['blah', True])

def test_items_empty(self):
cut = Creator({
'type': 'array',
'items': {'type': 'string'}
})

self.assertEqual([], cut.create([]))


class ObjectTypeCheck(unittest.TestCase):
def test_no_pow_type(self):
cut = Creator({
'type': 'object',
})

with self.assertRaises(AssignmentValidationException):
cut.create({})

def test_make_instance(self):
class A(object):
pass

class C(Creator):
def make_instance(self, pow_type):
return A()

cut = C({
'type': 'object',
'_pow_type': 'whatever'
})
self.assertIsInstance(cut.create({}), A)

def test_assign(self):
class A(object):
pass

called = [False]

class C(Creator):
def make_instance(self, pt):
return A()

def assign(self, obj, name, val):
called[0] = True

cut = C({
'type': 'object',
'_pow_type': 'whatever'
})
cut.create({'duck': 'sauce'})
self.assertTrue(called[0])

def test_additionalProperties(self):
pass

def test_patternProperties(self):
pass

def test_properties(self):
pass

0 comments on commit d7f32b0

Please sign in to comment.