Container May 27, 2006
A general container of attributes, with support for pretty printing. Very useful for debugging, etc. Used extensively in Construct to represent parsed objects.
Code
#
# module Container.py
#
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)
return wrapper
return decorator
class Container(object):
def __init__(self, **kw):
self.__dict__.update(kw)
@recursion_lock("<...>")
def __repr__(self):
attrs = sorted("%s = %r" % (k, v) for k, v in self.__dict__.iteritems() if not k.startswith("_"))
return "%s(%s)" % (self.__class__.__name__, ", ".join(attrs))
@recursion_lock("<...>")
def __str__(self, nesting = 1):
attrs = []
indentation = " " * nesting
for k, v in self.__dict__.iteritems():
if not k.startswith("_"):
text = [indentation, k, " = "]
if isinstance(v, Container):
text.append(v.__str__(nesting + 1))
else:
text.append(repr(v))
attrs.append("".join(text))
attrs.sort()
attrs.insert(0, self.__class__.__name__ + ":")
return "\n".join(attrs)
Example
>>> c = Container(a=1, b="baaa")
>>> c # calls repr()
Container(a = 1, b = 'baaa')
>>> print c # calls str()
Container:
a = 1
b = 'baaa'
>>> c.c = 1.23
>>> print c
Container:
a = 1
b = 'baaa'
c = 1.23
>>> c.d = Container(e = 6, f = "g")
>>> c
Container(a = 1, b = 'baaa', c = 1.23, d = Container(e = 6, f = 'g'))
>>> print c
Container:
a = 1
b = 'baaa'
c = 1.23
d = Container:
e = 6
f = 'g'
>>> c.h = c # recursive referencing
>>> c
Container(a = 1, b = 'baaa', c = 1.23, d = Container(e = 6, f = 'g'), h = <...>)
>>> print c
Container:
a = 1
b = 'baaa'
c = 1.23
d = Container:
e = 6
f = 'g'
h = <...>
>>>