2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-22 18:08:16 +00:00
kea/doc/sphinx/mes2doc.py
2025-05-30 09:24:25 +00:00

175 lines
5.0 KiB
Python
Executable File

#!/usr/bin/env python3
# Copyright (C) 2019-2024 Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http:#mozilla.org/MPL/2.0/.
# Produce System Messages Manual
#
# This tool reads all the message files given on the command line.
# It pulls all the messages and description out, sorts them by
# message ID, and writes them out as a single (formatted) file.
#
# Invocation:
# The code is invoked using the command line:
#
# mes2doc.py [-o <output-file>] <files>
#
# If no output file is specified, output is written to stdout.
# The produced format is ReStructuredText.
import argparse
import os
import pathlib
import re
import sys
def parse_args():
parser = argparse.ArgumentParser(description='Convert set of *.mes files to .rst documentation format')
parser.add_argument('-o', '--output', help='Output file name (default to stdout).')
parser.add_argument('files', help='Input .mes files.', nargs='?')
args = parser.parse_args()
return args
def read_input_files(files):
messages = {}
for f in files:
if '/premium/' in f and not pathlib.Path(f).is_file():
# Premium can be missing which is fine for daily development, and CI tasks.
print(f'Ignoring non-existing file {f}')
continue
with open(f, encoding='utf-8') as fp:
print(f'Processing {f}')
msg_descr = None
msg_id = None
msg_text = None
for line in fp.readlines():
line = line.strip()
if not line or line.startswith('#'):
pass
elif line.startswith('//'):
pass
elif line.startswith('$'):
pass
elif line.startswith('%'):
# end previous message
if msg_id is not None:
section = msg_id.split('_')[0]
messages[msg_id] = (section, msg_id, msg_text, msg_descr)
# start next message
m = re.search(r'^%\s?([A-Z0-9_]+)\s+(.*)', line)
msg_id, msg_text = m.groups()
msg_descr = []
else:
msg_descr.append(line)
if msg_id is not None:
section = msg_id.split('_')[0]
messages[msg_id] = (section, msg_id, msg_text, msg_descr)
return messages
def generate_rst(messages):
rst = '..\n'
rst += ' File generated by "doc/sphinx/mes2doc.py" or by "make -C doc/sphinx". Do not edit by hand.\n\n'
rst += '''.. _kea-messages:
###################
Kea Messages Manual
###################
Kea is an open source implementation of the Dynamic Host Configuration
Protocol (DHCP) servers, developed and maintained by Internet Systems
Consortium (ISC).
This is the reference guide for Kea version |release|.
Links to the most up-to-date version of this document (in PDF, HTML,
and plain text formats), along with other useful information about
Kea, can be found in ISC's `Knowledgebase <https://kea.readthedocs.io>`_.
Please note that in the messages below, the percent sign (``%``) followed by a number is
used to indicate a placeholder for data that is provided by the Kea code during its operation.
.. toctree::
:numbered:
:maxdepth: 5
'''
prev_section = None
for _, msg in sorted(messages.items()):
section, msg_id, msg_text, msg_descr = msg
if section != prev_section:
prev_section = section
rst += '*' * len(section) + '\n'
rst += section + '\n'
rst += '*' * len(section) + '\n'
rst += '\n'
rst += msg_id + '\n'
rst += '=' * len(msg_id) + '\n'
rst += '\n'
rst += '.. code-block:: text\n'
rst += '\n'
rst += ' ' + msg_text + '\n'
rst += '\n'
rst += ''.join([line + '\n' for line in msg_descr])
rst += '\n'
rst += '''.. _kea-debug-messages:
*******************************
Kea Debug Messages By Log Level
*******************************
'''
rst += '.. include:: debug-messages.rst'
rst += '\n'
return rst
def generate(in_files, out_file):
messages = read_input_files(in_files)
rst = generate_rst(messages)
if out_file:
with open(out_file, 'w', encoding='utf-8') as f:
f.write(rst)
print('Wrote generated RST content to: %s' % out_file)
else:
print(rst)
def main():
args = parse_args()
if args.files is None:
parent_dir = os.path.dirname(os.path.realpath(os.path.abspath(sys.argv[0])))
mes_files = sorted(pathlib.Path(f'{parent_dir}/../..').glob('**/*.mes'))
# Convert from Path to str.
mes_files = [str(i) for i in mes_files]
else:
mes_files = args.files
generate(mes_files, args.output)
if __name__ == '__main__':
main()