fixed more unittests

--HG--
branch : trunk
diff --git a/jinja2/_speedups.c b/jinja2/_speedups.c
index 6aad8ec..36a1404 100644
--- a/jinja2/_speedups.c
+++ b/jinja2/_speedups.c
@@ -115,7 +115,7 @@
 escape(PyObject *self, PyObject *args)
 {
 	PyObject *text = NULL, *s = NULL, *rv = NULL;
-	if (!PyArg_UnpackTuple(args, "escape", 1, 2, &text))
+	if (!PyArg_UnpackTuple(args, "escape", 1, 1, &text))
 		return NULL;
 
 	/* we don't have to escape integers, bools or floats */
diff --git a/jinja2/environment.py b/jinja2/environment.py
index 1ed0464..35b01e7 100644
--- a/jinja2/environment.py
+++ b/jinja2/environment.py
@@ -182,7 +182,10 @@
     """Represents a template."""
 
     def __init__(self, environment, code, globals, uptodate=None):
-        namespace = {'environment': environment}
+        namespace = {
+            'environment':          environment,
+            '__jinja_template__':   self
+        }
         exec code in namespace
         self.environment = environment
         self.name = namespace['name']
@@ -191,18 +194,27 @@
         self.blocks = namespace['blocks']
         self.globals = globals
 
-        # debug helpers
+        # debug and loader helpers
         self._get_debug_info = namespace['get_debug_info']
         self._uptodate = uptodate
-        namespace['__jinja_template__'] = self
 
     def render(self, *args, **kwargs):
         """Render the template into a string."""
-        return u''.join(self.generate(*args, **kwargs))
+        try:
+            return u''.join(self.generate(*args, **kwargs))
+        except:
+            # hide the `generate` frame
+            exc_type, exc_value, tb = sys.exc_info()
+            raise exc_type, exc_value, tb.tb_next
 
     def stream(self, *args, **kwargs):
         """Return a `TemplateStream` that generates the template."""
-        return TemplateStream(self.generate(*args, **kwargs))
+        try:
+            return TemplateStream(self.generate(*args, **kwargs))
+        except:
+            # hide the `generate` frame
+            exc_type, exc_value, tb = sys.exc_info()
+            raise exc_type, exc_value, tb.tb_next
 
     def generate(self, *args, **kwargs):
         """Return a generator that generates the template."""
diff --git a/jinja2/loaders.py b/jinja2/loaders.py
index b621bbf..dc3ccfb 100644
--- a/jinja2/loaders.py
+++ b/jinja2/loaders.py
@@ -39,10 +39,12 @@
     """
 
     def __init__(self, cache_size=50, auto_reload=True):
-        if cache_size > 0:
-            self.cache = LRUCache(cache_size)
-        else:
+        if cache_size == 0:
             self.cache = None
+        elif cache_size < 0:
+            self.cache = {}
+        else:
+            self.cache = LRUCache(cache_size)
         self.auto_reload = auto_reload
 
     def get_source(self, environment, template):
@@ -134,7 +136,8 @@
 class DictLoader(BaseLoader):
     """Loads a template from a python dict.  Used for unittests mostly."""
 
-    def __init__(self, mapping):
+    def __init__(self, mapping, cache_size=50):
+        BaseLoader.__init__(self, cache_size, False)
         self.mapping = mapping
 
     def get_source(self, environment, template):
diff --git a/jinja2/runtime.py b/jinja2/runtime.py
index e1bf486..e0630cc 100644
--- a/jinja2/runtime.py
+++ b/jinja2/runtime.py
@@ -277,7 +277,7 @@
                     self._undefined_name
                 )
             else:
-                hint = '%r object has no attribute %s' % (
+                hint = '%r object has no attribute %r' % (
                     self._undefined_obj.__class__.__name__,
                     self._undefined_name
                 )
diff --git a/tests/conftest.py b/tests/conftest.py
index 0f1439b..e38299f 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -15,7 +15,8 @@
 
 import py
 from jinja2 import Environment
-from jinja2.parser import Parser
+from jinja2.loaders import BaseLoader
+from jinja2.exceptions import TemplateNotFound
 
 try:
     # This code adds support for coverage.py (see
@@ -52,45 +53,20 @@
     coverage = None
 
 
-class GlobalLoader(object):
+class GlobalLoader(BaseLoader):
+    scope = globals()
 
-    def __init__(self, scope):
-        self.scope = scope
-
-    def get_source(self, environment, name, parent, scope=None):
-        return self.scope[name.upper() + 'TEMPLATE']
-
-    def parse(self, environment, name, parent, scope=None):
-        return Parser(environment, self.get_source(environment, name,
-                      parent, scope), name).parse()
-
-    def load(self, environment, name, translator, scope=None):
-        return translator.process(environment, self.parse(environment,
-                                  name, None, scope))
+    def get_source(self, environment, name):
+        try:
+            return self.scope[name.upper() + 'TEMPLATE'], None, None
+        except KeyError:
+            raise TemplateNotFound(name)
 
 
-loader = GlobalLoader(globals())
+loader = GlobalLoader(cache_size=0)
 simple_env = Environment(trim_blocks=True, loader=loader)
 
 
-class MemcacheClient(object):
-    """
-    Helper for the loader test.
-    """
-
-    def __init__(self, hosts):
-        self.cache = {}
-
-    def get(self, name):
-        return self.cache.get(name)
-
-    def set(self, name, data, time):
-        self.cache[name] = data
-
-sys.modules['memcache'] = memcache = type(sys)('memcache')
-memcache.Client = MemcacheClient
-
-
 class Module(py.test.collect.Module):
 
     def __init__(self, *args, **kwargs):
diff --git a/tests/test_inheritance.py b/tests/test_inheritance.py
index 53ebfac..34e5738 100644
--- a/tests/test_inheritance.py
+++ b/tests/test_inheritance.py
@@ -36,15 +36,6 @@
 {% block block3 %}block 3 from level4{% endblock %}
 '''
 
-BROKENTEMPLATE = '''\
-{% extends "layout" %}
-{% if false %}
-  {% block block1 %}
-    this is broken
-  {% endblock %}
-{% endif %}
-'''
-
 WORKINGTEMPLATE = '''\
 {% extends "layout" %}
 {% block block1 %}
@@ -100,19 +91,5 @@
     assert tmpl.render() == '--INTRO--|BEFORE|[(INNER)]|AFTER'
 
 
-def test_broken(env):
-    try:
-        tmpl = env.get_template('broken')
-    except TemplateSyntaxError:
-        pass
-    else:
-        raise RuntimeError('no syntax error occured')
-
-
 def test_working(env):
     tmpl = env.get_template('working')
-
-
-def test_shortcut(env):
-    tmpl = env.from_string('{% block foo "42" %}')
-    assert tmpl.render() == '42'
diff --git a/tests/test_undefined.py b/tests/test_undefined.py
index 7b312c0..f0544bb 100644
--- a/tests/test_undefined.py
+++ b/tests/test_undefined.py
@@ -1,67 +1,74 @@
 # -*- coding: utf-8 -*-
 """
-    unit test for the undefined singletons
-    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    unit test for the undefined types
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-    :copyright: 2007 by Armin Ronacher.
+    :copyright: 2008 by Armin Ronacher.
     :license: BSD, see LICENSE for more details.
 """
 
-from jinja2 import Environment
-from jinja2.exceptions import TemplateRuntimeError
-from jinja2.datastructure import SilentUndefined, ComplainingUndefined
 
+test_default_undefined = '''
+>>> from jinja2 import Environment, Undefined
+>>> env = Environment(undefined=Undefined)
+>>> env.from_string('{{ missing }}').render()
+u''
+>>> env.from_string('{{ missing.attribute }}').render()
+Traceback (most recent call last):
+  ...
+UndefinedError: 'missing' is undefined
+>>> env.from_string('{{ missing|list }}').render()
+u'[]'
+>>> env.from_string('{{ missing is not defined }}').render()
+u'True'
+>>> env.from_string('{{ foo.missing }}').render(foo=42)
+u''
+>>> env.from_string('{{ not missing }}').render()
+u'True'
+'''
 
-silent_env = Environment(undefined_singleton=SilentUndefined)
-complaining_env = Environment(undefined_singleton=ComplainingUndefined)
+test_debug_undefined = '''
+>>> from jinja2 import Environment, DebugUndefined
+>>> env = Environment(undefined=DebugUndefined)
+>>> env.from_string('{{ missing }}').render()
+u'{{ missing }}'
+>>> env.from_string('{{ missing.attribute }}').render()
+Traceback (most recent call last):
+  ...
+UndefinedError: 'missing' is undefined
+>>> env.from_string('{{ missing|list }}').render()
+u'[]'
+>>> env.from_string('{{ missing is not defined }}').render()
+u'True'
+>>> env.from_string('{{ foo.missing }}').render(foo=42)
+u"{{ no such element: int['missing'] }}"
+>>> env.from_string('{{ not missing }}').render()
+u'True'
+'''
 
-
-JUSTUNDEFINED = '''{{ missing }}'''
-DEFINEDUNDEFINED = '''{{ missing is defined }}|{{ given is defined }}'''
-ITERATION = '''{% for item in missing %}{{ item }}{% endfor %}'''
-CONCATENATION = '''{{ missing + [1, 2] + missing + [3] }}'''
-
-
-def test_silent_defined():
-    tmpl = silent_env.from_string(DEFINEDUNDEFINED)
-    assert tmpl.render(given=0) == 'False|True'
-
-
-def test_complaining_defined():
-    tmpl = complaining_env.from_string(DEFINEDUNDEFINED)
-    assert tmpl.render(given=0) == 'False|True'
-
-
-def test_silent_rendering():
-    tmpl = silent_env.from_string(JUSTUNDEFINED)
-    assert tmpl.render() == ''
-
-
-def test_complaining_undefined():
-    tmpl = complaining_env.from_string(JUSTUNDEFINED)
-    try:
-        tmpl.render()
-    except TemplateRuntimeError:
-        pass
-    else:
-        raise ValueError('template runtime error expected')
-
-
-def test_silent_iteration():
-    tmpl = silent_env.from_string(ITERATION)
-    assert tmpl.render() == ''
-
-
-def test_complaining_iteration():
-    tmpl = complaining_env.from_string(ITERATION)
-    try:
-        tmpl.render()
-    except TemplateRuntimeError:
-        pass
-    else:
-        raise ValueError('template runtime error expected')
-
-
-def test_concatenation():
-    tmpl = silent_env.from_string(CONCATENATION)
-    assert tmpl.render() == '[1, 2, 3]'
+test_strict_undefined = '''
+>>> from jinja2 import Environment, StrictUndefined
+>>> env = Environment(undefined=StrictUndefined)
+>>> env.from_string('{{ missing }}').render()
+Traceback (most recent call last):
+  ...
+UndefinedError: 'missing' is undefined
+>>> env.from_string('{{ missing.attribute }}').render()
+Traceback (most recent call last):
+  ...
+UndefinedError: 'missing' is undefined
+>>> env.from_string('{{ missing|list }}').render()
+Traceback (most recent call last):
+  ...
+UndefinedError: 'missing' is undefined
+>>> env.from_string('{{ missing is not defined }}').render()
+u'True'
+>>> env.from_string('{{ foo.missing }}').render(foo=42)
+Traceback (most recent call last):
+  ...
+UndefinedError: 'int' object has no attribute 'missing'
+>>> env.from_string('{{ not missing }}').render()
+Traceback (most recent call last):
+  ...
+UndefinedError: 'missing' is undefined
+'''