Commit fe8484ef authored by Aymeric Augustin's avatar Aymeric Augustin
Browse files

[py3] Ported django.utils.functional.

parent 7e01e532
Loading
Loading
Loading
Loading
+37 −21
Original line number Diff line number Diff line
@@ -93,13 +93,19 @@ def lazy(func, *resultclasses):
                        if hasattr(cls, k):
                            continue
                        setattr(cls, k, meth)
            cls._delegate_str = bytes in resultclasses
            cls._delegate_unicode = six.text_type in resultclasses
            assert not (cls._delegate_str and cls._delegate_unicode), "Cannot call lazy() with both str and unicode return types."
            if cls._delegate_unicode:
                cls.__unicode__ = cls.__unicode_cast
            elif cls._delegate_str:
                cls.__str__ = cls.__str_cast
            cls._delegate_bytes = bytes in resultclasses
            cls._delegate_text = six.text_type in resultclasses
            assert not (cls._delegate_bytes and cls._delegate_text), "Cannot call lazy() with both bytes and text return types."
            if cls._delegate_text:
                if six.PY3:
                    cls.__str__ = cls.__text_cast
                else:
                    cls.__unicode__ = cls.__text_cast
            elif cls._delegate_bytes:
                if six.PY3:
                    cls.__bytes__ = cls.__bytes_cast
                else:
                    cls.__str__ = cls.__bytes_cast
        __prepare_class__ = classmethod(__prepare_class__)

        def __promise__(cls, klass, funcname, method):
@@ -120,17 +126,17 @@ def lazy(func, *resultclasses):
            return __wrapper__
        __promise__ = classmethod(__promise__)

        def __unicode_cast(self):
        def __text_cast(self):
            return func(*self.__args, **self.__kw)

        def __str_cast(self):
            return str(func(*self.__args, **self.__kw))
        def __bytes_cast(self):
            return bytes(func(*self.__args, **self.__kw))

        def __cast(self):
            if self._delegate_str:
                return self.__str_cast()
            elif self._delegate_unicode:
                return self.__unicode_cast()
            if self._delegate_bytes:
                return self.__bytes_cast()
            elif self._delegate_text:
                return self.__text_cast()
            else:
                return func(*self.__args, **self.__kw)

@@ -144,10 +150,12 @@ def lazy(func, *resultclasses):
                other = other.__cast()
            return self.__cast() < other

        __hash__ = object.__hash__

        def __mod__(self, rhs):
            if self._delegate_str:
                return str(self) % rhs
            elif self._delegate_unicode:
            if self._delegate_bytes and not six.PY3:
                return bytes(self) % rhs
            elif self._delegate_text:
                return six.text_type(self) % rhs
            else:
                raise AssertionError('__mod__ not supported for non-string types')
@@ -234,6 +242,9 @@ class LazyObject(object):
    __dir__ = new_method_proxy(dir)


# Workaround for http://bugs.python.org/issue12370
_super = super

class SimpleLazyObject(LazyObject):
    """
    A lazy object initialised from any function.
@@ -251,13 +262,17 @@ class SimpleLazyObject(LazyObject):
        value.
        """
        self.__dict__['_setupfunc'] = func
        super(SimpleLazyObject, self).__init__()
        _super(SimpleLazyObject, self).__init__()

    def _setup(self):
        self._wrapped = self._setupfunc()

    __str__ = new_method_proxy(bytes)
    __unicode__ = new_method_proxy(six.text_type)
    if six.PY3:
        __bytes__ = new_method_proxy(bytes)
        __str__ = new_method_proxy(str)
    else:
        __str__ = new_method_proxy(str)
        __unicode__ = new_method_proxy(unicode)

    def __deepcopy__(self, memo):
        if self._wrapped is empty:
@@ -284,7 +299,8 @@ class SimpleLazyObject(LazyObject):
    __class__ = property(new_method_proxy(operator.attrgetter("__class__")))
    __eq__ = new_method_proxy(operator.eq)
    __hash__ = new_method_proxy(hash)
    __nonzero__ = new_method_proxy(bool)
    __bool__ = new_method_proxy(bool)       # Python 3
    __nonzero__ = __bool__                  # Python 2


class lazy_property(property):
+2 −2
Original line number Diff line number Diff line
@@ -96,7 +96,7 @@ def mark_safe(s):
    """
    if isinstance(s, SafeData):
        return s
    if isinstance(s, bytes) or (isinstance(s, Promise) and s._delegate_str):
    if isinstance(s, bytes) or (isinstance(s, Promise) and s._delegate_bytes):
        return SafeString(s)
    if isinstance(s, (six.text_type, Promise)):
        return SafeUnicode(s)
@@ -112,7 +112,7 @@ def mark_for_escaping(s):
    """
    if isinstance(s, (SafeData, EscapeData)):
        return s
    if isinstance(s, bytes) or (isinstance(s, Promise) and s._delegate_str):
    if isinstance(s, bytes) or (isinstance(s, Promise) and s._delegate_bytes):
        return EscapeString(s)
    if isinstance(s, (six.text_type, Promise)):
        return EscapeUnicode(s)
+18 −8
Original line number Diff line number Diff line
@@ -19,17 +19,27 @@ class _ComplexObject(object):
    def __hash__(self):
        return hash(self.name)

    if six.PY3:
        def __bytes__(self):
            return ("I am _ComplexObject(%r)" % self.name).encode("utf-8")

        def __str__(self):
            return self.name

    else:
        def __str__(self):
        return "I am _ComplexObject(%r)" % self.name
            return b"I am _ComplexObject(%r)" % str(self.name)

        def __unicode__(self):
        return six.text_type(self.name)
            return self.name

    def __repr__(self):
        return "_ComplexObject(%r)" % self.name


complex_object = lambda: _ComplexObject("joe")


class TestUtilsSimpleLazyObject(TestCase):
    """
    Tests for SimpleLazyObject
@@ -54,11 +64,11 @@ class TestUtilsSimpleLazyObject(TestCase):
        # proxy __repr__
        self.assertTrue("SimpleLazyObject" in repr(SimpleLazyObject(complex_object)))

    def test_str(self):
        self.assertEqual(str_prefix("I am _ComplexObject(%(_)s'joe')"),
            str(SimpleLazyObject(complex_object)))
    def test_bytes(self):
        self.assertEqual(b"I am _ComplexObject('joe')",
                bytes(SimpleLazyObject(complex_object)))

    def test_unicode(self):
    def test_text(self):
        self.assertEqual("joe", six.text_type(SimpleLazyObject(complex_object)))

    def test_class(self):