From be4ae24b6207d370a90d9fc3cfe0a943c1fa1761 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Fri, 18 Apr 2008 09:49:08 +0200 Subject: [PATCH] fixed a few bugs from the unittests --HG-- branch : trunk --- jinja2/compiler.py | 4 ++-- jinja2/filters.py | 22 +++++++++------------- jinja2/parser.py | 2 +- jinja2/utils.py | 42 +++++++++++++++--------------------------- tests/test_filters.py | 10 +++++----- tests/test_tests.py | 8 -------- 6 files changed, 32 insertions(+), 56 deletions(-) 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 @@ class CodeGenerator(NodeVisitor): # 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 @@ class CodeGenerator(NodeVisitor): 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 @@ try: 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 @@ def do_xmlattr(d, autospace=False): 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 @@ def do_int(value, default=0): 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 @@ def do_float(value, default=0.0): 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 @@ def do_slice(value, slices, fill_with=None): 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 @@ FILTERS = { '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 @@ class Parser(object): 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 functools import update_wrapper from itertools import imap +_word_split_re = re.compile(r'(\s+)') +_punctuation_re = re.compile( + '^(?P(?:%s)*)(?P.*?)(?P(?:%s)*)$' % ( + '|'.join(imap(re.escape, ('(', '<', '<'))), + '|'.join(imap(re.escape, ('.', ',', ')', '>', '\n', '>'))) + ) +) +_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 soft_unicode(s): 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 @@ def pformat(obj, verbose=False): return pformat(obj) -_word_split_re = re.compile(r'(\s+)') - -_punctuation_re = re.compile( - '^(?P(?:%s)*)(?P.*?)(?P(?:%s)*)$' % ( - '|'.join(imap(re.escape, ('(', '<', '<'))), - '|'.join(imap(re.escape, ('.', ',', ')', '>', '\n', '>'))) - ) -) - -_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 @@ class LRUCache(object): 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 @@ class LRUCache(object): 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 @@ class LRUCache(object): __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 @@ DEFAULT = '''{{ missing|default("no") }}|{{ false|default('no') }}|\ 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 @@ LENGTH = '''{{ "hello world"|length }}''' 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_slice(env): def test_escape(env): tmpl = env.from_string(ESCAPE) out = tmpl.render() - assert out == '<">&|<">&' + assert out == '<">&' 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 @@ def test_lower(env): 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' -- 2.26.2