I am converting code from python2 to python3 for newstyle
classes using future
. My project is in Django 1.11
I have a class in forms.py as:
class Address:
...rest of code...
class AddressForm(Address, forms.ModelForm):
...rest of code...
in Python 2
which is converted to :
from buitlins import object
class Address(object):
...rest of code...
class AddressForm(Address, forms.ModelForm):
...rest of code...
in Python 3
I have a selenium test that fails when this Form is invoked after it is converted to Python3 with the following error:
File "<path_to_venv>/local/lib/python2.7/site-packages/django/utils/six.py", line 842, in <lambda>
klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
File "<path_to_venv>/local/lib/python2.7/site-packages/future/types/newobject.py", line 78, in __unicode__
s = type(self).__str__(self)
RuntimeError: maximum recursion depth exceeded
However, when I remove the import from buitlins import object
the test passes.
But as I have added a future check, I get a future difference error & thus every class has to be converted to newstyle. I want it to work in both Python2 and Python3.
Is there a way this module builtins
module import can affect just one class and not others in the forms.py
file. Or is there some other method to handle this?
The problem you're running up against seems to be from two different Python 2 modernization tools fighting. You seem to be using the python_2_unicode_compatible
decorator from django.utils.six
def python_2_unicode_compatible(klass):
"""
A decorator that defines __unicode__ and __str__ methods under Python 2.
Under Python 3 it does nothing.
To support Python 2 and 3 with a single code base, define a __str__ method
returning text and apply this decorator to the class.
"""
if PY2:
if '__str__' not in klass.__dict__:
raise ValueError("@python_2_unicode_compatible cannot be applied "
"to %s because it doesn't define __str__()." %
klass.__name__)
klass.__unicode__ = klass.__str__
klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
return klass
and inheriting from newobject
, which has this __unicode__
method
def __unicode__(self):
# All subclasses of the builtin object should have __str__ defined.
# Note that old-style classes do not have __str__ defined.
if hasattr(self, '__str__'):
s = type(self).__str__(self)
else:
s = str(self)
if isinstance(s, unicode):
return s
else:
return s.decode('utf-8')
And because the two have slightly different strategies for providing both __unicode__
and __str__
methods, they ed up calling each other infinitely, which leads to your recursion error.
The module that provides builtins.object provides its own python_2_unicode_compatible
decorator. Have you tried using that over the one from django.utils.six
?