Source code for reconfigure.nodes

[docs]class Node (object): """ A base node class for the Node Tree. This class represents a named container node. """ def __init__(self, name=None, *args, **kwargs): """ :param name: Node name :param *args: Children :param comment: Node comment string :param origin: Node's source location (usually path to the file) """ self.name = name self.origin = None self.children = [] self._extra_content = kwargs.pop('extra_content', None) for node in list(args) + kwargs.pop('children', []): self.append(node) self.comment = kwargs.pop('comment', None) self.__dict__.update(kwargs) def __str__(self): s = '(%s)' % self.name if self.comment: s += ' (%s)' % self.comment s += '\n' for child in self.children: if child.origin != self.origin: s += '\t@%s\n' % child.origin s += '\n'.join('\t' + x for x in str(child).splitlines()) + '\n' return s def __hash__(self): return sum(hash(x) for x in [self.name, self.origin, self.comment] + self.children) def __eq__(self, other): if other is None: return False return \ self.name == other.name and \ self.comment == other.comment and \ self.origin == other.origin and \ set(self.children) == set(other.children) def __iter__(self): return iter(self.children) def __len__(self): return len(self.children) def __nonzero__(self): return True def __getitem__(self, key): if type(key) in (int, slice): return self.children[key] return self.get(key) def __setitem__(self, key, value): if type(key) is int: self.children[key] = value self.set_property(key, value) def __contains__(self, item): return item in self.children
[docs] def indexof(self, node): """ :returns: index of the node in the children array or ``None`` if it's not a child """ if node in self.children: return self.children.index(node) else: return None
[docs] def get(self, name, default=None): """ :returns: a child node by its name or ``default`` """ for child in self.children: if child.name == name: return child if default: self.append(default) return default
[docs] def get_all(self, name): """ :returns: list of child nodes with supplied ``name`` """ return [n for n in self.children if n.name == name]
[docs] def append(self, node): if not node.origin: node.origin = self.origin self.children.append(node) node.parent = self
[docs] def remove(self, node): self.children.remove(node)
[docs] def replace(self, name, node=None): """ Replaces the child nodes by ``name`` :param node: replacement node or list of nodes :: n.append(Node('a')) n.append(Node('a')) n.replace('a', None) assert(len(n.get_all('a')) == 0) """ if name: self.children = [c for c in self.children if c.name != name] if node is not None: if type(node) == list: for n in node: self.children.append(n) else: self.children.append(node)
[docs] def set_property(self, name, value): """ Creates or replaces a child :class:`PropertyNode` by name. """ node = self.get(name) if node is None: node = PropertyNode(name, value) self.append(node) node.value = value return self
[docs]class RootNode (Node): """ A special node class that indicates tree root """
[docs]class PropertyNode (Node): """ A node that serves as a property of its parent node. """ def __init__(self, name, value, comment=None): """ :param name: Property name :param value: Property value """ Node.__init__(self, name, comment=comment) self.value = value def __eq__(self, other): if other is None: return False return \ Node.__eq__(self, other) and \ self.value == other.value def __hash__(self): return Node.__hash__(self) + hash(self.value) def __str__(self): s = '%s = %s' % (self.name, self.value) if self.comment: s += ' (%s)' % self.comment return s
[docs]class IncludeNode (Node): """ A node that indicates a junction point between two config files """ def __init__(self, files): """ :param files: an includer-dependent config location specifier """ Node.__init__(self) self.name = '<include>' self.files = files def __str__(self): return '<include> %s' % self.files