Index: genshi/template/tests/text.py
===================================================================
--- genshi/template/tests/text.py	(revision 494)
+++ genshi/template/tests/text.py	(working copy)
@@ -37,7 +37,7 @@
         #if foo
           bar
         #end 'if foo'""")
-        self.assertEqual('\n', str(tmpl.generate()))
+        self.assertEqual('\n', str(tmpl.generate(foo=False)))
 
     def test_latin1_encoded(self):
         text = u'$foo\xf6$bar'.encode('iso-8859-1')
Index: genshi/template/tests/eval.py
===================================================================
--- genshi/template/tests/eval.py	(revision 500)
+++ genshi/template/tests/eval.py	(working copy)
@@ -16,7 +16,7 @@
 import unittest
 
 from genshi.core import Markup
-from genshi.template.eval import Expression, Suite, Undefined
+from genshi.template.eval import Expression, Suite, UndefinedError
 
 
 class ExpressionTestCase(unittest.TestCase):
@@ -40,8 +40,6 @@
     def test_builtins(self):
         expr = Expression('Markup')
         self.assertEqual(expr.evaluate({}), Markup)
-        expr = Expression('Undefined')
-        self.assertEqual(expr.evaluate({}), Undefined)
 
     def test_str_literal(self):
         self.assertEqual('foo', Expression('"foo"').evaluate({}))
@@ -323,82 +321,68 @@
 
     def test_error_access_undefined(self):
         expr = Expression("nothing", filename='index.html', lineno=50)
-        self.assertEqual(Undefined, type(expr.evaluate({})))
-
-    def test_error_call_undefined(self):
-        expr = Expression("nothing()", filename='index.html', lineno=50)
         try:
             expr.evaluate({})
-            self.fail('Expected NameError')
-        except NameError, e:
+            self.fail('Expected UndefinedError')
+        except UndefinedError, e:
             exc_type, exc_value, exc_traceback = sys.exc_info()
             frame = exc_traceback.tb_next
             frames = []
             while frame.tb_next:
                 frame = frame.tb_next
                 frames.append(frame)
-            self.assertEqual('Variable "nothing" is not defined', str(e))
-            self.assertEqual("<Expression 'nothing()'>",
-                             frames[-3].tb_frame.f_code.co_name)
+            self.assertEqual('"nothing" not defined', str(e))
+            self.assertEqual("<Expression 'nothing'>",
+                             frames[-2].tb_frame.f_code.co_name)
             self.assertEqual('index.html',
-                             frames[-3].tb_frame.f_code.co_filename)
-            self.assertEqual(50, frames[-3].tb_lineno)
+                             frames[-2].tb_frame.f_code.co_filename)
+            self.assertEqual(50, frames[-2].tb_lineno)
 
     def test_error_getattr_undefined(self):
-        expr = Expression("nothing.nil", filename='index.html', lineno=50)
+        class Something(object):
+            def __repr__(self):
+                return '<Something>'
+        expr = Expression('something.nil', filename='index.html', lineno=50)
         try:
-            expr.evaluate({})
-            self.fail('Expected NameError')
-        except NameError, e:
+            expr.evaluate({'something': Something()})
+            self.fail('Expected UndefinedError')
+        except UndefinedError, e:
             exc_type, exc_value, exc_traceback = sys.exc_info()
             frame = exc_traceback.tb_next
             frames = []
             while frame.tb_next:
                 frame = frame.tb_next
                 frames.append(frame)
-            self.assertEqual('Variable "nothing" is not defined', str(e))
-            self.assertEqual("<Expression 'nothing.nil'>",
-                             frames[-3].tb_frame.f_code.co_name)
+            self.assertEqual('<Something> has no member named "nil"', str(e))
+            self.assertEqual("<Expression 'something.nil'>",
+                             frames[-2].tb_frame.f_code.co_name)
             self.assertEqual('index.html',
-                             frames[-3].tb_frame.f_code.co_filename)
-            self.assertEqual(50, frames[-3].tb_lineno)
+                             frames[-2].tb_frame.f_code.co_filename)
+            self.assertEqual(50, frames[-2].tb_lineno)
 
-    def test_error_getitem_undefined(self):
-        expr = Expression("nothing[0]", filename='index.html', lineno=50)
+    def test_error_getitem_undefined_string(self):
+        class Something(object):
+            def __repr__(self):
+                return '<Something>'
+        expr = Expression('something["nil"]', filename='index.html', lineno=50)
         try:
-            expr.evaluate({})
-            self.fail('Expected NameError')
-        except NameError, e:
+            expr.evaluate({'something': Something()})
+            self.fail('Expected UndefinedError')
+        except UndefinedError, e:
             exc_type, exc_value, exc_traceback = sys.exc_info()
             frame = exc_traceback.tb_next
             frames = []
             while frame.tb_next:
                 frame = frame.tb_next
                 frames.append(frame)
-            self.assertEqual('Variable "nothing" is not defined', str(e))
-            self.assertEqual("<Expression 'nothing[0]'>",
-                             frames[-3].tb_frame.f_code.co_name)
+            self.assertEqual('<Something> has no member named "nil"', str(e))
+            self.assertEqual('''<Expression 'something["nil"]'>''',
+                             frames[-2].tb_frame.f_code.co_name)
             self.assertEqual('index.html',
-                             frames[-3].tb_frame.f_code.co_filename)
-            self.assertEqual(50, frames[-3].tb_lineno)
+                             frames[-2].tb_frame.f_code.co_filename)
+            self.assertEqual(50, frames[-2].tb_lineno)
 
