diff --git a/Lib/fontbakery/checks/glyphset.py b/Lib/fontbakery/checks/glyphset.py index e0f20eb4a3..c08c9e0af1 100644 --- a/Lib/fontbakery/checks/glyphset.py +++ b/Lib/fontbakery/checks/glyphset.py @@ -1,3 +1,5 @@ +from copy import deepcopy + from fontbakery.constants import ( NameID, PlatformID, @@ -370,6 +372,11 @@ def check_soft_hyphen(ttFont): def unreachable_glyphs(ttFont, config): """Check font contains no unreachable glyphs""" + # remove_lookup_outputs() mutates the TTF; deep copy to avoid this, and so + # avoid issues with concurrent tests that also use ttFont. + # See https://github.com/fonttools/fontbakery/issues/4834 + ttFont = deepcopy(ttFont) + def remove_lookup_outputs(all_glyphs, lookup): if lookup.LookupType == 1: # Single: # Replace one glyph with one glyph diff --git a/Lib/fontbakery/utils.py b/Lib/fontbakery/utils.py index d541c45a30..c9e817ff0b 100644 --- a/Lib/fontbakery/utils.py +++ b/Lib/fontbakery/utils.py @@ -17,6 +17,7 @@ import subprocess import sys from typing import Text, Optional +from copy import deepcopy from fontTools.pens.basePen import BasePen from fontTools.ttLib import TTFont @@ -537,19 +538,19 @@ def iterate_lookup_list_with_extensions(ttFont, table, callback, *args): if table not in ttFont or not ttFont[table].table.LookupList: return + # This function mutates the TTF; deep copy to avoid this, and so avoid + # issues with concurrent tests that also use ttFont. + # See https://github.com/fonttools/fontbakery/issues/4834 + ttFont = deepcopy(ttFont) + extension_type = 9 if table == "GPOS" else 7 for lookup in ttFont[table].table.LookupList.Lookup: if lookup.LookupType == extension_type: for xt in lookup.SubTable: - original_LookupType = xt.LookupType - try: - xt.SubTable = [xt.ExtSubTable] - xt.LookupType = xt.ExtSubTable.LookupType - callback(xt, *args) - finally: - del xt.SubTable - xt.LookupType = original_LookupType + xt.SubTable = [xt.ExtSubTable] + xt.LookupType = xt.ExtSubTable.LookupType + callback(xt, *args) else: callback(lookup, *args)