for name, property in ((name, item) for name, item in dictionary.iteritems() if isinstance(item, AbstractProperty)):
property.name = name
cls.__properties__ = PropertyContainer(cls)
class JSONObject(object):
__metaclass__ = JSONObjectType
# noinspection PyShadowingBuiltins
def __init__(self, **data):
for property in self.__properties__:
if property.name in data:
property.__set__(self, data[property.name])
elif not property.optional:
raise ValueError('Mandatory property {property.name!r} of {object.__class__.__name__!r} object is missing'.format(property=property, object=self))
@property
def __data__(self):
return {name: value.__data__ if isinstance(value, (JSONArray, JSONObject)) else value for name, value in self.__properties__.items(self) if value is not None or name in self.__dict__}
class ArrayParser(object):
def __init__(self, cls):
self.item_type = MultiType(*cls.item_type) if isinstance(cls.item_type, (list, tuple)) else cls.item_type
self.item_validator = cls.item_validator # this is only used for primitive item types
if isinstance(self.item_type, JSONObjectType):
self.parse_item = self.__parse_object_item
self.parse_list = self.__parse_object_list
elif isinstance(self.item_type, JSONArrayType):
self.parse_item = self.__parse_array_item
self.parse_list = self.__parse_array_list
else:
self.parse_item = self.__parse_primitive_item
self.parse_list = self.__parse_primitive_list
def __parse_primitive_item(self, item):
if not isinstance(item, self.item_type):
raise ValueError('Invalid value for {type.__name__}: {item!r}'.format(type=self.item_type, item=item))
if self.item_validator is not None:
item = self.item_validator.validate(item)
return item
def __parse_primitive_list(self, iterable):
item_type = self.item_type
for item in iterable:
if not isinstance(item, item_type):
raise ValueError('Invalid value for {type.__name__}: {item!r}'.format(type=item_type, item=item))
if self.item_validator is not None: # note: can be optimized by moving this test outside the loop (not sure if the decreased readability is worth it)
item = self.item_validator.validate(item)
yield item
def __parse_array_item(self, item):
try:
return item if type(item) is self.item_type else self.item_type(item)
except TypeError:
raise ValueError('Invalid value for {type.__name__}: {item!r}'.format(type=self.item_type, item=item))
def __parse_array_list(self, iterable):
item_type = self.item_type
for item in iterable:
try:
yield item if type(item) is item_type else item_type(item)
except TypeError:
raise ValueError('Invalid value for {type.__name__}: {item!r}'.format(type=item_type, item=item))
def __parse_object_item(self, item):
try:
return item if type(item) is self.item_type else self.item_type(**item)
except TypeError:
raise ValueError('Invalid value for {type.__name__}: {item!r}'.format(type=self.item_type, item=item))
def __parse_object_list(self, iterable):
item_type = self.item_type
for item in iterable:
try:
yield item if type(item) is item_type else item_type(**item)
except TypeError:
raise ValueError('Invalid value for {type.__name__}: {item!r}'.format(type=item_type, item=item))