From e5ec554f85559efe3c8822c19e0a9b7929bb3473 Mon Sep 17 00:00:00 2001 From: anz Date: Tue, 12 Sep 2023 09:10:32 +0200 Subject: [PATCH] Close file handle in preloadFont Commit 785f90a7f546f0e94a40ad0e9cc3e5e64322805d introduced a regression by not using a context manager when opening the file, which eventually lead to a resource leak because the file handle 'f' never gets closed. This is fixed by passing the font path, instead of the open file handle, and by opening the handle using a 'with' context manager. The issue can be reproduced by running pytest with the '-W error' flag for the following minimal example: def test_file_gets_closed(): Figlet().renderText("") This will succeed now, but fails for v1.0.1. --- pyfiglet/__init__.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/pyfiglet/__init__.py b/pyfiglet/__init__.py index 5543054..9ef4525 100755 --- a/pyfiglet/__init__.py +++ b/pyfiglet/__init__.py @@ -135,30 +135,31 @@ def preloadFont(cls, font): """ # Find a plausible looking font file. data = None - f = None + font_path = None for extension in ('tlf', 'flf'): fn = '%s.%s' % (font, extension) path = importlib.resources.files('pyfiglet.fonts').joinpath(fn) if path.exists(): - f = path.open('rb') + font_path = path break else: for location in ("./", SHARED_DIRECTORY): full_name = os.path.join(location, fn) if os.path.isfile(full_name): - f = open(full_name, 'rb') + font_path = full_name break # Unzip the first file if this file/stream looks like a ZIP file. - if f: - if zipfile.is_zipfile(f): - with zipfile.ZipFile(f) as zip_file: - zip_font = zip_file.open(zip_file.namelist()[0]) - data = zip_font.read() - else: - # ZIP file check moves the current file pointer - reset to start of file. - f.seek(0) - data = f.read() + if font_path: + with open(font_path, 'rb') as f: + if zipfile.is_zipfile(f): + with zipfile.ZipFile(f) as zip_file: + zip_font = zip_file.open(zip_file.namelist()[0]) + data = zip_font.read() + else: + # ZIP file check moves the current file pointer - reset to start of file. + f.seek(0) + data = f.read() # Return the decoded data (if any). if data: