comparison doc/check-seclevel.py @ 26411:dd62eaa82cbe

check-seclevel: use ui to show status and error messages Future patches will require ui module to be passed to a help function, so let's use it where appropriate. Additional parens are necessary to silence a check-code warning.
author Yuya Nishihara <yuya@tcha.org>
date Sun, 27 Sep 2015 22:29:07 +0900
parents 70abba798098
children e0c572d4d112
comparison
equal deleted inserted replaced
26410:4c4b3c37776c 26411:dd62eaa82cbe
12 from mercurial import demandimport; demandimport.enable() 12 from mercurial import demandimport; demandimport.enable()
13 from mercurial.commands import table 13 from mercurial.commands import table
14 from mercurial.help import helptable 14 from mercurial.help import helptable
15 from mercurial import extensions 15 from mercurial import extensions
16 from mercurial import minirst 16 from mercurial import minirst
17 17 from mercurial import ui as uimod
18 _verbose = False
19
20 def verbose(msg):
21 if _verbose:
22 print msg
23
24 def error(msg):
25 sys.stderr.write('%s\n' % msg)
26 18
27 level2mark = ['"', '=', '-', '.', '#'] 19 level2mark = ['"', '=', '-', '.', '#']
28 reservedmarks = ['"'] 20 reservedmarks = ['"']
29 21
30 mark2level = {} 22 mark2level = {}
35 initlevel_topic = 0 27 initlevel_topic = 0
36 initlevel_cmd = 1 28 initlevel_cmd = 1
37 initlevel_ext = 1 29 initlevel_ext = 1
38 initlevel_ext_cmd = 3 30 initlevel_ext_cmd = 3
39 31
40 def showavailables(initlevel): 32 def showavailables(ui, initlevel):
41 error(' available marks and order of them in this help: %s' % 33 ui.warn((' available marks and order of them in this help: %s\n') %
42 (', '.join(['%r' % (m * 4) for m in level2mark[initlevel + 1:]]))) 34 (', '.join(['%r' % (m * 4) for m in level2mark[initlevel + 1:]])))
43 35
44 def checkseclevel(doc, name, initlevel): 36 def checkseclevel(ui, doc, name, initlevel):
45 verbose('checking "%s"' % name) 37 ui.note(('checking "%s"\n') % name)
46 blocks, pruned = minirst.parse(doc, 0, ['verbose']) 38 blocks, pruned = minirst.parse(doc, 0, ['verbose'])
47 errorcnt = 0 39 errorcnt = 0
48 curlevel = initlevel 40 curlevel = initlevel
49 for block in blocks: 41 for block in blocks:
50 if block['type'] != 'section': 42 if block['type'] != 'section':
51 continue 43 continue
52 mark = block['underline'] 44 mark = block['underline']
53 title = block['lines'][0] 45 title = block['lines'][0]
54 if (mark not in mark2level) or (mark2level[mark] <= initlevel): 46 if (mark not in mark2level) or (mark2level[mark] <= initlevel):
55 error('invalid section mark %r for "%s" of %s' % 47 ui.warn(('invalid section mark %r for "%s" of %s\n') %
56 (mark * 4, title, name)) 48 (mark * 4, title, name))
57 showavailables(initlevel) 49 showavailables(ui, initlevel)
58 errorcnt += 1 50 errorcnt += 1
59 continue 51 continue
60 nextlevel = mark2level[mark] 52 nextlevel = mark2level[mark]
61 if curlevel < nextlevel and curlevel + 1 != nextlevel: 53 if curlevel < nextlevel and curlevel + 1 != nextlevel:
62 error('gap of section level at "%s" of %s' % 54 ui.warn(('gap of section level at "%s" of %s\n') %
63 (title, name)) 55 (title, name))
64 showavailables(initlevel) 56 showavailables(ui, initlevel)
65 errorcnt += 1 57 errorcnt += 1
66 continue 58 continue
67 verbose('appropriate section level for "%s %s"' % 59 ui.note(('appropriate section level for "%s %s"\n') %
68 (mark * (nextlevel * 2), title)) 60 (mark * (nextlevel * 2), title))
69 curlevel = nextlevel 61 curlevel = nextlevel
70 62
71 return errorcnt 63 return errorcnt
72 64
73 def checkcmdtable(cmdtable, namefmt, initlevel): 65 def checkcmdtable(ui, cmdtable, namefmt, initlevel):
74 errorcnt = 0 66 errorcnt = 0
75 for k, entry in cmdtable.items(): 67 for k, entry in cmdtable.items():
76 name = k.split("|")[0].lstrip("^") 68 name = k.split("|")[0].lstrip("^")
77 if not entry[0].__doc__: 69 if not entry[0].__doc__:
78 verbose('skip checking %s: no help document' % 70 ui.note(('skip checking %s: no help document\n') %
79 (namefmt % name)) 71 (namefmt % name))
80 continue 72 continue
81 errorcnt += checkseclevel(entry[0].__doc__, 73 errorcnt += checkseclevel(ui, entry[0].__doc__,
82 namefmt % name, 74 namefmt % name,
83 initlevel) 75 initlevel)
84 return errorcnt 76 return errorcnt
85 77
86 def checkhghelps(): 78 def checkhghelps(ui):
87 errorcnt = 0 79 errorcnt = 0
88 for names, sec, doc in helptable: 80 for names, sec, doc in helptable:
89 if callable(doc): 81 if callable(doc):
90 doc = doc() 82 doc = doc()
91 errorcnt += checkseclevel(doc, 83 errorcnt += checkseclevel(ui, doc,
92 '%s help topic' % names[0], 84 '%s help topic' % names[0],
93 initlevel_topic) 85 initlevel_topic)
94 86
95 errorcnt += checkcmdtable(table, '%s command', initlevel_cmd) 87 errorcnt += checkcmdtable(ui, table, '%s command', initlevel_cmd)
96 88
97 for name in sorted(extensions.enabled().keys() + 89 for name in sorted(extensions.enabled().keys() +
98 extensions.disabled().keys()): 90 extensions.disabled().keys()):
99 mod = extensions.load(None, name, None) 91 mod = extensions.load(None, name, None)
100 if not mod.__doc__: 92 if not mod.__doc__:
101 verbose('skip checking %s extension: no help document' % name) 93 ui.note(('skip checking %s extension: no help document\n') % name)
102 continue 94 continue
103 errorcnt += checkseclevel(mod.__doc__, 95 errorcnt += checkseclevel(ui, mod.__doc__,
104 '%s extension' % name, 96 '%s extension' % name,
105 initlevel_ext) 97 initlevel_ext)
106 98
107 cmdtable = getattr(mod, 'cmdtable', None) 99 cmdtable = getattr(mod, 'cmdtable', None)
108 if cmdtable: 100 if cmdtable:
109 errorcnt += checkcmdtable(cmdtable, 101 errorcnt += checkcmdtable(ui, cmdtable,
110 '%s command of ' + name + ' extension', 102 '%s command of ' + name + ' extension',
111 initlevel_ext_cmd) 103 initlevel_ext_cmd)
112 return errorcnt 104 return errorcnt
113 105
114 def checkfile(filename, initlevel): 106 def checkfile(ui, filename, initlevel):
115 if filename == '-': 107 if filename == '-':
116 filename = 'stdin' 108 filename = 'stdin'
117 doc = sys.stdin.read() 109 doc = sys.stdin.read()
118 else: 110 else:
119 fp = open(filename) 111 fp = open(filename)
120 try: 112 try:
121 doc = fp.read() 113 doc = fp.read()
122 finally: 114 finally:
123 fp.close() 115 fp.close()
124 116
125 verbose('checking input from %s with initlevel %d' % 117 ui.note(('checking input from %s with initlevel %d\n') %
126 (filename, initlevel)) 118 (filename, initlevel))
127 return checkseclevel(doc, 'input from %s' % filename, initlevel) 119 return checkseclevel(ui, doc, 'input from %s' % filename, initlevel)
128 120
129 def main(): 121 def main():
130 optparser = optparse.OptionParser("""%prog [options] 122 optparser = optparse.OptionParser("""%prog [options]
131 123
132 This checks all help documents of Mercurial (topics, commands, 124 This checks all help documents of Mercurial (topics, commands,
157 help="set initial section level manually", 149 help="set initial section level manually",
158 action="store", type="int", default=0) 150 action="store", type="int", default=0)
159 151
160 (options, args) = optparser.parse_args() 152 (options, args) = optparser.parse_args()
161 153
162 global _verbose 154 ui = uimod.ui()
163 _verbose = options.verbose 155 ui.setconfig('ui', 'verbose', options.verbose, '--verbose')
164 156
165 if options.file: 157 if options.file:
166 if checkfile(options.file, options.initlevel): 158 if checkfile(ui, options.file, options.initlevel):
167 sys.exit(1) 159 sys.exit(1)
168 else: 160 else:
169 if checkhghelps(): 161 if checkhghelps(ui):
170 sys.exit(1) 162 sys.exit(1)
171 163
172 if __name__ == "__main__": 164 if __name__ == "__main__":
173 main() 165 main()