From aeb8d6652545f25ac8f74a045076cef1632d5c26 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 4 Mar 2022 20:02:00 +0100 Subject: [PATCH] Ensure files get closed when they go out of scope This is automatic in CPython but not guaranteed by the language. Be friendly to other Python implementations. Signed-off-by: Gilles Peskine --- scripts/abi_check.py | 51 +++++++++++++------------- scripts/assemble_changelog.py | 19 ++++++---- scripts/mbedtls_dev/macro_collector.py | 9 +++-- scripts/min_requirements.py | 25 +++++++------ 4 files changed, 56 insertions(+), 48 deletions(-) diff --git a/scripts/abi_check.py b/scripts/abi_check.py index 1f6ac53a7..f11cdf259 100755 --- a/scripts/abi_check.py +++ b/scripts/abi_check.py @@ -249,32 +249,33 @@ class AbiChecker: at_paragraph_start = True description = None full_path = os.path.join(directory, filename) - for line_number, line in enumerate(open(full_path), 1): - line = line.strip() - if not line: - at_paragraph_start = True - continue - if line.startswith('#'): - continue - if at_paragraph_start: - description = line.strip() - at_paragraph_start = False - continue - if line.startswith('depends_on:'): - continue - # We've reached a test case data line - test_case_data = self._normalize_storage_test_case_data(line) - if not is_generated: - # In manual test data, only look at read tests. - function_name = test_case_data.split(':', 1)[0] - if 'read' not in function_name.split('_'): + with open(full_path) as fd: + for line_number, line in enumerate(fd, 1): + line = line.strip() + if not line: + at_paragraph_start = True continue - metadata = SimpleNamespace( - filename=filename, - line_number=line_number, - description=description - ) - storage_tests[test_case_data] = metadata + if line.startswith('#'): + continue + if at_paragraph_start: + description = line.strip() + at_paragraph_start = False + continue + if line.startswith('depends_on:'): + continue + # We've reached a test case data line + test_case_data = self._normalize_storage_test_case_data(line) + if not is_generated: + # In manual test data, only look at read tests. + function_name = test_case_data.split(':', 1)[0] + if 'read' not in function_name.split('_'): + continue + metadata = SimpleNamespace( + filename=filename, + line_number=line_number, + description=description + ) + storage_tests[test_case_data] = metadata @staticmethod def _list_generated_test_data_files(git_worktree_path): diff --git a/scripts/assemble_changelog.py b/scripts/assemble_changelog.py index b8a63c9e9..b742cc8ca 100755 --- a/scripts/assemble_changelog.py +++ b/scripts/assemble_changelog.py @@ -407,14 +407,17 @@ def check_output(generated_output_file, main_input_file, merged_files): is also present in an output file. This is not perfect but good enough for now. """ - generated_output = set(open(generated_output_file, 'r', encoding='utf-8')) - for line in open(main_input_file, 'r', encoding='utf-8'): - if line not in generated_output: - raise LostContent('original file', line) - for merged_file in merged_files: - for line in open(merged_file, 'r', encoding='utf-8'): - if line not in generated_output: - raise LostContent(merged_file, line) + with open(generated_output_file, 'r', encoding='utf-8') as out_fd: + generated_output = set(out_fd) + with open(main_input_file, 'r', encoding='utf-8') as in_fd: + for line in in_fd: + if line not in generated_output: + raise LostContent('original file', line) + for merged_file in merged_files: + with open(merged_file, 'r', encoding='utf-8') as in_fd: + for line in in_fd: + if line not in generated_output: + raise LostContent(merged_file, line) def finish_output(changelog, output_file, input_file, merged_files): """Write the changelog to the output file. diff --git a/scripts/mbedtls_dev/macro_collector.py b/scripts/mbedtls_dev/macro_collector.py index 3440ba74b..e93940d6e 100644 --- a/scripts/mbedtls_dev/macro_collector.py +++ b/scripts/mbedtls_dev/macro_collector.py @@ -18,7 +18,7 @@ import itertools import re -from typing import Dict, Iterable, Iterator, List, Optional, Pattern, Set, Tuple, Union +from typing import Dict, IO, Iterable, Iterator, List, Optional, Pattern, Set, Tuple, Union class ReadFileLineException(Exception): @@ -50,12 +50,13 @@ class read_file_lines: """ def __init__(self, filename: str, binary: bool = False) -> 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.generator = enumerate(open(self.filename, - 'rb' if self.binary else 'r')) + self.file = open(self.filename, 'rb' if self.binary else 'r') + self.generator = enumerate(self.file) return self def __iter__(self) -> Iterator[str]: assert self.generator is not None @@ -64,6 +65,8 @@ class read_file_lines: yield content self.line_number = 'exit' def __exit__(self, exc_type, exc_value, exc_traceback) -> None: + if self.file is not None: + self.file.close() if exc_type is not None: raise ReadFileLineException(self.filename, self.line_number) \ from exc_value diff --git a/scripts/min_requirements.py b/scripts/min_requirements.py index eecab1c1e..01c9de13c 100755 --- a/scripts/min_requirements.py +++ b/scripts/min_requirements.py @@ -56,18 +56,19 @@ class Requirements: * Comments (``#`` at the beginning of the line or after whitespace). * ``-r FILENAME`` to include another file. """ - for line in open(filename): - line = line.strip() - line = re.sub(r'(\A|\s+)#.*', r'', line) - if not line: - continue - m = re.match(r'-r\s+', line) - if m: - nested_file = os.path.join(os.path.dirname(filename), - line[m.end(0):]) - self.add_file(nested_file) - continue - self.requirements.append(self.adjust_requirement(line)) + with open(filename) as fd: + for line in fd: + line = line.strip() + line = re.sub(r'(\A|\s+)#.*', r'', line) + if not line: + continue + m = re.match(r'-r\s+', line) + if m: + nested_file = os.path.join(os.path.dirname(filename), + line[m.end(0):]) + self.add_file(nested_file) + continue + self.requirements.append(self.adjust_requirement(line)) def write(self, out: typing_util.Writable) -> None: """List the gathered requirements."""