##// END OF EJS Templates
gendoc: add support for loading extensions from config settings...
gendoc: add support for loading extensions from config settings We manage our installation and ship some extensions, enabled by default for our users, that are in hgext3rd or other directories not scanned by this tool by default. We want to generate docs during the build process, and having those docs include the extensions that users don't have to manually enable is desirable. This is *not* desirable for the normal build process, however, and should never be enabled by default. Differential Revision: https://phab.mercurial-scm.org/D9989

File last commit:

r47267:eb36f7a7 default
r47267:eb36f7a7 default
Show More
gendoc.py
341 lines | 10.6 KiB | text/x-python | PythonLexer
Gregory Szorc
global: use python3 in shebangs...
r46434 #!/usr/bin/env python3
Takumi IINO
gendoc: dispatch print document content by commandline arguments...
r19425 """usage: %s DOC ...
where DOC is the name of a document
"""
Pulkit Goyal
py3: make gendoc use absolute_import...
r28966 from __future__ import absolute_import
import os
import sys
import textwrap
Gregory Szorc
doc: make gendoc.py module import policy aware...
r27330
Matt Harbison
py3: byteify gendoc.py...
r41040 try:
import msvcrt
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Harbison
py3: byteify gendoc.py...
r41040 msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
except ImportError:
pass
Gregory Szorc
doc: make gendoc.py module import policy aware...
r27330 # This script is executed during installs and may not have C extensions
# available. Relax C module requirements.
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 os.environ['HGMODULEPOLICY'] = 'allow'
Benoit Boissinot
generate hg manpage from commands.py docstring...
r1814 # import from the live mercurial repo
Augie Fackler
cleanup: remove pointless r-prefixes on double-quoted strings...
r43809 sys.path.insert(0, "..")
Augie Fackler
formatting: blacken the codebase...
r43346 from mercurial import demandimport
demandimport.enable()
Pulkit Goyal
py3: make gendoc use absolute_import...
r28966 from mercurial import (
commands,
Matt Harbison
py3: byteify sys.argv in gendoc.py
r41059 encoding,
Pulkit Goyal
py3: make gendoc use absolute_import...
r28966 extensions,
Kyle Lippincott
gendoc: support defaults on customopts a bit better...
r47266 fancyopts,
Pulkit Goyal
py3: make gendoc use absolute_import...
r28966 help,
minirst,
Matt Harbison
py3: byteify gendoc.py...
r41040 pycompat,
Pulkit Goyal
py3: make gendoc use absolute_import...
r28966 ui as uimod,
)
from mercurial.i18n import (
gettext,
_,
)
Kyle Lippincott
py3: fix broken man page generation, it was generating `(default: NUL*)`...
r45509 from mercurial.utils import stringutil
Pulkit Goyal
py3: make gendoc use absolute_import...
r28966
table = commands.table
globalopts = commands.globalopts
helptable = help.helptable
loaddoc = help.loaddoc
Benoit Boissinot
generate hg manpage from commands.py docstring...
r1814
Augie Fackler
formatting: blacken the codebase...
r43346
Benoit Boissinot
generate hg manpage from commands.py docstring...
r1814 def get_desc(docstr):
if not docstr:
Matt Harbison
py3: byteify gendoc.py...
r41040 return b"", b""
Benoit Boissinot
generate hg manpage from commands.py docstring...
r1814 # sanitize
Matt Harbison
py3: byteify gendoc.py...
r41040 docstr = docstr.strip(b"\n")
Benoit Boissinot
generate hg manpage from commands.py docstring...
r1814 docstr = docstr.rstrip()
shortdesc = docstr.splitlines()[0].strip()
Matt Harbison
py3: byteify gendoc.py...
r41040 i = docstr.find(b"\n")
Benoit Boissinot
generate hg manpage from commands.py docstring...
r1814 if i != -1:
Augie Fackler
formatting: blacken the codebase...
r43346 desc = docstr[i + 2 :]
Benoit Boissinot
generate hg manpage from commands.py docstring...
r1814 else:
Erik Zielke
gendoc: dedent documentation from docstrings...
r12780 desc = shortdesc
Matt Harbison
py3: byteify gendoc.py...
r41040 desc = textwrap.dedent(desc.decode('latin1')).encode('latin1')
Erik Zielke
gendoc: dedent documentation from docstrings...
r12780
Benoit Boissinot
generate hg manpage from commands.py docstring...
r1814 return (shortdesc, desc)
Augie Fackler
formatting: blacken the codebase...
r43346
Benoit Boissinot
generate hg manpage from commands.py docstring...
r1814 def get_opts(opts):
FUJIWARA Katsunori
help: show value requirement and multiple occurrence of options...
r11321 for opt in opts:
if len(opt) == 5:
shortopt, longopt, default, desc, optlabel = opt
else:
shortopt, longopt, default, desc = opt
Matt Harbison
py3: byteify gendoc.py...
r41040 optlabel = _(b"VALUE")
Benoit Boissinot
generate hg manpage from commands.py docstring...
r1814 allopts = []
if shortopt:
Matt Harbison
py3: byteify gendoc.py...
r41040 allopts.append(b"-%s" % shortopt)
Benoit Boissinot
generate hg manpage from commands.py docstring...
r1814 if longopt:
Matt Harbison
py3: byteify gendoc.py...
r41040 allopts.append(b"--%s" % longopt)
FUJIWARA Katsunori
doc: show details of command options in pages generated by docutils...
r20081 if isinstance(default, list):
Matt Harbison
py3: byteify gendoc.py...
r41040 allopts[-1] += b" <%s[+]>" % optlabel
FUJIWARA Katsunori
doc: show details of command options in pages generated by docutils...
r20081 elif (default is not None) and not isinstance(default, bool):
Matt Harbison
py3: byteify gendoc.py...
r41040 allopts[-1] += b" <%s>" % optlabel
if b'\n' in desc:
Simon Heimberg
doc: gendoc.py creates valid output for option descriptions with newlines...
r20655 # only remove line breaks and indentation
Matt Harbison
py3: byteify gendoc.py...
r41040 desc = b' '.join(l.lstrip() for l in desc.split(b'\n'))
Kyle Lippincott
gendoc: support defaults on customopts a bit better...
r47266 if isinstance(default, fancyopts.customopt):
default = default.getdefaultvalue()
Kyle Lippincott
py3: fix broken man page generation, it was generating `(default: NUL*)`...
r45509 if default:
default = stringutil.forcebytestr(default)
desc += _(b" (default: %s)") % default
Matt Harbison
py3: byteify gendoc.py...
r41040 yield (b", ".join(allopts), desc)
Benoit Boissinot
generate hg manpage from commands.py docstring...
r1814
Augie Fackler
formatting: blacken the codebase...
r43346
Erik Zielke
gendoc: refactor get_cmd...
r12756 def get_cmd(cmd, cmdtable):
Benoit Boissinot
generate hg manpage from commands.py docstring...
r1814 d = {}
Erik Zielke
gendoc: refactor get_cmd...
r12756 attr = cmdtable[cmd]
Matt Harbison
py3: byteify gendoc.py...
r41040 cmds = cmd.lstrip(b"^").split(b"|")
Benoit Boissinot
generate hg manpage from commands.py docstring...
r1814
Matt Harbison
py3: byteify gendoc.py...
r41040 d[b'cmd'] = cmds[0]
d[b'aliases'] = cmd.split(b"|")[1:]
d[b'desc'] = get_desc(gettext(pycompat.getdoc(attr[0])))
d[b'opts'] = list(get_opts(attr[1]))
Matt Mackall
doc: handle shortened command synopses
r7376
Matt Harbison
py3: byteify gendoc.py...
r41040 s = b'hg ' + cmds[0]
Matt Mackall
doc: handle shortened command synopses
r7376 if len(attr) > 2:
Matt Harbison
py3: byteify gendoc.py...
r41040 if not attr[2].startswith(b'hg'):
s += b' ' + attr[2]
Matt Mackall
doc: handle shortened command synopses
r7376 else:
s = attr[2]
Matt Harbison
py3: byteify gendoc.py...
r41040 d[b'synopsis'] = s.strip()
Matt Mackall
doc: handle shortened command synopses
r7376
Benoit Boissinot
generate hg manpage from commands.py docstring...
r1814 return d
Augie Fackler
formatting: blacken the codebase...
r43346
Takumi IINO
gendoc: rename to showdoc from show_doc...
r19423 def showdoc(ui):
Benoit Boissinot
generate hg manpage from commands.py docstring...
r1814 # print options
Matt Harbison
py3: byteify gendoc.py...
r41040 ui.write(minirst.section(_(b"Options")))
FUJIWARA Katsunori
doc: show details of command options in pages generated by docutils...
r20081 multioccur = False
Benoit Boissinot
generate hg manpage from commands.py docstring...
r1814 for optstr, desc in get_opts(globalopts):
Matt Harbison
py3: byteify gendoc.py...
r41040 ui.write(b"%s\n %s\n\n" % (optstr, desc))
if optstr.endswith(b"[+]>"):
FUJIWARA Katsunori
doc: show details of command options in pages generated by docutils...
r20081 multioccur = True
if multioccur:
Matt Harbison
py3: byteify gendoc.py...
r41040 ui.write(_(b"\n[+] marked option can be specified multiple times\n"))
ui.write(b"\n")
Benoit Boissinot
generate hg manpage from commands.py docstring...
r1814
# print cmds
Matt Harbison
py3: byteify gendoc.py...
r41040 ui.write(minirst.section(_(b"Commands")))
Sietse Brouwer
gendoc: nest command headers under category headers...
r42438 commandprinter(ui, table, minirst.subsection, minirst.subsubsection)
Erik Zielke
gendoc: refactor get_cmd...
r12756
Takumi IINO
gendoc: extract print help topics into a dedicated function...
r19233 # print help topics
# The config help topic is included in the hgrc.5 man page.
Matt Harbison
py3: byteify gendoc.py...
r41040 helpprinter(ui, helptable, minirst.section, exclude=[b'config'])
Erik Zielke
gendoc: refactor get_cmd...
r12756
Matt Harbison
py3: byteify gendoc.py...
r41040 ui.write(minirst.section(_(b"Extensions")))
Augie Fackler
formatting: blacken the codebase...
r43346 ui.write(
_(
b"This section contains help for extensions that are "
b"distributed together with Mercurial. Help for other "
b"extensions is available in the help system."
)
)
ui.write(
(
b"\n\n"
b".. contents::\n"
b" :class: htmlonly\n"
b" :local:\n"
b" :depth: 1\n\n"
)
)
Erik Zielke
gendoc: automatically create help for default extensions....
r12781
for extensionname in sorted(allextensionnames()):
Jun Wu
mercurial: pass ui to extensions.load (issue5007)...
r27660 mod = extensions.load(ui, extensionname, None)
Dan Villiom Podlaski Christiansen
help: use a full header for topic titles...
r18748 ui.write(minirst.subsection(extensionname))
Matt Harbison
py3: byteify gendoc.py...
r41040 ui.write(b"%s\n\n" % gettext(pycompat.getdoc(mod)))
Erik Zielke
gendoc: automatically create help for default extensions....
r12781 cmdtable = getattr(mod, 'cmdtable', None)
if cmdtable:
Matt Harbison
py3: byteify gendoc.py...
r41040 ui.write(minirst.subsubsection(_(b'Commands')))
Augie Fackler
formatting: blacken the codebase...
r43346 commandprinter(
ui,
cmdtable,
minirst.subsubsubsection,
minirst.subsubsubsubsection,
)
Erik Zielke
gendoc: automatically create help for default extensions....
r12781
Takumi IINO
gendoc: add showtopic...
r19424 def showtopic(ui, topic):
extrahelptable = [
Matt Harbison
py3: byteify gendoc.py...
r41040 ([b"common"], b'', loaddoc(b'common'), help.TOPIC_CATEGORY_MISC),
([b"hg.1"], b'', loaddoc(b'hg.1'), help.TOPIC_CATEGORY_CONFIG),
([b"hg-ssh.8"], b'', loaddoc(b'hg-ssh.8'), help.TOPIC_CATEGORY_CONFIG),
Augie Fackler
formatting: blacken the codebase...
r43346 (
[b"hgignore.5"],
b'',
loaddoc(b'hgignore.5'),
help.TOPIC_CATEGORY_CONFIG,
),
Matt Harbison
py3: byteify gendoc.py...
r41040 ([b"hgrc.5"], b'', loaddoc(b'hgrc.5'), help.TOPIC_CATEGORY_CONFIG),
Augie Fackler
formatting: blacken the codebase...
r43346 (
[b"hgignore.5.gendoc"],
b'',
loaddoc(b'hgignore'),
help.TOPIC_CATEGORY_CONFIG,
),
(
[b"hgrc.5.gendoc"],
b'',
loaddoc(b'config'),
help.TOPIC_CATEGORY_CONFIG,
),
Takumi IINO
gendoc: add showtopic...
r19424 ]
helpprinter(ui, helptable + extrahelptable, None, include=[topic])
Augie Fackler
formatting: blacken the codebase...
r43346
Takumi IINO
gendoc: extract print help topics into a dedicated function...
r19233 def helpprinter(ui, helptable, sectionfunc, include=[], exclude=[]):
rdamazio@google.com
help: adding support for command categories...
r40327 for h in helptable:
names, sec, doc = h[0:3]
Takumi IINO
gendoc: extract print help topics into a dedicated function...
r19233 if exclude and names[0] in exclude:
continue
if include and names[0] not in include:
continue
for name in names:
Matt Harbison
py3: byteify gendoc.py...
r41040 ui.write(b".. _%s:\n" % name)
ui.write(b"\n")
Takumi IINO
gendoc: extract print help topics into a dedicated function...
r19233 if sectionfunc:
ui.write(sectionfunc(sec))
Augie Fackler
gendoc: restore use of callable() since it was readded in Python 3.2
r21793 if callable(doc):
Yuya Nishihara
help: pass around ui to doc loader (API)...
r26413 doc = doc(ui)
Takumi IINO
gendoc: extract print help topics into a dedicated function...
r19233 ui.write(doc)
Matt Harbison
py3: byteify gendoc.py...
r41040 ui.write(b"\n")
Takumi IINO
gendoc: extract print help topics into a dedicated function...
r19233
Augie Fackler
formatting: blacken the codebase...
r43346
Sietse Brouwer
gendoc: nest command headers under category headers...
r42438 def commandprinter(ui, cmdtable, sectionfunc, subsectionfunc):
"""Render restructuredtext describing a list of commands and their
documentations, grouped by command category.
Args:
ui: UI object to write the output to
cmdtable: a dict that maps a string of the command name plus its aliases
(separated with pipes) to a 3-tuple of (the command's function, a list
of its option descriptions, and a string summarizing available
options). Example, with aliases added for demonstration purposes:
'phase|alias1|alias2': (
<function phase at 0x7f0816b05e60>,
[ ('p', 'public', False, 'set changeset phase to public'),
...,
('r', 'rev', [], 'target revision', 'REV')],
'[-p|-d|-s] [-f] [-r] [REV...]'
)
sectionfunc: minirst function to format command category headers
subsectionfunc: minirst function to format command headers
"""
Benoit Boissinot
generate hg manpage from commands.py docstring...
r1814 h = {}
Erik Zielke
gendoc: refactor get_cmd...
r12756 for c, attr in cmdtable.items():
Matt Harbison
py3: byteify gendoc.py...
r41040 f = c.split(b"|")[0]
f = f.lstrip(b"^")
Christian Ebert
gendoc: fix indentation
r6488 h[f] = c
Benoit Boissinot
generate hg manpage from commands.py docstring...
r1814 cmds = h.keys()
Sietse Brouwer
gendoc: group commands by category in man page and HTML help...
r42435 def helpcategory(cmd):
"""Given a canonical command name from `cmds` (above), retrieve its
help category. If helpcategory is None, default to CATEGORY_NONE.
"""
fullname = h[cmd]
details = cmdtable[fullname]
helpcategory = details[0].helpcategory
return helpcategory or help.registrar.command.CATEGORY_NONE
Sietse Brouwer
gendoc: guarantee that all commands were processed...
r42436 cmdsbycategory = {category: [] for category in help.CATEGORY_ORDER}
for cmd in cmds:
# If a command category wasn't registered, the command won't get
# rendered below, so we raise an AssertionError.
if helpcategory(cmd) not in cmdsbycategory:
raise AssertionError(
"The following command did not register its (category) in "
Augie Fackler
formatting: blacken the codebase...
r43346 "help.CATEGORY_ORDER: %s (%s)" % (cmd, helpcategory(cmd))
)
Sietse Brouwer
gendoc: guarantee that all commands were processed...
r42436 cmdsbycategory[helpcategory(cmd)].append(cmd)
Sietse Brouwer
gendoc: group commands by category in man page and HTML help...
r42435 # Print the help for each command. We present the commands grouped by
# category, and we use help.CATEGORY_ORDER as a guide for a helpful order
# in which to present the categories.
for category in help.CATEGORY_ORDER:
categorycmds = cmdsbycategory[category]
if not categorycmds:
# Skip empty categories
continue
# Print a section header for the category.
# For now, the category header is at the same level as the headers for
# the commands in the category; this is fixed in the next commit.
ui.write(sectionfunc(help.CATEGORY_NAMES[category]))
# Print each command in the category
for f in sorted(categorycmds):
Sietse Brouwer
gendoc: indent loop to make next patch more legible...
r42434 if f.startswith(b"debug"):
continue
d = get_cmd(h[f], cmdtable)
Sietse Brouwer
gendoc: nest command headers under category headers...
r42438 ui.write(subsectionfunc(d[b'cmd']))
Sietse Brouwer
gendoc: indent loop to make next patch more legible...
r42434 # short description
ui.write(d[b'desc'][0])
Martin Geisler
gendoc: support multi-line synopses
r12813 # synopsis
Sietse Brouwer
gendoc: indent loop to make next patch more legible...
r42434 ui.write(b"::\n\n")
synopsislines = d[b'synopsis'].splitlines()
for line in synopsislines:
# some commands (such as rebase) have a multi-line
# synopsis
ui.write(b" %s\n" % line)
ui.write(b'\n')
# description
ui.write(b"%s\n\n" % d[b'desc'][1])
# options
opt_output = list(d[b'opts'])
if opt_output:
opts_len = max([len(line[0]) for line in opt_output])
ui.write(_(b"Options:\n\n"))
multioccur = False
for optstr, desc in opt_output:
if desc:
s = b"%-*s %s" % (opts_len, optstr, desc)
else:
s = optstr
ui.write(b"%s\n" % s)
if optstr.endswith(b"[+]>"):
multioccur = True
if multioccur:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.write(
_(
b"\n[+] marked option can be specified"
b" multiple times\n"
)
)
Sietse Brouwer
gendoc: indent loop to make next patch more legible...
r42434 ui.write(b"\n")
# aliases
if d[b'aliases']:
ui.write(_(b" aliases: %s\n\n") % b" ".join(d[b'aliases']))
Benoit Boissinot
generate hg manpage from commands.py docstring...
r1814
Augie Fackler
formatting: blacken the codebase...
r43346
Erik Zielke
gendoc: automatically create help for default extensions....
r12781 def allextensionnames():
Matt Harbison
py3: byteify gendoc.py...
r41040 return set(extensions.enabled().keys()) | set(extensions.disabled().keys())
Erik Zielke
gendoc: automatically create help for default extensions....
r12781
Augie Fackler
formatting: blacken the codebase...
r43346
Benoit Boissinot
generate hg manpage from commands.py docstring...
r1814 if __name__ == "__main__":
Matt Harbison
py3: byteify gendoc.py...
r41040 doc = b'hg.1.gendoc'
Takumi IINO
gendoc: dispatch print document content by commandline arguments...
r19425 if len(sys.argv) > 1:
Matt Harbison
py3: byteify sys.argv in gendoc.py
r41059 doc = encoding.strtolocal(sys.argv[1])
Takumi IINO
gendoc: dispatch print document content by commandline arguments...
r19425
Yuya Nishihara
ui: factor out ui.load() to create a ui without loading configs (API)...
r30559 ui = uimod.ui.load()
Kyle Lippincott
gendoc: add support for loading extensions from config settings...
r47267 # Trigger extensions to load. This is disabled by default because it uses
# the current user's configuration, which is often not what is wanted.
if encoding.environ.get(b'GENDOC_LOAD_CONFIGURED_EXTENSIONS', b'0') != b'0':
extensions.loadall(ui)
Matt Harbison
py3: byteify gendoc.py...
r41040 if doc == b'hg.1.gendoc':
Yuya Nishihara
gendoc: use real ui in place of stdout...
r26412 showdoc(ui)
Takumi IINO
gendoc: dispatch print document content by commandline arguments...
r19425 else:
Matt Harbison
py3: byteify one more sys.argv in gendoc.py
r41066 showtopic(ui, encoding.strtolocal(sys.argv[1]))