fixed a few bugs from the unittests

--HG--
branch : trunk
diff --git a/jinja2/compiler.py b/jinja2/compiler.py
index 955403d..4b093ff 100644
--- a/jinja2/compiler.py
+++ b/jinja2/compiler.py
@@ -632,7 +632,7 @@
         # the expression pointing to the parent loop.  We make the
         # undefined a bit more debug friendly at the same time.
         parent_loop = 'loop' in aliases and aliases['loop'] \
-                      or "environment.undefined('loop', extra=%r)" % \
+                      or "environment.undefined(%r)" % "'loop' is undefined. " \
                          'the filter section of a loop as well as the ' \
                          'else block doesn\'t have access to the special ' \
                          "'loop' variable of the current loop.  Because " \
@@ -670,7 +670,7 @@
             self.writeline('continue')
             self.outdent(2)
 
-        self.blockvisit(node.body, loop_frame, force_generator=False)
+        self.blockvisit(node.body, loop_frame, force_generator=True)
 
         if node.else_:
             self.writeline('if l_loop is None:')
diff --git a/jinja2/filters.py b/jinja2/filters.py
index 633dbdf..2fc1b30 100644
--- a/jinja2/filters.py
+++ b/jinja2/filters.py
@@ -16,7 +16,7 @@
 except ImportError:
     itemgetter = lambda a: lambda b: b[a]
 from urllib import urlencode, quote
-from itertools import imap
+from itertools import imap, groupby
 from jinja2.utils import Markup, escape, pformat, urlize, soft_unicode
 from jinja2.runtime import Undefined
 
@@ -108,10 +108,7 @@
     result = []
     for key, value in d.iteritems():
         if value is not None and not isinstance(value, Undefined):
-            result.append(u'%s="%s"' % (
-                escape(env.to_unicode(key)),
-                escape(env.to_unicode(value), True)
-            ))
+            result.append(u'%s="%s"' % (escape(key), escape(value)))
     rv = u' '.join(
         u'%s="%s"' % (escape(key), escape(value))
         for key, value in d.iteritems()
@@ -386,7 +383,10 @@
     try:
         return int(value)
     except (TypeError, ValueError):
-        return default
+        try:
+            return int(float(value))
+        except (TypeError, ValueError):
+            return default
 
 
 def do_float(value, default=0.0):
@@ -400,11 +400,6 @@
         return default
 
 
-def do_string(value):
-    """Convert the value into an string."""
-    return soft_unicode(value)
-
-
 def do_format(value, *args, **kwargs):
     """
     Apply python string formatting on an object:
@@ -451,7 +446,7 @@
     If you pass it a second argument it's used to fill missing
     values on the last iteration.
     """
-    seq = list(seq)
+    seq = list(value)
     length = len(seq)
     items_per_slice = length // slices
     slices_with_extra = length % slices
@@ -599,7 +594,8 @@
     'wordcount':            do_wordcount,
     'int':                  do_int,
     'float':                do_float,
-    'string':               do_string,
+    'string':               soft_unicode,
+    'list':                 list,
     'urlize':               do_urlize,
     'format':               do_format,
     'trim':                 do_trim,
diff --git a/jinja2/parser.py b/jinja2/parser.py
index a8969a8..84a317c 100644
--- a/jinja2/parser.py
+++ b/jinja2/parser.py
@@ -481,7 +481,7 @@
             value = self.parse_expression()
             items.append(nodes.Pair(key, value, lineno=key.lineno))
         self.stream.expect('rbrace')
-        return nodes.Dict(items, token.lineno, self.filename)
+        return nodes.Dict(items, lineno=token.lineno)
 
     def parse_postfix(self, node):
         while 1:
diff --git a/jinja2/utils.py b/jinja2/utils.py
index 5e6b403..2c857f4 100644
--- a/jinja2/utils.py
+++ b/jinja2/utils.py
@@ -16,6 +16,16 @@
 from itertools import imap
 
 
+_word_split_re = re.compile(r'(\s+)')
+_punctuation_re = re.compile(
+    '^(?P<lead>(?:%s)*)(?P<middle>.*?)(?P<trail>(?:%s)*)$' % (
+        '|'.join(imap(re.escape, ('(', '<', '&lt;'))),
+        '|'.join(imap(re.escape, ('.', ',', ')', '>', '\n', '&gt;')))
+    )
+)
+_simple_email_re = re.compile(r'^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$')
+
+
 def soft_unicode(s):
     """Make a string unicode if it isn't already.  That way a markup
     string is not converted back to unicode.
@@ -26,8 +36,7 @@
 
 
 def pformat(obj, verbose=False):
-    """
-    Prettyprint an object.  Either use the `pretty` library or the
+    """Prettyprint an object.  Either use the `pretty` library or the
     builtin `pprint`.
     """
     try:
@@ -38,21 +47,8 @@
         return pformat(obj)
 
 
-_word_split_re = re.compile(r'(\s+)')
-
-_punctuation_re = re.compile(
-    '^(?P<lead>(?:%s)*)(?P<middle>.*?)(?P<trail>(?:%s)*)$' % (
-        '|'.join(imap(re.escape, ('(', '<', '&lt;'))),
-        '|'.join(imap(re.escape, ('.', ',', ')', '>', '\n', '&gt;')))
-    )
-)
-
-_simple_email_re = re.compile(r'^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$')
-
-
 def urlize(text, trim_url_limit=None, nofollow=False):
-    """
-    Converts any URLs in text into clickable links. Works on http://,
+    """Converts any URLs in text into clickable links. Works on http://,
     https:// and www. links. Links can have trailing punctuation (periods,
     commas, close-parens) and leading punctuation (opening parens) and
     it'll still do the right thing.
