comparison doc/gendoc.py @ 41004:e10641c48fa7

py3: byteify gendoc.py This is mostly b'' prefixing, with some cargoculting of help.py to get around `textwrap.dedent()` and __doc__ string requirements.
author Matt Harbison <matt_harbison@yahoo.com>
date Tue, 18 Dec 2018 21:17:27 -0500
parents fabbf9310025
children c0865f3da285
comparison
equal deleted inserted replaced
41003:87c98ffbc8c7 41004:e10641c48fa7
8 8
9 import os 9 import os
10 import sys 10 import sys
11 import textwrap 11 import textwrap
12 12
13 try:
14 import msvcrt
15 msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
16 msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
17 except ImportError:
18 pass
19
13 # This script is executed during installs and may not have C extensions 20 # This script is executed during installs and may not have C extensions
14 # available. Relax C module requirements. 21 # available. Relax C module requirements.
15 os.environ['HGMODULEPOLICY'] = 'allow' 22 os.environ[r'HGMODULEPOLICY'] = r'allow'
16 # import from the live mercurial repo 23 # import from the live mercurial repo
17 sys.path.insert(0, "..") 24 sys.path.insert(0, r"..")
18 from mercurial import demandimport; demandimport.enable() 25 from mercurial import demandimport; demandimport.enable()
19 # Load util so that the locale path is set by i18n.setdatapath() before 26 # Load util so that the locale path is set by i18n.setdatapath() before
20 # calling _(). 27 # calling _().
21 from mercurial import util 28 from mercurial import util
22 util.datapath 29 util.datapath
23 from mercurial import ( 30 from mercurial import (
24 commands, 31 commands,
25 extensions, 32 extensions,
26 help, 33 help,
27 minirst, 34 minirst,
35 pycompat,
28 ui as uimod, 36 ui as uimod,
29 ) 37 )
30 from mercurial.i18n import ( 38 from mercurial.i18n import (
31 gettext, 39 gettext,
32 _, 40 _,
37 helptable = help.helptable 45 helptable = help.helptable
38 loaddoc = help.loaddoc 46 loaddoc = help.loaddoc
39 47
40 def get_desc(docstr): 48 def get_desc(docstr):
41 if not docstr: 49 if not docstr:
42 return "", "" 50 return b"", b""
43 # sanitize 51 # sanitize
44 docstr = docstr.strip("\n") 52 docstr = docstr.strip(b"\n")
45 docstr = docstr.rstrip() 53 docstr = docstr.rstrip()
46 shortdesc = docstr.splitlines()[0].strip() 54 shortdesc = docstr.splitlines()[0].strip()
47 55
48 i = docstr.find("\n") 56 i = docstr.find(b"\n")
49 if i != -1: 57 if i != -1:
50 desc = docstr[i + 2:] 58 desc = docstr[i + 2:]
51 else: 59 else:
52 desc = shortdesc 60 desc = shortdesc
53 61
54 desc = textwrap.dedent(desc) 62 desc = textwrap.dedent(desc.decode('latin1')).encode('latin1')
55 63
56 return (shortdesc, desc) 64 return (shortdesc, desc)
57 65
58 def get_opts(opts): 66 def get_opts(opts):
59 for opt in opts: 67 for opt in opts:
60 if len(opt) == 5: 68 if len(opt) == 5:
61 shortopt, longopt, default, desc, optlabel = opt 69 shortopt, longopt, default, desc, optlabel = opt
62 else: 70 else:
63 shortopt, longopt, default, desc = opt 71 shortopt, longopt, default, desc = opt
64 optlabel = _("VALUE") 72 optlabel = _(b"VALUE")
65 allopts = [] 73 allopts = []
66 if shortopt: 74 if shortopt:
67 allopts.append("-%s" % shortopt) 75 allopts.append(b"-%s" % shortopt)
68 if longopt: 76 if longopt:
69 allopts.append("--%s" % longopt) 77 allopts.append(b"--%s" % longopt)
70 if isinstance(default, list): 78 if isinstance(default, list):
71 allopts[-1] += " <%s[+]>" % optlabel 79 allopts[-1] += b" <%s[+]>" % optlabel
72 elif (default is not None) and not isinstance(default, bool): 80 elif (default is not None) and not isinstance(default, bool):
73 allopts[-1] += " <%s>" % optlabel 81 allopts[-1] += b" <%s>" % optlabel
74 if '\n' in desc: 82 if b'\n' in desc:
75 # only remove line breaks and indentation 83 # only remove line breaks and indentation
76 desc = ' '.join(l.lstrip() for l in desc.split('\n')) 84 desc = b' '.join(l.lstrip() for l in desc.split(b'\n'))
77 desc += default and _(" (default: %s)") % default or "" 85 desc += default and _(b" (default: %s)") % bytes(default) or b""
78 yield (", ".join(allopts), desc) 86 yield (b", ".join(allopts), desc)
79 87
80 def get_cmd(cmd, cmdtable): 88 def get_cmd(cmd, cmdtable):
81 d = {} 89 d = {}
82 attr = cmdtable[cmd] 90 attr = cmdtable[cmd]
83 cmds = cmd.lstrip("^").split("|") 91 cmds = cmd.lstrip(b"^").split(b"|")
84 92
85 d['cmd'] = cmds[0] 93 d[b'cmd'] = cmds[0]
86 d['aliases'] = cmd.split("|")[1:] 94 d[b'aliases'] = cmd.split(b"|")[1:]
87 d['desc'] = get_desc(gettext(attr[0].__doc__)) 95 d[b'desc'] = get_desc(gettext(pycompat.getdoc(attr[0])))
88 d['opts'] = list(get_opts(attr[1])) 96 d[b'opts'] = list(get_opts(attr[1]))
89 97
90 s = 'hg ' + cmds[0] 98 s = b'hg ' + cmds[0]
91 if len(attr) > 2: 99 if len(attr) > 2:
92 if not attr[2].startswith('hg'): 100 if not attr[2].startswith(b'hg'):
93 s += ' ' + attr[2] 101 s += b' ' + attr[2]
94 else: 102 else:
95 s = attr[2] 103 s = attr[2]
96 d['synopsis'] = s.strip() 104 d[b'synopsis'] = s.strip()
97 105
98 return d 106 return d
99 107
100 def showdoc(ui): 108 def showdoc(ui):
101 # print options 109 # print options
102 ui.write(minirst.section(_("Options"))) 110 ui.write(minirst.section(_(b"Options")))
103 multioccur = False 111 multioccur = False
104 for optstr, desc in get_opts(globalopts): 112 for optstr, desc in get_opts(globalopts):
105 ui.write("%s\n %s\n\n" % (optstr, desc)) 113 ui.write(b"%s\n %s\n\n" % (optstr, desc))
106 if optstr.endswith("[+]>"): 114 if optstr.endswith(b"[+]>"):
107 multioccur = True 115 multioccur = True
108 if multioccur: 116 if multioccur:
109 ui.write(_("\n[+] marked option can be specified multiple times\n")) 117 ui.write(_(b"\n[+] marked option can be specified multiple times\n"))
110 ui.write("\n") 118 ui.write(b"\n")
111 119
112 # print cmds 120 # print cmds
113 ui.write(minirst.section(_("Commands"))) 121 ui.write(minirst.section(_(b"Commands")))
114 commandprinter(ui, table, minirst.subsection) 122 commandprinter(ui, table, minirst.subsection)
115 123
116 # print help topics 124 # print help topics
117 # The config help topic is included in the hgrc.5 man page. 125 # The config help topic is included in the hgrc.5 man page.
118 helpprinter(ui, helptable, minirst.section, exclude=['config']) 126 helpprinter(ui, helptable, minirst.section, exclude=[b'config'])
119 127
120 ui.write(minirst.section(_("Extensions"))) 128 ui.write(minirst.section(_(b"Extensions")))
121 ui.write(_("This section contains help for extensions that are " 129 ui.write(_(b"This section contains help for extensions that are "
122 "distributed together with Mercurial. Help for other " 130 b"distributed together with Mercurial. Help for other "
123 "extensions is available in the help system.")) 131 b"extensions is available in the help system."))
124 ui.write(("\n\n" 132 ui.write((b"\n\n"
125 ".. contents::\n" 133 b".. contents::\n"
126 " :class: htmlonly\n" 134 b" :class: htmlonly\n"
127 " :local:\n" 135 b" :local:\n"
128 " :depth: 1\n\n")) 136 b" :depth: 1\n\n"))
129 137
130 for extensionname in sorted(allextensionnames()): 138 for extensionname in sorted(allextensionnames()):
131 mod = extensions.load(ui, extensionname, None) 139 mod = extensions.load(ui, extensionname, None)
132 ui.write(minirst.subsection(extensionname)) 140 ui.write(minirst.subsection(extensionname))
133 ui.write("%s\n\n" % gettext(mod.__doc__)) 141 ui.write(b"%s\n\n" % gettext(pycompat.getdoc(mod)))
134 cmdtable = getattr(mod, 'cmdtable', None) 142 cmdtable = getattr(mod, 'cmdtable', None)
135 if cmdtable: 143 if cmdtable:
136 ui.write(minirst.subsubsection(_('Commands'))) 144 ui.write(minirst.subsubsection(_(b'Commands')))
137 commandprinter(ui, cmdtable, minirst.subsubsubsection) 145 commandprinter(ui, cmdtable, minirst.subsubsubsection)
138 146
139 def showtopic(ui, topic): 147 def showtopic(ui, topic):
140 extrahelptable = [ 148 extrahelptable = [
141 (["common"], '', loaddoc('common'), help.TOPIC_CATEGORY_MISC), 149 ([b"common"], b'', loaddoc(b'common'), help.TOPIC_CATEGORY_MISC),
142 (["hg.1"], '', loaddoc('hg.1'), help.TOPIC_CATEGORY_CONFIG), 150 ([b"hg.1"], b'', loaddoc(b'hg.1'), help.TOPIC_CATEGORY_CONFIG),
143 (["hg-ssh.8"], '', loaddoc('hg-ssh.8'), help.TOPIC_CATEGORY_CONFIG), 151 ([b"hg-ssh.8"], b'', loaddoc(b'hg-ssh.8'), help.TOPIC_CATEGORY_CONFIG),
144 (["hgignore.5"], '', loaddoc('hgignore.5'), help.TOPIC_CATEGORY_CONFIG), 152 ([b"hgignore.5"], b'', loaddoc(b'hgignore.5'),
145 (["hgrc.5"], '', loaddoc('hgrc.5'), help.TOPIC_CATEGORY_CONFIG),
146 (["hgignore.5.gendoc"], '', loaddoc('hgignore'),
147 help.TOPIC_CATEGORY_CONFIG), 153 help.TOPIC_CATEGORY_CONFIG),
148 (["hgrc.5.gendoc"], '', loaddoc('config'), help.TOPIC_CATEGORY_CONFIG), 154 ([b"hgrc.5"], b'', loaddoc(b'hgrc.5'), help.TOPIC_CATEGORY_CONFIG),
155 ([b"hgignore.5.gendoc"], b'', loaddoc(b'hgignore'),
156 help.TOPIC_CATEGORY_CONFIG),
157 ([b"hgrc.5.gendoc"], b'', loaddoc(b'config'),
158 help.TOPIC_CATEGORY_CONFIG),
149 ] 159 ]
150 helpprinter(ui, helptable + extrahelptable, None, include=[topic]) 160 helpprinter(ui, helptable + extrahelptable, None, include=[topic])
151 161
152 def helpprinter(ui, helptable, sectionfunc, include=[], exclude=[]): 162 def helpprinter(ui, helptable, sectionfunc, include=[], exclude=[]):
153 for h in helptable: 163 for h in helptable:
155 if exclude and names[0] in exclude: 165 if exclude and names[0] in exclude:
156 continue 166 continue
157 if include and names[0] not in include: 167 if include and names[0] not in include:
158 continue 168 continue
159 for name in names: 169 for name in names:
160 ui.write(".. _%s:\n" % name) 170 ui.write(b".. _%s:\n" % name)
161 ui.write("\n") 171 ui.write(b"\n")
162 if sectionfunc: 172 if sectionfunc:
163 ui.write(sectionfunc(sec)) 173 ui.write(sectionfunc(sec))
164 if callable(doc): 174 if callable(doc):
165 doc = doc(ui) 175 doc = doc(ui)
166 ui.write(doc) 176 ui.write(doc)
167 ui.write("\n") 177 ui.write(b"\n")
168 178
169 def commandprinter(ui, cmdtable, sectionfunc): 179 def commandprinter(ui, cmdtable, sectionfunc):
170 h = {} 180 h = {}
171 for c, attr in cmdtable.items(): 181 for c, attr in cmdtable.items():
172 f = c.split("|")[0] 182 f = c.split(b"|")[0]
173 f = f.lstrip("^") 183 f = f.lstrip(b"^")
174 h[f] = c 184 h[f] = c
175 cmds = h.keys() 185 cmds = h.keys()
176 cmds.sort() 186
177 187 for f in sorted(cmds):
178 for f in cmds: 188 if f.startswith(b"debug"):
179 if f.startswith("debug"):
180 continue 189 continue
181 d = get_cmd(h[f], cmdtable) 190 d = get_cmd(h[f], cmdtable)
182 ui.write(sectionfunc(d['cmd'])) 191 ui.write(sectionfunc(d[b'cmd']))
183 # short description 192 # short description
184 ui.write(d['desc'][0]) 193 ui.write(d[b'desc'][0])
185 # synopsis 194 # synopsis
186 ui.write("::\n\n") 195 ui.write(b"::\n\n")
187 synopsislines = d['synopsis'].splitlines() 196 synopsislines = d[b'synopsis'].splitlines()
188 for line in synopsislines: 197 for line in synopsislines:
189 # some commands (such as rebase) have a multi-line 198 # some commands (such as rebase) have a multi-line
190 # synopsis 199 # synopsis
191 ui.write(" %s\n" % line) 200 ui.write(b" %s\n" % line)
192 ui.write('\n') 201 ui.write(b'\n')
193 # description 202 # description
194 ui.write("%s\n\n" % d['desc'][1]) 203 ui.write(b"%s\n\n" % d[b'desc'][1])
195 # options 204 # options
196 opt_output = list(d['opts']) 205 opt_output = list(d[b'opts'])
197 if opt_output: 206 if opt_output:
198 opts_len = max([len(line[0]) for line in opt_output]) 207 opts_len = max([len(line[0]) for line in opt_output])
199 ui.write(_("Options:\n\n")) 208 ui.write(_(b"Options:\n\n"))
200 multioccur = False 209 multioccur = False
201 for optstr, desc in opt_output: 210 for optstr, desc in opt_output:
202 if desc: 211 if desc:
203 s = "%-*s %s" % (opts_len, optstr, desc) 212 s = b"%-*s %s" % (opts_len, optstr, desc)
204 else: 213 else:
205 s = optstr 214 s = optstr
206 ui.write("%s\n" % s) 215 ui.write(b"%s\n" % s)
207 if optstr.endswith("[+]>"): 216 if optstr.endswith(b"[+]>"):
208 multioccur = True 217 multioccur = True
209 if multioccur: 218 if multioccur:
210 ui.write(_("\n[+] marked option can be specified" 219 ui.write(_(b"\n[+] marked option can be specified"
211 " multiple times\n")) 220 b" multiple times\n"))
212 ui.write("\n") 221 ui.write(b"\n")
213 # aliases 222 # aliases
214 if d['aliases']: 223 if d[b'aliases']:
215 ui.write(_(" aliases: %s\n\n") % " ".join(d['aliases'])) 224 ui.write(_(b" aliases: %s\n\n") % b" ".join(d[b'aliases']))
216 225
217 226
218 def allextensionnames(): 227 def allextensionnames():
219 return extensions.enabled().keys() + extensions.disabled().keys() 228 return set(extensions.enabled().keys()) | set(extensions.disabled().keys())
220 229
221 if __name__ == "__main__": 230 if __name__ == "__main__":
222 doc = 'hg.1.gendoc' 231 doc = b'hg.1.gendoc'
223 if len(sys.argv) > 1: 232 if len(sys.argv) > 1:
224 doc = sys.argv[1] 233 doc = sys.argv[1]
225 234
226 ui = uimod.ui.load() 235 ui = uimod.ui.load()
227 if doc == 'hg.1.gendoc': 236 if doc == b'hg.1.gendoc':
228 showdoc(ui) 237 showdoc(ui)
229 else: 238 else:
230 showtopic(ui, sys.argv[1]) 239 showtopic(ui, sys.argv[1])