From 32d50dec2a8125196b65ac48737d0f316eced21e Mon Sep 17 00:00:00 2001 From: Peter Nowee Date: Sat, 29 May 2021 16:12:20 +0200 Subject: [PATCH 1/3] black -l 79 --skip-string-normalization # 21.5b1 --- dot_parser.py | 196 ++++++++----- pydot.py | 624 ++++++++++++++++++++++++++++------------- setup.py | 6 +- test/pydot_unittest.py | 126 +++++---- 4 files changed, 628 insertions(+), 324 deletions(-) diff --git a/dot_parser.py b/dot_parser.py index a6b8ee0b..e9bc2538 100644 --- a/dot_parser.py +++ b/dot_parser.py @@ -12,14 +12,25 @@ import sys from pyparsing import ( - nestedExpr, Literal, CaselessLiteral, - Word, OneOrMore, + nestedExpr, + Literal, + CaselessLiteral, + Word, + OneOrMore, Forward, - Group, Optional, Combine, - restOfLine, cStyleComment, nums, alphanums, + Group, + Optional, + Combine, + restOfLine, + cStyleComment, + nums, + alphanums, printables, - ParseException, ParseResults, CharsNotIn, - QuotedString) + ParseException, + ParseResults, + CharsNotIn, + QuotedString, +) import pydot @@ -35,15 +46,14 @@ 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] + if i + 2 < len(toks) and toks[i + 1] == '=': + attrvalue = toks[i + 2] i += 3 else: attrvalue = None @@ -56,14 +66,16 @@ def __repr__(self): 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) + return "%s(%s, %r)" % ( + self.__class__.__name__, + self.default_type, + self.attrs, + ) top_graphs = list() @@ -75,9 +87,11 @@ def push_top_graph_stmt(str, loc, toks): for element in toks: - if (isinstance(element, (ParseResults, tuple, list)) and - len(element) == 1 and - isinstance(element[0], str_type)): + if ( + isinstance(element, (ParseResults, tuple, list)) + and len(element) == 1 + and isinstance(element[0], str_type) + ): element = element[0] @@ -113,7 +127,8 @@ def push_top_graph_stmt(str, loc, toks): else: raise ValueError( - 'Unknown element statement: {s}'.format(s=element)) + 'Unknown element statement: {s}'.format(s=element) + ) for g in top_graphs: update_parent_graph_hierarchy(g) @@ -140,8 +155,10 @@ def update_parent_graph_hierarchy(g, parent_graph=None, level=0): 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 ( + 'parent_graph' in obj + and obj['parent_graph'].get_parent_graph() == g + ): if obj['parent_graph'] is g: pass else: @@ -149,16 +166,18 @@ def update_parent_graph_hierarchy(g, parent_graph=None, level=0): if key_name == 'edges' and len(key) == 2: for idx, vertex in enumerate(obj['points']): - if isinstance(vertex, - (pydot.Graph, - pydot.Subgraph, pydot.Cluster)): + 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) + parent_graph + ) def add_defaults(element, defaults): @@ -168,8 +187,9 @@ def add_defaults(element, defaults): d[key] = value -def add_elements(g, toks, defaults_graph=None, - defaults_node=None, defaults_edge=None): +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: @@ -197,8 +217,9 @@ def add_elements(g, toks, defaults_graph=None, elif isinstance(element, ParseResults): for e in element: - add_elements(g, [e], defaults_graph, - defaults_node, defaults_edge) + add_elements( + g, [e], defaults_graph, defaults_node, defaults_edge + ) elif isinstance(element, DefaultStatement): @@ -221,7 +242,9 @@ def add_elements(g, toks, defaults_graph=None, else: raise ValueError( 'Unknown DefaultStatement: {s}'.format( - s=element.default_type)) + s=element.default_type + ) + ) elif isinstance(element, P_AttrList): @@ -229,7 +252,8 @@ def add_elements(g, toks, defaults_graph=None, else: raise ValueError( - 'Unknown element statement: {s}'.format(s=element)) + 'Unknown element statement: {s}'.format(s=element) + ) def push_graph_stmt(str, loc, toks): @@ -268,8 +292,7 @@ def push_default_stmt(str, loc, toks): if default_type in ['graph', 'node', 'edge']: return DefaultStatement(default_type, attrs) else: - raise ValueError( - 'Unknown default statement: {s}'.format(s=toks)) + raise ValueError('Unknown default statement: {s}'.format(s=toks)) def push_attr_list(str, loc, toks): @@ -290,7 +313,7 @@ def get_port(node): def do_node_ports(node): node_port = '' if len(node) > 1: - node_port = ''.join([str(a)+str(b) for a, b in node[1]]) + node_port = ''.join([str(a) + str(b) for a, b in node[1]]) return node_port @@ -311,16 +334,21 @@ def push_edge_stmt(str, loc, toks): if isinstance(toks[2][0], ParseResults): - n_next_list = [[n.get_name(), ] for n in toks[2][0]] + 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)) + 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)) + e.append( + pydot.Edge(n_prev, pydot.frozendict(toks[2][0].obj_dict), **attrs) + ) elif isinstance(toks[2][0], pydot.Node): @@ -338,18 +366,21 @@ def push_edge_stmt(str, loc, toks): 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)): + 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)) + e.append(pydot.Edge(n_prev, n_next[0] + n_next_port, **attrs)) - n_prev = n_next[0]+n_next_port + 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]))) + r=toks[2][0], s=type(toks[2][0]) + ) + ) return e @@ -417,16 +448,18 @@ def parse_html(s, loc, toks): opener = '<' closer = '>' - html_text = nestedExpr( - opener, closer, (CharsNotIn(opener + closer)) - ).setParseAction(parse_html).leaveWhitespace() + html_text = ( + nestedExpr(opener, closer, (CharsNotIn(opener + closer))) + .setParseAction(parse_html) + .leaveWhitespace() + ) - ID = (identifier | html_text | double_quoted_string | - alphastring_).setName("ID") + ID = ( + identifier | html_text | double_quoted_string | alphastring_ + ).setName("ID") float_number = Combine( - Optional(minus) + - OneOrMore(Word(nums + ".")) + Optional(minus) + OneOrMore(Word(nums + ".")) ).setName("float_number") righthand_id = (float_number | ID).setName("righthand_id") @@ -434,39 +467,36 @@ def parse_html(s, loc, toks): port_angle = (at + ID).setName("port_angle") port_location = ( - OneOrMore(Group(colon + ID)) | - Group(colon + lparen + ID + comma + ID + rparen) + 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)) + Group(port_location + Optional(port_angle)) + | Group(port_angle + Optional(port_location)) ).setName("port") - node_id = (ID + Optional(port)) + node_id = ID + Optional(port) a_list = OneOrMore( - ID + - Optional(equals + righthand_id) + - Optional(comma.suppress()) + ID + Optional(equals + righthand_id) + Optional(comma.suppress()) ).setName("a_list") attr_list = OneOrMore( - lbrack.suppress() + - Optional(a_list) + - rbrack.suppress() + lbrack.suppress() + Optional(a_list) + rbrack.suppress() ).setName("attr_list") - attr_stmt = (Group(graph_ | node_ | edge_) + - attr_list).setName("attr_stmt") + 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()) + lbrace.suppress() + + Optional(stmt_list) + + rbrace.suppress() + + Optional(semi.suppress()) ).setName("graph_stmt") edge_point = Forward() @@ -474,27 +504,39 @@ def parse_html(s, loc, toks): edgeRHS = OneOrMore(edgeop + edge_point) edge_stmt = edge_point + edgeRHS + Optional(attr_list) - subgraph = Group( - subgraph_ + Optional(ID) + graph_stmt).setName("subgraph") + subgraph = Group(subgraph_ + Optional(ID) + graph_stmt).setName( + "subgraph" + ) - edge_point << Group( - subgraph | graph_stmt | node_id).setName('edge_point') + edge_point << Group(subgraph | graph_stmt | node_id).setName( + 'edge_point' + ) node_stmt = ( - node_id + Optional(attr_list) + - Optional(semi.suppress())).setName("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 = ( + 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")) + ( + Optional(strict_) + + Group((graph_ | digraph_)) + + Optional(ID) + + graph_stmt + ).setResultsName("graph") + ) - singleLineComment = Group( - "//" + restOfLine) | Group("#" + restOfLine) + singleLineComment = Group("//" + restOfLine) | Group("#" + restOfLine) # actions diff --git a/pydot.py b/pydot.py index c8c461d8..28efdbb5 100644 --- a/pydot.py +++ b/pydot.py @@ -17,7 +17,8 @@ warnings.warn( "`pydot` could not import `dot_parser`, " "so `pydot` will be unable to parse DOT files. " - "The error was: {e}".format(e=e)) + "The error was: {e}".format(e=e) + ) __author__ = 'Ero Carrera' @@ -33,59 +34,231 @@ GRAPH_ATTRIBUTES = { - 'Damping', 'K', 'URL', 'aspect', 'bb', 'bgcolor', - 'center', 'charset', 'clusterrank', 'colorscheme', 'comment', 'compound', - 'concentrate', 'defaultdist', 'dim', 'dimen', 'diredgeconstraints', - 'dpi', 'epsilon', 'esep', 'fontcolor', 'fontname', 'fontnames', - 'fontpath', 'fontsize', 'id', 'label', 'labeljust', 'labelloc', - 'landscape', 'layers', 'layersep', 'layout', 'levels', 'levelsgap', - 'lheight', 'lp', 'lwidth', 'margin', 'maxiter', 'mclimit', 'mindist', - 'mode', 'model', 'mosek', 'nodesep', 'nojustify', 'normalize', 'nslimit', - 'nslimit1', 'ordering', 'orientation', 'outputorder', 'overlap', - 'overlap_scaling', 'pack', 'packmode', 'pad', 'page', 'pagedir', - 'quadtree', 'quantum', 'rankdir', 'ranksep', 'ratio', 'remincross', - 'repulsiveforce', 'resolution', 'root', 'rotate', 'searchsize', 'sep', - 'showboxes', 'size', 'smoothing', 'sortv', 'splines', 'start', - 'stylesheet', 'target', 'truecolor', 'viewport', 'voro_margin', + 'Damping', + 'K', + 'URL', + 'aspect', + 'bb', + 'bgcolor', + 'center', + 'charset', + 'clusterrank', + 'colorscheme', + 'comment', + 'compound', + 'concentrate', + 'defaultdist', + 'dim', + 'dimen', + 'diredgeconstraints', + 'dpi', + 'epsilon', + 'esep', + 'fontcolor', + 'fontname', + 'fontnames', + 'fontpath', + 'fontsize', + 'id', + 'label', + 'labeljust', + 'labelloc', + 'landscape', + 'layers', + 'layersep', + 'layout', + 'levels', + 'levelsgap', + 'lheight', + 'lp', + 'lwidth', + 'margin', + 'maxiter', + 'mclimit', + 'mindist', + 'mode', + 'model', + 'mosek', + 'nodesep', + 'nojustify', + 'normalize', + 'nslimit', + 'nslimit1', + 'ordering', + 'orientation', + 'outputorder', + 'overlap', + 'overlap_scaling', + 'pack', + 'packmode', + 'pad', + 'page', + 'pagedir', + 'quadtree', + 'quantum', + 'rankdir', + 'ranksep', + 'ratio', + 'remincross', + 'repulsiveforce', + 'resolution', + 'root', + 'rotate', + 'searchsize', + 'sep', + 'showboxes', + 'size', + 'smoothing', + 'sortv', + 'splines', + 'start', + 'stylesheet', + 'target', + 'truecolor', + 'viewport', + 'voro_margin', # for subgraphs - 'rank' + 'rank', } EDGE_ATTRIBUTES = { - 'URL', 'arrowhead', 'arrowsize', 'arrowtail', - 'color', 'colorscheme', 'comment', 'constraint', 'decorate', 'dir', - 'edgeURL', 'edgehref', 'edgetarget', 'edgetooltip', 'fontcolor', - 'fontname', 'fontsize', 'headURL', 'headclip', 'headhref', 'headlabel', - 'headport', 'headtarget', 'headtooltip', 'href', 'id', 'label', - 'labelURL', 'labelangle', 'labeldistance', 'labelfloat', 'labelfontcolor', - 'labelfontname', 'labelfontsize', 'labelhref', 'labeltarget', - 'labeltooltip', 'layer', 'len', 'lhead', 'lp', 'ltail', 'minlen', - 'nojustify', 'penwidth', 'pos', 'samehead', 'sametail', 'showboxes', - 'style', 'tailURL', 'tailclip', 'tailhref', 'taillabel', 'tailport', - 'tailtarget', 'tailtooltip', 'target', 'tooltip', 'weight', - 'rank' + 'URL', + 'arrowhead', + 'arrowsize', + 'arrowtail', + 'color', + 'colorscheme', + 'comment', + 'constraint', + 'decorate', + 'dir', + 'edgeURL', + 'edgehref', + 'edgetarget', + 'edgetooltip', + 'fontcolor', + 'fontname', + 'fontsize', + 'headURL', + 'headclip', + 'headhref', + 'headlabel', + 'headport', + 'headtarget', + 'headtooltip', + 'href', + 'id', + 'label', + 'labelURL', + 'labelangle', + 'labeldistance', + 'labelfloat', + 'labelfontcolor', + 'labelfontname', + 'labelfontsize', + 'labelhref', + 'labeltarget', + 'labeltooltip', + 'layer', + 'len', + 'lhead', + 'lp', + 'ltail', + 'minlen', + 'nojustify', + 'penwidth', + 'pos', + 'samehead', + 'sametail', + 'showboxes', + 'style', + 'tailURL', + 'tailclip', + 'tailhref', + 'taillabel', + 'tailport', + 'tailtarget', + 'tailtooltip', + 'target', + 'tooltip', + 'weight', + 'rank', } NODE_ATTRIBUTES = { - 'URL', 'color', 'colorscheme', 'comment', - 'distortion', 'fillcolor', 'fixedsize', 'fontcolor', 'fontname', - 'fontsize', 'group', 'height', 'id', 'image', 'imagescale', 'label', - 'labelloc', 'layer', 'margin', 'nojustify', 'orientation', 'penwidth', - 'peripheries', 'pin', 'pos', 'rects', 'regular', 'root', 'samplepoints', - 'shape', 'shapefile', 'showboxes', 'sides', 'skew', 'sortv', 'style', - 'target', 'tooltip', 'vertices', 'width', 'z', + 'URL', + 'color', + 'colorscheme', + 'comment', + 'distortion', + 'fillcolor', + 'fixedsize', + 'fontcolor', + 'fontname', + 'fontsize', + 'group', + 'height', + 'id', + 'image', + 'imagescale', + 'label', + 'labelloc', + 'layer', + 'margin', + 'nojustify', + 'orientation', + 'penwidth', + 'peripheries', + 'pin', + 'pos', + 'rects', + 'regular', + 'root', + 'samplepoints', + 'shape', + 'shapefile', + 'showboxes', + 'sides', + 'skew', + 'sortv', + 'style', + 'target', + 'tooltip', + 'vertices', + 'width', + 'z', # The following are attributes dot2tex - 'texlbl', 'texmode' + 'texlbl', + 'texmode', } CLUSTER_ATTRIBUTES = { - 'K', 'URL', 'bgcolor', 'color', 'colorscheme', - 'fillcolor', 'fontcolor', 'fontname', 'fontsize', 'label', 'labeljust', - 'labelloc', 'lheight', 'lp', 'lwidth', 'nojustify', 'pencolor', - 'penwidth', 'peripheries', 'sortv', 'style', 'target', 'tooltip' + 'K', + 'URL', + 'bgcolor', + 'color', + 'colorscheme', + 'fillcolor', + 'fontcolor', + 'fontname', + 'fontsize', + 'label', + 'labeljust', + 'labelloc', + 'lheight', + 'lp', + 'lwidth', + 'nojustify', + 'pencolor', + 'penwidth', + 'peripheries', + 'sortv', + 'style', + 'target', + 'tooltip', } @@ -107,6 +280,7 @@ def is_windows(): def is_anaconda(): # type: () -> bool import glob + conda_pattern = os.path.join(sys.prefix, 'conda-meta\\graphviz*.json') return glob.glob(conda_pattern) != [] @@ -136,7 +310,9 @@ def call_graphviz(program, arguments, working_dir, **kwargs): 'SYSTEMROOT': os.environ.get('SYSTEMROOT', ''), } - program_with_args = [program, ] + arguments + program_with_args = [ + program, + ] + arguments process = subprocess.Popen( program_with_args, @@ -160,9 +336,9 @@ def call_graphviz(program, arguments, working_dir, **kwargs): # This version freezes dictionaries used as values within dictionaries. # class frozendict(dict): - def _blocked_attribute(obj): raise AttributeError('A frozendict cannot be modified.') + _blocked_attribute = property(_blocked_attribute) __delitem__ = __setitem__ = clear = _blocked_attribute @@ -214,7 +390,8 @@ def __repr__(self): id_re_alpha_nums = re.compile('^[_a-zA-Z][a-zA-Z0-9_,]*$', re.UNICODE) id_re_alpha_nums_with_ports = re.compile( - '^[_a-zA-Z][a-zA-Z0-9_,:\"]*[a-zA-Z0-9_,\"]+$', re.UNICODE) + '^[_a-zA-Z][a-zA-Z0-9_,:\"]*[a-zA-Z0-9_,\"]+$', re.UNICODE +) id_re_num = re.compile('^[0-9,]+$', re.UNICODE) id_re_with_port = re.compile('^([^:]*):([^:]*)$', re.UNICODE) id_re_dbl_quoted = re.compile('^\".*\"$', re.S | re.UNICODE) @@ -240,13 +417,17 @@ def needs_quotes(s): if s in dot_keywords: return False - chars = [ord(c) for c in s if ord(c) > 0x7f or ord(c) == 0] + chars = [ord(c) for c in s if ord(c) > 0x7F or ord(c) == 0] if chars and not id_re_dbl_quoted.match(s) and not id_re_html.match(s): return True - for test_re in [id_re_alpha_nums, id_re_num, - id_re_dbl_quoted, id_re_html, - id_re_alpha_nums_with_ports]: + for test_re in [ + id_re_alpha_nums, + id_re_num, + id_re_dbl_quoted, + id_re_html, + id_re_alpha_nums_with_ports, + ]: if test_re.match(s): return False @@ -271,9 +452,7 @@ def quote_if_necessary(s): return s if needs_quotes(s): - replace = {'"': r'\"', - "\n": r'\n', - "\r": r'\r'} + replace = {'"': r'\"', "\n": r'\n', "\r": r'\r'} for (a, b) in replace.items(): s = s.replace(a, b) @@ -370,13 +549,16 @@ def graph_from_adjacency_matrix(matrix, node_prefix=u'', directed=False): else: skip = 0 r = row - node_dest = skip+1 + node_dest = skip + 1 for e in r: if e: graph.add_edge( - Edge('%s%s' % (node_prefix, node_orig), - '%s%s' % (node_prefix, node_dest))) + Edge( + '%s%s' % (node_prefix, node_orig), + '%s%s' % (node_prefix, node_dest), + ) + ) node_dest += 1 node_orig += 1 @@ -403,14 +585,17 @@ def graph_from_incidence_matrix(matrix, node_prefix='', directed=False): for node in row: if node: - nodes.append(c*node) + nodes.append(c * node) c += 1 nodes.sort() if len(nodes) == 2: graph.add_edge( - Edge('%s%s' % (node_prefix, abs(nodes[0])), - '%s%s' % (node_prefix, nodes[1]))) + Edge( + '%s%s' % (node_prefix, abs(nodes[0])), + '%s%s' % (node_prefix, nodes[1]), + ) + ) if not directed: graph.set_simplify(True) @@ -518,21 +703,21 @@ def create_attribute_methods(self, obj_attributes): # Generate all the Setter methods. # self.__setattr__( - 'set_'+attr, - lambda x, a=attr: - self.obj_dict['attributes'].__setitem__(a, x) + 'set_' + attr, + lambda x, a=attr: self.obj_dict['attributes'].__setitem__( + a, x + ), ) # Generate all the Getter methods. # self.__setattr__( - 'get_'+attr, lambda a=attr: self.__get_attribute__(a) + 'get_' + attr, lambda a=attr: self.__get_attribute__(a) ) class Error(Exception): - """General error handling class. - """ + """General error handling class.""" def __init__(self, value): self.value = value @@ -542,8 +727,7 @@ def __str__(self): class InvocationException(Exception): - """Indicate problem while running any GraphViz executable. - """ + """Indicate problem while running any GraphViz executable.""" def __init__(self, value): self.value = value @@ -593,7 +777,7 @@ def __init__(self, name='', obj_dict=None, **attrs): port = None if isinstance(name, str_type) and not name.startswith('"'): idx = name.find(':') - if idx > 0 and idx+1 < len(name): + if idx > 0 and idx + 1 < len(name): name, port = name[:idx], name[idx:] if isinstance(name, int): @@ -642,9 +826,7 @@ def to_string(self): if value == '': value = '""' if value is not None: - node_attr.append( - '%s=%s' % (attr, quote_if_necessary(value)) - ) + node_attr.append('%s=%s' % (attr, quote_if_necessary(value))) else: node_attr.append(attr) @@ -697,8 +879,7 @@ def __init__(self, src='', dst='', obj_dict=None, **attrs): src = src.get_name() if isinstance(dst, (Node, Subgraph, Cluster)): dst = dst.get_name() - points = (quote_if_necessary(src), - quote_if_necessary(dst)) + points = (quote_if_necessary(src), quote_if_necessary(dst)) self.obj_dict['points'] = points if obj_dict is None: # Copy the attributes @@ -723,9 +904,7 @@ def get_destination(self): return self.obj_dict['points'][1] def __hash__(self): - return hash( - hash(self.get_source()) + hash(self.get_destination()) - ) + return hash(hash(self.get_source()) + hash(self.get_destination())) def __eq__(self, edge): """Compare two edges. @@ -739,28 +918,33 @@ def __eq__(self, edge): """ if not isinstance(edge, Edge): - raise Error('Can not compare and ' - 'edge to a non-edge object.') + raise Error('Can not compare and ' 'edge to a non-edge object.') if self.get_parent_graph().get_top_graph_type() == 'graph': # If the graph is undirected, the edge has neither # source nor destination. # - if ((self.get_source() == edge.get_source() and - self.get_destination() == edge.get_destination()) or - (edge.get_source() == self.get_destination() and - edge.get_destination() == self.get_source())): + if ( + self.get_source() == edge.get_source() + and self.get_destination() == edge.get_destination() + ) or ( + edge.get_source() == self.get_destination() + and edge.get_destination() == self.get_source() + ): return True else: - if (self.get_source() == edge.get_source() and - self.get_destination() == edge.get_destination()): + if ( + self.get_source() == edge.get_source() + and self.get_destination() == edge.get_destination() + ): return True return False if not PY3: + def __ne__(self, other): result = self.__eq__(other) if result is NotImplemented: @@ -777,13 +961,16 @@ def parse_node_ref(self, node_str): node_port_idx = node_str.rfind(':') - if (node_port_idx > 0 and node_str[0] == '"' and - node_str[node_port_idx-1] == '"'): + if ( + node_port_idx > 0 + and node_str[0] == '"' + and node_str[node_port_idx - 1] == '"' + ): return node_str if node_port_idx > 0: a = node_str[:node_port_idx] - b = node_str[node_port_idx+1:] + b = node_str[node_port_idx + 1 :] node = quote_if_necessary(a) node += ':' + quote_if_necessary(b) @@ -805,9 +992,9 @@ def to_string(self): edge = [src] if ( - self.get_parent_graph() and - self.get_parent_graph().get_top_graph_type() and - self.get_parent_graph().get_top_graph_type() == 'digraph' + self.get_parent_graph() + and self.get_parent_graph().get_top_graph_type() + and self.get_parent_graph().get_top_graph_type() == 'digraph' ): edge.append('->') @@ -828,8 +1015,7 @@ def to_string(self): if value == '': value = '""' if value is not None: - edge_attr.append( - '%s=%s' % (attr, quote_if_necessary(value))) + edge_attr.append('%s=%s' % (attr, quote_if_necessary(value))) else: edge_attr.append(attr) @@ -877,9 +1063,16 @@ class Graph(Common): graph_instance.obj_dict['attributes']['fontname'] """ - def __init__(self, graph_name='G', obj_dict=None, - graph_type='digraph', strict=False, - suppress_disconnected=False, simplify=False, **attrs): + def __init__( + self, + graph_name='G', + obj_dict=None, + graph_type='digraph', + strict=False, + suppress_disconnected=False, + simplify=False, + **attrs + ): if obj_dict is not None: self.obj_dict = obj_dict @@ -890,10 +1083,13 @@ def __init__(self, graph_name='G', obj_dict=None, self.obj_dict['attributes'] = dict(attrs) if graph_type not in ['graph', 'digraph']: - raise Error(( - 'Invalid type "{t}". ' - 'Accepted graph types are: ' - 'graph, digraph').format(t=graph_type)) + raise Error( + ( + 'Invalid type "{t}". ' + 'Accepted graph types are: ' + 'graph, digraph' + ).format(t=graph_type) + ) self.obj_dict['name'] = quote_if_necessary(graph_name) self.obj_dict['type'] = graph_type @@ -1042,8 +1238,10 @@ def add_node(self, graph_node): """ if not isinstance(graph_node, Node): raise TypeError( - 'add_node() received ' + - 'a non node class object: ' + str(graph_node)) + 'add_node() received ' + + 'a non node class object: ' + + str(graph_node) + ) node = self.get_node(graph_node.get_name()) @@ -1081,8 +1279,7 @@ def del_node(self, name, index=None): if name in self.obj_dict['nodes']: - if (index is not None and - index < len(self.obj_dict['nodes'][name])): + if index is not None and index < len(self.obj_dict['nodes'][name]): del self.obj_dict['nodes'][name][index] return True else: @@ -1106,8 +1303,11 @@ def get_node(self, name): if name in self.obj_dict['nodes']: match.extend( - [Node(obj_dict=obj_dict) - for obj_dict in self.obj_dict['nodes'][name]]) + [ + Node(obj_dict=obj_dict) + for obj_dict in self.obj_dict['nodes'][name] + ] + ) return match @@ -1125,10 +1325,7 @@ def get_node_list(self): for node in self.obj_dict['nodes']: obj_dict_list = self.obj_dict['nodes'][node] - node_objs.extend([ - Node(obj_dict=obj_d) - for obj_d in obj_dict_list - ]) + node_objs.extend([Node(obj_dict=obj_d) for obj_d in obj_dict_list]) return node_objs @@ -1140,11 +1337,11 @@ def add_edge(self, graph_edge): """ if not isinstance(graph_edge, Edge): raise TypeError( - 'add_edge() received a non edge class object: ' + - str(graph_edge)) + 'add_edge() received a non edge class object: ' + + str(graph_edge) + ) - edge_points = (graph_edge.get_source(), - graph_edge.get_destination()) + edge_points = (graph_edge.get_source(), graph_edge.get_destination()) if edge_points in self.obj_dict['edges']: edge_list = self.obj_dict['edges'][edge_points] @@ -1185,8 +1382,9 @@ def del_edge(self, src_or_list, dst=None, index=None): dst = dst.get_name() if (src, dst) in self.obj_dict['edges']: - if (index is not None and - index < len(self.obj_dict['edges'][(src, dst)])): + if index is not None and index < len( + self.obj_dict['edges'][(src, dst)] + ): del self.obj_dict['edges'][(src, dst)][index] return True else: @@ -1215,18 +1413,20 @@ def get_edge(self, src_or_list, dst=None): match = list() if edge_points in self.obj_dict['edges'] or ( - self.get_top_graph_type() == 'graph' and - edge_points_reverse in self.obj_dict['edges'] + self.get_top_graph_type() == 'graph' + and edge_points_reverse in self.obj_dict['edges'] ): edges_obj_dict = self.obj_dict['edges'].get( edge_points, - self.obj_dict['edges'].get(edge_points_reverse, None)) + self.obj_dict['edges'].get(edge_points_reverse, None), + ) for edge_obj_dict in edges_obj_dict: match.append( - Edge(edge_points[0], - edge_points[1], - obj_dict=edge_obj_dict)) + Edge( + edge_points[0], edge_points[1], obj_dict=edge_obj_dict + ) + ) return match @@ -1243,10 +1443,7 @@ def get_edge_list(self): for edge in self.obj_dict['edges']: obj_dict_list = self.obj_dict['edges'][edge] - edge_objs.extend([ - Edge(obj_dict=obj_d) - for obj_d in obj_dict_list - ]) + edge_objs.extend([Edge(obj_dict=obj_d) for obj_d in obj_dict_list]) return edge_objs @@ -1256,11 +1453,13 @@ def add_subgraph(self, sgraph): It takes a subgraph object as its only argument and returns None. """ - if (not isinstance(sgraph, Subgraph) and - not isinstance(sgraph, Cluster)): + if not isinstance(sgraph, Subgraph) and not isinstance( + sgraph, Cluster + ): raise TypeError( - 'add_subgraph() received a non subgraph class object:' + - str(sgraph)) + 'add_subgraph() received a non subgraph class object:' + + str(sgraph) + ) if sgraph.get_name() in self.obj_dict['subgraphs']: @@ -1268,8 +1467,7 @@ def add_subgraph(self, sgraph): sgraph_list.append(sgraph.obj_dict) else: - self.obj_dict['subgraphs'][sgraph.get_name()] = [ - sgraph.obj_dict] + self.obj_dict['subgraphs'][sgraph.get_name()] = [sgraph.obj_dict] sgraph.set_sequence(self.get_next_sequence_number()) sgraph.set_parent_graph(self.get_parent_graph()) @@ -1308,10 +1506,9 @@ def get_subgraph_list(self): for sgraph in self.obj_dict['subgraphs']: obj_dict_list = self.obj_dict['subgraphs'][sgraph] - sgraph_objs.extend([ - Subgraph(obj_dict=obj_d) - for obj_d in obj_dict_list - ]) + sgraph_objs.extend( + [Subgraph(obj_dict=obj_d) for obj_d in obj_dict_list] + ) return sgraph_objs @@ -1343,18 +1540,18 @@ def to_string(self): if self.obj_dict.get('strict', None) is not None: - if (self == self.get_parent_graph() and - self.obj_dict['strict']): + if self == self.get_parent_graph() and self.obj_dict['strict']: graph.append('strict ') graph_type = self.obj_dict['type'] - if (graph_type == 'subgraph' and - not self.obj_dict.get('show_keyword', True)): + if graph_type == 'subgraph' and not self.obj_dict.get( + 'show_keyword', True + ): graph_type = '' s = '{type} {name} {{\n'.format( - type=graph_type, - name=self.obj_dict['name']) + type=graph_type, name=self.obj_dict['name'] + ) graph.append(s) for attr in sorted(self.obj_dict['attributes']): @@ -1365,8 +1562,7 @@ def to_string(self): if val == '': val = '""' if val is not None: - graph.append('%s=%s' % - (attr, quote_if_necessary(val))) + graph.append('%s=%s' % (attr, quote_if_necessary(val))) else: graph.append(attr) @@ -1379,8 +1575,9 @@ def to_string(self): edge_obj_dicts.extend(self.obj_dict['edges'][k]) if edge_obj_dicts: - edge_src_set, edge_dst_set = list(zip( - *[obj['points'] for obj in edge_obj_dicts])) + edge_src_set, edge_dst_set = list( + zip(*[obj['points'] for obj in edge_obj_dicts]) + ) edge_src_set, edge_dst_set = set(edge_src_set), set(edge_dst_set) else: edge_src_set, edge_dst_set = set(), set() @@ -1406,8 +1603,10 @@ def to_string(self): if self.obj_dict.get('suppress_disconnected', False): - if (node.get_name() not in edge_src_set and - node.get_name() not in edge_dst_set): + if ( + node.get_name() not in edge_src_set + and node.get_name() not in edge_dst_set + ): continue graph.append(node.to_string() + '\n') @@ -1415,8 +1614,7 @@ def to_string(self): elif obj['type'] == 'edge': edge = Edge(obj_dict=obj) - if (self.obj_dict.get('simplify', False) and - edge in edges_done): + if self.obj_dict.get('simplify', False) and edge in edges_done: continue graph.append(edge.to_string() + '\n') @@ -1424,7 +1622,7 @@ def to_string(self): else: sgraph = Subgraph(obj_dict=obj) - graph.append(sgraph.to_string()+'\n') + graph.append(sgraph.to_string() + '\n') graph.append('}\n') @@ -1466,13 +1664,22 @@ class Subgraph(Graph): # attributes of graph so it can be passed # as a graph to all methods # - def __init__(self, graph_name='', - obj_dict=None, suppress_disconnected=False, - simplify=False, **attrs): + def __init__( + self, + graph_name='', + obj_dict=None, + suppress_disconnected=False, + simplify=False, + **attrs + ): Graph.__init__( - self, graph_name=graph_name, obj_dict=obj_dict, + self, + graph_name=graph_name, + obj_dict=obj_dict, suppress_disconnected=suppress_disconnected, - simplify=simplify, **attrs) + simplify=simplify, + **attrs + ) if obj_dict is None: @@ -1511,18 +1718,27 @@ class Cluster(Graph): cluster_instance.obj_dict['attributes']['fontname'] """ - def __init__(self, graph_name='subG', - obj_dict=None, suppress_disconnected=False, - simplify=False, **attrs): + def __init__( + self, + graph_name='subG', + obj_dict=None, + suppress_disconnected=False, + simplify=False, + **attrs + ): Graph.__init__( - self, graph_name=graph_name, obj_dict=obj_dict, + self, + graph_name=graph_name, + obj_dict=obj_dict, suppress_disconnected=suppress_disconnected, - simplify=simplify, **attrs) + simplify=simplify, + **attrs + ) if obj_dict is None: self.obj_dict['type'] = 'subgraph' - self.obj_dict['name'] = quote_if_necessary('cluster_'+graph_name) + self.obj_dict['name'] = quote_if_necessary('cluster_' + graph_name) self.create_attribute_methods(CLUSTER_ATTRIBUTES) @@ -1540,15 +1756,43 @@ def __init__(self, *argsl, **argsd): self.shape_files = list() self.formats = [ - 'canon', 'cmap', 'cmapx', - 'cmapx_np', 'dia', 'dot', - 'fig', 'gd', 'gd2', 'gif', - 'hpgl', 'imap', 'imap_np', 'ismap', - 'jpe', 'jpeg', 'jpg', 'mif', - 'mp', 'pcl', 'pdf', 'pic', 'plain', - 'plain-ext', 'png', 'ps', 'ps2', - 'svg', 'svgz', 'vml', 'vmlz', - 'vrml', 'vtx', 'wbmp', 'xdot', 'xlib'] + 'canon', + 'cmap', + 'cmapx', + 'cmapx_np', + 'dia', + 'dot', + 'fig', + 'gd', + 'gd2', + 'gif', + 'hpgl', + 'imap', + 'imap_np', + 'ismap', + 'jpe', + 'jpeg', + 'jpg', + 'mif', + 'mp', + 'pcl', + 'pdf', + 'pic', + 'plain', + 'plain-ext', + 'png', + 'ps', + 'ps2', + 'svg', + 'svgz', + 'vml', + 'vmlz', + 'vrml', + 'vtx', + 'wbmp', + 'xdot', + 'xlib', + ] self.prog = 'dot' @@ -1556,23 +1800,20 @@ def __init__(self, *argsl, **argsd): # the methods enabling the creation # of output in any of the supported formats. for frmt in self.formats: - def new_method( - f=frmt, prog=self.prog, - encoding=None): + + def new_method(f=frmt, prog=self.prog, encoding=None): """Refer to docstring of method `create`.""" - return self.create( - format=f, prog=prog, encoding=encoding) + return self.create(format=f, prog=prog, encoding=encoding) + name = 'create_{fmt}'.format(fmt=frmt) self.__setattr__(name, new_method) - for frmt in self.formats+['raw']: - def new_method( - path, f=frmt, prog=self.prog, - encoding=None): + for frmt in self.formats + ['raw']: + + def new_method(path, f=frmt, prog=self.prog, encoding=None): """Refer to docstring of method `write.`""" - self.write( - path, format=f, prog=prog, - encoding=encoding) + self.write(path, format=f, prog=prog, encoding=encoding) + name = 'write_{fmt}'.format(fmt=frmt) self.__setattr__(name, new_method) @@ -1739,7 +1980,13 @@ def create(self, prog=None, format='ps', encoding=None): f.write(f_data) f.close() - arguments = ['-T{}'.format(format), ] + args + [tmp_name] + arguments = ( + [ + '-T{}'.format(format), + ] + + args + + [tmp_name] + ) try: stdout_data, stderr_data, process = call_graphviz( @@ -1750,8 +1997,7 @@ def create(self, prog=None, format='ps', encoding=None): except OSError as e: if e.errno == errno.ENOENT: args = list(e.args) - args[1] = '"{prog}" not found in path.'.format( - prog=prog) + args[1] = '"{prog}" not found in path.'.format(prog=prog) raise OSError(*args) else: raise @@ -1775,12 +2021,12 @@ def create(self, prog=None, format='ps', encoding=None): ) print(message) - assert process.returncode == 0, ( - '"{prog}" with args {arguments} returned code: {code}'.format( - prog=prog, - arguments=arguments, - code=process.returncode, - ) - ) + assert ( + process.returncode == 0 + ), '"{prog}" with args {arguments} returned code: {code}'.format( + prog=prog, + arguments=arguments, + code=process.returncode, + ) return stdout_data diff --git a/setup.py b/setup.py index 97da6968..ae3d3eeb 100644 --- a/setup.py +++ b/setup.py @@ -63,9 +63,11 @@ def get_version(): 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Topic :: Scientific/Engineering :: Visualization', - 'Topic :: Software Development :: Libraries :: Python Modules'], + 'Topic :: Software Development :: Libraries :: Python Modules', + ], long_description=get_long_description(), long_description_content_type="text/markdown", py_modules=['pydot', 'dot_parser'], install_requires=['pyparsing>=2.1.4'], - tests_require=['chardet']) + tests_require=['chardet'], +) diff --git a/test/pydot_unittest.py b/test/pydot_unittest.py index 4df26f8b..e4cece7d 100644 --- a/test/pydot_unittest.py +++ b/test/pydot_unittest.py @@ -26,13 +26,11 @@ class TestGraphAPI(unittest.TestCase): - def setUp(self): self._reset_graphs() def _reset_graphs(self): - self.graph_directed = pydot.Graph('testgraph', - graph_type='digraph') + self.graph_directed = pydot.Graph('testgraph', graph_type='digraph') def test_keep_graph_type(self): g = pydot.Dot(graph_name='Test', graph_type='graph') @@ -78,10 +76,8 @@ def test_subgraphs(self): g.add_subgraph(s) - self.assertEqual(g.get_subgraphs()[0].get_name(), - s.get_name()) - self.assertEqual(g.get_subgraph_list()[0].get_name(), - s.get_name()) + self.assertEqual(g.get_subgraphs()[0].get_name(), s.get_name()) + self.assertEqual(g.get_subgraph_list()[0].get_name(), s.get_name()) def test_graph_pickling(self): g = pydot.Graph() @@ -125,18 +121,22 @@ def test_graph_simplify(self): g.add_edge(pydot.Edge('b', 'a')) g.add_edge(pydot.Edge('b', 'a')) test_combinations = [ - ('graph', False, - 'graph G { a -- b; a -- b; b -- a; b -- a; }'), - ('graph', True, - 'graph G { a -- b; }'), - ('digraph', False, - 'digraph G { a -> b; a -> b; b -> a; b -> a; }'), - ('digraph', True, - 'digraph G { a -> b; b -> a; }')] + ('graph', False, 'graph G { a -- b; a -- b; b -- a; b -- a; }'), + ('graph', True, 'graph G { a -- b; }'), + ( + 'digraph', + False, + 'digraph G { a -> b; a -> b; b -> a; b -> a; }', + ), + ('digraph', True, 'digraph G { a -> b; b -> a; }'), + ] expected_concat = observed_concat = '' for (graph_type, simplify, expected) in test_combinations: expected_concat += 'graph_type %s, simplify %s: %s\n' % ( - graph_type, simplify, expected) + graph_type, + simplify, + expected, + ) g.set_type(graph_type) g.set_simplify(simplify) try: @@ -144,7 +144,10 @@ def test_graph_simplify(self): except (NameError, TypeError) as e: observed = '%s: %s' % (type(e).__name__, e) observed_concat += 'graph_type %s, simplify %s: %s\n' % ( - graph_type, simplify, observed) + graph_type, + simplify, + observed, + ) self.maxDiff = None self.assertMultiLineEqual(expected_concat, observed_concat) @@ -152,8 +155,10 @@ def test_graph_with_shapefiles(self): shapefile_dir = os.path.join(test_dir, 'from-past-to-future') # image files are omitted from sdist if not os.path.isdir(shapefile_dir): - warnings.warn('Skipping tests that involve images, ' - 'they can be found in the `git` repository.') + warnings.warn( + 'Skipping tests that involve images, ' + 'they can be found in the `git` repository.' + ) return dot_file = os.path.join(shapefile_dir, 'from-past-to-future.dot') @@ -175,7 +180,8 @@ def test_graph_with_shapefiles(self): hexdigest = sha256(jpe_data).hexdigest() hexdigest_original = self._render_with_graphviz( - dot_file, encoding='ascii') + dot_file, encoding='ascii' + ) self.assertEqual(hexdigest, hexdigest_original) def test_multiple_graphs(self): @@ -190,7 +196,9 @@ def _render_with_graphviz(self, filename, encoding): with io.open(filename, 'rt', encoding=encoding) as stdin: stdout_data, stderr_data, process = pydot.call_graphviz( program=TEST_PROGRAM, - arguments=['-Tjpe', ], + arguments=[ + '-Tjpe', + ], working_dir=os.path.dirname(filename), stdin=stdin, ) @@ -202,8 +210,9 @@ def _render_with_pydot(self, filename, encoding): c = pydot.graph_from_dot_file(filename, encoding=encoding) jpe_data = bytearray() for g in c: - jpe_data.extend(g.create(prog=TEST_PROGRAM, format='jpe', - encoding=encoding)) + jpe_data.extend( + g.create(prog=TEST_PROGRAM, format='jpe', encoding=encoding) + ) return sha256(jpe_data).hexdigest() def test_my_regression_tests(self): @@ -216,11 +225,10 @@ def test_graphviz_regression_tests(self): def _render_and_compare_dot_files(self, directory): # files that confuse `chardet` - encodings = { - 'Latin1.dot': 'latin-1'} + encodings = {'Latin1.dot': 'latin-1'} dot_files = [ - fname for fname in os.listdir(directory) - if fname.endswith('.dot')] + fname for fname in os.listdir(directory) if fname.endswith('.dot') + ] for fname in dot_files: fpath = os.path.join(directory, fname) with open(fpath, 'rb') as f: @@ -255,28 +263,23 @@ def test_quoted_node_id_to_string_no_attributes(self): def test_keyword_node_id(self): self._reset_graphs() self.graph_directed.add_node(pydot.Node('node')) - self.assertEqual( - self.graph_directed.get_nodes()[0].get_name(), 'node' - ) + self.assertEqual(self.graph_directed.get_nodes()[0].get_name(), 'node') def test_keyword_node_id_to_string_no_attributes(self): self._reset_graphs() self.graph_directed.add_node(pydot.Node('node')) - self.assertEqual( - self.graph_directed.get_nodes()[0].to_string(), '' - ) + self.assertEqual(self.graph_directed.get_nodes()[0].to_string(), '') def test_keyword_node_id_to_string_with_attributes(self): self._reset_graphs() self.graph_directed.add_node(pydot.Node('node', shape='box')) self.assertEqual( - self.graph_directed.get_nodes()[0].to_string(), - 'node [shape=box];' + self.graph_directed.get_nodes()[0].to_string(), 'node [shape=box];' ) def test_names_of_a_thousand_nodes(self): self._reset_graphs() - names = {'node_%05d' % i for i in range(10**3)} + names = {'node_%05d' % i for i in range(10 ** 3)} for name in names: self.graph_directed.add_node(pydot.Node(name, label=name)) @@ -286,22 +289,22 @@ def test_names_of_a_thousand_nodes(self): def test_executable_not_found_exception(self): graph = pydot.Dot('graphname', graph_type='digraph') - self.assertRaises(Exception, graph.create, prog='dothehe') + self.assertRaises(Exception, graph.create, prog='dothehe') def test_graph_add_node_argument_type(self): self._reset_graphs() - self.assertRaises(TypeError, self.graph_directed.add_node, 1) - self.assertRaises(TypeError, self.graph_directed.add_node, 'a') + self.assertRaises(TypeError, self.graph_directed.add_node, 1) + self.assertRaises(TypeError, self.graph_directed.add_node, 'a') def test_graph_add_edge_argument_type(self): self._reset_graphs() - self.assertRaises(TypeError, self.graph_directed.add_edge, 1) - self.assertRaises(TypeError, self.graph_directed.add_edge, 'a') + self.assertRaises(TypeError, self.graph_directed.add_edge, 1) + self.assertRaises(TypeError, self.graph_directed.add_edge, 'a') def test_graph_add_subgraph_argument_type(self): self._reset_graphs() - self.assertRaises(TypeError, self.graph_directed.add_subgraph, 1) - self.assertRaises(TypeError, self.graph_directed.add_subgraph, 'a') + self.assertRaises(TypeError, self.graph_directed.add_subgraph, 1) + self.assertRaises(TypeError, self.graph_directed.add_subgraph, 'a') def test_quoting(self): g = pydot.Dot() @@ -328,7 +331,8 @@ def test_edge_point_namestr(self): self._reset_graphs() self.graph_directed.add_edge(pydot.Edge('a', 'b')) self.assertEqual( - self.graph_directed.get_edges()[0].to_string(), 'a -> b;') + self.graph_directed.get_edges()[0].to_string(), 'a -> b;' + ) def test_edge_point_object_node(self): self._reset_graphs() @@ -336,7 +340,8 @@ def test_edge_point_object_node(self): pydot.Edge(pydot.Node('a'), pydot.Node('b')) ) self.assertEqual( - self.graph_directed.get_edges()[0].to_string(), 'a -> b;') + self.graph_directed.get_edges()[0].to_string(), 'a -> b;' + ) def test_edge_point_object_subgraph(self): self._reset_graphs() @@ -344,7 +349,8 @@ def test_edge_point_object_subgraph(self): pydot.Edge(pydot.Subgraph('a'), pydot.Subgraph('b')) ) self.assertEqual( - self.graph_directed.get_edges()[0].to_string(), 'a -> b;') + self.graph_directed.get_edges()[0].to_string(), 'a -> b;' + ) def test_edge_point_object_cluster(self): self._reset_graphs() @@ -353,26 +359,30 @@ def test_edge_point_object_cluster(self): ) self.assertEqual( self.graph_directed.get_edges()[0].to_string(), - 'cluster_a -> cluster_b;' + 'cluster_a -> cluster_b;', ) def test_graph_from_adjacency_matrix(self): g = pydot.graph_from_adjacency_matrix( - [[0, 1, 0], [1, 0, 0], [0, 1, 1]], directed=True) + [[0, 1, 0], [1, 0, 0], [0, 1, 1]], directed=True + ) s = ' '.join(g.to_string().split()) self.assertEqual(s, 'digraph G { 1 -> 2; 2 -> 1; 3 -> 2; 3 -> 3; }') g = pydot.graph_from_adjacency_matrix( - [[0, 1, 0], [1, 0, 0], [0, 0, 1]], directed=False) + [[0, 1, 0], [1, 0, 0], [0, 0, 1]], directed=False + ) s = ' '.join(g.to_string().split()) self.assertEqual(s, 'graph G { 1 -- 2; 3 -- 3; }') def test_graph_from_incidence_matrix(self): g = pydot.graph_from_incidence_matrix( - [[-1, 1, 0], [1, -1, 0], [0, 1, -1]], directed=True) + [[-1, 1, 0], [1, -1, 0], [0, 1, -1]], directed=True + ) s = ' '.join(g.to_string().split()) self.assertEqual(s, 'digraph G { 1 -> 2; 2 -> 1; 3 -> 2; }') g = pydot.graph_from_incidence_matrix( - [[1, 1, 0], [0, 1, 1]], directed=False) + [[1, 1, 0], [0, 1, 1]], directed=False + ) s = ' '.join(g.to_string().split()) self.assertEqual(s, 'graph G { 1 -- 2; 2 -- 3; }') @@ -382,17 +392,21 @@ def check_path(): if not_check: return assert not os.path.isfile('setup.py'), ( - 'running out of source does not ' - 'test the installed `pydot`.') + 'running out of source does not ' 'test the installed `pydot`.' + ) def parse_args(): """Return arguments.""" parser = argparse.ArgumentParser() parser.add_argument( - '--no-check', action='store_true', - help=('do not require that no `setup.py` be present ' - 'in the current working directory.')) + '--no-check', + action='store_true', + help=( + 'do not require that no `setup.py` be present ' + 'in the current working directory.' + ), + ) args, unknown = parser.parse_known_args() # avoid confusing `unittest` sys.argv = [sys.argv[0]] + unknown From 7629cd970af2e78f11fdecde96c232ba8a2a3f7d Mon Sep 17 00:00:00 2001 From: Peter Nowee Date: Mon, 31 May 2021 15:10:59 +0200 Subject: [PATCH 2/3] format-black: Manual corrections --- pydot.py | 4 ++-- test/pydot_unittest.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pydot.py b/pydot.py index 28efdbb5..acce2525 100644 --- a/pydot.py +++ b/pydot.py @@ -452,7 +452,7 @@ def quote_if_necessary(s): return s if needs_quotes(s): - replace = {'"': r'\"', "\n": r'\n', "\r": r'\r'} + replace = {'"': r'\"', "\n": r'\n', "\r": r'\r',} for (a, b) in replace.items(): s = s.replace(a, b) @@ -918,7 +918,7 @@ def __eq__(self, edge): """ if not isinstance(edge, Edge): - raise Error('Can not compare and ' 'edge to a non-edge object.') + raise Error('Can not compare and edge to a non-edge object.') if self.get_parent_graph().get_top_graph_type() == 'graph': diff --git a/test/pydot_unittest.py b/test/pydot_unittest.py index e4cece7d..c107741b 100644 --- a/test/pydot_unittest.py +++ b/test/pydot_unittest.py @@ -121,14 +121,14 @@ def test_graph_simplify(self): g.add_edge(pydot.Edge('b', 'a')) g.add_edge(pydot.Edge('b', 'a')) test_combinations = [ - ('graph', False, 'graph G { a -- b; a -- b; b -- a; b -- a; }'), - ('graph', True, 'graph G { a -- b; }'), + ('graph', False, 'graph G { a -- b; a -- b; b -- a; b -- a; }',), + ('graph', True, 'graph G { a -- b; }',), ( 'digraph', False, 'digraph G { a -> b; a -> b; b -> a; b -> a; }', ), - ('digraph', True, 'digraph G { a -> b; b -> a; }'), + ('digraph', True, 'digraph G { a -> b; b -> a; }',), ] expected_concat = observed_concat = '' for (graph_type, simplify, expected) in test_combinations: @@ -392,7 +392,7 @@ def check_path(): if not_check: return assert not os.path.isfile('setup.py'), ( - 'running out of source does not ' 'test the installed `pydot`.' + 'running out of source does not test the installed `pydot`.' ) From 8041854f80aeef80a74aa321fb99339e3ebcce7d Mon Sep 17 00:00:00 2001 From: Peter Nowee Date: Mon, 31 May 2021 15:11:00 +0200 Subject: [PATCH 3/3] format-black: Second run --- pydot.py | 6 +++++- test/pydot_unittest.py | 24 ++++++++++++++++++------ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/pydot.py b/pydot.py index acce2525..89ff3de7 100644 --- a/pydot.py +++ b/pydot.py @@ -452,7 +452,11 @@ def quote_if_necessary(s): return s if needs_quotes(s): - replace = {'"': r'\"', "\n": r'\n', "\r": r'\r',} + replace = { + '"': r'\"', + "\n": r'\n', + "\r": r'\r', + } for (a, b) in replace.items(): s = s.replace(a, b) diff --git a/test/pydot_unittest.py b/test/pydot_unittest.py index c107741b..df3b3f1b 100644 --- a/test/pydot_unittest.py +++ b/test/pydot_unittest.py @@ -121,14 +121,26 @@ def test_graph_simplify(self): g.add_edge(pydot.Edge('b', 'a')) g.add_edge(pydot.Edge('b', 'a')) test_combinations = [ - ('graph', False, 'graph G { a -- b; a -- b; b -- a; b -- a; }',), - ('graph', True, 'graph G { a -- b; }',), + ( + 'graph', + False, + 'graph G { a -- b; a -- b; b -- a; b -- a; }', + ), + ( + 'graph', + True, + 'graph G { a -- b; }', + ), ( 'digraph', False, 'digraph G { a -> b; a -> b; b -> a; b -> a; }', ), - ('digraph', True, 'digraph G { a -> b; b -> a; }',), + ( + 'digraph', + True, + 'digraph G { a -> b; b -> a; }', + ), ] expected_concat = observed_concat = '' for (graph_type, simplify, expected) in test_combinations: @@ -391,9 +403,9 @@ def check_path(): not_check = parse_args() if not_check: return - assert not os.path.isfile('setup.py'), ( - 'running out of source does not test the installed `pydot`.' - ) + assert not os.path.isfile( + 'setup.py' + ), 'running out of source does not test the installed `pydot`.' def parse_args():