From e9e43bbabc4e98c4e6f2add5f02f17ae69068cfd Mon Sep 17 00:00:00 2001 From: Christoph Hack Date: Sun, 13 Apr 2008 23:35:48 +0200 Subject: [PATCH] converted unit tests, started rewriting filters --HG-- branch : trunk --- jinja2/defaults.py | 4 +- jinja2/environment.py | 4 +- jinja2/filters.py | 195 +++++++++++++---------------------- jinja2/nodes.py | 6 +- jinja2/utils.py | 13 +++ tests/conftest.py | 12 +-- tests/runtime/bigbench.py | 2 +- tests/runtime/bigtable.py | 2 +- tests/runtime/columntest.py | 2 +- tests/runtime/exception.py | 4 +- tests/runtime/inheritance.py | 6 +- tests/runtime/layout.py | 6 +- tests/runtime/modglobals.py | 2 +- tests/runtime/strange.py | 2 +- tests/runtime/super.py | 2 +- tests/test_filters.py | 10 +- tests/test_i18n.py | 2 +- tests/test_inheritance.py | 4 +- tests/test_lexer.py | 6 +- tests/test_loaders.py | 4 +- tests/test_macros.py | 2 +- tests/test_parser.py | 2 +- tests/test_security.py | 2 +- tests/test_syntax.py | 6 +- tests/test_undefined.py | 6 +- tests/test_various.py | 10 +- 26 files changed, 140 insertions(+), 176 deletions(-) diff --git a/jinja2/defaults.py b/jinja2/defaults.py index 84c1b08..4ad0e3a 100644 --- a/jinja2/defaults.py +++ b/jinja2/defaults.py @@ -10,7 +10,9 @@ """ from jinja2.filters import FILTERS as DEFAULT_FILTERS from jinja.tests import TESTS as DEFAULT_TESTS -DEFAULT_NAMESPACE = {} +DEFAULT_NAMESPACE = { + 'range': xrange +} __all__ = ['DEFAULT_FILTERS', 'DEFAULT_TESTS', 'DEFAULT_NAMESPACE'] diff --git a/jinja2/environment.py b/jinja2/environment.py index 8458a23..ae3e2ec 100644 --- a/jinja2/environment.py +++ b/jinja2/environment.py @@ -136,7 +136,9 @@ class Template(object): """Represents a template.""" def __init__(self, environment, code): - namespace = {'environment': environment} + namespace = { + 'environment': environment + } exec code in namespace self.environment = environment self.name = namespace['filename'] diff --git a/jinja2/filters.py b/jinja2/filters.py index 1c3ffcb..db0ea22 100644 --- a/jinja2/filters.py +++ b/jinja2/filters.py @@ -15,7 +15,9 @@ try: except ImportError: itemgetter = lambda a: lambda b: b[a] from urllib import urlencode, quote -from jinja2.utils import escape +from jinja2.utils import escape, pformat +from jinja2.nodes import Undefined + _striptags_re = re.compile(r'(|<[^>]*>)') @@ -138,7 +140,7 @@ def do_title(s): return unicode(s).title() -def do_dictsort(case_sensitive=False, by='key'): +def do_dictsort(value, case_sensitive=False, by='key'): """ Sort a dict and yield (key, value) pairs. Because python dicts are unsorted you may want to use this function to order them by either @@ -163,19 +165,16 @@ def do_dictsort(case_sensitive=False, by='key'): else: raise FilterArgumentError('You can only sort by either ' '"key" or "value"') - def sort_func(value, env): + def sort_func(value): if isinstance(value, basestring): - value = env.to_unicode(value) + value = unicode(value) if not case_sensitive: value = value.lower() return value - def wrapped(env, context, value): - items = value.items() - items.sort(lambda a, b: cmp(sort_func(a[pos], env), - sort_func(b[pos], env))) - return items - return wrapped + items = value.items() + items.sort(lambda a, b: cmp(sort_func(a[pos]), sort_func(b[pos]))) + return items def do_default(value, default_value=u'', boolean=False): @@ -196,8 +195,7 @@ def do_default(value, default_value=u'', boolean=False): {{ ''|default('the string was empty', true) }} """ - # XXX: undefined_sigleton - if (boolean and not value) or value in (env.undefined_singleton, None): + if (boolean and not value) or isinstance(value, Undefined): return default_value return value @@ -219,7 +217,7 @@ def do_join(value, d=u''): return unicode(d).join([unicode(x) for x in value]) -def do_count(): +def do_count(value): """ Return the length of the value. In case if getting an integer or float it will convert it into a string an return the length of the new @@ -233,7 +231,7 @@ def do_count(): return 0 -def do_reverse(l): +def do_reverse(value): """ Return a reversed list of the sequence filtered. You can use this for example for reverse iteration: @@ -279,7 +277,7 @@ def do_last(seq): return env.undefined_singleton -def do_random(): +def do_random(seq): """ Return a random item from the sequence. """ @@ -331,26 +329,24 @@ def do_jsonencode(value): return simplejson.dumps(value) -def do_filesizeformat(): +def do_filesizeformat(value): """ Format the value like a 'human-readable' file size (i.e. 13 KB, 4.1 MB, 102 bytes, etc). """ - def wrapped(env, context, value): - # fail silently - try: - bytes = float(value) - except TypeError: - bytes = 0 - - if bytes < 1024: - return "%d Byte%s" % (bytes, bytes != 1 and 's' or '') - elif bytes < 1024 * 1024: - return "%.1f KB" % (bytes / 1024) - elif bytes < 1024 * 1024 * 1024: - return "%.1f MB" % (bytes / (1024 * 1024)) - return "%.1f GB" % (bytes / (1024 * 1024 * 1024)) - return wrapped + # fail silently + try: + bytes = float(value) + except TypeError: + bytes = 0 + + if bytes < 1024: + return "%d Byte%s" % (bytes, bytes != 1 and 's' or '') + elif bytes < 1024 * 1024: + return "%.1f KB" % (bytes / 1024) + elif bytes < 1024 * 1024 * 1024: + return "%.1f MB" % (bytes / (1024 * 1024)) + return "%.1f GB" % (bytes / (1024 * 1024 * 1024)) def do_pprint(value, verbose=False): @@ -495,45 +491,42 @@ def do_rst(s): parts = publish_parts(source=s, writer_name='html4css1') return parts['fragment'] -def do_int(default=0): + +def do_int(value, default=0): """ Convert the value into an integer. If the conversion doesn't work it will return ``0``. You can override this default using the first parameter. """ - def wrapped(env, context, value): + try: + return int(value) + except (TypeError, ValueError): try: - return int(value) + return int(float(value)) except (TypeError, ValueError): - try: - return int(float(value)) - except (TypeError, ValueError): - return default - return wrapped + return default -def do_float(default=0.0): +def do_float(value, default=0.0): """ Convert the value into a floating point number. If the conversion doesn't work it will return ``0.0``. You can override this default using the first parameter. """ - def wrapped(env, context, value): - try: - return float(value) - except (TypeError, ValueError): - return default - return wrapped + try: + return float(value) + except (TypeError, ValueError): + return default -def do_string(): +def do_string(value): """ Convert the value into an string. """ - return lambda e, c, v: e.to_unicode(v) + return unicode(value) -def do_format(*args): +def do_format(value, *args): """ Apply python string formatting on an object: @@ -545,9 +538,7 @@ def do_format(*args): Note that you cannot use the mapping syntax (``%(name)s``) like in python. Use `|dformat` for that. """ - def wrapped(env, context, value): - return env.to_unicode(value) % args - return wrapped + return unicode(value) % args def do_dformat(d): @@ -578,39 +569,6 @@ def do_trim(value): return value.strip() -def do_capture(name='captured', clean=False): - """ - Store the value in a variable called ``captured`` or a variable - with the name provided. Useful for filter blocks: - - .. sourcecode:: jinja - - {% filter capture('foo') %} - ... - {% endfilter %} - {{ foo }} - - This will output "..." two times. One time from the filter block - and one time from the variable. If you don't want the filter to - output something you can use it in `clean` mode: - - .. sourcecode:: jinja - - {% filter capture('foo', True) %} - ... - {% endfilter %} - {{ foo }} - """ - if not isinstance(name, basestring): - raise FilterArgumentError('You can only capture into variables') - def wrapped(env, context, value): - context[name] = value - if clean: - return TemplateData() - return value - return wrapped - - def do_striptags(value): """ Strip SGML/XML tags and replace adjacent whitespace by one space. @@ -620,7 +578,7 @@ def do_striptags(value): return ' '.join(_striptags_re.sub('', value).split()) -def do_slice(slices, fill_with=None): +def do_slice(value, slices, fill_with=None): """ Slice an iterator and return a list of lists containing those items. Useful if you want to create a div containing @@ -643,27 +601,25 @@ def do_slice(slices, fill_with=None): *new in Jinja 1.1* """ - def wrapped(env, context, value): - result = [] - seq = list(value) - length = len(seq) - items_per_slice = length // slices - slices_with_extra = length % slices - offset = 0 - for slice_number in xrange(slices): - start = offset + slice_number * items_per_slice - if slice_number < slices_with_extra: - offset += 1 - end = offset + (slice_number + 1) * items_per_slice - tmp = seq[start:end] - if fill_with is not None and slice_number >= slices_with_extra: - tmp.append(fill_with) - result.append(tmp) - return result - return wrapped - - -def do_batch(linecount, fill_with=None): + result = [] + seq = list(value) + length = len(seq) + items_per_slice = length // slices + slices_with_extra = length % slices + offset = 0 + for slice_number in xrange(slices): + start = offset + slice_number * items_per_slice + if slice_number < slices_with_extra: + offset += 1 + end = offset + (slice_number + 1) * items_per_slice + tmp = seq[start:end] + if fill_with is not None and slice_number >= slices_with_extra: + tmp.append(fill_with) + result.append(tmp) + return result + + +def do_batch(value, linecount, fill_with=None): """ A filter that batches items. It works pretty much like `slice` just the other way round. It returns a list of lists with the @@ -684,20 +640,18 @@ def do_batch(linecount, fill_with=None): *new in Jinja 1.1* """ - def wrapped(env, context, value): - result = [] - tmp = [] - for item in value: - if len(tmp) == linecount: - result.append(tmp) - tmp = [] - tmp.append(item) - if tmp: - if fill_with is not None and len(tmp) < linecount: - tmp += [fill_with] * (linecount - len(tmp)) + result = [] + tmp = [] + for item in value: + if len(tmp) == linecount: result.append(tmp) - return result - return wrapped + tmp = [] + tmp.append(item) + if tmp: + if fill_with is not None and len(tmp) < linecount: + tmp += [fill_with] * (linecount - len(tmp)) + result.append(tmp) + return result def do_sum(): @@ -888,7 +842,6 @@ FILTERS = { 'urlize': do_urlize, 'format': do_format, 'dformat': do_dformat, - 'capture': do_capture, 'trim': do_trim, 'striptags': do_striptags, 'slice': do_slice, diff --git a/jinja2/nodes.py b/jinja2/nodes.py index ecc3f1e..02eb3c0 100644 --- a/jinja2/nodes.py +++ b/jinja2/nodes.py @@ -405,7 +405,7 @@ class Filter(Expr): raise Impossible() filter = self.environment.filters.get(self.name) if filter is None or getattr(filter, 'contextfilter', False): - raise nodes.Impossible() + raise Impossible() if obj is None: obj = self.node.as_const() args = [x.as_const() for x in self.args] @@ -423,7 +423,7 @@ class Filter(Expr): try: return filter(obj, *args, **kwargs) except: - raise nodes.Impossible() + raise Impossible() class Test(Expr): @@ -452,7 +452,7 @@ class Call(Expr): try: return obj(*args, **kwargs) except: - raise nodes.Impossible() + raise Impossible() class Subscript(Expr): diff --git a/jinja2/utils.py b/jinja2/utils.py index 4ee245d..90f30e9 100644 --- a/jinja2/utils.py +++ b/jinja2/utils.py @@ -19,3 +19,16 @@ def escape(obj, attribute=False): .replace('>', '>') \ .replace('<', '<') \ .replace('"', '"') + + +def pformat(obj, verbose=False): + """ + Prettyprint an object. Either use the `pretty` library or the + builtin `pprint`. + """ + try: + from pretty import pretty + return pretty(obj, verbose=verbose) + except ImportError: + from pprint import pformat + return pformat(obj) diff --git a/tests/conftest.py b/tests/conftest.py index 0c5a5ff..0f1439b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -14,8 +14,8 @@ import sys sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) import py -from jinja import Environment -from jinja.parser import Parser +from jinja2 import Environment +from jinja2.parser import Parser try: # This code adds support for coverage.py (see @@ -25,15 +25,15 @@ try: import coverage, atexit - IGNORED_MODULES = ['jinja._speedups', 'jinja.defaults', - 'jinja.translators'] + IGNORED_MODULES = ['jinja2._speedups', 'jinja2.defaults', + 'jinja2.translators'] def report_coverage(): coverage.stop() module_list = [ mod for name, mod in sys.modules.copy().iteritems() if getattr(mod, '__file__', None) and - name.startswith('jinja.') and + name.startswith('jinja2.') and name not in IGNORED_MODULES ] module_list.sort() @@ -70,7 +70,7 @@ class GlobalLoader(object): loader = GlobalLoader(globals()) -simple_env = Environment(trim_blocks=True, friendly_traceback=False, loader=loader) +simple_env = Environment(trim_blocks=True, loader=loader) class MemcacheClient(object): diff --git a/tests/runtime/bigbench.py b/tests/runtime/bigbench.py index 2ac975a..58014bf 100644 --- a/tests/runtime/bigbench.py +++ b/tests/runtime/bigbench.py @@ -1,6 +1,6 @@ import jdebug from time import time -from jinja import Environment +from jinja2 import Environment tmpl = Environment().from_string('''