@@ -213,9 +209,9 @@
 
     def copy(self):
         """Return an shallow copy of the instance."""
-        rv = LRUCache(self.capacity)
+        rv = self.__class__(self.capacity)
         rv._mapping.update(self._mapping)
-        rv._queue = self._queue[:]
+        rv._queue = deque(self._queue)
         return rv
 
     def get(self, key, default=None):
@@ -225,8 +221,7 @@
         return default
 
     def setdefault(self, key, default=None):
-        """
-        Set `default` if the key is not in the cache otherwise
+        """Set `default` if the key is not in the cache otherwise
         leave unchanged. Return the value of this key.
         """
         if key in self:
@@ -297,13 +292,6 @@
 
     __copy__ = copy
 
-    def __deepcopy__(self):
-        """Return a deep copy of the LRU Cache"""
-        rv = LRUCache(self.capacity)
-        rv._mapping = deepcopy(self._mapping)
-        rv._queue = deepcopy(self._queue)
-        return rv
-
 
 # we have to import it down here as the speedups module imports the
 # markup type which is define above.
diff --git a/tests/test_filters.py b/tests/test_filters.py
index 7a7ea9f..9a1b89d 100644
--- a/tests/test_filters.py
+++ b/tests/test_filters.py
@@ -21,9 +21,9 @@
 DICTSORT = '''{{ foo|dictsort }}|\
 {{ foo|dictsort(true) }}|\
 {{ foo|dictsort(false, 'value') }}'''
-BATCH = '''{{ foo|batch(3) }}|{{ foo|batch(3, 'X') }}'''
-SLICE = '''{{ foo|slice(3) }}|{{ foo|slice(3, 'X') }}'''
-ESCAPE = '''{{ '<">&'|escape }}|{{ '<">&'|escape(true) }}'''
+BATCH = '''{{ foo|batch(3)|list }}|{{ foo|batch(3, 'X')|list }}'''
+SLICE = '''{{ foo|slice(3)|list }}|{{ foo|slice(3, 'X')|list }}'''
+ESCAPE = '''{{ '<">&'|escape }}'''
 STRIPTAGS = '''{{ foo|striptags }}'''
 FILESIZEFORMAT = '{{ 100|filesizeformat }}|\
 {{ 1000|filesizeformat }}|\
@@ -41,7 +41,7 @@
 LOWER = '''{{ "FOO"|lower }}'''
 PPRINT = '''{{ data|pprint }}'''
 RANDOM = '''{{ seq|random }}'''
-REVERSE = '''{{ "foobar"|reverse }}|{{ [1, 2, 3]|reverse }}'''
+REVERSE = '''{{ "foobar"|reverse|join }}|{{ [1, 2, 3]|reverse|list }}'''
 STRING = '''{{ range(10)|string }}'''
 TITLE = '''{{ "foo bar"|title }}'''
 TRIM = '''{{ "      foo       "|trim }}'''
@@ -108,7 +108,7 @@
 def test_escape(env):
     tmpl = env.from_string(ESCAPE)
     out = tmpl.render()
-    assert out == '&lt;&quot;&gt;&amp;|&lt;&quot;&gt;&amp;'
+    assert out == '&lt;&quot;&gt;&amp;'
 
 
 def test_striptags(env):
diff --git a/tests/test_tests.py b/tests/test_tests.py
index 9d9a33f..fa665fb 100644
--- a/tests/test_tests.py
+++ b/tests/test_tests.py
@@ -10,9 +10,6 @@
 DEFINED = '''{{ missing is defined }}|{{ true is defined }}'''
 EVEN = '''{{ 1 is even }}|{{ 2 is even }}'''
 LOWER = '''{{ "foo" is lower }}|{{ "FOO" is lower }}'''
-MATCHING = '''{{ "42" is matching('^\\d+$') }}|\
-{{ "foo" is matching('^\\d+$') }}|\
-{{ "foo bar" is matching @/^foo\\s+BAR$/i }}'''
 NUMERIC = '''{{ "43" is numeric }}|{{ "foo" is numeric }}|\
 {{ 42 is numeric }}'''
 ODD = '''{{ 1 is odd }}|{{ 2 is odd }}'''
@@ -39,11 +36,6 @@
     assert tmpl.render() == 'True|False'
 
 
-def test_matching(env):
-    tmpl = env.from_string(MATCHING)
-    assert tmpl.render() == 'True|False|True'
-
-
 def test_numeric(env):
     tmpl = env.from_string(NUMERIC)
     assert tmpl.render() == 'True|False|True'