Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1635)

Side by Side Diff: third_party/logilab/common/graph.py

Issue 739393004: Revert "Revert "pylint: upgrade to 1.3.1"" (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools/
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/logilab/common/fileutils.py ('k') | third_party/logilab/common/hg.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. 1 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr 2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
3 # 3 #
4 # This file is part of logilab-common. 4 # This file is part of logilab-common.
5 # 5 #
6 # logilab-common is free software: you can redistribute it and/or modify it unde r 6 # logilab-common is free software: you can redistribute it and/or modify it unde r
7 # the terms of the GNU Lesser General Public License as published by the Free 7 # the terms of the GNU Lesser General Public License as published by the Free
8 # Software Foundation, either version 2.1 of the License, or (at your option) an y 8 # Software Foundation, either version 2.1 of the License, or (at your option) an y
9 # later version. 9 # later version.
10 # 10 #
(...skipping 10 matching lines...) Expand all
21 """ 21 """
22 22
23 __docformat__ = "restructuredtext en" 23 __docformat__ = "restructuredtext en"
24 24
25 __metaclass__ = type 25 __metaclass__ = type
26 26
27 import os.path as osp 27 import os.path as osp
28 import os 28 import os
29 import sys 29 import sys
30 import tempfile 30 import tempfile
31 from logilab.common.compat import str_encode 31 import codecs
32 import errno
32 33
33 def escape(value): 34 def escape(value):
34 """Make <value> usable in a dot file.""" 35 """Make <value> usable in a dot file."""
35 lines = [line.replace('"', '\\"') for line in value.split('\n')] 36 lines = [line.replace('"', '\\"') for line in value.split('\n')]
36 data = '\\l'.join(lines) 37 data = '\\l'.join(lines)
37 return '\\n' + data 38 return '\\n' + data
38 39
39 def target_info_from_filename(filename): 40 def target_info_from_filename(filename):
40 """Transforms /some/path/foo.png into ('/some/path', 'foo.png', 'png').""" 41 """Transforms /some/path/foo.png into ('/some/path', 'foo.png', 'png')."""
41 basename = osp.basename(filename) 42 basename = osp.basename(filename)
(...skipping 14 matching lines...) Expand all
56 if rankdir: 57 if rankdir:
57 self.emit('rankdir=%s' % rankdir) 58 self.emit('rankdir=%s' % rankdir)
58 if ratio: 59 if ratio:
59 self.emit('ratio=%s' % ratio) 60 self.emit('ratio=%s' % ratio)
60 if size: 61 if size:
61 self.emit('size="%s"' % size) 62 self.emit('size="%s"' % size)
62 if charset: 63 if charset:
63 assert charset.lower() in ('utf-8', 'iso-8859-1', 'latin1'), \ 64 assert charset.lower() in ('utf-8', 'iso-8859-1', 'latin1'), \
64 'unsupported charset %s' % charset 65 'unsupported charset %s' % charset
65 self.emit('charset="%s"' % charset) 66 self.emit('charset="%s"' % charset)
66 for param in additionnal_param.iteritems(): 67 for param in sorted(additionnal_param.items()):
67 self.emit('='.join(param)) 68 self.emit('='.join(param))
68 69
69 def get_source(self): 70 def get_source(self):
70 """returns self._source""" 71 """returns self._source"""
71 if self._source is None: 72 if self._source is None:
72 self.emit("}\n") 73 self.emit("}\n")
73 self._source = '\n'.join(self.lines) 74 self._source = '\n'.join(self.lines)
74 del self.lines 75 del self.lines
75 return self._source 76 return self._source
76 77
(...skipping 22 matching lines...) Expand all
99 pdot, dot_sourcepath = tempfile.mkstemp(".dot", name) 100 pdot, dot_sourcepath = tempfile.mkstemp(".dot", name)
100 os.close(pdot) 101 os.close(pdot)
101 else: 102 else:
102 dot_sourcepath = osp.join(storedir, dotfile) 103 dot_sourcepath = osp.join(storedir, dotfile)
103 else: 104 else:
104 target = 'png' 105 target = 'png'
105 pdot, dot_sourcepath = tempfile.mkstemp(".dot", name) 106 pdot, dot_sourcepath = tempfile.mkstemp(".dot", name)
106 ppng, outputfile = tempfile.mkstemp(".png", name) 107 ppng, outputfile = tempfile.mkstemp(".png", name)
107 os.close(pdot) 108 os.close(pdot)
108 os.close(ppng) 109 os.close(ppng)
109 pdot = open(dot_sourcepath, 'w') 110 pdot = codecs.open(dot_sourcepath, 'w', encoding='utf8')
110 pdot.write(str_encode(self.source, 'utf8')) 111 pdot.write(self.source)
111 pdot.close() 112 pdot.close()
112 if target != 'dot': 113 if target != 'dot':
113 if sys.platform == 'win32': 114 if sys.platform == 'win32':
114 use_shell = True 115 use_shell = True
115 else: 116 else:
116 use_shell = False 117 use_shell = False
117 if mapfile: 118 try:
118 subprocess.call([self.renderer, '-Tcmapx', '-o', mapfile, '-T', target, dot_sourcepath, '-o', outputfile], 119 if mapfile:
119 shell=use_shell) 120 subprocess.call([self.renderer, '-Tcmapx', '-o', mapfile, ' -T', target, dot_sourcepath, '-o', outputfile],
120 else: 121 shell=use_shell)
121 subprocess.call([self.renderer, '-T', target, 122 else:
122 dot_sourcepath, '-o', outputfile], 123 subprocess.call([self.renderer, '-T', target,
123 shell=use_shell) 124 dot_sourcepath, '-o', outputfile],
125 shell=use_shell)
126 except OSError as e:
127 if e.errno == errno.ENOENT:
128 e.strerror = 'File not found: {0}'.format(self.renderer)
129 raise
124 os.unlink(dot_sourcepath) 130 os.unlink(dot_sourcepath)
125 return outputfile 131 return outputfile
126 132
127 def emit(self, line): 133 def emit(self, line):
128 """Adds <line> to final output.""" 134 """Adds <line> to final output."""
129 self.lines.append(line) 135 self.lines.append(line)
130 136
131 def emit_edge(self, name1, name2, **props): 137 def emit_edge(self, name1, name2, **props):
132 """emit an edge from <name1> to <name2>. 138 """emit an edge from <name1> to <name2>.
133 edge properties: see http://www.graphviz.org/doc/info/attrs.html 139 edge properties: see http://www.graphviz.org/doc/info/attrs.html
134 """ 140 """
135 attrs = ['%s="%s"' % (prop, value) for prop, value in props.items()] 141 attrs = ['%s="%s"' % (prop, value) for prop, value in props.items()]
136 n_from, n_to = normalize_node_id(name1), normalize_node_id(name2) 142 n_from, n_to = normalize_node_id(name1), normalize_node_id(name2)
137 self.emit('%s -> %s [%s];' % (n_from, n_to, ", ".join(attrs)) ) 143 self.emit('%s -> %s [%s];' % (n_from, n_to, ', '.join(sorted(attrs))) )
138 144
139 def emit_node(self, name, **props): 145 def emit_node(self, name, **props):
140 """emit a node with given properties. 146 """emit a node with given properties.
141 node properties: see http://www.graphviz.org/doc/info/attrs.html 147 node properties: see http://www.graphviz.org/doc/info/attrs.html
142 """ 148 """
143 attrs = ['%s="%s"' % (prop, value) for prop, value in props.items()] 149 attrs = ['%s="%s"' % (prop, value) for prop, value in props.items()]
144 self.emit('%s [%s];' % (normalize_node_id(name), ", ".join(attrs))) 150 self.emit('%s [%s];' % (normalize_node_id(name), ', '.join(sorted(attrs) )))
145 151
146 def normalize_node_id(nid): 152 def normalize_node_id(nid):
147 """Returns a suitable DOT node id for `nid`.""" 153 """Returns a suitable DOT node id for `nid`."""
148 return '"%s"' % nid 154 return '"%s"' % nid
149 155
150 class GraphGenerator: 156 class GraphGenerator:
151 def __init__(self, backend): 157 def __init__(self, backend):
152 # the backend is responsible to output the graph in a particular format 158 # the backend is responsible to output the graph in a particular format
153 self.backend = backend 159 self.backend = backend
154 160
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 '''given a dictionary representing an ordered graph (i.e. key are vertices 225 '''given a dictionary representing an ordered graph (i.e. key are vertices
220 and values is a list of destination vertices representing edges), return a 226 and values is a list of destination vertices representing edges), return a
221 list of detected cycles 227 list of detected cycles
222 ''' 228 '''
223 if not graph_dict: 229 if not graph_dict:
224 return () 230 return ()
225 result = [] 231 result = []
226 if vertices is None: 232 if vertices is None:
227 vertices = graph_dict.keys() 233 vertices = graph_dict.keys()
228 for vertice in vertices: 234 for vertice in vertices:
229 _get_cycles(graph_dict, vertice, [], result) 235 _get_cycles(graph_dict, [], set(), result, vertice)
230 return result 236 return result
231 237
232 def _get_cycles(graph_dict, vertice=None, path=None, result=None): 238 def _get_cycles(graph_dict, path, visited, result, vertice):
233 """recursive function doing the real work for get_cycles""" 239 """recursive function doing the real work for get_cycles"""
234 if vertice in path: 240 if vertice in path:
235 cycle = [vertice] 241 cycle = [vertice]
236 for node in path[::-1]: 242 for node in path[::-1]:
237 if node == vertice: 243 if node == vertice:
238 break 244 break
239 cycle.insert(0, node) 245 cycle.insert(0, node)
240 # make a canonical representation 246 # make a canonical representation
241 start_from = min(cycle) 247 start_from = min(cycle)
242 index = cycle.index(start_from) 248 index = cycle.index(start_from)
243 cycle = cycle[index:] + cycle[0:index] 249 cycle = cycle[index:] + cycle[0:index]
244 # append it to result if not already in 250 # append it to result if not already in
245 if not cycle in result: 251 if not cycle in result:
246 result.append(cycle) 252 result.append(cycle)
247 return 253 return
248 path.append(vertice) 254 path.append(vertice)
249 try: 255 try:
250 for node in graph_dict[vertice]: 256 for node in graph_dict[vertice]:
251 _get_cycles(graph_dict, node, path, result) 257 # don't check already visited nodes again
258 if node not in visited:
259 _get_cycles(graph_dict, path, visited, result, node)
260 visited.add(node)
252 except KeyError: 261 except KeyError:
253 pass 262 pass
254 path.pop() 263 path.pop()
255 264
256 def has_path(graph_dict, fromnode, tonode, path=None): 265 def has_path(graph_dict, fromnode, tonode, path=None):
257 """generic function taking a simple graph definition as a dictionary, with 266 """generic function taking a simple graph definition as a dictionary, with
258 node has key associated to a list of nodes directly reachable from it. 267 node has key associated to a list of nodes directly reachable from it.
259 268
260 Return None if no path exists to go from `fromnode` to `tonode`, else the 269 Return None if no path exists to go from `fromnode` to `tonode`, else the
261 first path found (as a list including the destination node at last) 270 first path found (as a list including the destination node at last)
262 """ 271 """
263 if path is None: 272 if path is None:
264 path = [] 273 path = []
265 elif fromnode in path: 274 elif fromnode in path:
266 return None 275 return None
267 path.append(fromnode) 276 path.append(fromnode)
268 for destnode in graph_dict[fromnode]: 277 for destnode in graph_dict[fromnode]:
269 if destnode == tonode or has_path(graph_dict, destnode, tonode, path): 278 if destnode == tonode or has_path(graph_dict, destnode, tonode, path):
270 return path[1:] + [tonode] 279 return path[1:] + [tonode]
271 path.pop() 280 path.pop()
272 return None 281 return None
273 282
OLDNEW
« no previous file with comments | « third_party/logilab/common/fileutils.py ('k') | third_party/logilab/common/hg.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698