Импортировать объект из встроенных объектов, влияющих только на один класс - PullRequest
0 голосов
/ 29 августа 2018

Я конвертирую код из python2 в python3 для newstyle классов, используя future. Мой проект в Джанго 1.11

У меня есть класс в forms.py как:

class Address:
    ...rest of code...

class AddressForm(Address, forms.ModelForm):
    ...rest of code...

в Python 2

, который преобразуется в:

from buitlins import object
class Address(object):
        ...rest of code...

class AddressForm(Address, forms.ModelForm):
    ...rest of code...

в Python 3

У меня есть тест на селен, который не проходит, когда эта форма вызывается после ее преобразования в Python3 со следующей ошибкой:

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

Однако, когда я удаляю импорт from buitlins import object, тест проходит.

Но поскольку я добавил проверку в будущем, я получаю ошибку разницы в будущем, и поэтому каждый класс должен быть преобразован в новый стиль. Я хочу, чтобы он работал как в Python2, так и в Python3.

Есть ли способ, которым импорт модуля builtins может повлиять только на один класс, но не на другие в файле forms.py. Или есть другой способ справиться с этим?

Ответы [ 2 ]

0 голосов
/ 29 августа 2018

Проблема, с которой вы столкнулись, похоже, связана с борьбой двух разных инструментов модернизации Python 2. Вы, кажется, используете декоратор python_2_unicode_compatible из 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

и наследуется от newobject, который имеет этот __unicode__ метод

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')

И поскольку у них есть несколько разные стратегии предоставления методов __unicode__ и __str__, они бесконечно вызывали друг друга, вызывая вашу ошибку рекурсии.

Модуль, предоставляющий builtins.object, имеет собственный декоратор python_2_unicode_compatible. Вы пытались использовать это по сравнению с django.utils.six?

0 голосов
/ 29 августа 2018

Это путь python2.

class Address(object):

В классах python3 объект наследуется неявно, поэтому так и должно быть;

class Address:
...