Source code for typerighter.views

from typerighter import types


[docs]class Field(object): """A descriptor used to join a mutable View instance, that stores data, with the immutable Type instance, that only defines methods for operating on data. """ def __init__(self, name): self.name = name def __get__(self, instance, cls): if self.name in instance._data: return instance._data[self.name] return None def __set__(self, instance, value): instance._data[self.name] = value def __delete__(self, instance): del instance._data[self.name]
[docs]class View(object): """A View combines a `Record` with a dictionary to provide an object modeled after the record that can store data in a familiar object oriented manner. """ def __init__(self, record, data=None, native=True, primitive=False): self._record = record self._config = {} if primitive: self._config['primitive'] = True self._data = self._record.to_primitive(data) elif native: self._config['native'] = True self._data = self._record.to_native(data) else: self._data = data
[docs] def to_primitive(self, **convert_args): """ Uses the record's ``to_primitive`` to convert view data. """ return self._record.to_primitive(self._data, **convert_args)
[docs] def to_native(self, **convert_args): """ Uses the record's ``to_native`` to convert view data. """ return self._record.to_native(self._data, **convert_args)
[docs] def validate(self): """ Uses the record's ``validate`` function with view data. """ return self._record.validate(self._data)
def __iter__(self): for k, v in self._data.items(): if v is not types.Unset: yield k, v def __getattr__(self, name): if hasattr(self._record, name): return getattr(self._record, name)
[docs]def to_view(record, data=None, **view_config): """Takes both a record and some data and produces View instance. :param Type record: The type that defines the view's shape :param dict data: Any initial data for the view's fields """ if not data: data = {} # Wrap each field of the record in a `Field` instance attrs = {} for field_name, field_type in record: # All fields in the record are at least a View instance field = Field(field_name) # Records recurse to create RecordView instances instead if isinstance(field_type, types.Record): field = to_view(field_type, data[field_name]) # Pair field with a name attrs[field_name] = field # Collect any factory setters for name in dir(record): if name.startswith('set_'): attr = getattr(record.__class__, name) attrs[name] = attr # Normalize class name view_cls_name = '%sView' % (record.__class__.__name__) # Instantiate a View definition with the new fields RecordView = type(view_cls_name, (View,), attrs) return RecordView(record, data=data, **view_config)