Page MenuHomePhabricator

No OneTemporary

diff --git a/sylk/applications/webrtcgateway/models/jsonobjects.py b/sylk/applications/webrtcgateway/models/jsonobjects.py
index 74c24e1..c197114 100644
--- a/sylk/applications/webrtcgateway/models/jsonobjects.py
+++ b/sylk/applications/webrtcgateway/models/jsonobjects.py
@@ -1,493 +1,488 @@
class Validator(object):
def validate(self, value):
"""Check value and raise ValueError if invalid, else return the (possibly modified) value"""
return value
class CompositeValidator(Validator):
def __init__(self, *validators):
if len(validators) < 2:
raise TypeError('need at least two validators to create a CompositeValidator')
if not all(isinstance(validator, Validator) for validator in validators):
raise ValueError('validators need to be Validator instances')
self.validators = validators
def validate(self, value):
for validator in self.validators:
value = validator.validate(value)
return value
class MultiType(tuple):
"""
A collection of types for which isinstance(obj, multi_type) returns True if 'obj'
is an instance of any of the types in the multi_type.
Instantiating the multi_type will instantiate the first type in the multi_type.
"""
# noinspection PyArgumentList
def __new__(cls, *args):
if not args:
raise ValueError('{.__name__} must have at least one type'.format(cls))
instance = super(MultiType, cls).__new__(cls, args)
instance.__name__ = ', '.join(cls.__name__ for cls in args)
instance.main_type = args[0]
return instance
def __call__(self, value):
return self.main_type(value)
class AbstractProperty(object):
data_type = object
def __init__(self, optional=False, default=None, validator=None):
if validator is not None and not isinstance(validator, Validator):
raise TypeError('validator should be a Validator instance or None')
self.default = default
self.optional = optional
self.validator = validator
self.name = None # will be set by the JSONObjectType metaclass when associating properties with objects
def __get__(self, instance, owner):
if instance is None:
return self
- if self.optional:
- return instance.__dict__.get(self.name, self.default)
- try:
- return instance.__dict__[self.name]
- except KeyError:
- raise AttributeError('{instance.__class__.__name__!r} object has no attribute {property.name!r}'.format(instance=instance, property=self))
+ return instance.__dict__.get(self.name, self.default) # mandatory properties are guaranteed to be present, only optional ones can be missing
def __set__(self, instance, value):
if value is None and self.optional:
instance.__dict__[self.name] = None
else:
instance.__dict__[self.name] = self._parse(value)
def __delete__(self, instance):
if not self.optional:
raise AttributeError('Cannot delete mandatory property {property.name!r} of object {instance.__class__.__name__!r}'.format(instance=instance, property=self))
try:
del instance.__dict__[self.name]
except KeyError:
raise AttributeError(self.name)
def _parse(self, value):
if not isinstance(value, self.data_type):
raise ValueError('Invalid value for {property.name!r} property: {value!r}'.format(property=self, value=value))
if self.validator is not None:
value = self.validator.validate(value)
return value
class BooleanProperty(AbstractProperty):
data_type = bool
class IntegerProperty(AbstractProperty):
data_type = int, long
class NumberProperty(AbstractProperty):
data_type = int, long, float
class StringProperty(AbstractProperty):
data_type = str, unicode
class ArrayProperty(AbstractProperty):
data_type = list, tuple
def __init__(self, array_type, optional=False):
if not issubclass(array_type, JSONArray):
raise TypeError('array_type should be a subclass of JSONArray')
super(ArrayProperty, self).__init__(optional=optional, default=None, validator=None)
self.array_type = array_type
def _parse(self, value):
if type(value) is self.array_type:
return value
elif isinstance(value, self.data_type):
return self.array_type(value)
else:
raise ValueError('Invalid value for {property.name!r} property: {value!r}'.format(property=self, value=value))
class ObjectProperty(AbstractProperty):
data_type = dict
def __init__(self, object_type, optional=False):
if not issubclass(object_type, JSONObject):
raise TypeError('object_type should be a subclass of JSONObject')
super(ObjectProperty, self).__init__(optional=optional, default=None, validator=None)
self.object_type = object_type
def _parse(self, value):
if type(value) is self.object_type:
return value
elif isinstance(value, self.data_type):
return self.object_type(**value)
else:
raise ValueError('Invalid value for {property.name!r} property: {value!r}'.format(property=self, value=value))
class PropertyContainer(object):
def __init__(self, cls):
self.__dict__.update({item.name: item for cls in reversed(cls.__mro__) for item in cls.__dict__.itervalues() if isinstance(item, AbstractProperty)})
def __getitem__(self, name):
return self.__dict__[name]
def __contains__(self, name):
return name in self.__dict__
def __iter__(self):
return self.__dict__.itervalues()
@property
def names(self):
return set(self.__dict__)
# noinspection PyShadowingBuiltins
def items(self, instance):
return [(property.name, property.__get__(instance, None)) for property in self.__dict__.itervalues()]
class JSONObjectType(type):
# noinspection PyShadowingBuiltins
def __init__(cls, name, bases, dictionary):
super(JSONObjectType, cls).__init__(name, bases, dictionary)
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))
class JSONArrayType(type):
item_type = object
item_validator = None
list_validator = None
def __init__(cls, name, bases, dictionary):
super(JSONArrayType, cls).__init__(name, bases, dictionary)
if cls.item_validator is not None and isinstance(cls.item_type, (JSONArrayType, JSONObjectType)):
raise TypeError('item_validator is not used for JSONArray and JSONObject item types as they have their own validators')
if cls.item_validator is not None and not isinstance(cls.item_validator, Validator):
raise TypeError('item_validator should be a Validator instance or None')
if cls.list_validator is not None and not isinstance(cls.list_validator, Validator):
raise TypeError('list_validator should be a Validator instance or None')
cls.parser = ArrayParser(cls)
class JSONArray(object):
__metaclass__ = JSONArrayType
item_type = object
item_validator = None # this should only be defined for primitive item types
list_validator = None
def __init__(self, iterable):
if isinstance(iterable, basestring): # prevent iterable primitive types from being interpreted as arrays
raise ValueError('Invalid value for {.__class__.__name__}: {!r}'.format(self, iterable))
items = list(self.parser.parse_list(iterable))
if self.list_validator is not None:
items = self.list_validator.validate(items)
self.__items__ = items
@property
def __data__(self):
return [item.__data__ for item in self.__items__] if isinstance(self.item_type, (JSONArrayType, JSONObjectType)) else self.__items__[:]
def __repr__(self):
return '{0.__class__.__name__}({0.__items__!r})'.format(self)
def __contains__(self, item):
return item in self.__items__
def __iter__(self):
return iter(self.__items__)
def __len__(self):
return len(self.__items__)
def __reversed__(self):
return reversed(self.__items__)
__hash__ = None
def __getitem__(self, index):
return self.__items__[index]
def __setitem__(self, index, value):
value = self.parser.parse_item(value)
if self.list_validator is not None:
clone = self.__items__[:]
clone[index] = value
self.__items__ = self.list_validator.validate(clone)
else:
self.__items__[index] = value
def __delitem__(self, index):
if self.list_validator is not None:
clone = self.__items__[:]
del clone[index]
self.__items__ = self.list_validator.validate(clone)
else:
del self.__items__[index]
def __getslice__(self, i, j):
return self.__items__[i:j]
def __setslice__(self, i, j, sequence):
sequence = list(self.parser.parse_list(sequence))
if self.list_validator is not None:
clone = self.__items__[:]
clone[i:j] = sequence
self.__items__ = self.list_validator.validate(clone)
else:
self.__items__[i:j] = sequence
def __delslice__(self, i, j):
if self.list_validator is not None:
clone = self.__items__[:]
del clone[i:j]
self.__items__ = self.list_validator.validate(clone)
else:
del self.__items__[i:j]
def __add__(self, other):
if isinstance(other, JSONArray):
return self.__class__(self.__items__ + other.__items__)
else:
return self.__class__(self.__items__ + other)
def __radd__(self, other):
if isinstance(other, JSONArray):
return self.__class__(other.__items__ + self.__items__)
else:
return self.__class__(other + self.__items__)
def __iadd__(self, other):
if isinstance(other, JSONArray) and self.item_type == other.item_type:
items = other.__items__
else:
items = list(self.parser.parse_list(other))
if self.list_validator is not None:
clone = self.__items__[:]
clone += items
self.__items__ = self.list_validator.validate(clone)
else:
self.__items__ += items
return self
def __mul__(self, n):
return self.__class__(self.__items__ * n)
def __rmul__(self, n):
return self.__class__(self.__items__ * n)
def __imul__(self, n):
if self.list_validator is not None:
self.__items__ = self.list_validator.validate(n * self.__items__)
else:
self.__items__ *= n
return self
def __eq__(self, other):
return self.__items__ == other.__items__ if isinstance(other, JSONArray) else self.__items__ == other
def __ne__(self, other):
return self.__items__ != other.__items__ if isinstance(other, JSONArray) else self.__items__ != other
def __lt__(self, other):
return self.__items__ < other.__items__ if isinstance(other, JSONArray) else self.__items__ < other
def __le__(self, other):
return self.__items__ <= other.__items__ if isinstance(other, JSONArray) else self.__items__ <= other
def __gt__(self, other):
return self.__items__ > other.__items__ if isinstance(other, JSONArray) else self.__items__ > other
def __ge__(self, other):
return self.__items__ >= other.__items__ if isinstance(other, JSONArray) else self.__items__ >= other
def __format__(self, format_spec):
return self.__items__.__format__(format_spec)
def index(self, value, *args):
return self.__items__.index(value, *args)
def count(self, value):
return self.__items__.count(value)
def append(self, value):
value = self.parser.parse_item(value)
if self.list_validator is not None:
clone = self.__items__[:]
clone.append(value)
self.__items__ = self.list_validator.validate(clone)
else:
self.__items__.append(value)
def insert(self, index, value):
value = self.parser.parse_item(value)
if self.list_validator is not None:
clone = self.__items__[:]
clone.insert(index, value)
self.__items__ = self.list_validator.validate(clone)
else:
self.__items__.insert(index, value)
def extend(self, other):
if isinstance(other, JSONArray) and self.item_type == other.item_type:
items = other.__items__
else:
items = list(self.parser.parse_list(other))
if self.list_validator is not None:
clone = self.__items__[:]
clone.extend(items)
self.__items__ = self.list_validator.validate(clone)
else:
self.__items__.extend(items)
def pop(self, index=-1):
if self.list_validator is not None:
clone = self.__items__[:]
clone.pop(index)
self.__items__ = self.list_validator.validate(clone)
else:
self.__items__.pop(index)
def remove(self, value):
if self.list_validator is not None:
clone = self.__items__[:]
clone.remove(value)
self.__items__ = self.list_validator.validate(clone)
else:
self.__items__.remove(value)
def reverse(self):
if self.list_validator is not None:
clone = self.__items__[:]
clone.reverse()
self.__items__ = self.list_validator.validate(clone)
else:
self.__items__.reverse()
def sort(self, key=None, reverse=False):
if self.list_validator is not None:
clone = self.__items__[:]
clone.sort(key=key, reverse=reverse)
self.__items__ = self.list_validator.validate(clone)
else:
self.__items__.sort(key=key, reverse=reverse)
class BooleanArray(JSONArray):
item_type = bool
class IntegerArray(JSONArray):
item_type = int, long
class NumberArray(JSONArray):
item_type = int, long, float
class StringArray(JSONArray):
item_type = str, unicode
class ArrayOf(object):
def __new__(cls, item_type, name='GenericArray', item_validator=None, list_validator=None):
return JSONArrayType(name, (JSONArray,), dict(item_type=item_type, item_validator=item_validator, list_validator=list_validator))
JSONList = JSONArray
BooleanList = BooleanArray
IntegerList = IntegerArray
NumberList = NumberArray
StringList = StringArray
ListOf = ArrayOf

File Metadata

Mime Type
text/x-diff
Expires
Sat, Feb 1, 5:48 PM (1 d, 17 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3489428
Default Alt Text
(18 KB)

Event Timeline