I have an application where the composition of a string and display of the localized version to the user happen in different parts at different times and I use pickle to throw around objects between them. While being not the most elegant thing ever seen, that worked perfectly fine with Flask-Babel 0.9 and speaklater 1.3.
However, since Flask-Babel 0.10 with its integrated speaklater, unpickling a LazyString gives a RuntimeError: maximum recursion depth exceeded:
File "/usr/local/lib/python3.4/dist-packages/flask_babel/speaklater.py", line 12, in __getattr__
string = text_type(self)
File "/usr/local/lib/python3.4/dist-packages/flask_babel/speaklater.py", line 18, in __str__
return text_type(self._func(*self._args, **self._kwargs))
File "/usr/local/lib/python3.4/dist-packages/flask_babel/speaklater.py", line 12, in __getattr__
string = text_type(self)
File "/usr/local/lib/python3.4/dist-packages/flask_babel/speaklater.py", line 18, in __str__
return text_type(self._func(*self._args, **self._kwargs))
File "/usr/local/lib/python3.4/dist-packages/flask_babel/speaklater.py", line 12, in __getattr__
string = text_type(self)
[...]
This seems to happen when pickle upon unpickling tries to call __setstate__. This leads to __getattr__ being called which in turn calls __str__ but since the object is not yet unpickled, pickle tries to do that, leading to __getattr__ being called for __setstate__ which wants to call __str__...
A minimal example to reproduce the bug would be the following:
I have an application where the composition of a string and display of the localized version to the user happen in different parts at different times and I use pickle to throw around objects between them. While being not the most elegant thing ever seen, that worked perfectly fine with Flask-Babel 0.9 and speaklater 1.3.
However, since Flask-Babel 0.10 with its integrated speaklater, unpickling a LazyString gives a
RuntimeError: maximum recursion depth exceeded
:This seems to happen when pickle upon unpickling tries to call
__setstate__
. This leads to__getattr__
being called which in turn calls__str__
but since the object is not yet unpickled, pickle tries to do that, leading to__getattr__
being called for__setstate__
which wants to call__str__
...A minimal example to reproduce the bug would be the following:
s1
ands2
look okay:Pickling and unpickling
s1
works as expected:However, trying the same thing with
s2
fails: