<commit_before>from uqbar.unique_trees import UniqueTreeContainer
from uqbar.graphs.Attributes import Attributes
from uqbar.graphs.Node import Node


class Graph(UniqueTreeContainer):

    ### INITIALIZER ###

    def __init__(
        self,
        name=None,
        children=None,
        is_cluster=None,
        is_digraph=True,
        attributes=None,
        edge_attributes=None,
        node_attributes=None,
        ):
        UniqueTreeContainer.__init__(self, name=name, children=children)
        if is_cluster is not None:
            is_cluster = bool(is_cluster)
        mode = 'graph'
        if is_cluster:
            mode = 'cluster'
        self._attributes = Attributes(mode, **(attributes or {}))
        self._edge_attributes = Attributes('edge', **(attributes or {}))
        self._node_attributes = Attributes('node', **(attributes or {}))
        self._is_cluster = is_cluster
        self._is_digraph = bool(is_digraph)

    ### SPECIAL METHODS ###

    def __format__(self, format_spec=None):
        # TODO: make the format specification options machine-readable
        if format_spec == 'graphviz':
            return self.__format_graphviz__()
        return str(self)

    def __format_graphviz__(self):
        def recurse(graph):
            indent = '    '
            result = []
            if not graph.parent:
                if graph.is_digraph:
                    string = 'digraph {} {{'.format(
                        Attributes._format_value(graph.name))
                else:
                    string = 'graph {} {{'.format(
                        Attributes._format_value(graph.name))
            elif graph.is_cluster:
                string = 'subgraph {} {{'.format(
                    Attributes._format_value('cluster_{}'.format(graph.name)))
            else:
                string = 'subgraph {} {{'.format(
                    Attributes._format_value(graph.name))
            result.append(string)
            if graph.attributes:
                attributes = 'graph {}'.format(
                    format(graph.attributes, 'graphviz')).split('\n')
                result.extend(indent + line for line in attributes)
            if graph.node_attributes:
                attributes = 'node {}'.format(
                    format(graph.node_attributes, 'graphviz')).split('\n')
                result.extend(indent + line for line in attributes)
            if graph.edge_attributes:
                attributes = 'edge {}'.format(
                    format(graph.edge_attributes, 'graphviz')).split('\n')
                result.extend(indent + line for line in attributes)
            for child in graph:
                if isinstance(child, type(self)):
                    lines = (indent + line for line in recurse(child))
                else:<commit_msg>Hardening graph naming.<commit_after>from uqbar.unique_trees import UniqueTreeContainer
from uqbar.graphs.Attributes import Attributes
from uqbar.graphs.Node import Node


class Graph(UniqueTreeContainer):

    ### INITIALIZER ###

    def __init__(
        self,
        name=None,
        children=None,
        is_cluster=None,
        is_digraph=True,
        attributes=None,
        edge_attributes=None,
        node_attributes=None,
        ):
        UniqueTreeContainer.__init__(self, name=name, children=children)
        if is_cluster is not None:
            is_cluster = bool(is_cluster)
        mode = 'graph'
        if is_cluster:
            mode = 'cluster'
        self._attributes = Attributes(mode, **(attributes or {}))
        self._edge_attributes = Attributes('edge', **(attributes or {}))
        self._node_attributes = Attributes('node', **(attributes or {}))
        self._is_cluster = is_cluster
        self._is_digraph = bool(is_digraph)

    ### SPECIAL METHODS ###

    def __format__(self, format_spec=None):
        # TODO: make the format specification options machine-readable
        if format_spec == 'graphviz':
            return self.__format_graphviz__()
        return str(self)

    def __format_graphviz__(self):
        def recurse(graph):
            indent = '    '
            result = []
            if not graph.parent:
                name = graph.name or 'G'
                if graph.is_digraph:
                    string = 'digraph {} {{'.format(
                        Attributes._format_value(name))
                else:
                    string = 'graph {} {{'.format(
                        Attributes._format_value(name))
            elif graph.is_cluster:
                name = graph.name or graph._get_canonical_name()
                string = 'subgraph {} {{'.format(
                    Attributes._format_value('cluster_{}'.format(name)))
            else:
                name = graph.name or graph._get_canonical_name()
                string = 'subgraph {} {{'.format(
                    Attributes._format_value(name))
            result.append(string)
            if graph.attributes:
                attributes = 'graph {}'.format(
                    format(graph.attributes, 'graphviz')).split('\n')
                result.extend(indent + line for line in attributes)
            if graph.node_attributes:
                attributes = 'node {}'.format(
                    format(graph.node_attributes, 'graphviz')).split('\n')
                result.extend(indent + line for line in attributes)
            if graph.edge_attributes:
                attributes = 'edge {}'.format(
                    format(graph.edge_attributes, 'graphviz')).split('\n')
                result.extend(indent + line for line in attributes)
            for child in graph:
                if isinstance(child, type(self)):
                    lines = (indent + line for line in recurse(child))
                else:
{'fraction_non_alphanumeric': 0.1045650301464255, 'fraction_numerical': 0.0, 'mean_word_length': 1.7806513409961686, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6501073', 'n_tokens_mistral': 1521, 'n_tokens_neox': 1444, 'n_words': 337}