doc/check-seclevel.py
changeset 43076 2372284d9457
parent 41355 77763dc5b07b
child 43080 86e4daa2d54c
equal deleted inserted replaced
43075:57875cf423c9 43076:2372284d9457
     9 import sys
     9 import sys
    10 
    10 
    11 # import from the live mercurial repo
    11 # import from the live mercurial repo
    12 os.environ['HGMODULEPOLICY'] = 'py'
    12 os.environ['HGMODULEPOLICY'] = 'py'
    13 sys.path.insert(0, "..")
    13 sys.path.insert(0, "..")
    14 from mercurial import demandimport; demandimport.enable()
    14 from mercurial import demandimport
       
    15 
       
    16 demandimport.enable()
    15 from mercurial import (
    17 from mercurial import (
    16     commands,
    18     commands,
    17     extensions,
    19     extensions,
    18     help,
    20     help,
    19     minirst,
    21     minirst,
    34 initlevel_topic = 0
    36 initlevel_topic = 0
    35 initlevel_cmd = 1
    37 initlevel_cmd = 1
    36 initlevel_ext = 1
    38 initlevel_ext = 1
    37 initlevel_ext_cmd = 3
    39 initlevel_ext_cmd = 3
    38 
    40 
       
    41 
    39 def showavailables(ui, initlevel):
    42 def showavailables(ui, initlevel):
    40     avail = ('    available marks and order of them in this help: %s\n') % (
    43     avail = '    available marks and order of them in this help: %s\n' % (
    41         ', '.join(['%r' % (m * 4) for m in level2mark[initlevel + 1:]]))
    44         ', '.join(['%r' % (m * 4) for m in level2mark[initlevel + 1 :]])
       
    45     )
    42     ui.warn(avail.encode('utf-8'))
    46     ui.warn(avail.encode('utf-8'))
    43 
    47 
       
    48 
    44 def checkseclevel(ui, doc, name, initlevel):
    49 def checkseclevel(ui, doc, name, initlevel):
    45     ui.note(('checking "%s"\n') % name)
    50     ui.note('checking "%s"\n' % name)
    46     if not isinstance(doc, bytes):
    51     if not isinstance(doc, bytes):
    47         doc = doc.encode('utf-8')
    52         doc = doc.encode('utf-8')
    48     blocks, pruned = minirst.parse(doc, 0, ['verbose'])
    53     blocks, pruned = minirst.parse(doc, 0, ['verbose'])
    49     errorcnt = 0
    54     errorcnt = 0
    50     curlevel = initlevel
    55     curlevel = initlevel
    52         if block[b'type'] != b'section':
    57         if block[b'type'] != b'section':
    53             continue
    58             continue
    54         mark = block[b'underline']
    59         mark = block[b'underline']
    55         title = block[b'lines'][0]
    60         title = block[b'lines'][0]
    56         if (mark not in mark2level) or (mark2level[mark] <= initlevel):
    61         if (mark not in mark2level) or (mark2level[mark] <= initlevel):
    57             ui.warn((('invalid section mark %r for "%s" of %s\n') %
    62             ui.warn(
    58                      (mark * 4, title, name)).encode('utf-8'))
    63                 (
       
    64                     'invalid section mark %r for "%s" of %s\n'
       
    65                     % (mark * 4, title, name)
       
    66                 ).encode('utf-8')
       
    67             )
    59             showavailables(ui, initlevel)
    68             showavailables(ui, initlevel)
    60             errorcnt += 1
    69             errorcnt += 1
    61             continue
    70             continue
    62         nextlevel = mark2level[mark]
    71         nextlevel = mark2level[mark]
    63         if curlevel < nextlevel and curlevel + 1 != nextlevel:
    72         if curlevel < nextlevel and curlevel + 1 != nextlevel:
    64             ui.warn(('gap of section level at "%s" of %s\n') %
    73             ui.warn('gap of section level at "%s" of %s\n' % (title, name))
    65                     (title, name))
       
    66             showavailables(ui, initlevel)
    74             showavailables(ui, initlevel)
    67             errorcnt += 1
    75             errorcnt += 1
    68             continue
    76             continue
    69         ui.note(('appropriate section level for "%s %s"\n') %
    77         ui.note(
    70                 (mark * (nextlevel * 2), title))
    78             'appropriate section level for "%s %s"\n'
       
    79             % (mark * (nextlevel * 2), title)
       
    80         )
    71         curlevel = nextlevel
    81         curlevel = nextlevel
    72 
    82 
    73     return errorcnt
    83     return errorcnt
       
    84 
    74 
    85 
    75 def checkcmdtable(ui, cmdtable, namefmt, initlevel):
    86 def checkcmdtable(ui, cmdtable, namefmt, initlevel):
    76     errorcnt = 0
    87     errorcnt = 0
    77     for k, entry in cmdtable.items():
    88     for k, entry in cmdtable.items():
    78         name = k.split(b"|")[0].lstrip(b"^")
    89         name = k.split(b"|")[0].lstrip(b"^")
    79         if not entry[0].__doc__:
    90         if not entry[0].__doc__:
    80             ui.note(('skip checking %s: no help document\n') %
    91             ui.note('skip checking %s: no help document\n' % (namefmt % name))
    81                     (namefmt % name))
    92             continue
    82             continue
    93         errorcnt += checkseclevel(
    83         errorcnt += checkseclevel(ui, entry[0].__doc__,
    94             ui, entry[0].__doc__, namefmt % name, initlevel
    84                                   namefmt % name,
    95         )
    85                                   initlevel)
       
    86     return errorcnt
    96     return errorcnt
       
    97 
    87 
    98 
    88 def checkhghelps(ui):
    99 def checkhghelps(ui):
    89     errorcnt = 0
   100     errorcnt = 0
    90     for h in helptable:
   101     for h in helptable:
    91         names, sec, doc = h[0:3]
   102         names, sec, doc = h[0:3]
    92         if callable(doc):
   103         if callable(doc):
    93             doc = doc(ui)
   104             doc = doc(ui)
    94         errorcnt += checkseclevel(ui, doc,
   105         errorcnt += checkseclevel(
    95                                   '%s help topic' % names[0],
   106             ui, doc, '%s help topic' % names[0], initlevel_topic
    96                                   initlevel_topic)
   107         )
    97 
   108 
    98     errorcnt += checkcmdtable(ui, table, '%s command', initlevel_cmd)
   109     errorcnt += checkcmdtable(ui, table, '%s command', initlevel_cmd)
    99 
   110 
   100     for name in sorted(list(extensions.enabled()) +
   111     for name in sorted(
   101                        list(extensions.disabled())):
   112         list(extensions.enabled()) + list(extensions.disabled())
       
   113     ):
   102         mod = extensions.load(ui, name, None)
   114         mod = extensions.load(ui, name, None)
   103         if not mod.__doc__:
   115         if not mod.__doc__:
   104             ui.note(('skip checking %s extension: no help document\n') % name)
   116             ui.note('skip checking %s extension: no help document\n' % name)
   105             continue
   117             continue
   106         errorcnt += checkseclevel(ui, mod.__doc__,
   118         errorcnt += checkseclevel(
   107                                   '%s extension' % name,
   119             ui, mod.__doc__, '%s extension' % name, initlevel_ext
   108                                   initlevel_ext)
   120         )
   109 
   121 
   110         cmdtable = getattr(mod, 'cmdtable', None)
   122         cmdtable = getattr(mod, 'cmdtable', None)
   111         if cmdtable:
   123         if cmdtable:
   112             errorcnt += checkcmdtable(ui, cmdtable,
   124             errorcnt += checkcmdtable(
   113                                       '%%s command of %s extension' % name,
   125                 ui,
   114                                       initlevel_ext_cmd)
   126                 cmdtable,
       
   127                 '%%s command of %s extension' % name,
       
   128                 initlevel_ext_cmd,
       
   129             )
   115     return errorcnt
   130     return errorcnt
       
   131 
   116 
   132 
   117 def checkfile(ui, filename, initlevel):
   133 def checkfile(ui, filename, initlevel):
   118     if filename == '-':
   134     if filename == '-':
   119         filename = 'stdin'
   135         filename = 'stdin'
   120         doc = sys.stdin.read()
   136         doc = sys.stdin.read()
   121     else:
   137     else:
   122         with open(filename) as fp:
   138         with open(filename) as fp:
   123             doc = fp.read()
   139             doc = fp.read()
   124 
   140 
   125     ui.note(('checking input from %s with initlevel %d\n') %
   141     ui.note(
   126             (filename, initlevel))
   142         'checking input from %s with initlevel %d\n' % (filename, initlevel)
       
   143     )
   127     return checkseclevel(ui, doc, 'input from %s' % filename, initlevel)
   144     return checkseclevel(ui, doc, 'input from %s' % filename, initlevel)
   128 
   145 
       
   146 
   129 def main():
   147 def main():
   130     optparser = optparse.OptionParser("""%prog [options]
   148     optparser = optparse.OptionParser(
       
   149         """%prog [options]
   131 
   150 
   132 This checks all help documents of Mercurial (topics, commands,
   151 This checks all help documents of Mercurial (topics, commands,
   133 extensions and commands of them), if no file is specified by --file
   152 extensions and commands of them), if no file is specified by --file
   134 option.
   153 option.
   135 """)
   154 """
   136     optparser.add_option("-v", "--verbose",
   155     )
   137                          help="enable additional output",
   156     optparser.add_option(
   138                          action="store_true")
   157         "-v", "--verbose", help="enable additional output", action="store_true"
   139     optparser.add_option("-d", "--debug",
   158     )
   140                          help="debug mode",
   159     optparser.add_option(
   141                          action="store_true")
   160         "-d", "--debug", help="debug mode", action="store_true"
   142     optparser.add_option("-f", "--file",
   161     )
   143                          help="filename to read in (or '-' for stdin)",
   162     optparser.add_option(
   144                          action="store", default="")
   163         "-f",
   145 
   164         "--file",
   146     optparser.add_option("-t", "--topic",
   165         help="filename to read in (or '-' for stdin)",
   147                          help="parse file as help topic",
   166         action="store",
   148                          action="store_const", dest="initlevel", const=0)
   167         default="",
   149     optparser.add_option("-c", "--command",
   168     )
   150                          help="parse file as help of core command",
   169 
   151                          action="store_const", dest="initlevel", const=1)
   170     optparser.add_option(
   152     optparser.add_option("-e", "--extension",
   171         "-t",
   153                          help="parse file as help of extension",
   172         "--topic",
   154                          action="store_const", dest="initlevel", const=1)
   173         help="parse file as help topic",
   155     optparser.add_option("-C", "--extension-command",
   174         action="store_const",
   156                          help="parse file as help of extension command",
   175         dest="initlevel",
   157                          action="store_const", dest="initlevel", const=3)
   176         const=0,
   158 
   177     )
   159     optparser.add_option("-l", "--initlevel",
   178     optparser.add_option(
   160                          help="set initial section level manually",
   179         "-c",
   161                          action="store", type="int", default=0)
   180         "--command",
       
   181         help="parse file as help of core command",
       
   182         action="store_const",
       
   183         dest="initlevel",
       
   184         const=1,
       
   185     )
       
   186     optparser.add_option(
       
   187         "-e",
       
   188         "--extension",
       
   189         help="parse file as help of extension",
       
   190         action="store_const",
       
   191         dest="initlevel",
       
   192         const=1,
       
   193     )
       
   194     optparser.add_option(
       
   195         "-C",
       
   196         "--extension-command",
       
   197         help="parse file as help of extension command",
       
   198         action="store_const",
       
   199         dest="initlevel",
       
   200         const=3,
       
   201     )
       
   202 
       
   203     optparser.add_option(
       
   204         "-l",
       
   205         "--initlevel",
       
   206         help="set initial section level manually",
       
   207         action="store",
       
   208         type="int",
       
   209         default=0,
       
   210     )
   162 
   211 
   163     (options, args) = optparser.parse_args()
   212     (options, args) = optparser.parse_args()
   164 
   213 
   165     ui = uimod.ui.load()
   214     ui = uimod.ui.load()
   166     ui.setconfig(b'ui', b'verbose', options.verbose, b'--verbose')
   215     ui.setconfig(b'ui', b'verbose', options.verbose, b'--verbose')
   171             sys.exit(1)
   220             sys.exit(1)
   172     else:
   221     else:
   173         if checkhghelps(ui):
   222         if checkhghelps(ui):
   174             sys.exit(1)
   223             sys.exit(1)
   175 
   224 
       
   225 
   176 if __name__ == "__main__":
   226 if __name__ == "__main__":
   177     main()
   227     main()