Skip to content

Commit d9bc309

Browse files
authored
Merge pull request #165 from fonttools/unlazify-data-images
Unlazify `data` and `images` on comparison
2 parents 07dcbbd + 4341214 commit d9bc309

File tree

3 files changed

+55
-5
lines changed

3 files changed

+55
-5
lines changed

src/ufoLib2/objects/misc.py

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
Type,
1616
TypeVar,
1717
Union,
18+
cast,
1819
)
1920

2021
import attr
@@ -125,7 +126,7 @@ class Placeholder:
125126
Tds = TypeVar("Tds", bound="DataStore")
126127

127128

128-
@attr.s(auto_attribs=True, slots=True, repr=False)
129+
@attr.s(auto_attribs=True, slots=True, repr=False, eq=False)
129130
class DataStore(MutableMapping):
130131
"""Represents the base class for ImageSet and DataSet.
131132
@@ -135,10 +136,34 @@ class DataStore(MutableMapping):
135136

136137
_data: Dict[str, Union[bytes, Placeholder]] = attr.ib(factory=dict)
137138

139+
_lazy: Optional[bool] = attr.ib(default=False, kw_only=True, cmp=False, init=False)
138140
_reader: Optional[UFOReader] = attr.ib(
139-
default=None, init=False, repr=False, eq=False
141+
default=None, init=False, repr=False, cmp=False
140142
)
141-
_scheduledForDeletion: Set[str] = attr.ib(factory=set, init=False, repr=False)
143+
_scheduledForDeletion: Set[str] = attr.ib(
144+
factory=set, init=False, repr=False, cmp=False
145+
)
146+
147+
def __eq__(self, other: object) -> bool:
148+
# same as attrs-defined __eq__ method, only that it un-lazifies DataStores
149+
# if needed.
150+
# NOTE: Avoid isinstance check that mypy recognizes because we don't want to
151+
# test possible Font subclasses for equality.
152+
if other.__class__ is not self.__class__:
153+
return NotImplemented
154+
other = cast(DataStore, other)
155+
156+
for data_store in (self, other):
157+
if data_store._lazy:
158+
data_store.unlazify()
159+
160+
return self._data == other._data
161+
162+
def __ne__(self, other: object) -> bool:
163+
result = self.__eq__(other)
164+
if result is NotImplemented:
165+
return NotImplemented
166+
return not result
142167

143168
@classmethod
144169
def read(cls: Type[Tds], reader: UFOReader, lazy: bool = True) -> Tds:
@@ -149,6 +174,7 @@ def read(cls: Type[Tds], reader: UFOReader, lazy: bool = True) -> Tds:
149174
self._data[fileName] = _NOT_LOADED
150175
else:
151176
self._data[fileName] = cls.read_data(reader, fileName)
177+
self._lazy = lazy
152178
if lazy:
153179
self._reader = reader
154180
return self
@@ -179,8 +205,11 @@ def remove_data(writer: UFOWriter, filename: str) -> None:
179205

180206
def unlazify(self) -> None:
181207
"""Load all data into memory."""
182-
for _ in self.items():
183-
pass
208+
if self._lazy:
209+
assert self._reader is not None
210+
for _ in self.items():
211+
pass
212+
self._lazy = False
184213

185214
__deepcopy__ = _deepcopy_unlazify_attrs
186215

345 Bytes
Loading

tests/test_ufoLib2.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,27 @@ def test_unlazify(datadir):
113113
assert font._lazy is False
114114

115115

116+
def test_auto_unlazify_font(datadir):
117+
font1 = ufoLib2.Font.open(datadir / "UbuTestData.ufo", lazy=True)
118+
font2 = ufoLib2.Font.open(datadir / "UbuTestData.ufo", lazy=False)
119+
120+
assert font1 == font2
121+
122+
123+
def test_auto_unlazify_data(datadir):
124+
font1 = ufoLib2.Font.open(datadir / "UbuTestData.ufo", lazy=True)
125+
font2 = ufoLib2.Font.open(datadir / "UbuTestData.ufo", lazy=False)
126+
127+
assert font1.data == font2.data
128+
129+
130+
def test_auto_unlazify_images(datadir):
131+
font1 = ufoLib2.Font.open(datadir / "UbuTestData.ufo", lazy=True)
132+
font2 = ufoLib2.Font.open(datadir / "UbuTestData.ufo", lazy=False)
133+
134+
assert font1.images == font2.images
135+
136+
116137
def test_font_eq_and_ne(ufo_UbuTestData):
117138
font1 = ufo_UbuTestData
118139
font2 = deepcopy(font1)

0 commit comments

Comments
 (0)