def format(tree: Tree, indent: Union[int, None] = -1, compact: bool = False) -> str: """ Format *tree* into a PENMAN string. Args: tree: a Tree object indent: how to indent formatted strings compact: if ``True``, put initial attributes on the first line Returns: the PENMAN-serialized string of the Tree *t* Example: >>> import penman >>> print(penman.format( ... ('b', [('/', 'bark-01'), ... (':ARG0', ('d', [('/', 'dog')]))]))) (b / bark-01 :ARG0 (d / dog)) """ if not isinstance(tree, Tree): tree = Tree(tree) vars = [var for var, _ in tree.nodes()] if compact else [] parts = ['# ::{}{}'.format(key, ' ' + value if value else value) for key, value in tree.metadata.items()] parts.append(_format_node(tree.node, indent, 0, set(vars))) return '\n'.join(parts)
def format(self, tree: Tree, indent: Union[int, None] = -1, compact: bool = False) -> str: """ Format *tree* into a PENMAN string. """ if not isinstance(tree, Tree): tree = Tree(tree) vars = [var for var, _ in tree.nodes()] if compact else [] parts = [ '# ::{}{}'.format(key, ' ' + value if value else value) for key, value in tree.metadata.items() ] parts.append(self._format_node(tree.node, indent, 0, set(vars))) return '\n'.join(parts)
def interpret(t: Tree, model: Model = None) -> Graph: """ Interpret tree *t* as a graph using *model*. Tree interpretation is the process of transforming the nodes and edges of a tree into a directed graph. A semantic model determines which edges are inverted and how to deinvert them. If *model* is not provided, the default model will be used. Args: t: the :class:`~penman.tree.Tree` to interpret model: the :class:`~penman.model.Model` used to interpret *t* Returns: The interpreted :class:`~penman.graph.Graph`. Example: >>> from penman.tree import Tree >>> from penman import layout >>> t = Tree( ... ('b', [ ... ('/', 'bark-01'), ... ('ARG0', ('d', [ ... ('/', 'dog')]))])) >>> g = layout.interpret(t) >>> for triple in g.triples: ... print(triple) ... ('b', ':instance', 'bark-01') ('b', ':ARG0', 'd') ('d', ':instance', 'dog') """ if model is None: model = _default_model variables = {v for v, _ in t.nodes()} top, triples, epidata = _interpret_node(t.node, variables, model) epimap = {} for triple, epis in epidata: if triple in epimap: logger.warning( f'ignoring epigraph data for duplicate triple: {triple}' ) else: epimap[triple] = epis g = Graph(triples, top=top, epidata=epimap, metadata=t.metadata) logger.info('Interpreted: %s', g) return g
def rearrange(t: Tree, key: Callable[[Role], Any] = None, attributes_first: bool = False) -> None: """ Sort the branches at each node in tree *t* according to *key*. Each node in a tree contains a list of branches. This function sorts those lists in-place using the *key* function, which accepts a role and returns some sortable criterion. If the *attributes_first* argument is ``True``, attribute branches are appear before any edges. Instance branches (``/``) always appear before any other branches. Example: >>> from penman import layout >>> from penman.model import Model >>> from penman.codec import PENMANCodec >>> c = PENMANCodec() >>> t = c.parse( ... '(s / see-01' ... ' :ARG1 (c / cat)' ... ' :ARG0 (d / dog))') >>> layout.rearrange(t, key=Model().canonical_order) >>> print(c.format(t)) (s / see-01 :ARG0 (d / dog) :ARG1 (c / cat)) """ if attributes_first: variables = {node[0] for node in t.nodes()} else: variables = set() def sort_key(branch: Branch): role, target = branch if is_atomic(target): criterion1 = target in variables else: criterion1 = target[0] in variables criterion2 = True if key is None else key(role) return (criterion1, criterion2) _rearrange(t.node, sort_key)