Merge lp:~knitzsche/dotdepends/addresses-mfisch-review into lp:dotdepends

Proposed by Kyle Nitzsche
Status: Merged
Merged at revision: 75
Proposed branch: lp:~knitzsche/dotdepends/addresses-mfisch-review
Merge into: lp:dotdepends
Diff against target: 622 lines (+262/-185)
6 files modified
Dotdepends/Dot.py (+25/-18)
debian/changelog (+6/-0)
debian/copyright (+1/-1)
debian/rules (+2/-1)
usr/bin/dotdepends (+30/-14)
usr/bin/dotdepends-merge (+198/-151)
To merge this branch: bzr merge lp:~knitzsche/dotdepends/addresses-mfisch-review
Reviewer Review Type Date Requested Status
Matt Fischer (community) Approve
Review via email: mp+114498@code.launchpad.net

Description of the change

addresses most of mfisch's review comments. others (unit tests) left for carif.
    following bugs opened:
    - LP: #1023578. This is fixed in dotdepends-merge but should be addressed
      in dotdepends. User can now set node fill colors (and shapes) with args.
    - LP: #1023581. Not fixed.
    - LP: #1023564. Not fixxed.

To post a comment you must log in.
Revision history for this message
Matt Fischer (mfisch) wrote :

changelog:
You misspelled "fixed" - LP: #1023564. Not fixxed. I think maybe you just want to not list bugs that you didn't fix yet though, it will be confusing I think.

copyright:
Sorry to mention this again, I think it's supposed to be, I think I just said "Canonical" before
Copyright: 2012 Canonical Ltd.

I have more questions about colors that I will follow-up with you in IRC about.

review: Needs Fixing
74. By Kyle Nitzsche

addresses mfisch's review comments (except for those carif will do).

75. By Kyle Nitzsche

addresses non-unit test review comments

