Move lazy datastructures to misc.lazyTools

This commit is contained in:
Behdad Esfahbod 2023-12-16 20:58:51 -07:00
parent 3806fd2558
commit 3ff2ee61e1
4 changed files with 60 additions and 58 deletions

View File

@ -0,0 +1,42 @@
from collections import UserDict, UserList
__all__ = ["LazyDict", "LazyList"]
class LazyDict(UserDict):
def __init__(self, data):
super().__init__()
self.data = data
def __getitem__(self, k):
v = self.data[k]
if callable(v):
v = v(self, k)
self.data[k] = v
return v
class LazyList(UserList):
def __getitem__(self, k):
if isinstance(k, slice):
indices = range(*k.indices(len(self)))
return [self[i] for i in indices]
v = self.data[k]
if callable(v):
v = v(self, k)
self.data[k] = v
return v
def __add__(self, other):
if isinstance(other, LazyList):
other = list(other)
elif isinstance(other, list):
pass
else:
return NotImplemented
return list(self) + other
def __radd__(self, other):
if not isinstance(other, list):
return NotImplemented
return other + list(self)

View File

@ -1,7 +1,8 @@
from collections import UserDict, deque from collections import deque
from functools import partial from functools import partial
from fontTools.misc import sstruct from fontTools.misc import sstruct
from fontTools.misc.textTools import safeEval from fontTools.misc.textTools import safeEval
from fontTools.misc.lazyTools import LazyDict
from . import DefaultTable from . import DefaultTable
import array import array
import itertools import itertools
@ -39,19 +40,6 @@ GVAR_HEADER_FORMAT = """
GVAR_HEADER_SIZE = sstruct.calcsize(GVAR_HEADER_FORMAT) GVAR_HEADER_SIZE = sstruct.calcsize(GVAR_HEADER_FORMAT)
class _LazyDict(UserDict):
def __init__(self, data):
super().__init__()
self.data = data
def __getitem__(self, k):
v = self.data[k]
if callable(v):
v = v(self, k)
self.data[k] = v
return v
def _decompileVarGlyph(self, glyphName): def _decompileVarGlyph(self, glyphName):
gid = self.reverseGlyphMap[glyphName] gid = self.reverseGlyphMap[glyphName]
offsetSize = 2 if self.tableFormat == 0 else 4 offsetSize = 2 if self.tableFormat == 0 else 4
@ -143,7 +131,7 @@ class table__g_v_a_r(DefaultTable.DefaultTable):
offsetToData = self.offsetToGlyphVariationData offsetToData = self.offsetToGlyphVariationData
glyf = ttFont["glyf"] glyf = ttFont["glyf"]
l = _LazyDict( l = LazyDict(
{glyphs[gid]: _decompileVarGlyph for gid in range(self.glyphCount)} {glyphs[gid]: _decompileVarGlyph for gid in range(self.glyphCount)}
) )
l.reverseGlyphMap = ttFont.getReverseGlyphMap() l.reverseGlyphMap = ttFont.getReverseGlyphMap()

View File

@ -8,6 +8,7 @@ from fontTools.misc.fixedTools import (
) )
from fontTools.misc.roundTools import nearestMultipleShortestRepr, otRound from fontTools.misc.roundTools import nearestMultipleShortestRepr, otRound
from fontTools.misc.textTools import bytesjoin, tobytes, tostr, pad, safeEval from fontTools.misc.textTools import bytesjoin, tobytes, tostr, pad, safeEval
from fontTools.misc.lazyTools import LazyList
from fontTools.ttLib import getSearchRange from fontTools.ttLib import getSearchRange
from .otBase import ( from .otBase import (
CountReference, CountReference,
@ -108,38 +109,6 @@ def buildConverters(tableSpec, tableNamespace):
return converters, convertersByName return converters, convertersByName
try:
from collections import UserList
except ImportError:
from UserList import UserList
class _LazyList(UserList):
def __getitem__(self, k):
if isinstance(k, slice):
indices = range(*k.indices(len(self)))
return [self[i] for i in indices]
v = self.data[k]
if callable(v):
v = v(self, k)
self.data[k] = v
return v
def __add__(self, other):
if isinstance(other, _LazyList):
other = list(other)
elif isinstance(other, list):
pass
else:
return NotImplemented
return list(self) + other
def __radd__(self, other):
if not isinstance(other, list):
return NotImplemented
return other + list(self)
def _base_converter_read_item(self, i): def _base_converter_read_item(self, i):
self.reader.seek(self.pos + i * self.recordSize) self.reader.seek(self.pos + i * self.recordSize)
return self.conv.read(self.reader, self.font, {}) return self.conv.read(self.reader, self.font, {})
@ -192,7 +161,7 @@ class BaseConverter(object):
l.append(self.read(reader, font, tableDict)) l.append(self.read(reader, font, tableDict))
return l return l
else: else:
l = _LazyList(_base_converter_read_item for i in range(count)) l = LazyList(_base_converter_read_item for i in range(count))
l.reader = reader.copy() l.reader = reader.copy()
l.pos = l.reader.pos l.pos = l.reader.pos
l.font = font l.font = font
@ -1893,7 +1862,7 @@ class CFF2Index(BaseConverter):
lastOffset = offset lastOffset = offset
return items return items
else: else:
l = _LazyList([cff2_index_read_item] * count) l = LazyList([cff2_index_read_item] * count)
l.reader = reader.copy() l.reader = reader.copy()
l.offset_pos = l.reader.pos l.offset_pos = l.reader.pos
l.data_pos = l.offset_pos + (count + 1) * offSize l.data_pos = l.offset_pos + (count + 1) * offSize

View File

@ -427,9 +427,12 @@ class AATLookupTest(unittest.TestCase):
) )
from fontTools.misc.lazyTools import LazyList
class LazyListTest(unittest.TestCase): class LazyListTest(unittest.TestCase):
def test_slice(self): def test_slice(self):
ll = otConverters._LazyList([10, 11, 12, 13]) ll = LazyList([10, 11, 12, 13])
sl = ll[:] sl = ll[:]
self.assertIsNot(sl, ll) self.assertIsNot(sl, ll)
@ -439,8 +442,8 @@ class LazyListTest(unittest.TestCase):
self.assertEqual([11, 12], ll[1:3]) self.assertEqual([11, 12], ll[1:3])
def test_add_both_LazyList(self): def test_add_both_LazyList(self):
ll1 = otConverters._LazyList([1]) ll1 = LazyList([1])
ll2 = otConverters._LazyList([2]) ll2 = LazyList([2])
l3 = ll1 + ll2 l3 = ll1 + ll2
@ -448,7 +451,7 @@ class LazyListTest(unittest.TestCase):
self.assertEqual([1, 2], l3) self.assertEqual([1, 2], l3)
def test_add_LazyList_and_list(self): def test_add_LazyList_and_list(self):
ll1 = otConverters._LazyList([1]) ll1 = LazyList([1])
l2 = [2] l2 = [2]
l3 = ll1 + l2 l3 = ll1 + l2
@ -458,13 +461,13 @@ class LazyListTest(unittest.TestCase):
def test_add_not_implemented(self): def test_add_not_implemented(self):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
otConverters._LazyList() + 0 LazyList() + 0
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
otConverters._LazyList() + tuple() LazyList() + tuple()
def test_radd_list_and_LazyList(self): def test_radd_list_and_LazyList(self):
l1 = [1] l1 = [1]
ll2 = otConverters._LazyList([2]) ll2 = LazyList([2])
l3 = l1 + ll2 l3 = l1 + ll2
@ -473,9 +476,9 @@ class LazyListTest(unittest.TestCase):
def test_radd_not_implemented(self): def test_radd_not_implemented(self):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
0 + otConverters._LazyList() 0 + LazyList()
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
tuple() + otConverters._LazyList() tuple() + LazyList()
if __name__ == "__main__": if __name__ == "__main__":