2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-24 18:57:41 +00:00
kea/tools/reorder_message_file.py
Andrei Pavel 9c35a4db68
[#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-20 18:52:09 +03:00

191 lines
5.1 KiB
Python

# 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
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]
index = 1
while index < len(lines):
if lines[index].startswith("%"):
# Start of new message
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
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.
for line in dictionary[msgid]:
print(line.strip())
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
"""
with open(filename, encoding='utf-8') as f:
lines = f.read().splitlines()
# 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:
process_file(sys.argv[1])