Improved error message for undefineds
authorArmin Ronacher <armin.ronacher@active-4.com>
Mon, 12 Apr 2010 13:49:59 +0000 (15:49 +0200)
committerArmin Ronacher <armin.ronacher@active-4.com>
Mon, 12 Apr 2010 13:49:59 +0000 (15:49 +0200)
--HG--
branch : trunk

jinja2/runtime.py
jinja2/testsuite/api.py
jinja2/utils.py

index 16389e04e4375e4d699de3eb37aef2311339e1a1..1961e9f12684a23a0cabd04ab08b18f5935bf819 100644 (file)
@@ -12,7 +12,8 @@ import sys
 from itertools import chain, imap
 from jinja2.nodes import EvalContext
 from jinja2.utils import Markup, partial, soft_unicode, escape, missing, \
-     concat, MethodType, FunctionType, internalcode, next
+     concat, MethodType, FunctionType, internalcode, next, \
+     object_type_repr
 from jinja2.exceptions import UndefinedError, TemplateRuntimeError, \
      TemplateNotFound
 
@@ -437,13 +438,13 @@ class Undefined(object):
             if self._undefined_obj is missing:
                 hint = '%r is undefined' % self._undefined_name
             elif not isinstance(self._undefined_name, basestring):
-                hint = '%r object has no element %r' % (
-                    self._undefined_obj.__class__.__name__,
+                hint = '%s has no element %r' % (
+                    object_type_repr(self._undefined_obj),
                     self._undefined_name
                 )
             else:
-                hint = '%r object has no attribute %r' % (
-                    self._undefined_obj.__class__.__name__,
+                hint = '%r has no attribute %r' % (
+                    object_type_repr(self._undefined_obj),
                     self._undefined_name
                 )
         else:
@@ -501,7 +502,7 @@ class DebugUndefined(Undefined):
             if self._undefined_obj is missing:
                 return u'{{ %s }}' % self._undefined_name
             return '{{ no such element: %s[%r] }}' % (
-                self._undefined_obj.__class__.__name__,
+                object_type_repr(self._undefined_obj),
                 self._undefined_name
             )
         return u'{{ undefined value printed: %s }}' % self._undefined_hint
index 4134d26225f2adb3264125193c634ad738dfee93..dfd8b640f2ebac88b5e2ff6819b40d2e71ac5d93 100644 (file)
@@ -207,11 +207,19 @@ class UndefinedTestCase(JinjaTestCase):
         t = Template("{{ var[42].foo }}")
         assert_raises(UndefinedError, t.render, var=0)
 
-    def test_none_gives_propert_error(self):
+    def test_none_gives_proper_error(self):
         try:
-            Undefined(None).split()
+            Environment().getattr(None, 'split')
         except UndefinedError, e:
-            assert e.message == 'None is not defined'
+            assert e.message == "None has no attribute 'split'"
+        else:
+            assert False, 'expected exception'
+
+    def test_object_repr(self):
+        try:
+            Undefined(obj=42, name='upper')
+        except UndefinedError, e:
+            assert e.message == "'int' object has no attribute 'upper'"
         else:
             assert False, 'expected exception'
 
index 1fd6ec5dfd8215552bfb27b182a50e1a90aa07de..0ba86e768909a99798ceee69fbba9fb0d6d599e1 100644 (file)
@@ -227,6 +227,22 @@ def open_if_exists(filename, mode='rb'):
             raise
 
 
+def object_type_repr(obj):
+    """Returns the name of the object's type.  For some recognized
+    singletons the name of the object is returned instead. (For
+    example for `None` and `Ellipsis`).
+    """
+    if obj is None:
+        return 'None'
+    elif obj is Ellipsis:
+        return 'Ellipsis'
+    if obj.__class__.__module__ == '__builtin__':
+        name = obj.__name__
+    else:
+        name = obj.__class__.module__ + '.' + obj.__name__
+    return '%s object' % name
+
+
 def pformat(obj, verbose=False):
     """Prettyprint an object.  Either use the `pretty` library or the
     builtin `pprint`.