Make NameRecord comparison not fail on encoding errors #3006

This commit is contained in:
Johannes Neumeier 2023-02-24 15:58:53 +02:00
parent 4ffb9c7334
commit f52b3da721
2 changed files with 39 additions and 14 deletions

View File

@ -607,34 +607,40 @@ class NameRecord(object):
def __lt__(self, other):
if type(self) != type(other):
return NotImplemented
return NotImplemented()
try:
# implemented so that list.sort() sorts according to the spec.
selfTuple = (
self.platformID,
self.platEncID,
self.langID,
self.nameID,
self.toBytes(),
)
otherTuple = (
other.platformID,
other.platEncID,
other.langID,
other.nameID,
other.toBytes(),
)
return selfTuple < otherTuple
except (UnicodeEncodeError, AttributeError):
except (AttributeError):
# This can only happen for
# 1) an object that is not a NameRecord, or
# 2) an unlikely incomplete NameRecord object which has not been
# fully populated, or
# 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
# fully populated
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.warning("NameRecord sorting failed to decode: %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):
return "<NameRecord NameID=%d; PlatformID=%d; LanguageID=%d>" % (

View File

@ -72,15 +72,34 @@ class NameTableTest(unittest.TestCase):
]
table.compile(None)
def test_names_sort_bytes_str_encoding_error(self):
def test_names_sort_attributes(self):
table = table__n_a_m_e()
# Create an actual invalid NameRecord object
broken = makeName("Test", 25, 3, 1, 0x409)
delattr(broken, "platformID")
table.names = [
makeName("Test寬", 25, 1, 0, 0),
makeName("Test鬆鬆", 25, 1, 0, 0),
makeName("Test", 25, 3, 1, 0x409),
broken,
]
# Sorting these two is impossible, expect an error to be raised
with self.assertRaises(TypeError):
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):
table = table__n_a_m_e()
nameIDs = []