Update CLI Reference generation tool for RST
To migrate CLI Reference from DockBook to RST, output the documentation in RST format, with a few work around for RST/Sphinx specific issue. Change-Id: I32b4cfefa978436061d882f7520bbc92c1645b4e Implements: blueprint cli-ref-rst
This commit is contained in:
parent
4925655305
commit
a25b753af2
|
@ -89,6 +89,6 @@ git pull
|
||||||
branch=update_client_$project
|
branch=update_client_$project
|
||||||
git branch --list $branch && git branch -D $branch
|
git branch --list $branch && git branch -D $branch
|
||||||
git checkout -b $branch
|
git checkout -b $branch
|
||||||
mv ../output/ch_cli_${project}_commands.xml doc/cli-reference/generated
|
mv ../output/${project}.rst "doc/cli-reference/source"
|
||||||
version=$($project --version 2>&1)
|
version=$($project --version 2>&1)
|
||||||
git commit -a -m "Update CLI reference for python-${project}client ${version##* }"
|
git commit -a -m "Update CLI reference for python-${project}client ${version##* }"
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import yaml
|
import yaml
|
||||||
|
@ -21,6 +22,7 @@ import yaml
|
||||||
import os_doc_tools
|
import os_doc_tools
|
||||||
|
|
||||||
DEVNULL = open(os.devnull, 'wb')
|
DEVNULL = open(os.devnull, 'wb')
|
||||||
|
MAXLINELENGTH = 78
|
||||||
|
|
||||||
|
|
||||||
def use_help_flag(os_command):
|
def use_help_flag(os_command):
|
||||||
|
@ -33,28 +35,35 @@ def use_help_flag(os_command):
|
||||||
return os_command == "swift" or "-manage" in os_command
|
return os_command == "swift" or "-manage" in os_command
|
||||||
|
|
||||||
|
|
||||||
def quote_xml(line):
|
def quote_rst(line):
|
||||||
"""Convert special characters for XML output."""
|
"""Convert special characters for RST output."""
|
||||||
|
|
||||||
line = line.replace('&', '&').replace('<', '<').replace('>', '>')
|
line = line.replace('\\', '\\\\').replace('`', '\\`').replace('*', '\\*')
|
||||||
|
|
||||||
|
if '--' in line:
|
||||||
|
line = re.sub(r'(--[^ .\'\\]*)', r":option:`\1`", line)
|
||||||
|
# work around for "`--`" at murano
|
||||||
|
line = line.replace('\\`:option:`--`\\`', '```--```')
|
||||||
|
|
||||||
if 'DEPRECATED!' in line:
|
if 'DEPRECATED!' in line:
|
||||||
line = line.replace('DEPRECATED!', '<emphasis>DEPRECATED!</emphasis>')
|
line = line.replace('DEPRECATED!', '**DEPRECATED!**')
|
||||||
elif 'DEPRECATED' in line:
|
elif 'DEPRECATED' in line:
|
||||||
line = line.replace('DEPRECATED', '<emphasis>DEPRECATED</emphasis>')
|
line = line.replace('DEPRECATED', '**DEPRECATED**')
|
||||||
|
|
||||||
if 'env[' in line:
|
if 'env[' in line:
|
||||||
line = line.replace('env[', '<code>env[').replace(']', ']</code>')
|
line = line.replace('env[', '``env[').replace(']', ']``')
|
||||||
|
# work around for "Default=env[...]" at cinder
|
||||||
|
line = line.replace('=``', '= ``')
|
||||||
|
|
||||||
return line
|
return line
|
||||||
|
|
||||||
|
|
||||||
def generate_heading(os_command, api_name, title, os_file):
|
def generate_heading(os_command, api_name, title, os_file):
|
||||||
"""Write DocBook file header.
|
"""Write RST file header.
|
||||||
|
|
||||||
:param os_command: client command to document
|
:param os_command: client command to document
|
||||||
:param api_name: string description of the API of os_command
|
:param api_name: string description of the API of os_command
|
||||||
:param os_file: open filehandle for output of DocBook file
|
:param os_file: open filehandle for output of RST file
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -70,72 +79,41 @@ def generate_heading(os_command, api_name, title, os_file):
|
||||||
|
|
||||||
print("Documenting '%s help (version %s)'" % (os_command, version))
|
print("Documenting '%s help (version %s)'" % (os_command, version))
|
||||||
|
|
||||||
if use_help_flag(os_command):
|
os_file.write(".. ## WARNING ######################################\n")
|
||||||
help_str = "<replaceable>COMMAND</replaceable> <option>--help</option>"
|
os_file.write(".. This file is automatically generated, do not edit\n")
|
||||||
else:
|
os_file.write(".. #################################################\n\n")
|
||||||
help_str = "<option>help</option> <replaceable>COMMAND</replaceable>"
|
format_heading(title, 1, os_file)
|
||||||
|
|
||||||
header1 = """<?xml version=\"1.0\" encoding=\"UTF-8\"?>
|
|
||||||
<chapter xmlns=\"http://docbook.org/ns/docbook\"
|
|
||||||
xmlns:xi=\"http://www.w3.org/2001/XInclude\"
|
|
||||||
xmlns:xlink=\"http://www.w3.org/1999/xlink\"
|
|
||||||
version=\"5.0\"
|
|
||||||
xml:id=\"%(os_command)sclient_commands\">
|
|
||||||
|
|
||||||
<!-- This file is automatically generated, do not edit -->
|
|
||||||
|
|
||||||
<?dbhtml stop-chunking?>
|
|
||||||
|
|
||||||
<title>%(title)s</title>\n"""
|
|
||||||
if os_command == "openstack":
|
|
||||||
header2 = """
|
|
||||||
<para>The <command>%(os_command)s</command> client is a common
|
|
||||||
OpenStack command-line interface (CLI).\n"""
|
|
||||||
else:
|
|
||||||
header2 = """
|
|
||||||
<para>The <command>%(os_command)s</command> client is the command-line
|
|
||||||
interface (CLI) for the %(api_name)s and its extensions.\n"""
|
|
||||||
|
|
||||||
header3 = """
|
|
||||||
This chapter documents <command>%(os_command)s</command> version
|
|
||||||
<literal>%(version)s</literal>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>For help on a specific <command>%(os_command)s</command>
|
|
||||||
command, enter:
|
|
||||||
</para>
|
|
||||||
<screen><prompt>$</prompt> <userinput><command>%(os_command)s</command> \
|
|
||||||
%(help_str)s</userinput></screen>
|
|
||||||
|
|
||||||
<section xml:id=\"%(os_command)sclient_command_usage\">
|
|
||||||
<title>%(os_command)s usage</title>\n"""
|
|
||||||
|
|
||||||
if os_command == "keystone":
|
if os_command == "keystone":
|
||||||
header_deprecation = """
|
os_file.write(".. warning::\n\n")
|
||||||
<warning>
|
os_file.write(" The " + os_command + " CLI is deprecated\n")
|
||||||
<para>The %(os_command)s CLI is deprecated in favor of
|
os_file.write(" in favor of python-openstackclient.\n")
|
||||||
python-openstackclient. For more information on
|
os_file.write(" For more information, see :doc:`openstack`.\n")
|
||||||
python-openstackclient, please see
|
os_file.write(" For a Python library, continue using\n")
|
||||||
<xref linkend="openstack_cli_identity_api_v2" /> and
|
os_file.write(" python-" + os_command + "client.\n\n")
|
||||||
<xref linkend="openstack_cli_with_identity_api_v3" />.
|
|
||||||
For a Python library, continue
|
|
||||||
using python-%(os_command)sclient.</para>
|
|
||||||
</warning>\n"""
|
|
||||||
else:
|
|
||||||
header_deprecation = None
|
|
||||||
|
|
||||||
format_dict = {
|
if os_command == "openstack":
|
||||||
"os_command": os_command,
|
os_file.write("The openstack client is a common OpenStack")
|
||||||
"api_name": api_name,
|
os_file.write("command-line interface (CLI).\n\n")
|
||||||
"title": title,
|
else:
|
||||||
"version": version,
|
os_file.write("The " + os_command + " client is the command-line ")
|
||||||
"help_str": help_str
|
os_file.write("interface (CLI) for\n")
|
||||||
}
|
os_file.write("the " + api_name + " and its extensions.\n\n")
|
||||||
os_file.write(header1 % format_dict)
|
|
||||||
if header_deprecation:
|
os_file.write("This chapter documents :command:`" + os_command + "` ")
|
||||||
os_file.write(header_deprecation % format_dict)
|
os_file.write("version ``" + version + "``.\n\n")
|
||||||
os_file.write(header2 % format_dict)
|
|
||||||
os_file.write(header3 % format_dict)
|
os_file.write("For help on a specific :command:`" + os_command + "` ")
|
||||||
|
os_file.write("command, enter:\n\n")
|
||||||
|
|
||||||
|
os_file.write(".. code-block:: console\n\n")
|
||||||
|
if use_help_flag(os_command):
|
||||||
|
os_file.write(" $ " + os_command + " COMMAND --help\n\n")
|
||||||
|
else:
|
||||||
|
os_file.write(" $ " + os_command + " help COMMAND\n\n")
|
||||||
|
|
||||||
|
os_file.write(".. _" + os_command + "_command_usage:\n\n")
|
||||||
|
format_heading(os_command + " usage", 2, os_file)
|
||||||
|
|
||||||
|
|
||||||
def is_option(string):
|
def is_option(string):
|
||||||
|
@ -233,13 +211,42 @@ def extract_options(line):
|
||||||
return split_line
|
return split_line
|
||||||
|
|
||||||
|
|
||||||
def format_table(title, lines, os_file):
|
def format_heading(heading, level, os_file):
|
||||||
"""Nicely print section of lines."""
|
"""Nicely print heading.
|
||||||
|
|
||||||
|
:param heading: heading strings
|
||||||
|
:param level: heading level
|
||||||
|
:param os_file: open filehandle for output of RST file
|
||||||
|
"""
|
||||||
|
|
||||||
|
if level == 1:
|
||||||
|
os_file.write("=" * len(heading) + "\n")
|
||||||
|
|
||||||
|
os_file.write(heading + "\n")
|
||||||
|
|
||||||
|
if level == 1:
|
||||||
|
os_file.write("=" * len(heading) + "\n\n")
|
||||||
|
elif level == 2:
|
||||||
|
os_file.write("~" * len(heading) + "\n\n")
|
||||||
|
elif level == 3:
|
||||||
|
os_file.write("-" * len(heading) + "\n\n")
|
||||||
|
else:
|
||||||
|
os_file.write("\n")
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def format_help(title, lines, os_file):
|
||||||
|
"""Nicely print section of lines.
|
||||||
|
|
||||||
|
:param title: help title, if exist
|
||||||
|
:param lines: strings to format
|
||||||
|
:param os_file: open filehandle for output of RST file
|
||||||
|
"""
|
||||||
|
|
||||||
close_entry = False
|
close_entry = False
|
||||||
os_file.write(" <variablelist wordsize=\"10\">\n")
|
|
||||||
if title:
|
if title:
|
||||||
os_file.write(" <title>%s</title>\n" % title)
|
format_heading(title, 3, os_file)
|
||||||
|
|
||||||
for line in lines:
|
for line in lines:
|
||||||
if not line or line[0] != ' ':
|
if not line or line[0] != ' ':
|
||||||
|
@ -252,9 +259,13 @@ def format_table(title, lines, os_file):
|
||||||
# on next line
|
# on next line
|
||||||
# If there are more than 8 spaces, let's treat it as
|
# If there are more than 8 spaces, let's treat it as
|
||||||
# explanation.
|
# explanation.
|
||||||
if line.startswith(' '):
|
if line.startswith(' '):
|
||||||
# Explanation
|
# Explanation
|
||||||
os_file.write(" %s\n" % quote_xml(line.lstrip(' ')))
|
xline = quote_rst(line.lstrip(' '))
|
||||||
|
if len(xline) > (MAXLINELENGTH - 2):
|
||||||
|
# check niceness
|
||||||
|
xline = xline.replace(' ', '\n ')
|
||||||
|
os_file.write(" " + xline + "\n")
|
||||||
continue
|
continue
|
||||||
# Now we have a command or parameter to handle
|
# Now we have a command or parameter to handle
|
||||||
split_line = extract_options(line)
|
split_line = extract_options(line)
|
||||||
|
@ -262,31 +273,41 @@ def format_table(title, lines, os_file):
|
||||||
if not close_entry:
|
if not close_entry:
|
||||||
close_entry = True
|
close_entry = True
|
||||||
else:
|
else:
|
||||||
os_file.write(" </para>\n")
|
os_file.write("\n")
|
||||||
os_file.write(" </listitem>\n")
|
|
||||||
os_file.write(" </varlistentry>\n")
|
xline = split_line[0]
|
||||||
|
|
||||||
|
# check niceness work around for long option name
|
||||||
|
if len(xline) > (MAXLINELENGTH - 4):
|
||||||
|
xline = xline.replace(', -', ',``\n\n``-')
|
||||||
|
|
||||||
|
# check niceness work around for long option name, openstack
|
||||||
|
xline = xline.replace('--nic <net-id=net-uuid,v4-fixed-ip',
|
||||||
|
'--nic <net-id=net-uuid,``\n\n``v4-fixed-ip')
|
||||||
|
|
||||||
|
# check niceness work around for long option name, glance
|
||||||
|
xline = xline.replace('--sort-key {name,status,container',
|
||||||
|
'--sort-key {name,status,``\n\n``container')
|
||||||
|
|
||||||
|
os_file.write("``" + xline + "``\n")
|
||||||
|
|
||||||
os_file.write(" <varlistentry>\n")
|
|
||||||
os_file.write(" <term><command>%s</command></term>\n"
|
|
||||||
% quote_xml(split_line[0]))
|
|
||||||
os_file.write(" <listitem>\n")
|
|
||||||
os_file.write(" <para>\n")
|
|
||||||
if len(split_line) > 1:
|
if len(split_line) > 1:
|
||||||
os_file.write(" %s\n" % quote_xml(split_line[1]))
|
xline = quote_rst(split_line[1])
|
||||||
|
if len(xline) > (MAXLINELENGTH - 2):
|
||||||
|
# check niceness
|
||||||
|
xline = xline.replace(' ', '\n ')
|
||||||
|
os_file.write(" " + xline + "\n")
|
||||||
|
|
||||||
os_file.write(" </para>\n")
|
os_file.write("\n")
|
||||||
os_file.write(" </listitem>\n")
|
|
||||||
os_file.write(" </varlistentry>\n")
|
|
||||||
os_file.write(" </variablelist>\n")
|
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
def generate_command(os_command, os_file):
|
def generate_command(os_command, os_file):
|
||||||
"""Convert os_command --help to DocBook.
|
"""Convert os_command --help to RST.
|
||||||
|
|
||||||
:param os_command: client command to document
|
:param os_command: client command to document
|
||||||
:param os_file: open filehandle for output of DocBook file
|
:param os_file: open filehandle for output of RST file
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if os_command == "glance":
|
if os_command == "glance":
|
||||||
|
@ -300,13 +321,11 @@ def generate_command(os_command, os_file):
|
||||||
|
|
||||||
ignore_next_lines = False
|
ignore_next_lines = False
|
||||||
next_line_screen = True
|
next_line_screen = True
|
||||||
next_line_screen = True
|
|
||||||
line_index = -1
|
line_index = -1
|
||||||
in_screen = False
|
in_screen = False
|
||||||
subcommands = 'complete'
|
subcommands = 'complete'
|
||||||
for line in help_lines:
|
for line in help_lines:
|
||||||
line_index += 1
|
line_index += 1
|
||||||
xline = quote_xml(line)
|
|
||||||
if line and line[0] != ' ':
|
if line and line[0] != ' ':
|
||||||
# XXX: Might have whitespace before!!
|
# XXX: Might have whitespace before!!
|
||||||
if '<subcommands>' in line:
|
if '<subcommands>' in line:
|
||||||
|
@ -315,69 +334,52 @@ def generate_command(os_command, os_file):
|
||||||
if 'Positional arguments' in line:
|
if 'Positional arguments' in line:
|
||||||
ignore_next_lines = True
|
ignore_next_lines = True
|
||||||
next_line_screen = True
|
next_line_screen = True
|
||||||
os_file.write("</computeroutput></screen>\n")
|
os_file.write("\n\n")
|
||||||
in_screen = False
|
in_screen = False
|
||||||
if os_command != "glance":
|
if os_command != "glance":
|
||||||
format_table('Subcommands',
|
format_help('Subcommands',
|
||||||
help_lines[line_index + 2:], os_file)
|
help_lines[line_index + 2:], os_file)
|
||||||
continue
|
continue
|
||||||
if line.startswith(('Optional arguments:', 'Optional:',
|
if line.startswith(('Optional arguments:', 'Optional:',
|
||||||
'Options:', 'optional arguments')):
|
'Options:', 'optional arguments')):
|
||||||
if in_screen:
|
if in_screen:
|
||||||
os_file.write("</computeroutput></screen>\n")
|
os_file.write("\n\n")
|
||||||
in_screen = False
|
in_screen = False
|
||||||
os_file.write(" </section>\n")
|
os_file.write(".. _" + os_command + "_command_options:\n\n")
|
||||||
os_file.write(" <section ")
|
format_heading(os_command + " optional arguments", 2, os_file)
|
||||||
os_file.write("xml:id=\"%sclient_command_optional\">\n"
|
format_help('', help_lines[line_index + 1:], os_file)
|
||||||
% os_command)
|
|
||||||
os_file.write(" <title>%s optional arguments</title>\n"
|
|
||||||
% os_command)
|
|
||||||
format_table('', help_lines[line_index + 1:],
|
|
||||||
os_file)
|
|
||||||
next_line_screen = True
|
next_line_screen = True
|
||||||
ignore_next_lines = True
|
ignore_next_lines = True
|
||||||
continue
|
continue
|
||||||
# sahara
|
# magnum and sahara
|
||||||
if line.startswith('Common auth options'):
|
if line.startswith('Common auth options'):
|
||||||
if in_screen:
|
if in_screen:
|
||||||
os_file.write("</computeroutput></screen>\n")
|
os_file.write("\n\n")
|
||||||
in_screen = False
|
in_screen = False
|
||||||
os_file.write(" </section>\n")
|
os_file.write("\n")
|
||||||
os_file.write(" <section ")
|
os_file.write(os_command)
|
||||||
os_file.write("xml:id=\"%sclient_command_common_auth\">\n"
|
os_file.write(".. _" + os_command + "_common_auth:\n\n")
|
||||||
% os_command)
|
format_heading(os_command + " common authentication arguments",
|
||||||
os_file.write(" <title>%s common authentication "
|
2, os_file)
|
||||||
"arguments</title>\n"
|
format_help('', help_lines[line_index + 1:], os_file)
|
||||||
% os_command)
|
|
||||||
format_table('', help_lines[line_index + 1:],
|
|
||||||
os_file)
|
|
||||||
next_line_screen = True
|
next_line_screen = True
|
||||||
ignore_next_lines = True
|
ignore_next_lines = True
|
||||||
continue
|
continue
|
||||||
# neutron
|
# neutron
|
||||||
if line.startswith('Commands for API v2.0:'):
|
if line.startswith('Commands for API v2.0:'):
|
||||||
if in_screen:
|
if in_screen:
|
||||||
os_file.write("</computeroutput></screen>\n")
|
os_file.write("\n\n")
|
||||||
in_screen = False
|
in_screen = False
|
||||||
os_file.write(" </section>\n")
|
os_file.write(".. _" + os_command + "_common_api_v2:\n\n")
|
||||||
os_file.write(" <section ")
|
format_heading(os_command + " API v2.0 commands", 2, os_file)
|
||||||
os_file.write("xml:id=\"%sclient_command_api_2_0\">\n"
|
format_help('', help_lines[line_index + 1:], os_file)
|
||||||
% os_command)
|
|
||||||
os_file.write(" <title>%s API v2.0 commands</title>\n"
|
|
||||||
% os_command)
|
|
||||||
format_table('', help_lines[line_index + 1:],
|
|
||||||
os_file)
|
|
||||||
next_line_screen = True
|
next_line_screen = True
|
||||||
ignore_next_lines = True
|
ignore_next_lines = True
|
||||||
continue
|
continue
|
||||||
# swift
|
# swift
|
||||||
if line.startswith('Examples:'):
|
if line.startswith('Examples:'):
|
||||||
os_file.write(" </section>\n")
|
os_file.write(".. _" + os_command + "_examples:\n\n")
|
||||||
os_file.write(" <section ")
|
format_heading(os_command + " examples", 2, os_file)
|
||||||
os_file.write("xml:id=\"%sclient_command_examples\">\n"
|
|
||||||
% os_command)
|
|
||||||
os_file.write(" <title>%s examples</title>\n"
|
|
||||||
% os_command)
|
|
||||||
next_line_screen = True
|
next_line_screen = True
|
||||||
ignore_next_lines = False
|
ignore_next_lines = False
|
||||||
continue
|
continue
|
||||||
|
@ -385,31 +387,31 @@ def generate_command(os_command, os_file):
|
||||||
continue
|
continue
|
||||||
if not ignore_next_lines:
|
if not ignore_next_lines:
|
||||||
if next_line_screen:
|
if next_line_screen:
|
||||||
os_file.write(" <screen><computeroutput>%s" % xline)
|
os_file.write(".. code-block:: console\n\n")
|
||||||
|
os_file.write(" " + line)
|
||||||
next_line_screen = False
|
next_line_screen = False
|
||||||
in_screen = True
|
in_screen = True
|
||||||
elif line:
|
elif line:
|
||||||
os_file.write("\n%s" % xline.rstrip())
|
os_file.write("\n " + line.rstrip())
|
||||||
# subcommands (select bash-completion, complete for bash-completion)
|
# subcommands (select bash-completion, complete for bash-completion)
|
||||||
if 'bash-completion' in line:
|
if 'bash-completion' in line:
|
||||||
subcommands = 'bash-completion'
|
subcommands = 'bash-completion'
|
||||||
|
|
||||||
if in_screen:
|
if in_screen:
|
||||||
os_file.write("</computeroutput></screen>\n")
|
os_file.write("\n\n")
|
||||||
|
|
||||||
os_file.write(" </section>\n")
|
|
||||||
return subcommands
|
return subcommands
|
||||||
|
|
||||||
|
|
||||||
def generate_subcommand(os_command, os_subcommand, os_file, extra_params,
|
def generate_subcommand(os_command, os_subcommand, os_file, extra_params,
|
||||||
suffix, title_suffix):
|
suffix, title_suffix):
|
||||||
"""Convert os_command help os_subcommand to DocBook.
|
"""Convert os_command help os_subcommand to RST.
|
||||||
|
|
||||||
:param os_command: client command to document
|
:param os_command: client command to document
|
||||||
:param os_subcommand: client subcommand to document
|
:param os_subcommand: client subcommand to document
|
||||||
:param os_file: open filehandle for output of DocBook file
|
:param os_file: open filehandle for output of RST file
|
||||||
:param extra_params: Extra parameter to pass to os_command
|
:param extra_params: Extra parameter to pass to os_command
|
||||||
:param suffix: Extra suffix to add to xml:id
|
:param suffix: Extra suffix to add to link ID
|
||||||
:param title_suffix: Extra suffix for title
|
:param title_suffix: Extra suffix for title
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -440,17 +442,14 @@ def generate_subcommand(os_command, os_subcommand, os_file, extra_params,
|
||||||
help_lines = help_lines.split('\n')
|
help_lines = help_lines.split('\n')
|
||||||
|
|
||||||
os_subcommandid = os_subcommand.replace(' ', '_')
|
os_subcommandid = os_subcommand.replace(' ', '_')
|
||||||
os_file.write(" <section xml:id=\"%sclient_subcommand_%s%s\">\n"
|
os_file.write(".. _" + os_command + "_" + os_subcommandid + suffix)
|
||||||
% (os_command, os_subcommandid, suffix))
|
os_file.write(":\n\n")
|
||||||
os_file.write(" <title>%s %s%s</title>\n"
|
format_heading(os_command + " " + os_subcommand + title_suffix, 2, os_file)
|
||||||
% (os_command, os_subcommand, title_suffix))
|
|
||||||
|
|
||||||
if os_command == "swift":
|
if os_command == "swift":
|
||||||
next_line_screen = False
|
next_line_screen = False
|
||||||
os_file.write("\n <screen><computeroutput>Usage: swift %s"
|
os_file.write(".. code-block:: console\n\n")
|
||||||
"</computeroutput></screen>"
|
os_file.write("Usage: swift " + os_subcommand + "\n\n")
|
||||||
% (os_subcommand))
|
|
||||||
os_file.write("\n <para>")
|
|
||||||
in_para = True
|
in_para = True
|
||||||
else:
|
else:
|
||||||
next_line_screen = True
|
next_line_screen = True
|
||||||
|
@ -477,39 +476,47 @@ def generate_subcommand(os_command, os_subcommand, os_file, extra_params,
|
||||||
'optional arguments')):
|
'optional arguments')):
|
||||||
if in_para:
|
if in_para:
|
||||||
in_para = False
|
in_para = False
|
||||||
os_file.write("\n </para>")
|
os_file.write("\n")
|
||||||
if line.startswith(('Positional arguments',
|
if line.startswith(('Positional arguments',
|
||||||
'positional arguments')):
|
'positional arguments')):
|
||||||
format_table('Positional arguments',
|
format_help('Positional arguments',
|
||||||
help_lines[line_index + 1:], os_file)
|
help_lines[line_index + 1:], os_file)
|
||||||
skip_lines = True
|
skip_lines = True
|
||||||
continue
|
continue
|
||||||
elif line.startswith(('Optional arguments:',
|
elif line.startswith(('Optional arguments:',
|
||||||
'optional arguments')):
|
'optional arguments')):
|
||||||
format_table('Optional arguments',
|
format_help('Optional arguments',
|
||||||
help_lines[line_index + 1:], os_file)
|
help_lines[line_index + 1:], os_file)
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
format_table('Arguments', help_lines[line_index + 1:], os_file)
|
format_help('Arguments', help_lines[line_index + 1:], os_file)
|
||||||
break
|
break
|
||||||
if skip_lines:
|
if skip_lines:
|
||||||
continue
|
continue
|
||||||
if not line:
|
if not line:
|
||||||
if not in_para:
|
if not in_para:
|
||||||
os_file.write("</computeroutput></screen>")
|
os_file.write("\n")
|
||||||
os_file.write("\n <para>")
|
|
||||||
in_para = True
|
in_para = True
|
||||||
continue
|
continue
|
||||||
xline = quote_xml(line)
|
|
||||||
if next_line_screen:
|
if next_line_screen:
|
||||||
os_file.write(" <screen><computeroutput>%s" % xline)
|
os_file.write(".. code-block:: console\n\n")
|
||||||
|
os_file.write(" " + line + "\n")
|
||||||
next_line_screen = False
|
next_line_screen = False
|
||||||
|
elif line.startswith(' '):
|
||||||
|
# ceilometer alarm-gnocchi-aggregation-by-metrics-threshold-create
|
||||||
|
# has 7 white space indentation
|
||||||
|
if not line.isspace():
|
||||||
|
# skip blank line, such as "trove help cluster-grow" command.
|
||||||
|
os_file.write(" " + line + "\n")
|
||||||
else:
|
else:
|
||||||
os_file.write("\n%s" % (xline))
|
xline = quote_rst(line)
|
||||||
|
if (len(xline) > MAXLINELENGTH):
|
||||||
|
# check niceness
|
||||||
|
xline = xline.replace(' ', '\n')
|
||||||
|
os_file.write(xline + "\n")
|
||||||
|
|
||||||
if in_para:
|
if in_para:
|
||||||
os_file.write("\n </para>\n")
|
os_file.write("\n")
|
||||||
os_file.write(" </section>\n")
|
|
||||||
|
|
||||||
|
|
||||||
def discover_subcommands(os_command, subcommands, extra_params):
|
def discover_subcommands(os_command, subcommands, extra_params):
|
||||||
|
@ -558,14 +565,14 @@ def discover_subcommands(os_command, subcommands, extra_params):
|
||||||
|
|
||||||
def generate_subcommands(os_command, os_file, subcommands, extra_params,
|
def generate_subcommands(os_command, os_file, subcommands, extra_params,
|
||||||
suffix, title_suffix):
|
suffix, title_suffix):
|
||||||
"""Convert os_command help subcommands for all subcommands to DocBook.
|
"""Convert os_command help subcommands for all subcommands to RST.
|
||||||
|
|
||||||
:param os_command: client command to document
|
:param os_command: client command to document
|
||||||
:param os_file: open filehandle for output of DocBook file
|
:param os_file: open filehandle for output of RST file
|
||||||
:param subcommands: list or type ('complete' or 'bash-completion')
|
:param subcommands: list or type ('complete' or 'bash-completion')
|
||||||
of subcommands to document
|
of subcommands to document
|
||||||
:param extra_params: Extra parameter to pass to os_command.
|
:param extra_params: Extra parameter to pass to os_command.
|
||||||
:param suffix: Extra suffix to add to xml:id
|
:param suffix: Extra suffix to add to link ID
|
||||||
:param title_suffix: Extra suffix for title
|
:param title_suffix: Extra suffix for title
|
||||||
"""
|
"""
|
||||||
for subcommand in subcommands:
|
for subcommand in subcommands:
|
||||||
|
@ -576,14 +583,14 @@ def generate_subcommands(os_command, os_file, subcommands, extra_params,
|
||||||
|
|
||||||
def discover_and_generate_subcommands(os_command, os_file, subcommands,
|
def discover_and_generate_subcommands(os_command, os_file, subcommands,
|
||||||
extra_params, suffix, title_suffix):
|
extra_params, suffix, title_suffix):
|
||||||
"""Convert os_command help subcommands for all subcommands to DocBook.
|
"""Convert os_command help subcommands for all subcommands to RST.
|
||||||
|
|
||||||
:param os_command: client command to document
|
:param os_command: client command to document
|
||||||
:param os_file: open filehandle for output of DocBook file
|
:param os_file: open filehandle for output of RST file
|
||||||
:param subcommands: list or type ('complete' or 'bash-completion')
|
:param subcommands: list or type ('complete' or 'bash-completion')
|
||||||
of subcommands to document
|
of subcommands to document
|
||||||
:param extra_params: Extra parameter to pass to os_command.
|
:param extra_params: Extra parameter to pass to os_command.
|
||||||
:param suffix: Extra suffix to add to xml:id
|
:param suffix: Extra suffix to add to link ID
|
||||||
:param title_suffix: Extra suffix for title
|
:param title_suffix: Extra suffix for title
|
||||||
"""
|
"""
|
||||||
subcommands = discover_subcommands(os_command, subcommands, extra_params)
|
subcommands = discover_subcommands(os_command, subcommands, extra_params)
|
||||||
|
@ -591,16 +598,6 @@ def discover_and_generate_subcommands(os_command, os_file, subcommands,
|
||||||
suffix, title_suffix)
|
suffix, title_suffix)
|
||||||
|
|
||||||
|
|
||||||
def generate_end(os_file):
|
|
||||||
"""Finish writing file.
|
|
||||||
|
|
||||||
:param os_file: open filehandle for output of DocBook file
|
|
||||||
"""
|
|
||||||
|
|
||||||
print("Finished.\n")
|
|
||||||
os_file.write("</chapter>\n")
|
|
||||||
|
|
||||||
|
|
||||||
def get_clients():
|
def get_clients():
|
||||||
"""Load client definitions from the resource file."""
|
"""Load client definitions from the resource file."""
|
||||||
fname = os.path.join(os.path.dirname(__file__),
|
fname = os.path.join(os.path.dirname(__file__),
|
||||||
|
@ -628,21 +625,18 @@ def document_single_project(os_command, output_dir):
|
||||||
api_name = ''
|
api_name = ''
|
||||||
title = data.get('title', '')
|
title = data.get('title', '')
|
||||||
|
|
||||||
out_filename = "ch_cli_" + os_command + "_commands.xml"
|
out_filename = os_command + ".rst"
|
||||||
out_file = open(os.path.join(output_dir, out_filename), 'w')
|
out_file = open(os.path.join(output_dir, out_filename), 'w')
|
||||||
generate_heading(os_command, api_name, title, out_file)
|
generate_heading(os_command, api_name, title, out_file)
|
||||||
subcommands = generate_command(os_command, out_file)
|
subcommands = generate_command(os_command, out_file)
|
||||||
|
|
||||||
if os_command == 'cinder':
|
if os_command == 'cinder':
|
||||||
out_file.write("""
|
format_heading("Block Storage API v1 commands (DEPRECATED)",
|
||||||
<section xml:id=\"cinder_cli_v1\">
|
2, out_file)
|
||||||
<title>Block Storage API v1 commands (DEPRECATED)</title>\n""")
|
|
||||||
discover_and_generate_subcommands(os_command, out_file, subcommands,
|
discover_and_generate_subcommands(os_command, out_file, subcommands,
|
||||||
None, "", "")
|
None, "", "")
|
||||||
elif os_command == 'openstack':
|
elif os_command == 'openstack':
|
||||||
out_file.write("""
|
format_heading("OpenStack with Identity API v2 commands", 2, out_file)
|
||||||
<section xml:id=\"openstack_cli_identity_api_v2\">
|
|
||||||
<title>OpenStack with Identity API v2 commands</title>\n""")
|
|
||||||
auth_type_token = ["--os-auth-type", "token"]
|
auth_type_token = ["--os-auth-type", "token"]
|
||||||
identity_api_v2 = ["--os-identity-api-version", "2"]
|
identity_api_v2 = ["--os-identity-api-version", "2"]
|
||||||
extra_params = auth_type_token + identity_api_v2
|
extra_params = auth_type_token + identity_api_v2
|
||||||
|
@ -651,9 +645,7 @@ def document_single_project(os_command, output_dir):
|
||||||
generate_subcommands(os_command, out_file, subcommands_v2,
|
generate_subcommands(os_command, out_file, subcommands_v2,
|
||||||
extra_params, "_with_identity_api_v2", "")
|
extra_params, "_with_identity_api_v2", "")
|
||||||
elif os_command == 'glance':
|
elif os_command == 'glance':
|
||||||
out_file.write("""
|
format_heading("Image service API v1 commands", 2, out_file)
|
||||||
<section xml:id=\"glance_cli_v1\">
|
|
||||||
<title>Image service API v1 commands</title>\n""")
|
|
||||||
discover_and_generate_subcommands(os_command, out_file, subcommands,
|
discover_and_generate_subcommands(os_command, out_file, subcommands,
|
||||||
["--os-image-api-version", "1"],
|
["--os-image-api-version", "1"],
|
||||||
"_v1", " (v1)")
|
"_v1", " (v1)")
|
||||||
|
@ -663,40 +655,37 @@ def document_single_project(os_command, output_dir):
|
||||||
|
|
||||||
# Print subcommands for different API versions
|
# Print subcommands for different API versions
|
||||||
if os_command == 'cinder':
|
if os_command == 'cinder':
|
||||||
out_file.write(" </section>\n")
|
out_file.write("\n")
|
||||||
out_file.write("""
|
format_heading("Block Storage API v2 commands", 2, out_file)
|
||||||
<section xml:id=\"cinder_cli_v2\">
|
|
||||||
<title>Block Storage API v2 commands</title>
|
out_file.write("You can select an API version to use by adding the\n")
|
||||||
<para>
|
out_file.write(":option:`--os-volume-api-version` parameter or by\n")
|
||||||
You can select an API version to use by adding the
|
out_file.write("setting the corresponding environment variable:\n\n")
|
||||||
<parameter>--os-volume-api-version</parameter> parameter or by setting
|
|
||||||
the corresponding environment variable:\n""")
|
out_file.write(".. code-block:: console\n\n")
|
||||||
out_file.write("<screen><prompt>$</prompt> <userinput>"
|
out_file.write(" export OS_VOLUME_API_VERSION=2\n\n")
|
||||||
"export OS_VOLUME_API_VERSION=2</userinput></screen>\n"
|
|
||||||
"</para>\n")
|
|
||||||
|
|
||||||
discover_and_generate_subcommands(os_command, out_file, subcommands,
|
discover_and_generate_subcommands(os_command, out_file, subcommands,
|
||||||
["--os-volume-api-version", "2"],
|
["--os-volume-api-version", "2"],
|
||||||
"_v2", " (v2)")
|
"_v2", " (v2)")
|
||||||
out_file.write(" </section>\n")
|
|
||||||
if os_command == 'openstack':
|
if os_command == 'openstack':
|
||||||
# Print the additional subcommands possible by using v3 of identity API
|
# Print the additional subcommands possible by using v3 of identity API
|
||||||
out_file.write("""
|
out_file.write("\n")
|
||||||
</section>\n
|
format_heading("OpenStack with Identity API v3 commands (diff)",
|
||||||
<section xml:id=\"openstack_cli_with_identity_api_v3\">
|
2, out_file)
|
||||||
<title>OpenStack with Identity API v3 commands (diff)</title>
|
|
||||||
<para>
|
out_file.write("You can select the Identity API version to use by\n")
|
||||||
You can select the Identity API version to use by adding the
|
out_file.write("adding the :option:`--os-identity-api-version`\n")
|
||||||
<parameter>--os-identity-api-version</parameter> parameter or by setting
|
out_file.write("parameter or by setting the corresponding\n")
|
||||||
the corresponding environment variable:\n""")
|
out_file.write("environment variable:\n\n")
|
||||||
out_file.write("<screen><prompt>$</prompt> <userinput>"
|
|
||||||
"export OS_IDENTITY_API_VERSION=3</userinput>"
|
out_file.write(".. code-block:: console\n\n")
|
||||||
"</screen>\n</para>\n")
|
out_file.write(" export OS_IDENTITY_API_VERSION=3\n\n")
|
||||||
out_file.write("<para>\n"
|
|
||||||
"This section documents only the difference in"
|
out_file.write("This section documents only the difference in\n")
|
||||||
" subcommands available for the openstack client when"
|
out_file.write("subcommands available for the openstack client\n")
|
||||||
" the identity API version is changed from v2 to v3.\n"
|
out_file.write("when the Identity API version is changed from\n")
|
||||||
"</para>\n")
|
out_file.write("v2 to v3.\n\n")
|
||||||
|
|
||||||
identity_api_v3 = ["--os-identity-api-version", "3"]
|
identity_api_v3 = ["--os-identity-api-version", "3"]
|
||||||
extra_params = auth_type_token + identity_api_v3
|
extra_params = auth_type_token + identity_api_v3
|
||||||
|
@ -707,30 +696,24 @@ def document_single_project(os_command, output_dir):
|
||||||
generate_subcommands(os_command, out_file, subcommands_delta,
|
generate_subcommands(os_command, out_file, subcommands_delta,
|
||||||
extra_params, "_with_identity_api_v3",
|
extra_params, "_with_identity_api_v3",
|
||||||
" (Identity API v3)")
|
" (Identity API v3)")
|
||||||
out_file.write(" </section>\n")
|
|
||||||
if os_command == 'glance':
|
if os_command == 'glance':
|
||||||
out_file.write("""
|
out_file.write("\n")
|
||||||
</section>\n
|
format_heading("Image service API v2 commands", 2, out_file)
|
||||||
<section xml:id=\"glance_cli_v2\">
|
out_file.write("You can select an API version to use by adding the\n")
|
||||||
<title>Image service API v2 commands</title>
|
out_file.write(":option:`--os-image-api-version` parameter or by\n")
|
||||||
<para>
|
out_file.write("setting the corresponding environment variable:\n\n")
|
||||||
You can select an API version to use by adding the
|
|
||||||
<parameter>--os-image-api-version</parameter> parameter or by setting
|
out_file.write(".. code-block:: console\n\n")
|
||||||
the corresponding environment variable:\n""")
|
out_file.write(" export OS_IMAGE_API_VERSION=2\n\n")
|
||||||
out_file.write("<screen><prompt>$</prompt> <userinput>"
|
|
||||||
"export OS_IMAGE_API_VERSION=2</userinput></screen>\n"
|
|
||||||
"</para>\n")
|
|
||||||
|
|
||||||
discover_and_generate_subcommands(os_command, out_file, subcommands,
|
discover_and_generate_subcommands(os_command, out_file, subcommands,
|
||||||
["--os-image-api-version", "2"],
|
["--os-image-api-version", "2"],
|
||||||
"_v2", " (v2)")
|
"_v2", " (v2)")
|
||||||
out_file.write(" </section>\n")
|
|
||||||
|
|
||||||
if os_command == 'glance':
|
if os_command == 'glance':
|
||||||
out_file.write(" <xi:include "
|
out_file.write(".. include:: glance_property_keys.rst\n")
|
||||||
"href=\"../section_cli_glance_property_keys.xml\"/>\n")
|
|
||||||
|
|
||||||
generate_end(out_file)
|
print("Finished.\n")
|
||||||
out_file.close()
|
out_file.close()
|
||||||
|
|
||||||
|
|
||||||
|
@ -744,7 +727,7 @@ def main():
|
||||||
manage_clients = sorted([x for x in clients if x.endswith('-manage')])
|
manage_clients = sorted([x for x in clients if x.endswith('-manage')])
|
||||||
all_clients = api_clients + manage_clients
|
all_clients = api_clients + manage_clients
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="Generate DocBook XML files "
|
parser = argparse.ArgumentParser(description="Generate RST files "
|
||||||
"to document python-PROJECTclients.")
|
"to document python-PROJECTclients.")
|
||||||
parser.add_argument('client', nargs='?',
|
parser.add_argument('client', nargs='?',
|
||||||
help="OpenStack command to document. One of: " +
|
help="OpenStack command to document. One of: " +
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
features:
|
||||||
|
- Update CLI Reference generation tool for RST.
|
||||||
|
To migrate CLI Reference from DocBook to RST,
|
||||||
|
output the documentation in RST format,
|
||||||
|
with a few work arounds for RST/Sphinx specific issues.
|
Loading…
Reference in New Issue