""" Various containers. """ from collections import MutableMapping from pprint import pformat def recursion_lock(retval, lock_name = "__recursion_lock__"): def decorator(func): def wrapper(self, *args, **kw): if getattr(self, lock_name, False): return retval setattr(self, lock_name, True) try: return func(self, *args, **kw) finally: setattr(self, lock_name, False) wrapper.__name__ = func.__name__ return wrapper return decorator class Container(MutableMapping): """ A generic container of attributes. Containers are the common way to express parsed data. """ def __init__(self, **kw): self.__dict__ = kw # The core dictionary interface. def __getitem__(self, name): return self.__dict__[name] def __delitem__(self, name): del self.__dict__[name] def __setitem__(self, name, value): self.__dict__[name] = value def keys(self): return self.__dict__.keys() def __len__(self): return len(self.__dict__.keys()) # Extended dictionary interface. def update(self, other): self.__dict__.update(other) __update__ = update def __contains__(self, value): return value in self.__dict__ # Rich comparisons. def __eq__(self, other): try: return self.__dict__ == other.__dict__ except AttributeError: return False def __ne__(self, other): return not self == other # Copy interface. def copy(self): return self.__class__(**self.__dict__) __copy__ = copy # Iterator interface. def __iter__(self): return iter(self.__dict__) def __repr__(self): return "%s(%s)" % (self.__class__.__name__, repr(self.__dict__)) def __str__(self): return "%s(%s)" % (self.__class__.__name__, str(self.__dict__)) class FlagsContainer(Container): """ A container providing pretty-printing for flags. Only set flags are displayed. """ @recursion_lock("<...>") def __str__(self): d = dict((k, self[k]) for k in self if self[k] and not k.startswith("_")) return "%s(%s)" % (self.__class__.__name__, pformat(d)) class ListContainer(list): """ A container for lists. """ __slots__ = ["__recursion_lock__"] @recursion_lock("[...]") def __str__(self): return pformat(self) class LazyContainer(object): __slots__ = ["subcon", "stream", "pos", "context", "_value"] def __init__(self, subcon, stream, pos, context): self.subcon = subcon self.stream = stream self.pos = pos self.context = context self._value = NotImplemented def __eq__(self, other): try: return self._value == other._value except AttributeError: return False def __ne__(self, other): return not (self == other) def __str__(self): return self.__pretty_str__() def __pretty_str__(self, nesting = 1, indentation = " "): if self._value is NotImplemented: text = "" elif hasattr(self._value, "__pretty_str__"): text = self._value.__pretty_str__(nesting, indentation) else: text = str(self._value) return "%s: %s" % (self.__class__.__name__, text) def read(self): self.stream.seek(self.pos) return self.subcon._parse(self.stream, self.context) def dispose(self): self.subcon = None self.stream = None self.context = None self.pos = None def _get_value(self): if self._value is NotImplemented: self._value = self.read() return self._value value = property(_get_value) has_value = property(lambda self: self._value is not NotImplemented)