imported new version of construct with Python 3 compatibility
diff --git a/elftools/construct/lib/container.py b/elftools/construct/lib/container.py
index eb4b738..2f89b2d 100644
--- a/elftools/construct/lib/container.py
+++ b/elftools/construct/lib/container.py
@@ -1,3 +1,10 @@
+"""
+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):
@@ -12,249 +19,143 @@
return wrapper
return decorator
-class Container(object):
+class Container(MutableMapping):
"""
- A generic container of attributes
+ A generic container of attributes.
+
+ Containers are the common way to express parsed data.
"""
- __slots__ = ["__dict__", "__attrs__"]
+
def __init__(self, **kw):
- self.__dict__.update(kw)
- object.__setattr__(self, "__attrs__", kw.keys())
-
+ 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)
-
- def __delattr__(self, name):
- object.__delattr__(self, name)
- self.__attrs__.remove(name)
- def __setattr__(self, name, value):
- d = self.__dict__
- if name not in d:
- self.__attrs__.append(name)
- d[name] = value
- def __contains__(self, name):
- return name in self.__dict__
- def __getitem__(self, name):
- return self.__dict__[name]
- def __delitem__(self, name):
- self.__delattr__(name)
- def __setitem__(self, name, value):
- self.__setattr__(name, value)
- def __update__(self, obj):
- for name in obj.__attrs__:
- self[name] = obj[name]
- def __copy__(self):
- new = self.__class__()
- new.__attrs__ = self.__attrs__[:]
- new.__dict__ = self.__dict__.copy()
- return new
-
- @recursion_lock("<...>")
+ 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):
- 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))
+ return "%s(%s)" % (self.__class__.__name__, repr(self.__dict__))
+
def __str__(self):
- return self.__pretty_str__()
- @recursion_lock("<...>")
- def __pretty_str__(self, nesting = 1, indentation = " "):
- attrs = []
- ind = indentation * nesting
- for k in self.__attrs__:
- v = self.__dict__[k]
- if not k.startswith("_"):
- text = [ind, k, " = "]
- if hasattr(v, "__pretty_str__"):
- text.append(v.__pretty_str__(nesting + 1, indentation))
- else:
- text.append(str(v))
- attrs.append("".join(text))
- if not attrs:
- return "%s()" % (self.__class__.__name__,)
- attrs.insert(0, self.__class__.__name__ + ":")
- return "\n".join(attrs)
+ return "%s(%s)" % (self.__class__.__name__, str(self.__dict__))
class FlagsContainer(Container):
"""
- A container providing pretty-printing for flags. Only set flags are
- displayed.
+ A container providing pretty-printing for flags.
+
+ Only set flags are displayed.
"""
- def __pretty_str__(self, nesting = 1, indentation = " "):
- attrs = []
- ind = indentation * nesting
- for k in self.__attrs__:
- v = self.__dict__[k]
- if not k.startswith("_") and v:
- attrs.append(ind + k)
- if not attrs:
- return "%s()" % (self.__class__.__name__,)
- attrs.insert(0, self.__class__.__name__+ ":")
- return "\n".join(attrs)
+
+ @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
+ A container for lists.
"""
- __slots__ = ["__recursion_lock__"]
- def __str__(self):
- return self.__pretty_str__()
- @recursion_lock("[...]")
- def __pretty_str__(self, nesting = 1, indentation = " "):
- if not self:
- return "[]"
- ind = indentation * nesting
- lines = ["["]
- for elem in self:
- lines.append("\n")
- lines.append(ind)
- if hasattr(elem, "__pretty_str__"):
- lines.append(elem.__pretty_str__(nesting + 1, indentation))
- else:
- lines.append(repr(elem))
- lines.append("\n")
- lines.append(indentation * (nesting - 1))
- lines.append("]")
- return "".join(lines)
-class AttrDict(object):
- """
- A dictionary that can be accessed both using indexing and attributes,
- i.e.,
- x = AttrDict()
- x.foo = 5
- print x["foo"]
- """
- __slots__ = ["__dict__"]
- def __init__(self, **kw):
- self.__dict__ = kw
- def __contains__(self, key):
- return key in self.__dict__
- def __nonzero__(self):
- return bool(self.__dict__)
- def __repr__(self):
- return repr(self.__dict__)
+ __slots__ = ["__recursion_lock__"]
+
+ @recursion_lock("[...]")
def __str__(self):
- return self.__pretty_str__()
- def __pretty_str__(self, nesting = 1, indentation = " "):
- if not self:
- return "{}"
- text = ["{\n"]
- ind = nesting * indentation
- for k in sorted(self.__dict__.keys()):
- v = self.__dict__[k]
- text.append(ind)
- text.append(repr(k))
- text.append(" : ")
- if hasattr(v, "__pretty_str__"):
- try:
- text.append(v.__pretty_str__(nesting+1, indentation))
- except Exception:
- text.append(repr(v))
- else:
- text.append(repr(v))
- text.append("\n")
- text.append((nesting-1) * indentation)
- text.append("}")
- return "".join(text)
- def __delitem__(self, key):
- del self.__dict__[key]
- def __getitem__(self, key):
- return self.__dict__[key]
- def __setitem__(self, key, value):
- self.__dict__[key] = value
- def __copy__(self):
- new = self.__class__()
- new.__dict__ = self.__dict__.copy()
- return new
- def __update__(self, other):
- if isinstance(other, dict):
- self.__dict__.update(other)
- else:
- self.__dict__.update(other.__dict__)
+ 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 = "<unread>"
elif hasattr(self._value, "__pretty_str__"):
text = self._value.__pretty_str__(nesting, indentation)
else:
- text = repr(self._value)
+ 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)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-