merger: Convert input checking asserts into proper exceptions

This commit is contained in:
Nikolaus Waxweiler 2020-02-11 14:24:50 +00:00 committed by Nikolaus Waxweiler
parent af0567f847
commit 4320392eb5

View File

@ -14,6 +14,8 @@ from fontTools.varLib.varStore import VarStoreInstancer
from functools import reduce from functools import reduce
from fontTools.otlLib.builder import buildSinglePos from fontTools.otlLib.builder import buildSinglePos
from .errors import VarLibMergeError
class Merger(object): class Merger(object):
@ -66,8 +68,8 @@ class Merger(object):
if hasattr(item, "ensureDecompiled"): if hasattr(item, "ensureDecompiled"):
item.ensureDecompiled() item.ensureDecompiled()
keys = sorted(vars(out).keys()) keys = sorted(vars(out).keys())
assert all(keys == sorted(vars(v).keys()) for v in lst), \ if not all(keys == sorted(vars(v).keys()) for v in lst):
(keys, [sorted(vars(v).keys()) for v in lst]) raise VarLibMergeError((keys, [sorted(vars(v).keys()) for v in lst]))
mergers = self.mergersFor(out) mergers = self.mergersFor(out)
defaultMerger = mergers.get('*', self.__class__.mergeThings) defaultMerger = mergers.get('*', self.__class__.mergeThings)
try: try:
@ -82,7 +84,8 @@ class Merger(object):
raise raise
def mergeLists(self, out, lst): def mergeLists(self, out, lst):
assert allEqualTo(out, lst, len), (len(out), [len(v) for v in lst]) if not allEqualTo(out, lst, len):
raise VarLibMergeError((len(out), [len(v) for v in lst]))
for i,(value,values) in enumerate(zip(out, zip(*lst))): for i,(value,values) in enumerate(zip(out, zip(*lst))):
try: try:
self.mergeThings(value, values) self.mergeThings(value, values)
@ -92,7 +95,8 @@ class Merger(object):
def mergeThings(self, out, lst): def mergeThings(self, out, lst):
try: try:
assert allEqualTo(out, lst, type), (out, lst) if not allEqualTo(out, lst, type):
raise VarLibMergeError((out, lst))
mergerFunc = self.mergersFor(out).get(None, None) mergerFunc = self.mergersFor(out).get(None, None)
if mergerFunc is not None: if mergerFunc is not None:
mergerFunc(self, out, lst) mergerFunc(self, out, lst)
@ -101,7 +105,8 @@ class Merger(object):
elif isinstance(out, list): elif isinstance(out, list):
self.mergeLists(out, lst) self.mergeLists(out, lst)
else: else:
assert allEqualTo(out, lst), (out, lst) if not allEqualTo(out, lst):
raise VarLibMergeError((out, lst))
except Exception as e: except Exception as e:
e.args = e.args + (type(out).__name__,) e.args = e.args + (type(out).__name__,)
raise raise
@ -122,7 +127,8 @@ class AligningMerger(Merger):
@AligningMerger.merger(ot.GDEF, "GlyphClassDef") @AligningMerger.merger(ot.GDEF, "GlyphClassDef")
def merge(merger, self, lst): def merge(merger, self, lst):
if self is None: if self is None:
assert allNone(lst), (lst) if not allNone(lst):
raise VarLibMergeError(lst)
return return
lst = [l.classDefs for l in lst] lst = [l.classDefs for l in lst]
@ -134,7 +140,8 @@ def merge(merger, self, lst):
allKeys.update(*[l.keys() for l in lst]) allKeys.update(*[l.keys() for l in lst])
for k in allKeys: for k in allKeys:
allValues = nonNone(l.get(k) for l in lst) allValues = nonNone(l.get(k) for l in lst)
assert allEqual(allValues), allValues if not allEqual(allValues):
raise VarLibMergeError(allValues)
if not allValues: if not allValues:
self[k] = None self[k] = None
else: else:
@ -170,7 +177,8 @@ def _merge_GlyphOrders(font, lst, values_lst=None, default=None):
sortKey = font.getReverseGlyphMap().__getitem__ sortKey = font.getReverseGlyphMap().__getitem__
order = sorted(combined, key=sortKey) order = sorted(combined, key=sortKey)
# Make sure all input glyphsets were in proper order # Make sure all input glyphsets were in proper order
assert all(sorted(vs, key=sortKey) == vs for vs in lst), "glyph orders are not consistent across masters" if not all(sorted(vs, key=sortKey) == vs for vs in lst):
raise VarLibMergeError("Glyph order inconsistent across masters.")
del combined del combined
paddedValues = None paddedValues = None
@ -197,7 +205,10 @@ def _Lookup_SinglePos_get_effective_value(subtables, glyph):
elif self.Format == 2: elif self.Format == 2:
return self.Value[self.Coverage.glyphs.index(glyph)] return self.Value[self.Coverage.glyphs.index(glyph)]
else: else:
assert 0 raise VarLibMergeError(
"Cannot retrieve effective value for SinglePos lookup, unsupported "
f"format {self.Format}."
)
return None return None
def _Lookup_PairPos_get_effective_value_pair(subtables, firstGlyph, secondGlyph): def _Lookup_PairPos_get_effective_value_pair(subtables, firstGlyph, secondGlyph):
@ -219,13 +230,17 @@ def _Lookup_PairPos_get_effective_value_pair(subtables, firstGlyph, secondGlyph)
klass2 = self.ClassDef2.classDefs.get(secondGlyph, 0) klass2 = self.ClassDef2.classDefs.get(secondGlyph, 0)
return self.Class1Record[klass1].Class2Record[klass2] return self.Class1Record[klass1].Class2Record[klass2]
else: else:
assert 0 raise VarLibMergeError(
"Cannot retrieve effective value pair for PairPos lookup, unsupported "
f"format {self.Format}."
)
return None return None
@AligningMerger.merger(ot.SinglePos) @AligningMerger.merger(ot.SinglePos)
def merge(merger, self, lst): def merge(merger, self, lst):
self.ValueFormat = valueFormat = reduce(int.__or__, [l.ValueFormat for l in lst], 0) self.ValueFormat = valueFormat = reduce(int.__or__, [l.ValueFormat for l in lst], 0)
assert len(lst) == 1 or (valueFormat & ~0xF == 0), valueFormat if not (len(lst) == 1 or (valueFormat & ~0xF == 0)):
raise VarLibMergeError(f"SinglePos format {valueFormat} is unsupported.")
# If all have same coverage table and all are format 1, # If all have same coverage table and all are format 1,
coverageGlyphs = self.Coverage.glyphs coverageGlyphs = self.Coverage.glyphs
@ -511,7 +526,9 @@ def merge(merger, self, lst):
elif self.Format == 2: elif self.Format == 2:
_PairPosFormat2_merge(self, lst, merger) _PairPosFormat2_merge(self, lst, merger)
else: else:
assert False raise VarLibMergeError(
f"Cannot merge PairPos lookup, unsupported format {self.Format}."
)
del merger.valueFormat1, merger.valueFormat2 del merger.valueFormat1, merger.valueFormat2
@ -576,7 +593,8 @@ def _MarkBasePosFormat1_merge(self, lst, merger, Mark='Mark', Base='Base'):
# failures in that case will probably signify mistakes in the # failures in that case will probably signify mistakes in the
# input masters. # input masters.
assert allEqual(allClasses), allClasses if not allEqual(allClasses):
raise VarLibMergeError(allClasses)
if not allClasses: if not allClasses:
rec = None rec = None
else: else:
@ -625,19 +643,31 @@ def _MarkBasePosFormat1_merge(self, lst, merger, Mark='Mark', Base='Base'):
@AligningMerger.merger(ot.MarkBasePos) @AligningMerger.merger(ot.MarkBasePos)
def merge(merger, self, lst): def merge(merger, self, lst):
assert allEqualTo(self.Format, (l.Format for l in lst)) if not allEqualTo(self.Format, (l.Format for l in lst)):
raise VarLibMergeError(
f"MarkBasePos formats inconsistent across masters, "
f"expected {self.Format} but got {[l.Format for l in lst]}."
)
if self.Format == 1: if self.Format == 1:
_MarkBasePosFormat1_merge(self, lst, merger) _MarkBasePosFormat1_merge(self, lst, merger)
else: else:
assert False raise VarLibMergeError(
f"Cannot merge MarkBasePos lookup, unsupported format {self.Format}."
)
@AligningMerger.merger(ot.MarkMarkPos) @AligningMerger.merger(ot.MarkMarkPos)
def merge(merger, self, lst): def merge(merger, self, lst):
assert allEqualTo(self.Format, (l.Format for l in lst)) if not allEqualTo(self.Format, (l.Format for l in lst)):
raise VarLibMergeError(
f"MarkMarkPos formats inconsistent across masters, "
f"expected {self.Format} but got {[l.Format for l in lst]}."
)
if self.Format == 1: if self.Format == 1:
_MarkBasePosFormat1_merge(self, lst, merger, 'Mark1', 'Mark2') _MarkBasePosFormat1_merge(self, lst, merger, 'Mark1', 'Mark2')
else: else:
assert False raise VarLibMergeError(
f"Cannot merge MarkMarkPos lookup, unsupported format {self.Format}."
)
def _PairSet_flatten(lst, font): def _PairSet_flatten(lst, font):
@ -766,8 +796,16 @@ def merge(merger, self, lst):
if not sts: if not sts:
continue continue
if sts[0].__class__.__name__.startswith('Extension'): if sts[0].__class__.__name__.startswith('Extension'):
assert allEqual([st.__class__ for st in sts]) if not allEqual([st.__class__ for st in sts]):
assert allEqual([st.ExtensionLookupType for st in sts]) raise VarLibMergeError(
"Use of extensions inconsistent between masters: "
f"{[st.__class__.__name__ for st in sts]}."
)
if not allEqual([st.ExtensionLookupType for st in sts]):
raise VarLibMergeError(
"Extension lookup type differs between masters: "
f"{[st.ExtensionLookupType for st in sts]}."
)
l.LookupType = sts[0].ExtensionLookupType l.LookupType = sts[0].ExtensionLookupType
new_sts = [st.ExtSubTable for st in sts] new_sts = [st.ExtSubTable for st in sts]
del sts[:] del sts[:]
@ -995,7 +1033,8 @@ class VariationMerger(AligningMerger):
masterModel = None masterModel = None
if None in lst: if None in lst:
if allNone(lst): if allNone(lst):
assert out is None, (out, lst) if out is not None:
raise VarLibMergeError((out, lst))
return return
masterModel = self.model masterModel = self.model
model, lst = masterModel.getSubModel(lst) model, lst = masterModel.getSubModel(lst)
@ -1015,7 +1054,8 @@ def buildVarDevTable(store_builder, master_values):
@VariationMerger.merger(ot.CaretValue) @VariationMerger.merger(ot.CaretValue)
def merge(merger, self, lst): def merge(merger, self, lst):
assert self.Format == 1 if self.Format != 1:
raise VarLibMergeError(f"CaretValue format {self.Format} unsupported.")
self.Coordinate, DeviceTable = buildVarDevTable(merger.store_builder, [a.Coordinate for a in lst]) self.Coordinate, DeviceTable = buildVarDevTable(merger.store_builder, [a.Coordinate for a in lst])
if DeviceTable: if DeviceTable:
self.Format = 3 self.Format = 3
@ -1023,7 +1063,8 @@ def merge(merger, self, lst):
@VariationMerger.merger(ot.Anchor) @VariationMerger.merger(ot.Anchor)
def merge(merger, self, lst): def merge(merger, self, lst):
assert self.Format == 1 if self.Format != 1:
raise VarLibMergeError(f"Anchor format {self.Format} unsupported.")
self.XCoordinate, XDeviceTable = buildVarDevTable(merger.store_builder, [a.XCoordinate for a in lst]) self.XCoordinate, XDeviceTable = buildVarDevTable(merger.store_builder, [a.XCoordinate for a in lst])
self.YCoordinate, YDeviceTable = buildVarDevTable(merger.store_builder, [a.YCoordinate for a in lst]) self.YCoordinate, YDeviceTable = buildVarDevTable(merger.store_builder, [a.YCoordinate for a in lst])
if XDeviceTable or YDeviceTable: if XDeviceTable or YDeviceTable: