class Record(object): _identity_field = None def get(self, field): try: return self.__getattribute__(field) except: return None def _formatField(self, field): v = self.get(field) if callable(v): v = v() if hasattr(v, '__iter__'): if len(v) == 0: return '[]' else: return '[%d x %s]'%(len(v), type(v[0])) else: return repr(v) def _fields(self): ignore = self._ignore() keys = sorted(self.__class__.__dict__.keys()) return [(k,self._formatField(k)) for k in keys if k[0]!="_" and k not in ignore] def __repr__(self): classname = self.__class__.__name__ if self._identity_field: identity = self.__dict__.get(self._identity_field) identity = ' ' + (identity and repr(identity) or 'hash=%d'%hash(self)) else: identity = '' payload = " ".join(["%s=%s" % (k, v) for k,v in self._fields()]) if len(payload) > 0: payload = ": "+payload return "<%s%s%s>" % (classname, identity, payload) def _ignore(self): return [self._identity_field, 'c', 'query', 'get'] class FormattableRecord(Record): _format = {} def _formatField(self, field): func = self._format.get(field) if func: return func(self.get(field)) else: return super(FormattableRecord, self)._formatField(field) class NullableRecord(FormattableRecord): _default = {} def get(self, field): v = self.__dict__.get(field) if v != None: return v else: return self._default.get(field)