Bigtable

diff --git a/tests/runtime/bigtable.py b/tests/runtime/bigtable.py index ce853d9..c86a12a 100644 --- a/tests/runtime/bigtable.py +++ b/tests/runtime/bigtable.py @@ -24,7 +24,7 @@ try: except ImportError: have_genshi = False -from jinja import Environment +from jinja2 import Environment try: from django.conf import settings diff --git a/tests/runtime/columntest.py b/tests/runtime/columntest.py index ebb00fc..ebda8ca 100644 --- a/tests/runtime/columntest.py +++ b/tests/runtime/columntest.py @@ -1,5 +1,5 @@ import jdebug -from jinja import from_string +from jinja2 import from_string template = from_string(u'''\ diff --git a/tests/runtime/exception.py b/tests/runtime/exception.py index 9dffaeb..4fc2cff 100644 --- a/tests/runtime/exception.py +++ b/tests/runtime/exception.py @@ -3,8 +3,8 @@ import sys sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..')) import jdebug -from jinja import Environment, DictLoader -from jinja.exceptions import TemplateNotFound +from jinja2 import Environment, DictLoader +from jinja2.exceptions import TemplateNotFound from wsgiref.simple_server import make_server e = Environment(loader=DictLoader({ diff --git a/tests/runtime/inheritance.py b/tests/runtime/inheritance.py index a2275aa..1e1ff85 100644 --- a/tests/runtime/inheritance.py +++ b/tests/runtime/inheritance.py @@ -1,8 +1,8 @@ -from jinja import Environment, FileSystemLoader +from jinja2 import Environment, FileSystemLoader e = Environment(loader=FileSystemLoader('templates')) -from jinja.parser import Parser -from jinja.translators.python import PythonTranslator +from jinja2.parser import Parser +from jinja2.translators.python import PythonTranslator tmpl = e.loader.load('c.html') print tmpl.render() diff --git a/tests/runtime/layout.py b/tests/runtime/layout.py index 8b1ebec..9e1bce5 100644 --- a/tests/runtime/layout.py +++ b/tests/runtime/layout.py @@ -1,8 +1,8 @@ -from jinja import Environment, FileSystemLoader +from jinja2 import Environment, FileSystemLoader e = Environment(loader=FileSystemLoader('templates')) -from jinja.parser import Parser -from jinja.translators.python import PythonTranslator +from jinja2.parser import Parser +from jinja2.translators.python import PythonTranslator print PythonTranslator(e, e.loader.parse('index.html')).translate() diff --git a/tests/runtime/modglobals.py b/tests/runtime/modglobals.py index ea31c98..b8d784b 100644 --- a/tests/runtime/modglobals.py +++ b/tests/runtime/modglobals.py @@ -1,6 +1,6 @@ # test file for block super support import jdebug -from jinja import Environment, DictLoader +from jinja2 import Environment, DictLoader env = Environment(loader=DictLoader({ 'a': '''\ diff --git a/tests/runtime/strange.py b/tests/runtime/strange.py index 56a0852..baaae0d 100644 --- a/tests/runtime/strange.py +++ b/tests/runtime/strange.py @@ -1,5 +1,5 @@ import jdebug -from jinja import Environment, DictLoader +from jinja2 import Environment, DictLoader base_tmpl = """ {% block content %}Default{% endblock %} diff --git a/tests/runtime/super.py b/tests/runtime/super.py index 8954afe..d777760 100644 --- a/tests/runtime/super.py +++ b/tests/runtime/super.py @@ -1,6 +1,6 @@ # test file for block super support import jdebug -from jinja import Environment, DictLoader +from jinja2 import Environment, DictLoader env = Environment(loader=DictLoader({ 'a': '{% block intro %}INTRO{% endblock %}|BEFORE|{% block data %}INNER{% endblock %}|AFTER', diff --git a/tests/test_filters.py b/tests/test_filters.py index cc16194..2378d10 100644 --- a/tests/test_filters.py +++ b/tests/test_filters.py @@ -15,7 +15,6 @@ """ CAPITALIZE = '''{{ "foo bar"|capitalize }}''' -CAPTURE = '''{{ "foo"|capture('bar') }}|{{ bar }}''' CENTER = '''{{ "foo"|center(9) }}''' DEFAULT = '''{{ missing|default("no") }}|{{ false|default('no') }}|\ {{ false|default('no', true) }}|{{ given|default("no") }}''' @@ -75,11 +74,6 @@ def test_capitalize(env): assert tmpl.render() == 'Foo bar' -def test_capture(env): - tmpl = env.from_string(CAPTURE) - assert tmpl.render() == 'foo|foo' - - def test_center(env): tmpl = env.from_string(CENTER) assert tmpl.render() == ' foo ' @@ -115,7 +109,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): @@ -191,7 +185,7 @@ def test_lower(env): def test_pprint(env): from pprint import pformat tmpl = env.from_string(PPRINT) - data = range(10000) + data = range(1000) assert tmpl.render(data=data) == pformat(data) diff --git a/tests/test_i18n.py b/tests/test_i18n.py index 65f3d2f..afae0cd 100644 --- a/tests/test_i18n.py +++ b/tests/test_i18n.py @@ -6,7 +6,7 @@ :copyright: 2007 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ -from jinja import Environment, DictLoader +from jinja2 import Environment, DictLoader templates = { 'master.html': '{{ page_title|default(_("missing")) }}' diff --git a/tests/test_inheritance.py b/tests/test_inheritance.py index 64ec76d..53ebfac 100644 --- a/tests/test_inheritance.py +++ b/tests/test_inheritance.py @@ -6,8 +6,8 @@ :copyright: 2007 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ -from jinja import Environment, DictLoader -from jinja.exceptions import TemplateSyntaxError +from jinja2 import Environment, DictLoader +from jinja2.exceptions import TemplateSyntaxError LAYOUTTEMPLATE = '''\ |{% block block1 %}block 1 from layout{% endblock %} diff --git a/tests/test_lexer.py b/tests/test_lexer.py index 1296ea9..a6717e9 100644 --- a/tests/test_lexer.py +++ b/tests/test_lexer.py @@ -24,14 +24,14 @@ def test_raw(env): def test_balancing(): - from jinja import Environment + from jinja2 import Environment env = Environment('{%', '%}', '${', '}') tmpl = env.from_string(BALANCING) assert tmpl.render(seq=range(3)) == "{'FOO': 0}{'FOO': 1}{'FOO': 2}" def test_comments(): - from jinja import Environment + from jinja2 import Environment env = Environment('', '{', '}') tmpl = env.from_string(COMMENTS) assert tmpl.render(seq=range(3)) == ("