From 83ee6bcdab977e54f677eda4dd0214d77c3a2dba Mon Sep 17 00:00:00 2001 From: Cosimo Lupo Date: Thu, 17 Mar 2022 12:30:40 +0000 Subject: [PATCH] ttCollection: don't close file inside init if lazy=True Fixes 'seek of closed file' error #2549 --- Lib/fontTools/ttLib/ttCollection.py | 7 ++++++- Tests/ttLib/ttCollection_test.py | 23 ++++++++++++++++++----- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/Lib/fontTools/ttLib/ttCollection.py b/Lib/fontTools/ttLib/ttCollection.py index 88734ec79..f09221276 100644 --- a/Lib/fontTools/ttLib/ttCollection.py +++ b/Lib/fontTools/ttLib/ttCollection.py @@ -38,7 +38,12 @@ class TTCollection(object): font = TTFont(file, fontNumber=i, _tableCache=tableCache, **kwargs) fonts.append(font) - if closeStream: + # don't close file if lazy=True, as the TTFont hold a reference to the original + # file; the file will be closed once the TTFonts are closed in the + # TTCollection.close(). We still want to close the file if lazy is None or + # False, because in that case the TTFont no longer need the original file + # and we want to avoid 'ResourceWarning: unclosed file'. + if not kwargs.get("lazy") and closeStream: file.close() def __enter__(self): diff --git a/Tests/ttLib/ttCollection_test.py b/Tests/ttLib/ttCollection_test.py index e4c3b55a1..91a1117df 100644 --- a/Tests/ttLib/ttCollection_test.py +++ b/Tests/ttLib/ttCollection_test.py @@ -1,14 +1,27 @@ import os +from pathlib import Path from fontTools.ttLib import TTCollection import pytest -TTX_DATA_DIR = os.path.join(os.path.dirname(__file__), "..", "ttx", "data") +TTX_DATA_DIR = Path(__file__).parent.parent / "ttx" / "data" -@pytest.mark.parametrize("lazy", [None, True, False]) -def test_lazy_open(lazy): - ttc = os.path.join(TTX_DATA_DIR, "TestTTC.ttc") - with TTCollection(ttc, lazy=lazy) as collection: +@pytest.fixture(params=[None, True, False]) +def lazy(request): + return request.param + + +def test_lazy_open_path(lazy): + ttc_path = TTX_DATA_DIR / "TestTTC.ttc" + with TTCollection(ttc_path, lazy=lazy) as collection: + assert len(collection) == 2 + assert collection[0]["maxp"].numGlyphs == 6 + assert collection[1]["maxp"].numGlyphs == 6 + + +def test_lazy_open_file(lazy): + with (TTX_DATA_DIR / "TestTTC.ttc").open("rb") as file: + collection = TTCollection(file, lazy=lazy) assert len(collection) == 2 assert collection[0]["maxp"].numGlyphs == 6 assert collection[1]["maxp"].numGlyphs == 6