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 <Gilles.Peskine@arm.com>
This commit is contained in:
Gilles Peskine 2022-03-04 20:02:00 +01:00
parent 1177f37648
commit aeb8d66525
4 changed files with 56 additions and 48 deletions

View file

@ -249,32 +249,33 @@ class AbiChecker:
at_paragraph_start = True at_paragraph_start = True
description = None description = None
full_path = os.path.join(directory, filename) full_path = os.path.join(directory, filename)
for line_number, line in enumerate(open(full_path), 1): with open(full_path) as fd:
line = line.strip() for line_number, line in enumerate(fd, 1):
if not line: line = line.strip()
at_paragraph_start = True if not line:
continue at_paragraph_start = True
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 continue
metadata = SimpleNamespace( if line.startswith('#'):
filename=filename, continue
line_number=line_number, if at_paragraph_start:
description=description description = line.strip()
) at_paragraph_start = False
storage_tests[test_case_data] = metadata 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 @staticmethod
def _list_generated_test_data_files(git_worktree_path): def _list_generated_test_data_files(git_worktree_path):

View file

@ -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 is also present in an output file. This is not perfect but good enough
for now. for now.
""" """
generated_output = set(open(generated_output_file, 'r', encoding='utf-8')) with open(generated_output_file, 'r', encoding='utf-8') as out_fd:
for line in open(main_input_file, 'r', encoding='utf-8'): generated_output = set(out_fd)
if line not in generated_output: with open(main_input_file, 'r', encoding='utf-8') as in_fd:
raise LostContent('original file', line) for line in in_fd:
for merged_file in merged_files: if line not in generated_output:
for line in open(merged_file, 'r', encoding='utf-8'): raise LostContent('original file', line)
if line not in generated_output: for merged_file in merged_files:
raise LostContent(merged_file, line) 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): def finish_output(changelog, output_file, input_file, merged_files):
"""Write the changelog to the output file. """Write the changelog to the output file.

View file

@ -18,7 +18,7 @@
import itertools import itertools
import re 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): class ReadFileLineException(Exception):
@ -50,12 +50,13 @@ class read_file_lines:
""" """
def __init__(self, filename: str, binary: bool = False) -> None: def __init__(self, filename: str, binary: bool = False) -> None:
self.filename = filename self.filename = filename
self.file = None #type: Optional[IO[str]]
self.line_number = 'entry' #type: Union[int, str] self.line_number = 'entry' #type: Union[int, str]
self.generator = None #type: Optional[Iterable[Tuple[int, str]]] self.generator = None #type: Optional[Iterable[Tuple[int, str]]]
self.binary = binary self.binary = binary
def __enter__(self) -> 'read_file_lines': def __enter__(self) -> 'read_file_lines':
self.generator = enumerate(open(self.filename, self.file = open(self.filename, 'rb' if self.binary else 'r')
'rb' if self.binary else 'r')) self.generator = enumerate(self.file)
return self return self
def __iter__(self) -> Iterator[str]: def __iter__(self) -> Iterator[str]:
assert self.generator is not None assert self.generator is not None
@ -64,6 +65,8 @@ class read_file_lines:
yield content yield content
self.line_number = 'exit' self.line_number = 'exit'
def __exit__(self, exc_type, exc_value, exc_traceback) -> None: 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: if exc_type is not None:
raise ReadFileLineException(self.filename, self.line_number) \ raise ReadFileLineException(self.filename, self.line_number) \
from exc_value from exc_value

View file

@ -56,18 +56,19 @@ class Requirements:
* Comments (``#`` at the beginning of the line or after whitespace). * Comments (``#`` at the beginning of the line or after whitespace).
* ``-r FILENAME`` to include another file. * ``-r FILENAME`` to include another file.
""" """
for line in open(filename): with open(filename) as fd:
line = line.strip() for line in fd:
line = re.sub(r'(\A|\s+)#.*', r'', line) line = line.strip()
if not line: line = re.sub(r'(\A|\s+)#.*', r'', line)
continue if not line:
m = re.match(r'-r\s+', line) continue
if m: m = re.match(r'-r\s+', line)
nested_file = os.path.join(os.path.dirname(filename), if m:
line[m.end(0):]) nested_file = os.path.join(os.path.dirname(filename),
self.add_file(nested_file) line[m.end(0):])
continue self.add_file(nested_file)
self.requirements.append(self.adjust_requirement(line)) continue
self.requirements.append(self.adjust_requirement(line))
def write(self, out: typing_util.Writable) -> None: def write(self, out: typing_util.Writable) -> None:
"""List the gathered requirements.""" """List the gathered requirements."""