Merge pull request #3007 from kontur/name-sort-encode-warning-only

Make NameRecord comparison not fail on encoding errors #3006
This commit is contained in:
Cosimo Lupo 2023-02-27 16:31:19 +00:00 committed by GitHub
commit d4c5eac780
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 12 deletions

View File

@ -610,32 +610,38 @@ class NameRecord(object):
return NotImplemented return NotImplemented
try: try:
# implemented so that list.sort() sorts according to the spec.
selfTuple = ( selfTuple = (
self.platformID, self.platformID,
self.platEncID, self.platEncID,
self.langID, self.langID,
self.nameID, self.nameID,
self.toBytes(),
) )
otherTuple = ( otherTuple = (
other.platformID, other.platformID,
other.platEncID, other.platEncID,
other.langID, other.langID,
other.nameID, other.nameID,
other.toBytes(),
) )
return selfTuple < otherTuple except AttributeError:
except (UnicodeEncodeError, AttributeError):
# This can only happen for # This can only happen for
# 1) an object that is not a NameRecord, or # 1) an object that is not a NameRecord, or
# 2) an unlikely incomplete NameRecord object which has not been # 2) an unlikely incomplete NameRecord object which has not been
# fully populated, or # fully populated
# 3) when all IDs are identical but the strings can't be encoded
# for their platform encoding.
# In all cases it is best to return NotImplemented.
return NotImplemented return NotImplemented
try:
# Include the actual NameRecord string in the comparison tuples
selfTuple = selfTuple + (self.toBytes(),)
otherTuple = otherTuple + (other.toBytes(),)
except UnicodeEncodeError as e:
# toBytes caused an encoding error in either of the two, so content
# to sorting based on IDs only
log.error("NameRecord sorting failed to encode: %s" % e)
# Implemented so that list.sort() sorts according to the spec by using
# the order of the tuple items and their comparison
return selfTuple < otherTuple
def __repr__(self): def __repr__(self):
return "<NameRecord NameID=%d; PlatformID=%d; LanguageID=%d>" % ( return "<NameRecord NameID=%d; PlatformID=%d; LanguageID=%d>" % (
self.nameID, self.nameID,

View File

@ -72,15 +72,34 @@ class NameTableTest(unittest.TestCase):
] ]
table.compile(None) table.compile(None)
def test_names_sort_bytes_str_encoding_error(self): def test_names_sort_attributes(self):
table = table__n_a_m_e() table = table__n_a_m_e()
# Create an actual invalid NameRecord object
broken = makeName("Test", 25, 3, 1, 0x409)
delattr(broken, "platformID")
table.names = [ table.names = [
makeName("Test寬", 25, 1, 0, 0), makeName("Test", 25, 3, 1, 0x409),
makeName("Test鬆鬆", 25, 1, 0, 0), broken,
] ]
# Sorting these two is impossible, expect an error to be raised
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
table.names.sort() table.names.sort()
def test_names_sort_encoding(self):
"""
Confirm that encoding errors in name table strings do not prevent at
least sorting by other IDs
"""
table = table__n_a_m_e()
table.names = [
makeName("Mac Unicode 寬 encodes ok", 25, 3, 0, 0x409),
makeName("Win Latin 寬 fails to encode", 25, 1, 0, 0),
]
table.names.sort()
# Encoding errors or not, sort based on other IDs nonetheless
self.assertEqual(table.names[0].platformID, 1)
self.assertEqual(table.names[1].platformID, 3)
def test_addName(self): def test_addName(self):
table = table__n_a_m_e() table = table__n_a_m_e()
nameIDs = [] nameIDs = []