2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-22 18:08:16 +00:00
kea/tools/reorder_message_file.py

197 lines
5.2 KiB
Python
Raw Permalink Normal View History

#!/usr/bin/env python3
[#3287] fix pycodestyle warnings - E111 indentation is not a multiple of 4 - E117 over-indented - E125 continuation line with same indent as next logical line - E127 continuation line over-indented for visual indent - E128 continuation line under-indented for visual indent - E129 visually indented line with same indent as next logical line - E131 continuation line unaligned for hanging indent - E201 whitespace after '[' - E201 whitespace after '{' - E202 whitespace before ')' - E202 whitespace before ']' - E202 whitespace before '}' - E203 whitespace before ' - E203 whitespace before ',' - E222 multiple spaces after operator - E225 missing whitespace around operator - E228 missing whitespace around modulo operator - E231 missing whitespace after ',' - E251 unexpected spaces around keyword / parameter equals - E261 at least two spaces before inline comment - E262 inline comment should start with '# ' - E265 block comment should start with '# ' - E301 expected 1 blank line, found 0 - E302 expected 2 blank lines, found 1 - E303 too many blank lines (2) - E305 expected 2 blank lines after class or function definition, found 1 - E306 expected 1 blank line before a nested definition, found 0 - E401 multiple imports on one line - E402 module level import not at top of file - E501 line too long - E502 the backslash is redundant between brackets - E703 statement ends with a semicolon - E713 test for membership should be 'not in' - E722 do not use bare 'except' - E741 ambiguous variable name 'l' - W605 invalid escape sequence '\/'
2024-06-06 15:41:10 +03:00
# Copyright (C) 2011-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/.
# Reorder Message File
#
# Reads a message file into memory, then outputs it with the messages and
# associated descriptions in alphabetical order.
#
# Invocation:
# The code is invoked using the command line:
#
# python reorder.py message_file
#
# Output is written to stdout.
import sys
[#3287] fix pycodestyle warnings - E111 indentation is not a multiple of 4 - E117 over-indented - E125 continuation line with same indent as next logical line - E127 continuation line over-indented for visual indent - E128 continuation line under-indented for visual indent - E129 visually indented line with same indent as next logical line - E131 continuation line unaligned for hanging indent - E201 whitespace after '[' - E201 whitespace after '{' - E202 whitespace before ')' - E202 whitespace before ']' - E202 whitespace before '}' - E203 whitespace before ' - E203 whitespace before ',' - E222 multiple spaces after operator - E225 missing whitespace around operator - E228 missing whitespace around modulo operator - E231 missing whitespace after ',' - E251 unexpected spaces around keyword / parameter equals - E261 at least two spaces before inline comment - E262 inline comment should start with '# ' - E265 block comment should start with '# ' - E301 expected 1 blank line, found 0 - E302 expected 2 blank lines, found 1 - E303 too many blank lines (2) - E305 expected 2 blank lines after class or function definition, found 1 - E306 expected 1 blank line before a nested definition, found 0 - E401 multiple imports on one line - E402 module level import not at top of file - E501 line too long - E502 the backslash is redundant between brackets - E703 statement ends with a semicolon - E713 test for membership should be 'not in' - E722 do not use bare 'except' - E741 ambiguous variable name 'l' - W605 invalid escape sequence '\/'
2024-06-06 15:41:10 +03:00
2011-12-07 16:26:47 +00:00
def remove_empty_leading_trailing(lines):
"""
Removes leading and trailing empty lines.
A list of strings is passed as argument, some of which may be empty.
This function removes from the start and end of the list a contiguous
sequence of empty lines and returns the result. Embedded sequences of
empty lines are not touched.
Parameters:
lines List of strings to be modified.
Return:
Input list of strings with leading/trailing blank line sequences
removed.
"""
retlines = []
# Dispose of degenerate case of empty array
if len(lines) == 0:
return retlines
# Search for first non-blank line
start = 0
while start < len(lines):
if len(lines[start]) > 0:
break
start = start + 1
# Handle case when entire list is empty
if start >= len(lines):
return retlines
# Search for last non-blank line
finish = len(lines) - 1
while finish >= 0:
if len(lines[finish]) > 0:
break
finish = finish - 1
retlines = lines[start:finish + 1]
return retlines
def canonicalise_message_line(line):
"""
Given a line known to start with the '%' character (i.e. a line
introducing a message), canonicalise it by ensuring that the result
is of the form '%<single-space>MESSAGE_IDENTIFIER<single-space>text'.
Parameters:
line - input line. Known to start with a '%' and to have leading
and trailing spaces removed.
Return:
Canonicalised line.
"""
# Cope with degenerate case of a single "%"
if len(line) == 1:
return line
# Get the rest of the line
line = line[1:].lstrip()
# Extract the first word (the message ID)
words = line.split()
message_line = "% " + words[0]
# ... and now the rest of the line
if len(line) > len(words[0]):
message_line = message_line + " " + line[len(words[0]):].lstrip()
return message_line
def make_dict(lines):
"""
Split the lines into segments starting with the message definition and
place into a dictionary.
Parameters:
lines - list of lines containing the text of the message file (less the
header).
Returns:
dictionary - map of the messages, keyed by the line that holds the message
ID.
"""
dictionary = {}
message_key = canonicalise_message_line(lines[0])
message_lines = [message_key]
[#3287] fix pycodestyle warnings - E111 indentation is not a multiple of 4 - E117 over-indented - E125 continuation line with same indent as next logical line - E127 continuation line over-indented for visual indent - E128 continuation line under-indented for visual indent - E129 visually indented line with same indent as next logical line - E131 continuation line unaligned for hanging indent - E201 whitespace after '[' - E201 whitespace after '{' - E202 whitespace before ')' - E202 whitespace before ']' - E202 whitespace before '}' - E203 whitespace before ' - E203 whitespace before ',' - E222 multiple spaces after operator - E225 missing whitespace around operator - E228 missing whitespace around modulo operator - E231 missing whitespace after ',' - E251 unexpected spaces around keyword / parameter equals - E261 at least two spaces before inline comment - E262 inline comment should start with '# ' - E265 block comment should start with '# ' - E301 expected 1 blank line, found 0 - E302 expected 2 blank lines, found 1 - E303 too many blank lines (2) - E305 expected 2 blank lines after class or function definition, found 1 - E306 expected 1 blank line before a nested definition, found 0 - E401 multiple imports on one line - E402 module level import not at top of file - E501 line too long - E502 the backslash is redundant between brackets - E703 statement ends with a semicolon - E713 test for membership should be 'not in' - E722 do not use bare 'except' - E741 ambiguous variable name 'l' - W605 invalid escape sequence '\/'
2024-06-06 15:41:10 +03:00
index = 1
while index < len(lines):
if lines[index].startswith("%"):
# Start of new message
2011-12-07 16:26:47 +00:00
dictionary[message_key] = remove_empty_leading_trailing(message_lines)
message_key = canonicalise_message_line(lines[index])
message_lines = [message_key]
else:
message_lines.append(lines[index])
index = index + 1
2011-12-07 16:26:47 +00:00
dictionary[message_key] = remove_empty_leading_trailing(message_lines)
return dictionary
def print_dict(dictionary):
"""
Prints the dictionary with a blank line between entries.
Parameters:
dictionary - Map holding the message dictionary
"""
count = 0
for msgid in sorted(dictionary):
# Blank line before all entries but the first
if count > 0:
print("")
count = count + 1
# ... and the entry itself.
[#3287] fix pycodestyle warnings - E111 indentation is not a multiple of 4 - E117 over-indented - E125 continuation line with same indent as next logical line - E127 continuation line over-indented for visual indent - E128 continuation line under-indented for visual indent - E129 visually indented line with same indent as next logical line - E131 continuation line unaligned for hanging indent - E201 whitespace after '[' - E201 whitespace after '{' - E202 whitespace before ')' - E202 whitespace before ']' - E202 whitespace before '}' - E203 whitespace before ' - E203 whitespace before ',' - E222 multiple spaces after operator - E225 missing whitespace around operator - E228 missing whitespace around modulo operator - E231 missing whitespace after ',' - E251 unexpected spaces around keyword / parameter equals - E261 at least two spaces before inline comment - E262 inline comment should start with '# ' - E265 block comment should start with '# ' - E301 expected 1 blank line, found 0 - E302 expected 2 blank lines, found 1 - E303 too many blank lines (2) - E305 expected 2 blank lines after class or function definition, found 1 - E306 expected 1 blank line before a nested definition, found 0 - E401 multiple imports on one line - E402 module level import not at top of file - E501 line too long - E502 the backslash is redundant between brackets - E703 statement ends with a semicolon - E713 test for membership should be 'not in' - E722 do not use bare 'except' - E741 ambiguous variable name 'l' - W605 invalid escape sequence '\/'
2024-06-06 15:41:10 +03:00
for line in dictionary[msgid]:
print(line.strip())
2011-12-07 16:26:47 +00:00
def process_file(filename):
"""
Processes a file by reading it and searching for the first line starting
with the '%' sign. Everything before that line is treated as the file
header and is copied to the output with leading and trailing spaces removed.
After that, each message block is read and stored for later sorting.
Parameters:
filename Name of the message file to process
"""
[#3287] fix pylint warnings - C0115: Missing class docstring (missing-class-docstring) - C0123: Use isinstance() rather than type() for a typecheck. (unidiomatic-typecheck) - C0201: Consider iterating the dictionary directly instead of calling .keys() (consider-iterating-dictionary) - C0206: Consider iterating with .items() (consider-using-dict-items) - C0411: standard import "..." should be placed before "..." (wrong-import-order) - C0415: Import outside toplevel (...) (import-outside-toplevel) - C1802: Do not use `len(SEQUENCE)` without comparison to determine if a sequence is empty (use-implicit-booleaness-not-len) - E0001: Parsing failed: 'invalid syntax (<unknown>, line 2313)' (syntax-error) - E0401: Unable to import '...' (import-error) - E0602: Undefined variable 'l' (undefined-variable) - R0205: Class 'VagrantEnv' inherits from object, can be safely removed from bases in python3 (useless-object-inheritance) - E1101: Instance of 'NSECBASE' has no 'dump_fixedpart' member (no-member) - E1123: Unexpected keyword argument 'capture' in method call (unexpected-keyword-arg) - R0902: Too many instance attributes (too-many-instance-attributes) - R0913: Too many arguments (too-many-arguments) - R0916: Too many boolean expressions in if statement (6/5) (too-many-boolean-expressions) - R1717: Consider using a dictionary comprehension (consider-using-dict-comprehension) - R1722: Consider using 'sys.exit' instead (consider-using-sys-exit) - R1732: Consider using 'with' for resource-allocating operations (consider-using-with) - R1735: Consider using '{}' instead of a call to 'dict'. (use-dict-literal) - W0102: Dangerous default value sys.argv[1:] (builtins.list) as argument (dangerous-default-value) - W0102: Dangerous default value {} as argument (dangerous-default-value) - W0106: Expression "[f.write('%02x' % x) for x in bin_address]" is assigned to nothing (expression-not-assigned) - W0107: Unnecessary pass statement (unnecessary-pass) - W0201: Attribute 'config' defined outside __init__ (attribute-defined-outside-init) - W0404: Reimport '...' (imported line ...) (reimported) - W0611: Unused import ... (unused-import) - W0612: Unused variable '...' (unused-variable) - W0613: Unused argument '...' (unused-argument) - W0621: Redefining name '...' from outer scope (line 1471) (redefined-outer-name) - W0622: Redefining built-in '...' (redefined-builtin) - W0707: Consider explicitly re-raising using 'raise ... from ...' (raise-missing-from) - W0718: Catching too general exception Exception (broad-exception-caught) - W1202: Use lazy % formatting in logging functions (logging-format-interpolation) - W1203: Use lazy % formatting in logging functions (logging-fstring-interpolation) - W1308: Duplicate string formatting argument 'connection_type', consider passing as named argument (duplicate-string-formatting-argument) - W1401: Anomalous backslash in string: '\/'. String constant might be missing an r prefix. (anomalous-backslash-in-string) - W1406: The u prefix for strings is no longer necessary in Python >=3.0 (redundant-u-string-prefix) - W1514: Using open without explicitly specifying an encoding (unspecified-encoding) - W4901: Deprecated module 'optparse' (deprecated-module) - W4904: Using deprecated class SafeConfigParser of module configparser (deprecated-class)
2024-06-07 11:43:43 +03:00
with open(filename, encoding='utf-8') as f:
lines = f.read().splitlines()
2024-09-22 18:35:59 +00:00
# Do not process the file if it is empty.
if len(lines) == 0:
return
# Search for the first line starting with the percent character. Everything
# before it is considered the file header and is copied to the output with
# leading and trailing spaces removed.
index = 0
while index < len(lines):
if lines[index].startswith("%"):
break
print(lines[index].strip())
index = index + 1
# Now put the remaining lines into the message dictionary
dictionary = make_dict(lines[index:])
# ...and print it
print_dict(dictionary)
# Main program
if __name__ == "__main__":
# Read the files and load the data
if len(sys.argv) != 2:
print("Usage: python reorder.py message_file")
else:
2011-12-07 16:26:47 +00:00
process_file(sys.argv[1])