Skip to content

Commit

Permalink
[py3] Ported django.utils.functional.
Browse files Browse the repository at this point in the history
  • Loading branch information
aaugustin committed Aug 7, 2012
1 parent 7e01e53 commit fe8484e
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 31 deletions.
58 changes: 37 additions & 21 deletions django/utils/functional.py
Expand Up @@ -93,13 +93,19 @@ def __prepare_class__(cls):
if hasattr(cls, k): if hasattr(cls, k):
continue continue
setattr(cls, k, meth) setattr(cls, k, meth)
cls._delegate_str = bytes in resultclasses cls._delegate_bytes = bytes in resultclasses
cls._delegate_unicode = six.text_type in resultclasses cls._delegate_text = six.text_type in resultclasses
assert not (cls._delegate_str and cls._delegate_unicode), "Cannot call lazy() with both str and unicode return types." assert not (cls._delegate_bytes and cls._delegate_text), "Cannot call lazy() with both bytes and text return types."
if cls._delegate_unicode: if cls._delegate_text:
cls.__unicode__ = cls.__unicode_cast if six.PY3:
elif cls._delegate_str: cls.__str__ = cls.__text_cast
cls.__str__ = cls.__str_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__) __prepare_class__ = classmethod(__prepare_class__)


def __promise__(cls, klass, funcname, method): def __promise__(cls, klass, funcname, method):
Expand All @@ -120,17 +126,17 @@ def __wrapper__(self, *args, **kw):
return __wrapper__ return __wrapper__
__promise__ = classmethod(__promise__) __promise__ = classmethod(__promise__)


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


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


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


Expand All @@ -144,10 +150,12 @@ def __lt__(self, other):
other = other.__cast() other = other.__cast()
return self.__cast() < other return self.__cast() < other


__hash__ = object.__hash__

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




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

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


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


__str__ = new_method_proxy(bytes) if six.PY3:
__unicode__ = new_method_proxy(six.text_type) __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): def __deepcopy__(self, memo):
if self._wrapped is empty: if self._wrapped is empty:
Expand All @@ -284,7 +299,8 @@ def __getstate__(self):
__class__ = property(new_method_proxy(operator.attrgetter("__class__"))) __class__ = property(new_method_proxy(operator.attrgetter("__class__")))
__eq__ = new_method_proxy(operator.eq) __eq__ = new_method_proxy(operator.eq)
__hash__ = new_method_proxy(hash) __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): class lazy_property(property):
Expand Down
4 changes: 2 additions & 2 deletions django/utils/safestring.py
Expand Up @@ -96,7 +96,7 @@ def mark_safe(s):
""" """
if isinstance(s, SafeData): if isinstance(s, SafeData):
return s 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) return SafeString(s)
if isinstance(s, (six.text_type, Promise)): if isinstance(s, (six.text_type, Promise)):
return SafeUnicode(s) return SafeUnicode(s)
Expand All @@ -112,7 +112,7 @@ def mark_for_escaping(s):
""" """
if isinstance(s, (SafeData, EscapeData)): if isinstance(s, (SafeData, EscapeData)):
return s 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) return EscapeString(s)
if isinstance(s, (six.text_type, Promise)): if isinstance(s, (six.text_type, Promise)):
return EscapeUnicode(s) return EscapeUnicode(s)
Expand Down
26 changes: 18 additions & 8 deletions tests/regressiontests/utils/simplelazyobject.py
Expand Up @@ -19,17 +19,27 @@ def __eq__(self, other):
def __hash__(self): def __hash__(self):
return hash(self.name) return hash(self.name)


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


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

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

def __unicode__(self):
return self.name


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



complex_object = lambda: _ComplexObject("joe") complex_object = lambda: _ComplexObject("joe")



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


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


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


def test_class(self): def test_class(self):
Expand Down

0 comments on commit fe8484e

Please sign in to comment.