blob: d897c30aa3ad0c131db0c9585226d6981250d2e5 [file] [log] [blame]
import pickle
import six
class MetaNode(type):
def __new__(mcs, name, bases, dict):
attrs = list(dict['attrs'])
dict['attrs'] = list()
for base in bases:
if hasattr(base, 'attrs'):
dict['attrs'].extend(base.attrs)
dict['attrs'].extend(attrs)
return type.__new__(mcs, name, bases, dict)
@six.add_metaclass(MetaNode)
class Node(object):
attrs = ()
def __init__(self, **kwargs):
values = kwargs.copy()
for attr_name in self.attrs:
value = values.pop(attr_name, None)
setattr(self, attr_name, value)
if values:
raise ValueError('Extraneous arguments')
def __equals__(self, other):
if type(other) is not type(self):
return False
for attr in self.attrs:
if getattr(other, attr) != getattr(self, attr):
return False
return True
def __repr__(self):
return type(self).__name__
def __iter__(self):
return walk_tree(self)
def filter(self, pattern):
for path, node in self:
if ((isinstance(pattern, type) and isinstance(node, pattern)) or
(node == pattern)):
yield path, node
@property
def children(self):
return [getattr(self, attr_name) for attr_name in self.attrs]
@property
def position(self):
if hasattr(self, "_position"):
return self._position
def walk_tree(root):
children = None
if isinstance(root, Node):
yield (), root
children = root.children
else:
children = root
for child in children:
if isinstance(child, (Node, list, tuple)):
for path, node in walk_tree(child):
yield (root,) + path, node
def dump(ast, file):
pickle.dump(ast, file)
def load(file):
return pickle.load(file)