From 7f537471bd11966726fbe51a3d75e8b23d824ca1 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 31 Mar 2026 13:15:44 +0200 Subject: [PATCH] Clean up overly complicated typing in read_file_lines The `read_file_lines` context manager supported either text or binary streams, based on a parameter passed to the constructor. But the type annotation on the iterator claimed that all lines were text. The version of mypy that we use on the CI was happy with that, but modern versions are not. The advantage of `read_file_lines` over built-in functions is better tracking of line numbers. We never took advantage of this in our code with binary streams. Change the one place where `read_file_lines` was used with a binary stream to use built-in functions instead, and specialize `read_file_lines` to text streams. This fixes a legitimate complaint of modern mypy on `macro_collectory.py`. There was no runtime bug: the behavior was correct, only the type annotations were wrong. Signed-off-by: Gilles Peskine --- scripts/mbedtls_framework/macro_collector.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/scripts/mbedtls_framework/macro_collector.py b/scripts/mbedtls_framework/macro_collector.py index 515b9191f..ccc9a9691 100644 --- a/scripts/mbedtls_framework/macro_collector.py +++ b/scripts/mbedtls_framework/macro_collector.py @@ -37,14 +37,13 @@ class read_file_lines: except that if process(line) raises an exception, then the read_file_lines snippet annotates the exception with the file name and line number. """ - def __init__(self, filename: str, binary: bool = False) -> None: + def __init__(self, filename: str) -> None: self.filename = filename self.file = None #type: Optional[IO[str]] self.line_number = 'entry' #type: Union[int, str] self.generator = None #type: Optional[Iterable[Tuple[int, str]]] - self.binary = binary def __enter__(self) -> 'read_file_lines': - self.file = open(self.filename, 'rb' if self.binary else 'r') + self.file = open(self.filename) self.generator = enumerate(self.file) return self def __iter__(self) -> Iterator[str]: @@ -517,10 +516,10 @@ enumerate _nonascii_re = re.compile(rb'[^\x00-\x7f]+') #type: Pattern def parse_header(self, filename: str) -> None: """Parse a C header file, looking for "#define PSA_xxx".""" - with read_file_lines(filename, binary=True) as lines: - for line in lines: - line = re.sub(self._nonascii_re, rb'', line).decode('ascii') - self.parse_header_line(line) + with open(filename, 'rb') as input_: + for line in input_: + line = re.sub(self._nonascii_re, rb'', line) + self.parse_header_line(line.decode('ascii')) _macro_identifier_re = re.compile(r'[A-Z]\w+') def generate_undeclared_names(self, expr: str) -> Iterable[str]: