From 0ea5bf88dddd7fbdef7fe8d00162c9753565f5c0 Mon Sep 17 00:00:00 2001
From: Preston Holmes <preston@ptone.com>
Date: Wed, 6 Mar 2013 16:00:05 -0800
Subject: [PATCH] Fixed #19543 -- implemented SimpleLazyObject.__repr__

Thanks to Florian Hahn for the patch
---
 django/utils/functional.py            |  9 +++++++++
 docs/releases/1.6.txt                 |  3 +++
 tests/utils_tests/simplelazyobject.py | 16 ++++++++++++----
 3 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/django/utils/functional.py b/django/utils/functional.py
index 69a32b101a..3e58674501 100644
--- a/django/utils/functional.py
+++ b/django/utils/functional.py
@@ -305,6 +305,15 @@ class SimpleLazyObject(LazyObject):
     def __reduce__(self):
         return (self.__newobj__, (self.__class__,), self.__getstate__())
 
+    # Return a meaningful representation of the lazy object for debugging
+    # without evaluating the wrapped object.
+    def __repr__(self):
+        if self._wrapped is empty:
+            repr_attr = self._setupfunc
+        else:
+            repr_attr = self._wrapped
+        return '<SimpleLazyObject: %r>' % repr_attr
+
     # Need to pretend to be the wrapped class, for the sake of objects that care
     # about this (especially in equality tests)
     __class__ = property(new_method_proxy(operator.attrgetter("__class__")))
diff --git a/docs/releases/1.6.txt b/docs/releases/1.6.txt
index 609557073e..599da6847c 100644
--- a/docs/releases/1.6.txt
+++ b/docs/releases/1.6.txt
@@ -131,6 +131,9 @@ Minor features
   :setting:`TEMPLATE_STRING_IF_INVALID` for variables not present in the
   context, just like other template constructs.
 
+* SimpleLazyObjects will now present more helpful representations in shell
+  debugging situations.
+
 Backwards incompatible changes in 1.6
 =====================================
 
diff --git a/tests/utils_tests/simplelazyobject.py b/tests/utils_tests/simplelazyobject.py
index 3f81e8f608..dd52857c03 100644
--- a/tests/utils_tests/simplelazyobject.py
+++ b/tests/utils_tests/simplelazyobject.py
@@ -59,10 +59,18 @@ class TestUtilsSimpleLazyObject(TestCase):
                          hash(SimpleLazyObject(complex_object)))
 
     def test_repr(self):
-        # For debugging, it will really confuse things if there is no clue that
-        # SimpleLazyObject is actually a proxy object. So we don't
-        # proxy __repr__
-        self.assertTrue("SimpleLazyObject" in repr(SimpleLazyObject(complex_object)))
+        # First, for an unevaluated SimpleLazyObject
+        x = SimpleLazyObject(complex_object)
+        # __repr__ contains __repr__ of setup function and does not evaluate
+        # the SimpleLazyObject
+        self.assertEqual("<SimpleLazyObject: %r>" % complex_object, repr(x))
+        self.assertEqual(empty, x._wrapped)
+
+        # Second, for an evaluated SimpleLazyObject
+        name = x.name # evaluate
+        self.assertTrue(isinstance(x._wrapped, _ComplexObject))
+        # __repr__ contains __repr__ of wrapped object
+        self.assertEqual("<SimpleLazyObject: %r>" % x._wrapped, repr(x))
 
     def test_bytes(self):
         self.assertEqual(b"I am _ComplexObject('joe')",