Use standard code instead of the homemade FileWrapper

We had a home-made FileWrapper class, written in the days of Python 2,
whose main purpose was to add line numbers. Use the standard class fileinput
instead.

Signed-off-by: Gilles Peskine <[email protected]>
This commit is contained in:
Gilles Peskine
2024-11-05 18:00:43 +01:00
parent 612ccb7217
commit cb27d4f7a2
2 changed files with 27 additions and 68 deletions
+21 -68
View File
@@ -151,11 +151,12 @@ __MBEDTLS_TEST_TEMPLATE__PLATFORM_CODE
""" """
import argparse
import fileinput
import os import os
import re import re
import sys
import string import string
import argparse import sys
# Types recognized as signed integer arguments in test functions. # Types recognized as signed integer arguments in test functions.
@@ -228,57 +229,9 @@ class GeneratorInputError(Exception):
pass pass
class FileWrapper: def read_file(file_name: str) -> fileinput.FileInput:
""" return fileinput.input([file_name],
This class extends the file object with attribute line_no, openhook=fileinput.hook_encoded('utf-8'))
that indicates line number for the line that is read.
"""
def __init__(self, file_name) -> None:
"""
Instantiate the file object and initialize the line number to 0.
:param file_name: File path to open.
"""
# private mix-in file object
self._f = open(file_name, 'rb')
self._line_no = 0
def __iter__(self):
return self
def __next__(self):
"""
This method makes FileWrapper iterable.
It counts the line numbers as each line is read.
:return: Line read from file.
"""
line = self._f.__next__()
self._line_no += 1
# Convert byte array to string with correct encoding and
# strip any whitespaces added in the decoding process.
return line.decode(sys.getdefaultencoding()).rstrip()+ '\n'
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self._f.__exit__(exc_type, exc_val, exc_tb)
@property
def line_no(self):
"""
Property that indicates line number for the line that is read.
"""
return self._line_no
@property
def name(self):
"""
Property that indicates name of the file that is read.
"""
return self._f.name
def split_dep(dep): def split_dep(dep):
@@ -393,14 +346,14 @@ def parse_until_pattern(funcs_f, end_regex):
:param end_regex: Pattern to stop parsing :param end_regex: Pattern to stop parsing
:return: Lines read before the end pattern :return: Lines read before the end pattern
""" """
headers = '#line %d "%s"\n' % (funcs_f.line_no + 1, funcs_f.name) headers = '#line %d "%s"\n' % (funcs_f.lineno() + 1, funcs_f.filename())
for line in funcs_f: for line in funcs_f:
if re.search(end_regex, line): if re.search(end_regex, line):
break break
headers += line headers += line
else: else:
raise GeneratorInputError("file: %s - end pattern [%s] not found!" % raise GeneratorInputError("file: %s - end pattern [%s] not found!" %
(funcs_f.name, end_regex)) (funcs_f.filename(), end_regex))
return headers return headers
@@ -450,12 +403,12 @@ def parse_suite_dependencies(funcs_f):
dependencies = parse_dependencies(match.group('dependencies')) dependencies = parse_dependencies(match.group('dependencies'))
except GeneratorInputError as error: except GeneratorInputError as error:
raise GeneratorInputError( raise GeneratorInputError(
str(error) + " - %s:%d" % (funcs_f.name, funcs_f.line_no)) str(error) + " - %s:%d" % (funcs_f.filename(), funcs_f.lineno()))
if re.search(END_DEP_REGEX, line): if re.search(END_DEP_REGEX, line):
break break
else: else:
raise GeneratorInputError("file: %s - end dependency pattern [%s]" raise GeneratorInputError("file: %s - end dependency pattern [%s]"
" not found!" % (funcs_f.name, " not found!" % (funcs_f.filename(),
END_DEP_REGEX)) END_DEP_REGEX))
return dependencies return dependencies
@@ -639,7 +592,7 @@ def parse_function_code(funcs_f, dependencies, suite_dependencies):
:param suite_dependencies: List of test suite dependencies :param suite_dependencies: List of test suite dependencies
:return: Function name, arguments, function code and dispatch code. :return: Function name, arguments, function code and dispatch code.
""" """
line_directive = '#line %d "%s"\n' % (funcs_f.line_no + 1, funcs_f.name) line_directive = '#line %d "%s"\n' % (funcs_f.lineno() + 1, funcs_f.filename())
code = '' code = ''
has_exit_label = False has_exit_label = False
for line in funcs_f: for line in funcs_f:
@@ -666,7 +619,7 @@ def parse_function_code(funcs_f, dependencies, suite_dependencies):
code += line code += line
else: else:
raise GeneratorInputError("file: %s - Test functions not found!" % raise GeneratorInputError("file: %s - Test functions not found!" %
funcs_f.name) funcs_f.filename())
# Make the test function static # Make the test function static
code = code.replace('void', 'static void', 1) code = code.replace('void', 'static void', 1)
@@ -689,7 +642,7 @@ def parse_function_code(funcs_f, dependencies, suite_dependencies):
code += line code += line
else: else:
raise GeneratorInputError("file: %s - end case pattern [%s] not " raise GeneratorInputError("file: %s - end case pattern [%s] not "
"found!" % (funcs_f.name, END_CASE_REGEX)) "found!" % (funcs_f.filename(), END_CASE_REGEX))
code = line_directive + code code = line_directive + code
code = generate_function_code(name, code, local_vars, args_dispatch, code = generate_function_code(name, code, local_vars, args_dispatch,
@@ -727,7 +680,7 @@ def parse_functions(funcs_f):
dependencies = parse_function_dependencies(line) dependencies = parse_function_dependencies(line)
except GeneratorInputError as error: except GeneratorInputError as error:
raise GeneratorInputError( raise GeneratorInputError(
"%s:%d: %s" % (funcs_f.name, funcs_f.line_no, "%s:%d: %s" % (funcs_f.filename(), funcs_f.lineno(),
str(error))) str(error)))
func_name, args, func_code, func_dispatch =\ func_name, args, func_code, func_dispatch =\
parse_function_code(funcs_f, dependencies, suite_dependencies) parse_function_code(funcs_f, dependencies, suite_dependencies)
@@ -736,7 +689,7 @@ def parse_functions(funcs_f):
if func_name in func_info: if func_name in func_info:
raise GeneratorInputError( raise GeneratorInputError(
"file: %s - function %s re-declared at line %d" % "file: %s - function %s re-declared at line %d" %
(funcs_f.name, func_name, funcs_f.line_no)) (funcs_f.filename(), func_name, funcs_f.lineno()))
func_info[func_name] = (function_idx, args) func_info[func_name] = (function_idx, args)
dispatch_code += '/* Function Id: %d */\n' % function_idx dispatch_code += '/* Function Id: %d */\n' % function_idx
dispatch_code += func_dispatch dispatch_code += func_dispatch
@@ -798,7 +751,7 @@ def parse_test_data(data_f):
raise GeneratorInputError("[%s:%d] Newline before arguments. " raise GeneratorInputError("[%s:%d] Newline before arguments. "
"Test function and arguments " "Test function and arguments "
"missing for %s" % "missing for %s" %
(data_f.name, data_f.line_no, name)) (data_f.filename(), data_f.lineno(), name))
continue continue
if state == __state_read_name: if state == __state_read_name:
@@ -815,19 +768,19 @@ def parse_test_data(data_f):
except GeneratorInputError as error: except GeneratorInputError as error:
raise GeneratorInputError( raise GeneratorInputError(
str(error) + " - %s:%d" % str(error) + " - %s:%d" %
(data_f.name, data_f.line_no)) (data_f.filename(), data_f.lineno()))
else: else:
# Read test vectors # Read test vectors
parts = escaped_split(line, ':') parts = escaped_split(line, ':')
test_function = parts[0] test_function = parts[0]
args = parts[1:] args = parts[1:]
yield data_f.line_no, name, test_function, dependencies, args yield data_f.lineno(), name, test_function, dependencies, args
dependencies = [] dependencies = []
state = __state_read_name state = __state_read_name
if state == __state_read_args: if state == __state_read_args:
raise GeneratorInputError("[%s:%d] Newline before arguments. " raise GeneratorInputError("[%s:%d] Newline before arguments. "
"Test function and arguments missing for " "Test function and arguments missing for "
"%s" % (data_f.name, data_f.line_no, name)) "%s" % (data_f.filename(), data_f.lineno(), name))
def gen_dep_check(dep_id, dep): def gen_dep_check(dep_id, dep):
@@ -1144,7 +1097,7 @@ def parse_function_file(funcs_file, snippets):
substituted in the template. substituted in the template.
:return: :return:
""" """
with FileWrapper(funcs_file) as funcs_f: with read_file(funcs_file) as funcs_f:
suite_dependencies, dispatch_code, func_code, func_info = \ suite_dependencies, dispatch_code, func_code, func_info = \
parse_functions(funcs_f) parse_functions(funcs_f)
snippets['functions_code'] = func_code snippets['functions_code'] = func_code
@@ -1166,7 +1119,7 @@ def generate_intermediate_data_file(data_file, out_data_file,
substituted in the template. substituted in the template.
:return: :return:
""" """
with FileWrapper(data_file) as data_f, \ with read_file(data_file) as data_f, \
open(out_data_file, 'w', encoding='utf-8') as out_data_f: open(out_data_file, 'w', encoding='utf-8') as out_data_f:
dep_check_code, expression_code = gen_from_test_data( dep_check_code, expression_code = gen_from_test_data(
data_f, out_data_f, func_info, suite_dependencies) data_f, out_data_f, func_info, suite_dependencies)
+6
View File
@@ -285,6 +285,12 @@ class StringIOWrapper(StringIO):
self.line_no = line_no self.line_no = line_no
self.name = file_name self.name = file_name
def lineno(self):
return self.line_no
def filename(self):
return self.name
def next(self): def next(self):
""" """
Iterator method. This method overrides base class's Iterator method. This method overrides base class's