Revision history for this message
Matt Fischer (mfisch) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Dotdepends/Dot.py'
2--- Dotdepends/Dot.py 2012-07-10 21:54:13 +0000
3+++ Dotdepends/Dot.py 2012-07-11 21:15:25 +0000
4@@ -21,7 +21,9 @@
5 import subprocess
6
7 def dot2png(_f, shape="box"):
8- """Run dot on passed file handle to create png with box shapes as default"""
9+ """Run dot on passed file handle to create png with box shapes as
10+ default"""
11+
12 _fpng = _f.rstrip(".dot") + ".png"
13 cmd = ['dot', '-Tpng', '-Nshape=%s' % shape, '-o', _fpng, _f]
14 subprocess.call(cmd)
15@@ -113,7 +115,7 @@
16 """
17
18 joins = []
19- # joins structure: [lnode:[rnode,style]]
20+ # joins structure: [lnode:[rnode,style]]
21 for line in self.content:
22 line = line.strip()
23 if len(line) == 0: continue
24@@ -124,7 +126,11 @@
25 if len(tokens) == 3:
26 joins.append([tokens[0],tokens[2].rstrip(";\n"), ""])
27 if len(tokens) == 4:
28- joins.append([tokens[0],tokens[2], tokens[3].rstrip(";\n")])
29+ joins.append(
30+ [tokens[0],
31+ tokens[2],
32+ tokens[3].rstrip(";\n")]
33+ )
34 return joins
35
36 def get_nodes(self):
37@@ -467,15 +473,15 @@
38 type="string",
39 dest="root",
40 default="",
41- help="The root node. Pass it to prevent summarizing the\
42- root node into a family."
43+ help="The root node. Pass it to prevent summarizing the"\
44+ " root node into a family."
45 )
46 parser.add_option("-o", "--out-file",
47 type="string",
48 dest="out_file",
49 default="out",
50- help="The generated dot filename without the '.dot'\
51- extension."
52+ help="The generated dot filename without the '.dot'"\
53+ " extension."
54 )
55 parser.add_option("-d", "--dot-file",
56 type="string",
57@@ -487,37 +493,38 @@
58 dest="summarize",
59 action="store_true",
60 default=False,
61- help="Produce dot with families summarized as single\
62- nodes"
63+ help="Produce dot with families summarized as single "\
64+ "nodes"
65 )
66 parser.add_option("-l", "--get-popular-lnodes",
67 dest="get_pop_lnodes",
68 action="store_true",
69 default=False,
70- help="Output lnodes that point to at least 'popularity'\
71- rnodes"
72+ help="Output lnodes that point to at least 'popularity'"\
73+ " rnodes"
74 )
75 parser.add_option("-c", "--get-popular-rnodes",
76 dest="get_pop_rnodes",
77 action="store_true",
78 default=False,
79- help="Output rnodes that point to at least 'popularity'\
80- lnodes"
81+ help="Output rnodes that point to at least 'popularity'"\
82+ " lnodes"
83 )
84 parser.add_option("-p", "--popularity",
85 type="string",
86 dest="popularity",
87 default="",
88- help="The minimum poplarity needed to be reported when -l\
89- or -r are used."
90+ help="The minimum poplarity needed to be reported when"\
91+ " -l or -r are used."
92 )
93 parser.add_option("-n", "--dont-run-dot",
94 dest="dont_run_dot",
95 action="store_true",
96 default=False,
97- help="Execute dot to process the dot file to a png. Note\
98- very large dot files produced in rdepends mode for packages with many rdepends\
99- may take an unreasonable amount of time for dot to process."
100+ help="Execute dot to process the dot file to a png. "\
101+ "Note very large dot files produced in rdepends mode"\
102+ " for packages with many rdepends may take an "\
103+ "unreasonable amount of time for dot to process."
104 )
105 parser.add_option("-N", "--node-shape",
106 type="string",
107
108=== modified file 'debian/changelog'
109--- debian/changelog 2012-07-11 17:30:35 +0000
110+++ debian/changelog 2012-07-11 21:15:25 +0000
111@@ -1,3 +1,9 @@
112+dotdepends (0.3.16kyle1) UNRELEASED; urgency=low
113+
114+ * addresses non-unit test review comments
115+
116+ -- Kyle Nitzsche <kyle.nitzsche@canonical.com> Wed, 11 Jul 2012 17:12:39 -0400
117+
118 dotdepends (0.3.16) precise; urgency=low
119
120 * redundant 'color="red"' styles in nodes in generated pkg-DETAIL.dot files
121
122=== modified file 'debian/copyright'
123--- debian/copyright 2012-07-11 18:18:21 +0000
124+++ debian/copyright 2012-07-11 21:15:25 +0000
125@@ -3,7 +3,7 @@
126 Upstream-Contact: Kyle Nitzsche <kyle.nitzsche@canonical.com>
127
128 Files: *
129-Copyright: (C) 2012 Kyle Nitzsche, Canonical
130+Copyright: (C) Canonical Ltd. 2012
131 License: GPL-3
132 The full text of the GPL is distributed in
133 /usr/share/common-licenses/GPL-3 on Debian systems.
134
135=== modified file 'debian/rules'
136--- debian/rules 2012-07-10 21:54:13 +0000
137+++ debian/rules 2012-07-11 21:15:25 +0000
138@@ -4,7 +4,8 @@
139 dh $@ --with python2
140
141 override_dh_auto_install:
142- python ./setup.py install --root=$(CURDIR)/debian/tmp --prefix=/usr --install-layout=deb
143+ python ./setup.py install --root=$(CURDIR)/debian/tmp --prefix=/usr\
144+ --install-layout=deb
145
146 override_dh_auto_clean:
147 -find . -name '*.py[co]' | xargs rm -f
148
149=== modified file 'usr/bin/dotdepends'
150--- usr/bin/dotdepends 2012-07-10 21:54:13 +0000
151+++ usr/bin/dotdepends 2012-07-11 21:15:25 +0000
152@@ -25,7 +25,8 @@
153
154 # Running dotdepends "in place" in the source pkg
155 # Add location of modules to path
156-sys.path.insert(0, path.abspath(path.dirname(path.abspath(__file__)) + '../../..'))
157+sys.path.insert(0, path.abspath(path.dirname(path.abspath(__file__)) + \
158+'../../..'))
159 # Add location of executable to path because it calls itself
160 location = path.abspath(path.dirname(path.abspath(__file__)))
161 sys.path.insert(0, location)
162@@ -138,7 +139,11 @@
163 if __name__ == "__main__":
164
165 # dotdepends with no arguments or with -h should run help
166- if len(sys.argv) == 1 or sys.argv[1] == '-h' or sys.argv[1].find('help') > -1:
167+ if (
168+ len(sys.argv) == 1
169+ or sys.argv[1] == '-h'
170+ or sys.argv[1].find('help')
171+ ) > -1:
172 print sys.stderr, "See 'man dotdepends' for help"
173 sys.exit(0)
174
175@@ -191,15 +196,16 @@
176 pkg =""
177 #print args
178 if len(args) != 1:
179- print sys.stderr, "Error. A package must be be provided as the root node for the\
180- graph. Use '-h'. Stopping"
181+ print sys.stderr, "Error. A package must be be provided as the root "\
182+ "node for the graph. Use '-h'. Stopping"
183 else:
184 pkg = args[0]
185
186
187 # User set -m depends explicitly.
188 if opt.mode == 'depends' and opt.installed:
189- print >> sys.stderr, "Error. Installed (-i) is not valid for mode 'depends'. Stopping."
190+ print >> sys.stderr, "Error. Installed (-i) is not valid for mode "\
191+ "'depends'. Stopping."
192 sys.exit(1)
193
194 #print "pkg %s" % pkg
195@@ -221,13 +227,14 @@
196
197
198 if opt.installed:
199- print >> sys.stderr, "Error. Installed (-i) is not valid in default ('analyze') mode. Stopping."
200+ print >> sys.stderr, "Error. Installed (-i) is not valid in "\
201+ "default ('analyze') mode. Stopping."
202 sys.exit(1)
203
204
205 if opt.mode == "rdepends":
206- print sys.stderr, "Error. Analyze (-a) is only applicable to 'depends' mode\
207- (not '-m redepends'). Stopping."
208+ print sys.stderr, "Error. Analyze (-a) is only applicable to "\
209+ "'depends' mode (not '-m redepends'). Stopping."
210 sys.exit(1)
211
212 cmd = [
213@@ -240,16 +247,22 @@
214 if opt.dont_run_dot:
215 cmd.append('-d')
216
217- # output_dir_created is True iff the subprocess below will create (and populate)
218- # a new directory opt.output_dir.
219- # If subprocess creates the directory, but then we error out, we should clean up the directory.
220+ # output_dir_created is True iff the subprocess below will create (and
221+ # populate) a new directory opt.output_dir.
222+ # If subprocess creates the directory, but then we error out, we should
223+ # clean up the directory.
224 # We should not, however, remove directories we don't create.
225 output_dir_created = not path.isdir(opt.output_dir)
226
227- p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
228+ p = subprocess.Popen(
229+ cmd,
230+ stdout=subprocess.PIPE,
231+ stderr=subprocess.PIPE
232+ )
233 f1, error = p.communicate()
234 if p.returncode != 0 or error.startswith('E:'):
235- print >> sys.stderr, "Error. '%s'. Stopping." % error.rstrip() # remove possible newlines
236+ print >> sys.stderr, "Error. '%s'. Stopping." % error.rstrip()
237+ # ^ remove possible newlines
238 if output_dir_created: shutil.rmtree(opt.output_dir)
239 # return process return code iff more specific
240 sys.exit(max(1, p.returncode))
241@@ -269,7 +282,10 @@
242 p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
243 f2 = p.communicate()
244 # Did the process error?
245- if p.returncode > 0 or (f2[1] is not None and f2[1].startswith('Error')):
246+ if p.returncode > 0 or (
247+ f2[1] is not None
248+ and f2[1].startswith('Error')
249+ ):
250 # Yes, pass the error along
251 print >> sys.stderr, f2[1]
252 sys.exit(1)
253
254=== modified file 'usr/bin/dotdepends-merge'
255--- usr/bin/dotdepends-merge 2012-07-10 21:54:13 +0000
256+++ usr/bin/dotdepends-merge 2012-07-11 21:15:25 +0000
257@@ -17,48 +17,15 @@
258 # along with this program. If not, see <http://www.gnu.org/licenses/>.
259
260 import sys
261+from optparse import OptionParser
262 from Dotdepends.Dot import Dot as Dot, replacement
263
264-if "-h" in sys.argv or "--help" in sys.argv:
265- print "Use 'man dotdepends-merge' to display help."
266- sys.exit(1)
267-
268-# dot files
269-f1 = sys.argv[1]
270-f2 = sys.argv[2]
271-# shapes for nodes
272-s1 = "box"
273-s2 = "ellipse"
274-s3 = "diamond"
275-# colors for nodes
276-c1 = "grey"
277-c2 = "brown"
278-c3 = "orange"
279-# load dot files from API
280-d1 = Dot(f1)
281-d2 = Dot(f2)
282-# get root pkgs for each
283-r1 = d1.root
284-r2 = d2.root
285-
286-# quit if no root
287 def verify_root(d):
288+ """quit if no root pkg defined in dot file"""
289+
290 if len(d.root) < 1:
291 print sys.stderr("Error. %s has no defined root pkg. Stopping") % d
292 sys.exit(1)
293-verify_root(d1)
294-verify_root(d2)
295-
296-n1 = d1.get_nodes()
297-n1[replacement(r1)] = 'label="%s"' % r1
298-j1 = d1.get_joins()
299-n2 = d2.get_nodes()
300-n2[replacement(r2)] = 'label="%s"' % r2
301-j2 = d2.get_joins()
302-
303-_n1 = dict()
304-_n2 = dict()
305-rootNodeLines = []
306
307 def addShapes(nodes, shape, color):
308 newnodes = dict()
309@@ -76,120 +43,200 @@
310 _styles['shape'] = shape
311 newnodes[n] = _styles
312 return newnodes
313-_n1 = addShapes(n1,s1,c1)
314-_n2 = addShapes(n2,s2,c2)
315-
316-_shape='shape="diamond",fillcolor="orange",style="filled"'
317-_nFinal = dict()
318-
319-nBoth = set(_n1.keys()).intersection(set(_n2.keys()))
320-n1Only = set(_n1.keys()).difference(set(_n2.keys()))
321-n2Only = set(_n2.keys()).difference(set(_n1.keys()))
322-
323-nWorking = dict()
324-nFinal = dict()
325-
326-for node in nBoth:
327- n = _n1[node]
328- # if color:red is in both node sets, this pkg is only a Rec
329- # and needs to be red here too.
330- aRec = False
331- try:
332- if 'color' in _n1[node].keys():
333- if _n1[node][color] == 'red':
334- aRec = True
335- except:
336- pass
337- try:
338- if 'color' in _n2[node].keys():
339- if _n2[node][color] == 'red':
340- aRec = True
341- else:
342- aRec = False
343- except:
344- aRec = False
345-
346- if aRec:
347- n['color'] = 'red'
348-
349- n['shape'] = s3
350- n['fillcolor'] = c3
351- n['style'] = 'filled'
352- nFinal[node] = n
353-
354-for node in n1Only:
355- n = _n1[node]
356- aRec = False
357- try:
358- if 'color' in _n1[node].keys():
359- if _n1[node][color] == 'red':
360- n['color'] = 'red'
361- except:
362- pass
363- n['shape'] = s1
364- n['fillcolor'] = c1
365- n['style'] = 'filled'
366- nFinal[node] = n
367-
368-for node in n2Only:
369- n = _n2[node]
370- try:
371- if 'color' in _n1[node].keys():
372- if _n1[node][color] == 'red':
373- n['color'] = 'red'
374- except:
375- pass
376- n['shape'] = s2
377- n['fillcolor'] = c2
378- n['style'] = 'filled'
379- nFinal[node] = n
380-
381-for node in nFinal.keys():
382-# set fillcolor of root nodes blue
383- n = dict(nFinal[node])
384- pkg = node
385- if 'label' in n.keys():
386- pkg = n['label']
387- if pkg == r1 or pkg == r2:
388- n['fillcolor'] = 'blue'
389- n['fontcolor'] = 'white'
390- nFinal[node] = n
391-
392-# insert initial commented lines that show the root nodes
393-for line in rootNodeLines:
394- print line
395-
396-# start the dot file content
397-print "strict digraph dotdepends {"
398-print "subgraph cluster_program {"
399-
400-# print the nodes lines
401-for n in nFinal:
402- line = "%s [" % n
403- for style in nFinal[n]:
404- if style == '': continue
405- line += '%s="%s",' % (style, nFinal[n][style])
406- line = line[:len(line)-1]
407- line += '];'
408- print line
409-
410-#print the join ('edge') lines
411-def printJoins(j):
412- for join in j:
413- #print "JOIN %s" % join
414- line = "%s -> %s" % (join[0], join[1])
415- if len(join[2]) > 0:
416- line += " %s" % join[2]
417- line += ';'
418- print line
419-
420-printJoins(j1)
421-printJoins(j2)
422-
423-# finish the dot file
424-print "}"
425-print "}"
426-
427-sys.exit(0)
428+
429+if __name__ == "__main__":
430+
431+ # dotdepends with no arguments or with -h should run help
432+ if (
433+ len(sys.argv) == 1
434+ or sys.argv[1] == '-h'
435+ or sys.argv[1].find('help')
436+ ) > -1:
437+ print sys.stderr, "See 'man dotdepends' for help"
438+ sys.exit(0)
439+
440+ parser = OptionParser()
441+
442+ # NOTE: command help is in the dotdepends man page
443+
444+ parser.add_option("-c", "--color-1",
445+ dest="color1",
446+ type="string",
447+ default="grey",
448+ )
449+ parser.add_option("-d", "--color-2",
450+ dest="color2",
451+ type="string",
452+ default="brown",
453+ )
454+ parser.add_option("-e", "--color-3",
455+ dest="color3",
456+ type="string",
457+ default="orange",
458+ )
459+ parser.add_option("-s", "--shape-1",
460+ dest="shape1",
461+ type="string",
462+ default="box",
463+ )
464+ parser.add_option("-t", "--shape-2",
465+ dest="shape2",
466+ type="string",
467+ default="ellipse",
468+ )
469+ parser.add_option("-u", "--shape-3",
470+ dest="shape3",
471+ type="string",
472+ default="diamond",
473+ )
474+
475+ (opt, args) = parser.parse_args()
476+
477+ # dot files
478+ f1 = sys.argv[1]
479+ f2 = sys.argv[2]
480+ # shapes for nodes
481+ shape1 = opt.shape1
482+ shape2 = opt.shape2
483+ shape3 = opt.shape3
484+ # colors for nodes
485+ color1 = opt.color1
486+ color2 = opt.color2
487+ color3 = opt.color3
488+ # load dot files from API
489+ d1 = Dot(f1)
490+ d2 = Dot(f2)
491+ # get root pkgs for each
492+ r1 = d1.root
493+ r2 = d2.root
494+
495+ verify_root(d1)
496+ verify_root(d2)
497+
498+ n1 = d1.get_nodes()
499+ n1[replacement(r1)] = 'label="%s"' % r1
500+ j1 = d1.get_joins()
501+ n2 = d2.get_nodes()
502+ n2[replacement(r2)] = 'label="%s"' % r2
503+ j2 = d2.get_joins()
504+
505+ _n1 = dict()
506+ _n2 = dict()
507+ rootNodeLines = []
508+ _n1 = addShapes(n1,shape1,color1)
509+ _n2 = addShapes(n2,shape2,color2)
510+
511+ _shape='shape="diamond",fillcolor="orange",style="filled"'
512+ _nFinal = dict()
513+
514+ nBoth = set(_n1.keys()).intersection(set(_n2.keys()))
515+ n1Only = set(_n1.keys()).difference(set(_n2.keys()))
516+ n2Only = set(_n2.keys()).difference(set(_n1.keys()))
517+
518+ nWorking = dict()
519+ nFinal = dict()
520+
521+ for node in nBoth:
522+ n = _n1[node]
523+ # if color:red is in both node sets, this pkg is only a Rec
524+ # and needs to be red here too.
525+ aRec = False
526+ try:
527+ if 'color' in _n1[node].keys():
528+ if _n1[node][color] == 'red':
529+ aRec = True
530+ except:
531+ pass
532+ try:
533+ if 'color' in _n2[node].keys():
534+ if _n2[node][color] == 'red':
535+ aRec = True
536+ else:
537+ aRec = False
538+ except:
539+ aRec = False
540+
541+ if aRec:
542+ n['color'] = 'red'
543+
544+ n['shape'] = shape3
545+ n['fillcolor'] = color3
546+ n['style'] = 'filled'
547+ nFinal[node] = n
548+
549+ for node in n1Only:
550+ n = _n1[node]
551+ aRec = False
552+ try:
553+ if 'color' in _n1[node].keys():
554+ if _n1[node][color] == 'red':
555+ n['color'] = 'red'
556+ except:
557+ pass
558+ n['shape'] = shape1
559+ n['fillcolor'] = color1
560+ n['style'] = 'filled'
561+ nFinal[node] = n
562+
563+ for node in n2Only:
564+ n = _n2[node]
565+ try:
566+ if 'color' in _n1[node].keys():
567+ if _n1[node][color] == 'red':
568+ n['color'] = 'red'
569+ except:
570+ pass
571+ n['shape'] = shape2
572+ n['fillcolor'] = color2
573+ n['style'] = 'filled'
574+ nFinal[node] = n
575+
576+ for node in nFinal.keys():
577+ # set fillcolor of root nodes blue
578+ n = dict(nFinal[node])
579+ pkg = node
580+ if 'label' in n.keys():
581+ pkg = n['label']
582+ if pkg == r1 or pkg == r2:
583+ n['fillcolor'] = 'blue'
584+ n['fontcolor'] = 'white'
585+ nFinal[node] = n
586+
587+ # insert initial commented lines that show the root nodes
588+ for line in rootNodeLines:
589+ print line
590+
591+ # start the dot file content
592+ print "strict digraph dotdepends {"
593+ print "subgraph cluster_program {"
594+
595+ # print the nodes lines
596+ for n in nFinal:
597+ line = "%s [" % n
598+ for style in nFinal[n]:
599+ if style == '': continue
600+ line += '%s="%s",' % (style, nFinal[n][style])
601+ line = line[:len(line)-1]
602+ line += '];'
603+ print line
604+
605+ #print the join ('edge') lines
606+ def printJoins(j):
607+ for join in j:
608+ #print "JOIN %s" % join
609+ line = "%s -> %s" % (join[0], join[1])
610+ if len(join[2]) > 0:
611+ line += " %s" % join[2]
612+ line += ';'
613+ print line
614+
615+ printJoins(j1)
616+ printJoins(j2)
617+
618+ # finish the dot file
619+ print "}"
620+ print "}"
621+
622+ sys.exit(0)
623
624

Subscribers

People subscribed via source and target branches

to all changes: