2016-10-14 21:04:35 +02:00
|
|
|
|
from fontTools.misc.loggingTools import CapturingLogHandler
|
|
|
|
|
from fontTools.misc.testTools import FakeFont, makeXMLWriter
|
2015-10-17 06:47:52 +02:00
|
|
|
|
from fontTools.misc.textTools import deHexStr
|
|
|
|
|
import fontTools.ttLib.tables.otConverters as otConverters
|
2016-10-14 21:04:35 +02:00
|
|
|
|
from fontTools.ttLib import newTable
|
2015-10-17 06:47:52 +02:00
|
|
|
|
from fontTools.ttLib.tables.otBase import OTTableReader, OTTableWriter
|
|
|
|
|
import unittest
|
|
|
|
|
|
|
|
|
|
|
2017-03-10 12:17:14 +01:00
|
|
|
|
class Char64Test(unittest.TestCase):
|
|
|
|
|
font = FakeFont([])
|
|
|
|
|
converter = otConverters.Char64("char64", 0, None, None)
|
|
|
|
|
|
|
|
|
|
def test_read(self):
|
|
|
|
|
reader = OTTableReader(b"Hello\0junk after zero byte" + 100 * b"\0")
|
|
|
|
|
self.assertEqual(self.converter.read(reader, self.font, {}), "Hello")
|
|
|
|
|
self.assertEqual(reader.pos, 64)
|
|
|
|
|
|
|
|
|
|
def test_read_replace_not_ascii(self):
|
|
|
|
|
reader = OTTableReader(b"Hello \xE4 world" + 100 * b"\0")
|
|
|
|
|
with CapturingLogHandler(otConverters.log, "WARNING") as captor:
|
|
|
|
|
data = self.converter.read(reader, self.font, {})
|
|
|
|
|
self.assertEqual(data, "Hello <20> world")
|
|
|
|
|
self.assertEqual(reader.pos, 64)
|
|
|
|
|
self.assertIn(
|
|
|
|
|
'replaced non-ASCII characters in "Hello <20> world"',
|
|
|
|
|
[r.msg for r in captor.records],
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def test_write(self):
|
|
|
|
|
writer = OTTableWriter()
|
|
|
|
|
self.converter.write(writer, self.font, {}, "Hello world")
|
|
|
|
|
self.assertEqual(writer.getData(), b"Hello world" + 53 * b"\0")
|
|
|
|
|
|
|
|
|
|
def test_write_replace_not_ascii(self):
|
|
|
|
|
writer = OTTableWriter()
|
|
|
|
|
with CapturingLogHandler(otConverters.log, "WARNING") as captor:
|
2017-03-10 13:01:02 +01:00
|
|
|
|
self.converter.write(writer, self.font, {}, "Hello ☃")
|
2017-03-10 12:17:14 +01:00
|
|
|
|
self.assertEqual(writer.getData(), b"Hello ?" + 57 * b"\0")
|
2017-03-10 13:01:02 +01:00
|
|
|
|
self.assertIn(
|
|
|
|
|
'replacing non-ASCII characters in "Hello ☃"',
|
2017-03-10 12:17:14 +01:00
|
|
|
|
[r.msg for r in captor.records],
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def test_write_truncated(self):
|
|
|
|
|
writer = OTTableWriter()
|
|
|
|
|
with CapturingLogHandler(otConverters.log, "WARNING") as captor:
|
|
|
|
|
self.converter.write(writer, self.font, {}, "A" * 80)
|
|
|
|
|
self.assertEqual(writer.getData(), b"A" * 64)
|
|
|
|
|
self.assertIn(
|
|
|
|
|
'truncating overlong "' + "A" * 80 + '" to 64 bytes',
|
|
|
|
|
[r.msg for r in captor.records],
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def test_xmlRead(self):
|
|
|
|
|
value = self.converter.xmlRead({"value": "Foo"}, [], self.font)
|
|
|
|
|
self.assertEqual(value, "Foo")
|
|
|
|
|
|
|
|
|
|
def test_xmlWrite(self):
|
|
|
|
|
writer = makeXMLWriter()
|
|
|
|
|
self.converter.xmlWrite(
|
|
|
|
|
writer, self.font, "Hello world", "Element", [("attr", "v")]
|
|
|
|
|
)
|
|
|
|
|
xml = writer.file.getvalue().decode("utf-8").rstrip()
|
|
|
|
|
self.assertEqual(xml, '<Element attr="v" value="Hello world"/>')
|
|
|
|
|
|
|
|
|
|
|
2015-10-17 06:47:52 +02:00
|
|
|
|
class GlyphIDTest(unittest.TestCase):
|
|
|
|
|
font = FakeFont(".notdef A B C".split())
|
|
|
|
|
converter = otConverters.GlyphID("GlyphID", 0, None, None)
|
|
|
|
|
|
|
|
|
|
def test_readArray(self):
|
|
|
|
|
reader = OTTableReader(deHexStr("0002 0001 DEAD 0002"))
|
|
|
|
|
self.assertEqual(
|
|
|
|
|
self.converter.readArray(reader, self.font, {}, 4),
|
|
|
|
|
["B", "A", "glyph57005", "B"],
|
|
|
|
|
)
|
|
|
|
|
self.assertEqual(reader.pos, 8)
|
|
|
|
|
|
|
|
|
|
def test_read(self):
|
|
|
|
|
reader = OTTableReader(deHexStr("0003"))
|
|
|
|
|
self.assertEqual(self.converter.read(reader, self.font, {}), "C")
|
|
|
|
|
self.assertEqual(reader.pos, 2)
|
|
|
|
|
|
|
|
|
|
def test_write(self):
|
2016-12-28 20:41:07 -05:00
|
|
|
|
writer = OTTableWriter()
|
2015-10-17 06:47:52 +02:00
|
|
|
|
self.converter.write(writer, self.font, {}, "B")
|
|
|
|
|
self.assertEqual(writer.getData(), deHexStr("0002"))
|
|
|
|
|
|
|
|
|
|
|
2017-03-09 20:36:23 +01:00
|
|
|
|
class LongTest(unittest.TestCase):
|
|
|
|
|
font = FakeFont([])
|
|
|
|
|
converter = otConverters.Long("Long", 0, None, None)
|
|
|
|
|
|
|
|
|
|
def test_read(self):
|
|
|
|
|
reader = OTTableReader(deHexStr("FF0000EE"))
|
|
|
|
|
self.assertEqual(self.converter.read(reader, self.font, {}), -16776978)
|
|
|
|
|
self.assertEqual(reader.pos, 4)
|
|
|
|
|
|
|
|
|
|
def test_write(self):
|
|
|
|
|
writer = OTTableWriter()
|
|
|
|
|
self.converter.write(writer, self.font, {}, -16777213)
|
|
|
|
|
self.assertEqual(writer.getData(), deHexStr("FF000003"))
|
|
|
|
|
|
|
|
|
|
def test_xmlRead(self):
|
|
|
|
|
value = self.converter.xmlRead({"value": "314159"}, [], self.font)
|
|
|
|
|
self.assertEqual(value, 314159)
|
|
|
|
|
|
|
|
|
|
def test_xmlWrite(self):
|
|
|
|
|
writer = makeXMLWriter()
|
|
|
|
|
self.converter.xmlWrite(writer, self.font, 291, "Foo", [("attr", "v")])
|
|
|
|
|
xml = writer.file.getvalue().decode("utf-8").rstrip()
|
|
|
|
|
self.assertEqual(xml, '<Foo attr="v" value="291"/>')
|
|
|
|
|
|
|
|
|
|
|
2016-10-14 21:04:35 +02:00
|
|
|
|
class NameIDTest(unittest.TestCase):
|
|
|
|
|
converter = otConverters.NameID("NameID", 0, None, None)
|
|
|
|
|
|
|
|
|
|
def makeFont(self):
|
|
|
|
|
nameTable = newTable("name")
|
|
|
|
|
nameTable.setName("Demibold Condensed", 0x123, 3, 0, 0x409)
|
2018-01-19 13:25:59 +00:00
|
|
|
|
nameTable.setName("Copyright 2018", 0, 3, 0, 0x409)
|
2016-10-14 21:04:35 +02:00
|
|
|
|
return {"name": nameTable}
|
|
|
|
|
|
|
|
|
|
def test_read(self):
|
|
|
|
|
font = self.makeFont()
|
|
|
|
|
reader = OTTableReader(deHexStr("0123"))
|
|
|
|
|
self.assertEqual(self.converter.read(reader, font, {}), 0x123)
|
|
|
|
|
|
|
|
|
|
def test_write(self):
|
2016-12-28 20:41:07 -05:00
|
|
|
|
writer = OTTableWriter()
|
2016-10-14 21:04:35 +02:00
|
|
|
|
self.converter.write(writer, self.makeFont(), {}, 0x123)
|
|
|
|
|
self.assertEqual(writer.getData(), deHexStr("0123"))
|
|
|
|
|
|
|
|
|
|
def test_xmlWrite(self):
|
|
|
|
|
writer = makeXMLWriter()
|
|
|
|
|
self.converter.xmlWrite(
|
|
|
|
|
writer, self.makeFont(), 291, "FooNameID", [("attr", "val")]
|
|
|
|
|
)
|
2016-12-21 13:24:51 +00:00
|
|
|
|
xml = writer.file.getvalue().decode("utf-8").rstrip()
|
2016-10-14 21:04:35 +02:00
|
|
|
|
self.assertEqual(
|
|
|
|
|
xml, '<FooNameID attr="val" value="291"/> <!-- Demibold Condensed -->'
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def test_xmlWrite_missingID(self):
|
|
|
|
|
writer = makeXMLWriter()
|
|
|
|
|
with CapturingLogHandler(otConverters.log, "WARNING") as captor:
|
|
|
|
|
self.converter.xmlWrite(
|
|
|
|
|
writer, self.makeFont(), 666, "Entity", [("attrib", "val")]
|
|
|
|
|
)
|
|
|
|
|
self.assertIn(
|
|
|
|
|
"name id 666 missing from name table", [r.msg for r in captor.records]
|
|
|
|
|
)
|
2016-12-21 13:24:51 +00:00
|
|
|
|
xml = writer.file.getvalue().decode("utf-8").rstrip()
|
2016-10-14 21:04:35 +02:00
|
|
|
|
self.assertEqual(
|
|
|
|
|
xml,
|
|
|
|
|
'<Entity attrib="val"' ' value="666"/> <!-- missing from name table -->',
|
|
|
|
|
)
|
|
|
|
|
|
2018-01-19 13:25:59 +00:00
|
|
|
|
def test_xmlWrite_NULL(self):
|
|
|
|
|
writer = makeXMLWriter()
|
|
|
|
|
self.converter.xmlWrite(
|
|
|
|
|
writer, self.makeFont(), 0, "FooNameID", [("attr", "val")]
|
|
|
|
|
)
|
|
|
|
|
xml = writer.file.getvalue().decode("utf-8").rstrip()
|
|
|
|
|
self.assertEqual(xml, '<FooNameID attr="val" value="0"/>')
|
|
|
|
|
|
2016-10-14 21:04:35 +02:00
|
|
|
|
|
2017-03-09 20:52:26 +01:00
|
|
|
|
class UInt8Test(unittest.TestCase):
|
|
|
|
|
font = FakeFont([])
|
|
|
|
|
converter = otConverters.UInt8("UInt8", 0, None, None)
|
|
|
|
|
|
|
|
|
|
def test_read(self):
|
|
|
|
|
reader = OTTableReader(deHexStr("FE"))
|
|
|
|
|
self.assertEqual(self.converter.read(reader, self.font, {}), 254)
|
|
|
|
|
self.assertEqual(reader.pos, 1)
|
|
|
|
|
|
|
|
|
|
def test_write(self):
|
|
|
|
|
writer = OTTableWriter()
|
|
|
|
|
self.converter.write(writer, self.font, {}, 253)
|
|
|
|
|
self.assertEqual(writer.getData(), deHexStr("FD"))
|
|
|
|
|
|
|
|
|
|
def test_xmlRead(self):
|
|
|
|
|
value = self.converter.xmlRead({"value": "254"}, [], self.font)
|
|
|
|
|
self.assertEqual(value, 254)
|
|
|
|
|
|
|
|
|
|
def test_xmlWrite(self):
|
|
|
|
|
writer = makeXMLWriter()
|
|
|
|
|
self.converter.xmlWrite(writer, self.font, 251, "Foo", [("attr", "v")])
|
|
|
|
|
xml = writer.file.getvalue().decode("utf-8").rstrip()
|
|
|
|
|
self.assertEqual(xml, '<Foo attr="v" value="251"/>')
|
|
|
|
|
|
|
|
|
|
|
2017-06-07 10:49:47 +02:00
|
|
|
|
class AATLookupTest(unittest.TestCase):
|
2017-06-07 15:00:01 +02:00
|
|
|
|
font = FakeFont(".notdef A B C D E F G H A.alt B.alt".split())
|
2017-06-14 11:21:39 +02:00
|
|
|
|
converter = otConverters.AATLookup(
|
|
|
|
|
"AATLookup", 0, None, tableClass=otConverters.GlyphID
|
|
|
|
|
)
|
2017-06-07 10:49:47 +02:00
|
|
|
|
|
|
|
|
|
def __init__(self, methodName):
|
|
|
|
|
unittest.TestCase.__init__(self, methodName)
|
|
|
|
|
# Python 3 renamed assertRaisesRegexp to assertRaisesRegex,
|
|
|
|
|
# and fires deprecation warnings if a program uses the old name.
|
|
|
|
|
if not hasattr(self, "assertRaisesRegex"):
|
|
|
|
|
self.assertRaisesRegex = self.assertRaisesRegexp
|
|
|
|
|
|
|
|
|
|
def test_readFormat0(self):
|
|
|
|
|
reader = OTTableReader(deHexStr("0000 0000 0001 0002 0000 7D00 0001"))
|
|
|
|
|
self.assertEqual(
|
|
|
|
|
self.converter.read(reader, self.font, None),
|
|
|
|
|
{
|
2017-08-15 18:33:57 +02:00
|
|
|
|
".notdef": ".notdef",
|
|
|
|
|
"A": "A",
|
|
|
|
|
"B": "B",
|
2017-06-07 10:49:47 +02:00
|
|
|
|
"C": ".notdef",
|
|
|
|
|
"D": "glyph32000",
|
|
|
|
|
"E": "A",
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def test_readFormat2(self):
|
|
|
|
|
reader = OTTableReader(
|
|
|
|
|
deHexStr(
|
2017-08-16 19:43:25 +02:00
|
|
|
|
"0002 0006 0002 000C 0001 0006 "
|
2017-06-07 10:49:47 +02:00
|
|
|
|
"0002 0001 0003 " # glyph A..B: map to C
|
|
|
|
|
"0007 0005 0008 " # glyph E..G: map to H
|
|
|
|
|
"FFFF FFFF FFFF"
|
2022-12-13 11:26:36 +00:00
|
|
|
|
)
|
2017-06-07 10:49:47 +02:00
|
|
|
|
) # end of search table
|
|
|
|
|
self.assertEqual(
|
|
|
|
|
self.converter.read(reader, self.font, None),
|
|
|
|
|
{
|
|
|
|
|
"A": "C",
|
|
|
|
|
"B": "C",
|
|
|
|
|
"E": "H",
|
|
|
|
|
"F": "H",
|
|
|
|
|
"G": "H",
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def test_readFormat4(self):
|
|
|
|
|
reader = OTTableReader(
|
|
|
|
|
deHexStr(
|
|
|
|
|
"0004 0006 0003 000C 0001 0006 "
|
|
|
|
|
"0002 0001 001E " # glyph 1..2: mapping at offset 0x1E
|
|
|
|
|
"0005 0004 001E " # glyph 4..5: mapping at offset 0x1E
|
|
|
|
|
"FFFF FFFF FFFF " # end of search table
|
|
|
|
|
"0007 0008"
|
2022-12-13 11:26:36 +00:00
|
|
|
|
)
|
2017-06-07 10:49:47 +02:00
|
|
|
|
) # offset 0x18: glyphs [7, 8] = [G, H]
|
|
|
|
|
self.assertEqual(
|
|
|
|
|
self.converter.read(reader, self.font, None),
|
|
|
|
|
{
|
|
|
|
|
"A": "G",
|
|
|
|
|
"B": "H",
|
|
|
|
|
"D": "G",
|
|
|
|
|
"E": "H",
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def test_readFormat6(self):
|
|
|
|
|
reader = OTTableReader(
|
|
|
|
|
deHexStr(
|
2017-08-16 19:43:25 +02:00
|
|
|
|
"0006 0004 0002 0008 0001 0004 "
|
2017-06-07 10:49:47 +02:00
|
|
|
|
"0003 0001 " # C --> A
|
|
|
|
|
"0005 0002 " # E --> B
|
|
|
|
|
"FFFF FFFF"
|
2022-12-13 11:26:36 +00:00
|
|
|
|
)
|
2017-06-07 10:49:47 +02:00
|
|
|
|
) # end of search table
|
|
|
|
|
self.assertEqual(
|
|
|
|
|
self.converter.read(reader, self.font, None),
|
|
|
|
|
{
|
|
|
|
|
"C": "A",
|
|
|
|
|
"E": "B",
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def test_readFormat8(self):
|
|
|
|
|
reader = OTTableReader(
|
|
|
|
|
deHexStr("0008 " "0003 0003 " "0007 0001 0002") # first: C, count: 3
|
|
|
|
|
) # [G, A, B]
|
|
|
|
|
self.assertEqual(
|
|
|
|
|
self.converter.read(reader, self.font, None),
|
|
|
|
|
{
|
|
|
|
|
"C": "G",
|
|
|
|
|
"D": "A",
|
|
|
|
|
"E": "B",
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def test_readUnknownFormat(self):
|
|
|
|
|
reader = OTTableReader(deHexStr("0009"))
|
|
|
|
|
self.assertRaisesRegex(
|
|
|
|
|
AssertionError,
|
|
|
|
|
"unsupported lookup format: 9",
|
|
|
|
|
self.converter.read,
|
|
|
|
|
reader,
|
|
|
|
|
self.font,
|
|
|
|
|
None,
|
|
|
|
|
)
|
|
|
|
|
|
2017-06-07 18:12:29 +02:00
|
|
|
|
def test_writeFormat0(self):
|
|
|
|
|
writer = OTTableWriter()
|
|
|
|
|
font = FakeFont(".notdef A B C".split())
|
|
|
|
|
self.converter.write(
|
|
|
|
|
writer, font, {}, {".notdef": ".notdef", "A": "C", "B": "C", "C": "A"}
|
|
|
|
|
)
|
|
|
|
|
self.assertEqual(writer.getData(), deHexStr("0000 0000 0003 0003 0001"))
|
|
|
|
|
|
2017-06-13 11:52:01 +02:00
|
|
|
|
def test_writeFormat2(self):
|
|
|
|
|
writer = OTTableWriter()
|
|
|
|
|
font = FakeFont(".notdef A B C D E F G H".split())
|
|
|
|
|
self.converter.write(
|
|
|
|
|
writer,
|
|
|
|
|
font,
|
|
|
|
|
{},
|
|
|
|
|
{
|
|
|
|
|
"B": "C",
|
|
|
|
|
"C": "C",
|
|
|
|
|
"D": "C",
|
|
|
|
|
"E": "C",
|
|
|
|
|
"G": "A",
|
|
|
|
|
"H": "A",
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
self.assertEqual(
|
|
|
|
|
writer.getData(),
|
|
|
|
|
deHexStr(
|
|
|
|
|
"0002 " # format=2
|
|
|
|
|
"0006 " # binSrchHeader.unitSize=6
|
2017-08-16 19:43:25 +02:00
|
|
|
|
"0002 " # binSrchHeader.nUnits=2
|
2017-06-13 11:52:01 +02:00
|
|
|
|
"000C " # binSrchHeader.searchRange=12
|
|
|
|
|
"0001 " # binSrchHeader.entrySelector=1
|
2017-08-16 19:43:25 +02:00
|
|
|
|
"0000 " # binSrchHeader.rangeShift=0
|
2017-06-13 11:52:01 +02:00
|
|
|
|
"0005 0002 0003 " # segments[0].lastGlyph=E, firstGlyph=B, value=C
|
|
|
|
|
"0008 0007 0001 " # segments[1].lastGlyph=H, firstGlyph=G, value=A
|
2017-08-16 19:43:25 +02:00
|
|
|
|
"FFFF FFFF 0000 " # segments[2]=<END>
|
2022-12-13 11:26:36 +00:00
|
|
|
|
),
|
2017-06-13 11:52:01 +02:00
|
|
|
|
)
|
|
|
|
|
|
2017-06-07 18:12:29 +02:00
|
|
|
|
def test_writeFormat6(self):
|
|
|
|
|
writer = OTTableWriter()
|
2017-06-13 11:52:01 +02:00
|
|
|
|
font = FakeFont(".notdef A B C D E".split())
|
2017-06-07 18:12:29 +02:00
|
|
|
|
self.converter.write(
|
|
|
|
|
writer,
|
|
|
|
|
font,
|
|
|
|
|
{},
|
|
|
|
|
{
|
|
|
|
|
"A": "C",
|
2017-06-13 11:52:01 +02:00
|
|
|
|
"C": "B",
|
|
|
|
|
"D": "D",
|
|
|
|
|
"E": "E",
|
2017-06-07 18:12:29 +02:00
|
|
|
|
},
|
|
|
|
|
)
|
2017-06-13 09:42:55 +02:00
|
|
|
|
self.assertEqual(
|
|
|
|
|
writer.getData(),
|
|
|
|
|
deHexStr(
|
|
|
|
|
"0006 " # format=6
|
|
|
|
|
"0004 " # binSrchHeader.unitSize=4
|
2017-08-16 19:43:25 +02:00
|
|
|
|
"0004 " # binSrchHeader.nUnits=4
|
2017-06-13 11:52:01 +02:00
|
|
|
|
"0010 " # binSrchHeader.searchRange=16
|
|
|
|
|
"0002 " # binSrchHeader.entrySelector=2
|
2017-08-16 19:43:25 +02:00
|
|
|
|
"0000 " # binSrchHeader.rangeShift=0
|
2017-06-13 09:42:55 +02:00
|
|
|
|
"0001 0003 " # entries[0].glyph=A, .value=C
|
|
|
|
|
"0003 0002 " # entries[1].glyph=C, .value=B
|
2017-06-13 11:52:01 +02:00
|
|
|
|
"0004 0004 " # entries[2].glyph=D, .value=D
|
|
|
|
|
"0005 0005 " # entries[3].glyph=E, .value=E
|
2017-08-16 19:43:25 +02:00
|
|
|
|
"FFFF 0000 " # entries[4]=<END>
|
2022-12-13 11:26:36 +00:00
|
|
|
|
),
|
2017-06-13 09:42:55 +02:00
|
|
|
|
)
|
2017-06-07 18:12:29 +02:00
|
|
|
|
|
2017-06-13 14:39:13 +02:00
|
|
|
|
def test_writeFormat8(self):
|
|
|
|
|
writer = OTTableWriter()
|
|
|
|
|
font = FakeFont(".notdef A B C D E F G H".split())
|
|
|
|
|
self.converter.write(
|
|
|
|
|
writer,
|
|
|
|
|
font,
|
|
|
|
|
{},
|
|
|
|
|
{
|
|
|
|
|
"B": "B",
|
|
|
|
|
"C": "A",
|
|
|
|
|
"D": "B",
|
|
|
|
|
"E": "C",
|
|
|
|
|
"F": "B",
|
|
|
|
|
"G": "A",
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
self.assertEqual(
|
|
|
|
|
writer.getData(),
|
|
|
|
|
deHexStr(
|
|
|
|
|
"0008 " # format=8
|
|
|
|
|
"0002 " # firstGlyph=B
|
|
|
|
|
"0006 " # glyphCount=6
|
|
|
|
|
"0002 0001 0002 0003 0002 0001" # valueArray=[B, A, B, C, B, A]
|
2022-12-13 11:26:36 +00:00
|
|
|
|
),
|
2017-06-13 14:39:13 +02:00
|
|
|
|
)
|
|
|
|
|
|
2017-06-07 15:00:01 +02:00
|
|
|
|
def test_xmlRead(self):
|
|
|
|
|
value = self.converter.xmlRead(
|
|
|
|
|
{},
|
|
|
|
|
[
|
2017-08-15 19:40:50 +02:00
|
|
|
|
("Lookup", {"glyph": "A", "value": "A.alt"}, []),
|
|
|
|
|
("Lookup", {"glyph": "B", "value": "B.alt"}, []),
|
2017-06-07 15:00:01 +02:00
|
|
|
|
],
|
|
|
|
|
self.font,
|
|
|
|
|
)
|
|
|
|
|
self.assertEqual(value, {"A": "A.alt", "B": "B.alt"})
|
|
|
|
|
|
2017-06-07 14:46:31 +02:00
|
|
|
|
def test_xmlWrite(self):
|
|
|
|
|
writer = makeXMLWriter()
|
2017-06-07 15:00:01 +02:00
|
|
|
|
self.converter.xmlWrite(
|
|
|
|
|
writer,
|
|
|
|
|
self.font,
|
|
|
|
|
value={"A": "A.alt", "B": "B.alt"},
|
2017-06-07 14:46:31 +02:00
|
|
|
|
name="Foo",
|
|
|
|
|
attrs=[("attr", "val")],
|
|
|
|
|
)
|
|
|
|
|
xml = writer.file.getvalue().decode("utf-8").splitlines()
|
|
|
|
|
self.assertEqual(
|
|
|
|
|
xml,
|
|
|
|
|
[
|
|
|
|
|
'<Foo attr="val">',
|
2017-08-15 19:40:50 +02:00
|
|
|
|
' <Lookup glyph="A" value="A.alt"/>',
|
|
|
|
|
' <Lookup glyph="B" value="B.alt"/>',
|
2017-06-07 14:46:31 +02:00
|
|
|
|
"</Foo>",
|
|
|
|
|
],
|
|
|
|
|
)
|
|
|
|
|
|
2017-06-07 10:49:47 +02:00
|
|
|
|
|
2023-12-16 20:58:51 -07:00
|
|
|
|
from fontTools.misc.lazyTools import LazyList
|
|
|
|
|
|
|
|
|
|
|
2017-08-18 17:26:22 +01:00
|
|
|
|
class LazyListTest(unittest.TestCase):
|
|
|
|
|
def test_slice(self):
|
2023-12-16 20:58:51 -07:00
|
|
|
|
ll = LazyList([10, 11, 12, 13])
|
2017-08-18 17:26:22 +01:00
|
|
|
|
sl = ll[:]
|
|
|
|
|
|
|
|
|
|
self.assertIsNot(sl, ll)
|
|
|
|
|
self.assertIsInstance(sl, list)
|
|
|
|
|
self.assertEqual([10, 11, 12, 13], sl)
|
|
|
|
|
|
|
|
|
|
self.assertEqual([11, 12], ll[1:3])
|
|
|
|
|
|
|
|
|
|
def test_add_both_LazyList(self):
|
2023-12-16 20:58:51 -07:00
|
|
|
|
ll1 = LazyList([1])
|
|
|
|
|
ll2 = LazyList([2])
|
2017-08-18 17:26:22 +01:00
|
|
|
|
|
|
|
|
|
l3 = ll1 + ll2
|
|
|
|
|
|
|
|
|
|
self.assertIsInstance(l3, list)
|
|
|
|
|
self.assertEqual([1, 2], l3)
|
|
|
|
|
|
|
|
|
|
def test_add_LazyList_and_list(self):
|
2023-12-16 20:58:51 -07:00
|
|
|
|
ll1 = LazyList([1])
|
2017-08-18 17:26:22 +01:00
|
|
|
|
l2 = [2]
|
|
|
|
|
|
|
|
|
|
l3 = ll1 + l2
|
|
|
|
|
|
|
|
|
|
self.assertIsInstance(l3, list)
|
|
|
|
|
self.assertEqual([1, 2], l3)
|
|
|
|
|
|
|
|
|
|
def test_add_not_implemented(self):
|
|
|
|
|
with self.assertRaises(TypeError):
|
2023-12-16 20:58:51 -07:00
|
|
|
|
LazyList() + 0
|
2017-08-18 17:26:22 +01:00
|
|
|
|
with self.assertRaises(TypeError):
|
2023-12-16 20:58:51 -07:00
|
|
|
|
LazyList() + tuple()
|
2017-08-18 17:26:22 +01:00
|
|
|
|
|
|
|
|
|
def test_radd_list_and_LazyList(self):
|
|
|
|
|
l1 = [1]
|
2023-12-16 20:58:51 -07:00
|
|
|
|
ll2 = LazyList([2])
|
2017-08-18 17:26:22 +01:00
|
|
|
|
|
|
|
|
|
l3 = l1 + ll2
|
|
|
|
|
|
|
|
|
|
self.assertIsInstance(l3, list)
|
|
|
|
|
self.assertEqual([1, 2], l3)
|
|
|
|
|
|
|
|
|
|
def test_radd_not_implemented(self):
|
|
|
|
|
with self.assertRaises(TypeError):
|
2023-12-16 20:58:51 -07:00
|
|
|
|
0 + LazyList()
|
2017-08-18 17:26:22 +01:00
|
|
|
|
with self.assertRaises(TypeError):
|
2023-12-16 20:58:51 -07:00
|
|
|
|
tuple() + LazyList()
|
2017-08-18 17:26:22 +01:00
|
|
|
|
|
|
|
|
|
|
2015-10-17 06:47:52 +02:00
|
|
|
|
if __name__ == "__main__":
|
2017-01-11 13:05:35 +00:00
|
|
|
|
import sys
|
2022-12-13 11:26:36 +00:00
|
|
|
|
|
2017-01-11 13:05:35 +00:00
|
|
|
|
sys.exit(unittest.main())
|