Mercurial > repos > shellac > sam_consensus_v3
diff env/lib/python3.9/site-packages/dot_parser.py @ 0:4f3585e2f14b draft default tip
"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author | shellac |
---|---|
date | Mon, 22 Mar 2021 18:12:50 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/env/lib/python3.9/site-packages/dot_parser.py Mon Mar 22 18:12:50 2021 +0000 @@ -0,0 +1,554 @@ +"""Graphviz's dot language parser. + +The dotparser parses GraphViz files in +dot and dot files and transforms them +into a class representation defined by `pydot`. + +Author: Michael Krause <michael@krause-software.de> +Fixes by: Ero Carrera <ero.carrera@gmail.com> +""" +from __future__ import division +from __future__ import print_function +import sys + +from pyparsing import ( + nestedExpr, Literal, CaselessLiteral, + Word, OneOrMore, + Forward, + Group, Optional, Combine, + restOfLine, cStyleComment, nums, alphanums, + printables, + ParseException, ParseResults, CharsNotIn, + QuotedString) + +import pydot + +__author__ = ['Michael Krause', 'Ero Carrera'] +__license__ = 'MIT' + + +PY3 = sys.version_info >= (3, 0, 0) +if PY3: + str_type = str +else: + str_type = basestring + + +class P_AttrList(object): + + def __init__(self, toks): + + self.attrs = {} + i = 0 + + while i < len(toks): + attrname = toks[i] + if i+2 < len(toks) and toks[i+1] == '=': + attrvalue = toks[i+2] + i += 3 + else: + attrvalue = None + i += 1 + + self.attrs[attrname] = attrvalue + + + def __repr__(self): + + return "%s(%r)" % (self.__class__.__name__, self.attrs) + + + +class DefaultStatement(P_AttrList): + + def __init__(self, default_type, attrs): + + self.default_type = default_type + self.attrs = attrs + + def __repr__(self): + + return "%s(%s, %r)" % (self.__class__.__name__, + self.default_type, self.attrs) + + +top_graphs = list() + +def push_top_graph_stmt(str, loc, toks): + + attrs = {} + g = None + + for element in toks: + + if (isinstance(element, (ParseResults, tuple, list)) and + len(element) == 1 and + isinstance(element[0], str_type)): + + element = element[0] + + if element == 'strict': + attrs['strict'] = True + + elif element in ['graph', 'digraph']: + + attrs = {} + + g = pydot.Dot(graph_type=element, **attrs) + attrs['type'] = element + + top_graphs.append( g ) + + elif isinstance( element, str_type): + g.set_name( element ) + + elif isinstance(element, pydot.Subgraph): + + g.obj_dict['attributes'].update( element.obj_dict['attributes'] ) + g.obj_dict['edges'].update( element.obj_dict['edges'] ) + g.obj_dict['nodes'].update( element.obj_dict['nodes'] ) + g.obj_dict['subgraphs'].update( element.obj_dict['subgraphs'] ) + + g.set_parent_graph(g) + + elif isinstance(element, P_AttrList): + attrs.update(element.attrs) + + elif isinstance(element, (ParseResults, list)): + add_elements(g, element) + + else: + raise ValueError( + 'Unknown element statement: {s}'.format(s=element)) + + + for g in top_graphs: + update_parent_graph_hierarchy(g) + + if len( top_graphs ) == 1: + return top_graphs[0] + + return top_graphs + + +def update_parent_graph_hierarchy(g, parent_graph=None, level=0): + + + if parent_graph is None: + parent_graph = g + + for key_name in ('edges',): + + if isinstance(g, pydot.frozendict): + item_dict = g + else: + item_dict = g.obj_dict + + if key_name not in item_dict: + continue + + for key, objs in item_dict[key_name].items(): + for obj in objs: + if ('parent_graph' in obj and + obj['parent_graph'].get_parent_graph()==g): + if obj['parent_graph'] is g: + pass + else: + obj['parent_graph'].set_parent_graph(parent_graph) + + if key_name == 'edges' and len(key) == 2: + for idx, vertex in enumerate( obj['points'] ): + if isinstance( vertex, + (pydot.Graph, + pydot.Subgraph, pydot.Cluster)): + vertex.set_parent_graph(parent_graph) + if isinstance( vertex, pydot.frozendict): + if vertex['parent_graph'] is g: + pass + else: + vertex['parent_graph'].set_parent_graph( + parent_graph) + + + +def add_defaults(element, defaults): + + d = element.__dict__ + for key, value in defaults.items(): + if not d.get(key): + d[key] = value + + + +def add_elements(g, toks, defaults_graph=None, + defaults_node=None, defaults_edge=None): + + if defaults_graph is None: + defaults_graph = {} + if defaults_node is None: + defaults_node = {} + if defaults_edge is None: + defaults_edge = {} + + for elm_idx, element in enumerate(toks): + + if isinstance(element, (pydot.Subgraph, pydot.Cluster)): + + add_defaults(element, defaults_graph) + g.add_subgraph(element) + + elif isinstance(element, pydot.Node): + + add_defaults(element, defaults_node) + g.add_node(element) + + elif isinstance(element, pydot.Edge): + + add_defaults(element, defaults_edge) + g.add_edge(element) + + elif isinstance(element, ParseResults): + + for e in element: + add_elements(g, [e], defaults_graph, + defaults_node, defaults_edge) + + elif isinstance(element, DefaultStatement): + + if element.default_type == 'graph': + + default_graph_attrs = pydot.Node('graph', **element.attrs) + g.add_node(default_graph_attrs) + + elif element.default_type == 'node': + + default_node_attrs = pydot.Node('node', **element.attrs) + g.add_node(default_node_attrs) + + elif element.default_type == 'edge': + + default_edge_attrs = pydot.Node('edge', **element.attrs) + g.add_node(default_edge_attrs) + defaults_edge.update(element.attrs) + + else: + raise ValueError( + 'Unknown DefaultStatement: {s}'.format( + s=element.default_type)) + + elif isinstance(element, P_AttrList): + + g.obj_dict['attributes'].update(element.attrs) + + else: + raise ValueError( + 'Unknown element statement: {s}'.format(s=element)) + + +def push_graph_stmt(str, loc, toks): + + g = pydot.Subgraph('') + add_elements(g, toks) + return g + + +def push_subgraph_stmt(str, loc, toks): + + g = pydot.Subgraph('') + for e in toks: + if len(e)==3: + e[2].set_name(e[1]) + if e[0] == 'subgraph': + e[2].obj_dict['show_keyword'] = True + return e[2] + else: + if e[0] == 'subgraph': + e[1].obj_dict['show_keyword'] = True + return e[1] + + return g + + +def push_default_stmt(str, loc, toks): + + # The pydot class instances should be marked as + # default statements to be inherited by actual + # graphs, nodes and edges. + # + default_type = toks[0][0] + if len(toks) > 1: + attrs = toks[1].attrs + else: + attrs = {} + + if default_type in ['graph', 'node', 'edge']: + return DefaultStatement(default_type, attrs) + else: + raise ValueError( + 'Unknown default statement: {s}'.format(s=toks)) + + +def push_attr_list(str, loc, toks): + + p = P_AttrList(toks) + return p + + +def get_port(node): + + if len(node)>1: + if isinstance(node[1], ParseResults): + if len(node[1][0])==2: + if node[1][0][0]==':': + return node[1][0][1] + + return None + + +def do_node_ports(node): + + node_port = '' + if len(node) > 1: + node_port = ''.join( [str(a)+str(b) for a,b in node[1] ] ) + + return node_port + + +def push_edge_stmt(str, loc, toks): + + tok_attrs = [a for a in toks if isinstance(a, P_AttrList)] + attrs = {} + for a in tok_attrs: + attrs.update(a.attrs) + + e = [] + + if isinstance(toks[0][0], pydot.Graph): + + n_prev = pydot.frozendict(toks[0][0].obj_dict) + else: + n_prev = toks[0][0] + do_node_ports( toks[0] ) + + if isinstance(toks[2][0], ParseResults): + + n_next_list = [[n.get_name(),] for n in toks[2][0] ] + for n_next in [n for n in n_next_list]: + n_next_port = do_node_ports(n_next) + e.append(pydot.Edge(n_prev, n_next[0]+n_next_port, **attrs)) + + elif isinstance(toks[2][0], pydot.Graph): + + e.append(pydot.Edge(n_prev, + pydot.frozendict(toks[2][0].obj_dict), + **attrs)) + + elif isinstance(toks[2][0], pydot.Node): + + node = toks[2][0] + + if node.get_port() is not None: + name_port = node.get_name() + ":" + node.get_port() + else: + name_port = node.get_name() + + e.append(pydot.Edge(n_prev, name_port, **attrs)) + + # if the target of this edge is the name of a node + elif isinstance(toks[2][0], str_type): + + for n_next in [n for n in tuple(toks)[2::2]]: + + if (isinstance(n_next, P_AttrList) or + not isinstance(n_next[0], str_type)): + continue + + n_next_port = do_node_ports( n_next ) + e.append(pydot.Edge(n_prev, n_next[0]+n_next_port, **attrs)) + + n_prev = n_next[0]+n_next_port + else: + raise Exception( + 'Edge target {r} with type {s} unsupported.'.format( + r=toks[2][0], s=type(toks[2][0]))) + + return e + + + +def push_node_stmt(s, loc, toks): + + if len(toks) == 2: + attrs = toks[1].attrs + else: + attrs = {} + + node_name = toks[0] + if isinstance(node_name, list) or isinstance(node_name, tuple): + if len(node_name)>0: + node_name = node_name[0] + + n = pydot.Node(str(node_name), **attrs) + return n + + + + + + +graphparser = None + +def graph_definition(): + + global graphparser + + if not graphparser: + + # punctuation + colon = Literal(":") + lbrace = Literal("{") + rbrace = Literal("}") + lbrack = Literal("[") + rbrack = Literal("]") + lparen = Literal("(") + rparen = Literal(")") + equals = Literal("=") + comma = Literal(",") + dot = Literal(".") + slash = Literal("/") + bslash = Literal("\\") + star = Literal("*") + semi = Literal(";") + at = Literal("@") + minus = Literal("-") + + # keywords + strict_ = CaselessLiteral("strict") + graph_ = CaselessLiteral("graph") + digraph_ = CaselessLiteral("digraph") + subgraph_ = CaselessLiteral("subgraph") + node_ = CaselessLiteral("node") + edge_ = CaselessLiteral("edge") + + + # token definitions + + identifier = Word(alphanums + "_." ).setName("identifier") + + double_quoted_string = QuotedString( + '"', multiline=True, unquoteResults=False, escChar='\\') # dblQuotedString + + noncomma = "".join([c for c in printables if c != ","]) + alphastring_ = OneOrMore(CharsNotIn(noncomma + ' ')) + + def parse_html(s, loc, toks): + return '<%s>' % ''.join(toks[0]) + + + opener = '<' + closer = '>' + html_text = nestedExpr( opener, closer, + ( CharsNotIn( opener + closer ) ) + ).setParseAction(parse_html).leaveWhitespace() + + ID = ( identifier | html_text | + double_quoted_string | #.setParseAction(strip_quotes) | + alphastring_ ).setName("ID") + + + float_number = Combine(Optional(minus) + + OneOrMore(Word(nums + "."))).setName("float_number") + + righthand_id = (float_number | ID ).setName("righthand_id") + + port_angle = (at + ID).setName("port_angle") + + port_location = (OneOrMore(Group(colon + ID)) | + Group(colon + lparen + + ID + comma + ID + rparen)).setName("port_location") + + port = (Group(port_location + Optional(port_angle)) | + Group(port_angle + Optional(port_location))).setName("port") + + node_id = (ID + Optional(port)) + a_list = OneOrMore(ID + Optional(equals + righthand_id) + + Optional(comma.suppress())).setName("a_list") + + attr_list = OneOrMore(lbrack.suppress() + Optional(a_list) + + rbrack.suppress()).setName("attr_list") + + attr_stmt = (Group(graph_ | node_ | edge_) + + attr_list).setName("attr_stmt") + + edgeop = (Literal("--") | Literal("->")).setName("edgeop") + + stmt_list = Forward() + graph_stmt = Group(lbrace.suppress() + Optional(stmt_list) + + rbrace.suppress() + + Optional(semi.suppress())).setName("graph_stmt") + + + edge_point = Forward() + + edgeRHS = OneOrMore(edgeop + edge_point) + edge_stmt = edge_point + edgeRHS + Optional(attr_list) + + subgraph = Group( + subgraph_ + Optional(ID) + graph_stmt).setName("subgraph") + + edge_point << Group( + subgraph | graph_stmt | node_id).setName('edge_point') + + node_stmt = ( + node_id + Optional(attr_list) + + Optional(semi.suppress())).setName("node_stmt") + + assignment = (ID + equals + righthand_id).setName("assignment") + stmt = (assignment | edge_stmt | attr_stmt | + subgraph | graph_stmt | node_stmt).setName("stmt") + stmt_list << OneOrMore(stmt + Optional(semi.suppress())) + + graphparser = OneOrMore( + (Optional(strict_) + Group((graph_ | digraph_)) + + Optional(ID) + graph_stmt).setResultsName("graph")) + + singleLineComment = Group( + "//" + restOfLine) | Group("#" + restOfLine) + + + # actions + + graphparser.ignore(singleLineComment) + graphparser.ignore(cStyleComment) + + assignment.setParseAction(push_attr_list) + a_list.setParseAction(push_attr_list) + edge_stmt.setParseAction(push_edge_stmt) + node_stmt.setParseAction(push_node_stmt) + attr_stmt.setParseAction(push_default_stmt) + + subgraph.setParseAction(push_subgraph_stmt) + graph_stmt.setParseAction(push_graph_stmt) + graphparser.setParseAction(push_top_graph_stmt) + + + return graphparser + + +def parse_dot_data(s): + """Parse DOT description in (unicode) string `s`. + + @return: Graphs that result from parsing. + @rtype: `list` of `pydot.Dot` + """ + global top_graphs + top_graphs = list() + try: + graphparser = graph_definition() + graphparser.parseWithTabs() + tokens = graphparser.parseString(s) + return list(tokens) + except ParseException as err: + print(err.line) + print(" " * (err.column - 1) + "^") + print(err) + return None