def with_properties(cls, **properties): """ Returns a clone of the class whose :attr:`properties` contain the given `properties` in addition to the ones inherited from this one. """ return cls.using( properties=InheritingDictDescriptor('properties', **properties))
class BaseElement(object): """ A base class for elements, that allows describing python objects or meta-elements - elements that affect other elements but do not themselves describe data. .. versionadded:: 2.1.0 Was previously part of :class:`Element`, is now split up into a separate class. """ #: A dictionary whose contents are inherited by subclasses, which should be #: used for application-specific information associated with an element. properties = InheritingDictDescriptor('properties') name = Unnamed @class_cloner def using(cls, **kwargs): """ Returns a clone of the class whose attributes have been overwritten with the given keyword arguments. """ for key, value in iteritems(kwargs): if not hasattr(cls, key): raise TypeError("unexpected keyword argument %r" % key) setattr(cls, key, value) return cls @classmethod def with_properties(cls, **properties): """ Returns a clone of the class whose :attr:`properties` contain the given `properties` in addition to the ones inherited from this one. """ return cls.using( properties=InheritingDictDescriptor('properties', **properties)) def __init__(self, value=Unspecified): #: Defines the validation state of the element, may be one of the #: following values: #: #: `None` #: The element has not been validated, yet. #: #: `True` #: The element is valid. #: #: `False` #: The element is not valid. self.is_valid = None #: The unserialized concrete value this element represents. May also be #: :data:`~relief.Unspecified` if the value has not been set or #: :data:`~relief.NotUnserializable` if :meth:`unserialize` was unable #: to unserialize the value. self.value = Unspecified #: The concrete value this element represents. May also be #: :data:`~relief.Unspecified` if the value has not been set. This may #: be helpful to look at if :attr:`value` is #: :data:`~relief.NotUnserializable`. self.raw_value = Unspecified self.set_from_raw(value) def set_from_native(self, value): """ Sets :attr:`value` to the given `value` and sets attr:`raw_value` to the serialized form of `value`. .. versionadded:: 1.0.0 """ self.value = value self.raw_value = self.serialize(value) self.is_valid = None def set_from_raw(self, raw_value): """ Sets :attr:`raw_value` with the given `raw_value` and sets :attr:`value` to the unserialized form of `raw_value` if applicable. .. versionadded:: 1.0.0 Was previously named :meth:`set`. """ self.raw_value = raw_value self.value = self.unserialize(raw_value) self.is_valid = None def serialize(self, value): """ Tries to serialize the given `value` and returns an object than can be unserialized with :meth:`unserialize`. .. versionadded:: 1.0.0 """ return value def unserialize(self, raw_value): """ Tries to unserialize the given `raw_value` and returns an object whose type matches the type described by the element. return raw_value """ return raw_value def __str__(self): return str(self.value)
class Foo(object): properties = InheritingDictDescriptor('properties', foo=1)