Print out object hierarchy, when an Exception happens while compiling otData tables

The common stacktrace like this:

  File "fonttools/Lib/fontTools/ttLib/__init__.py", line 202, in save
    self._writeTable(tag, writer, done)
  File "fonttools/Lib/fontTools/ttLib/__init__.py", line 631, in _writeTable
    tabledata = self.getTableData(tag)
  File "fonttools/Lib/fontTools/ttLib/__init__.py", line 644, in getTableData
    return self.tables[tag].compile(self)
  File "fonttools/Lib/fontTools/ttLib/tables/otBase.py", line 86, in compile
    self.table.compile(writer, font)
  File "fonttools/Lib/fontTools/ttLib/tables/otBase.py", line 681, in compile
    conv.write(writer, font, table, value)
  File "fonttools/Lib/fontTools/ttLib/tables/otConverters.py", line 354, in write
    value.compile(subWriter, font)
  File "fonttools/Lib/fontTools/ttLib/tables/otBase.py", line 661, in compile
    conv.write(writer, font, table, value, i)
  File "fonttools/Lib/fontTools/ttLib/tables/otConverters.py", line 354, in write
    value.compile(subWriter, font)
  File "fonttools/Lib/fontTools/ttLib/tables/otBase.py", line 661, in compile
    conv.write(writer, font, table, value, i)
  File "fonttools/Lib/fontTools/ttLib/tables/otConverters.py", line 354, in write
    value.compile(subWriter, font)
  File "fonttools/Lib/fontTools/ttLib/tables/otBase.py", line 661, in compile
    conv.write(writer, font, table, value, i)
  File "fonttools/Lib/fontTools/ttLib/tables/otConverters.py", line 277, in write
    value.compile(writer, font)
  File "fonttools/Lib/fontTools/ttLib/tables/otBase.py", line 681, in compile
    conv.write(writer, font, table, value)
  File "fonttools/Lib/fontTools/ttLib/tables/otConverters.py", line 175, in write
    writer.writeUShort(value)
  File "fonttools/Lib/fontTools/ttLib/tables/otBase.py", line 457, in writeUShort
    assert 0 <= value < 0x10000, value
AssertionError: None

now has this as the last line:

AssertionError: (None, 'LookupListIndex', 'SubstLookupRecord', 'ChainContextSubst', 'Lookup', 'LookupList')

which means a value of None was tried for writing a LookupListIndex from a ChainContextSubset...

It's a hack, but a very useful one.
This commit is contained in:
Behdad Esfahbod 2016-01-23 14:20:33 +01:00
parent 929dada533
commit 1fbad696c9

View File

@ -643,6 +643,7 @@ class BaseTable(object):
if hasattr(self.__class__, 'LookupType'): if hasattr(self.__class__, 'LookupType'):
writer['LookupType'].setValue(self.__class__.LookupType) writer['LookupType'].setValue(self.__class__.LookupType)
try:
self.writeFormat(writer) self.writeFormat(writer)
for conv in self.getConverters(): for conv in self.getConverters():
value = table.get(conv.name) # TODO Handle defaults instead of defaulting to None! value = table.get(conv.name) # TODO Handle defaults instead of defaulting to None!
@ -655,7 +656,9 @@ class BaseTable(object):
else: else:
# conv.repeat is a propagated count # conv.repeat is a propagated count
writer[conv.repeat].setValue(countValue) writer[conv.repeat].setValue(countValue)
conv.writeArray(writer, font, table, value) values = value
for i, value in enumerate(values):
conv.write(writer, font, table, value, i)
elif conv.isCount: elif conv.isCount:
# Special-case Count values. # Special-case Count values.
# Assumption: a Count field will *always* precede # Assumption: a Count field will *always* precede
@ -678,6 +681,11 @@ class BaseTable(object):
conv.write(writer, font, table, value) conv.write(writer, font, table, value)
if conv.isPropagated: if conv.isPropagated:
writer[conv.name] = value writer[conv.name] = value
except Exception as e:
name = value.__class__.__name__ if value is not None else conv.name
info = (name,)
e.args = e.args + info
raise
def readFormat(self, reader): def readFormat(self, reader):
pass pass