[cffLib] Fix RecursionError in BaseDict.__getattr__ when unpickling
We need to raise AttributeError for non-existing dunder methods like '__deepcopy__' or '__getstate__', because deepcopy() and pickle.load() test for these on the instance using getattr() and treat the resulting AttributeError as a signal that the object doesn't implement these custom hooks. If we don't do that, we enter an infinite recursion as we attempt to look up the missing dunder methods in the 'rawDict' dictionary, because 'rawDict' is set inside __init__, but __init__ is not invoked while unpickling (only __new__ is); thus self.rawDict is also missing and __getattr__ is invoked with argument 'rawDict' again and again until it crashes with RecursionError. Phew. Fixes https://github.com/fonttools/fonttools/pull/1488
This commit is contained in:
parent
8832062c40
commit
649dc49dba
@ -2242,6 +2242,12 @@ class BaseDict(object):
|
||||
return self.compilerClass(self, strings, parent, isCFF2=isCFF2)
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name[:2] == name[-2:] == "__":
|
||||
# to make deepcopy() and pickle.load() work, we need to signal with
|
||||
# AttributeError that dunder methods like '__deepcopy__' or '__getstate__'
|
||||
# aren't implemented. For more details, see:
|
||||
# https://github.com/fonttools/fonttools/pull/1488
|
||||
raise AttributeError(name)
|
||||
value = self.rawDict.get(name, None)
|
||||
if value is None:
|
||||
value = self.defaults.get(name)
|
||||
|
Loading…
x
Reference in New Issue
Block a user