-    def test_error_getattr_nested_undefined(self):
-        expr = Expression("nothing.nil", filename='index.html', lineno=50)
-        val = expr.evaluate({'nothing': object()})
-        assert isinstance(val, Undefined)
-        self.assertEqual("nil", val._name)
 
-    def test_error_getitem_nested_undefined_string(self):
-        expr = Expression("nothing['bla']", filename='index.html', lineno=50)
-        val = expr.evaluate({'nothing': object()})
-        assert isinstance(val, Undefined)
-        self.assertEqual("bla", val._name)
-
-    def test_error_getitem_nested_undefined_int(self):
-        expr = Expression("nothing[0]", filename='index.html', lineno=50)
-        self.assertRaises(TypeError, expr.evaluate, {'nothing': object()})
-
-
 class SuiteTestCase(unittest.TestCase):
 
     def test_assign(self):
Index: genshi/template/eval.py
===================================================================
--- genshi/template/eval.py	(revision 500)
+++ genshi/template/eval.py	(working copy)
@@ -24,9 +24,10 @@
 import sys
 
 from genshi.core import Markup
+from genshi.template.base import TemplateRuntimeError
 from genshi.util import flatten
 
-__all__ = ['Expression', 'Suite', 'Undefined']
+__all__ = ['Expression', 'Suite']
 
 
 class Code(object):
@@ -148,63 +149,18 @@
                            '_lookup_item': _lookup_item}, data
 
 
-class Undefined(object):
-    """Represents a reference to an undefined variable.
-    
-    Unlike the Python runtime, template expressions can refer to an undefined
-    variable without causing a `NameError` to be raised. The result will be an
-    instance of the `Undefined´ class, which is treated the same as `False` in
-    conditions, and acts as an empty collection in iterations:
-    
-    >>> foo = Undefined('foo')
-    >>> bool(foo)
-    False
-    >>> list(foo)
-    []
-    >>> print foo
-    undefined
-    
-    However, calling an undefined variable, or trying to access an attribute
-    of that variable, will raise an exception that includes the name used to
-    reference that undefined variable.
-    
-    >>> foo('bar')
-    Traceback (most recent call last):
-        ...
-    NameError: Variable "foo" is not defined
-
-    >>> foo.bar
-    Traceback (most recent call last):
-        ...
-    NameError: Variable "foo" is not defined
+class UndefinedError(TemplateRuntimeError):
+    """Exception thrown when a template expression attempts to access a variable
+    not defined in the context.
     """
-    __slots__ = ['_name']
+    def __init__(self, name, owner=None):
+        if owner is not None:
+            message = '%r has no member named "%s"' % (owner, name)
+        else:
+            message = '"%s" not defined' % name
+        TemplateRuntimeError.__init__(self, message)
 
-    def __init__(self, name):
-        self._name = name
 
-    def __call__(self, *args, **kwargs):
-        __traceback_hide__ = True
-        self.throw()
-
-    def __getattr__(self, name):
-        __traceback_hide__ = True
-        self.throw()
-
-    def __iter__(self):
-        return iter([])
-
-    def __nonzero__(self):
-        return False
-
-    def __repr__(self):
-        return 'undefined'
-
-    def throw(self):
-        __traceback_hide__ = True
-        raise NameError('Variable "%s" is not defined' % self._name)
-
-
 def _parse(source, mode='eval'):
     if isinstance(source, unicode):
         source = '\xef\xbb\xbf' + source.encode('utf-8')
@@ -238,42 +194,38 @@
                     code.co_lnotab, (), ())
 
 BUILTINS = __builtin__.__dict__.copy()
-BUILTINS.update({'Markup': Markup, 'Undefined': Undefined})
-_UNDEF = Undefined(None)
+BUILTINS.update({'Markup': Markup})
+UNDEFINED = object()
 
 def _lookup_name(data, name):
     __traceback_hide__ = True
-    val = data.get(name, _UNDEF)
-    if val is _UNDEF:
+    val = data.get(name, UNDEFINED)
+    if val is UNDEFINED:
         val = BUILTINS.get(name, val)
-        if val is _UNDEF:
-            return Undefined(name)
+        if val is UNDEFINED:
+            raise UndefinedError(name)
     return val
 
 def _lookup_attr(data, obj, key):
     __traceback_hide__ = True
-    if type(obj) is Undefined:
-        obj.throw()
     if hasattr(obj, key):
         return getattr(obj, key)
     try:
         return obj[key]
     except (KeyError, TypeError):
-        return Undefined(key)
+        raise UndefinedError(key, owner=obj)
 
 def _lookup_item(data, obj, key):
     __traceback_hide__ = True
-    if type(obj) is Undefined:
-        obj.throw()
     if len(key) == 1:
         key = key[0]
     try:
         return obj[key]
     except (AttributeError, KeyError, IndexError, TypeError), e:
         if isinstance(key, basestring):
-            val = getattr(obj, key, _UNDEF)
-            if val is _UNDEF:
-                val = Undefined(key)
+            val = getattr(obj, key, UNDEFINED)
+            if val is UNDEFINED:
+                raise UndefinedError(key, owner=obj)
             return val
         raise
 
