updated a few filters and improved i18n
authorArmin Ronacher <armin.ronacher@active-4.com>
Wed, 16 Apr 2008 13:29:52 +0000 (15:29 +0200)
committerArmin Ronacher <armin.ronacher@active-4.com>
Wed, 16 Apr 2008 13:29:52 +0000 (15:29 +0200)
--HG--
branch : trunk

examples/translate.py
jinja2/defaults.py
jinja2/environment.py
jinja2/filters.py
jinja2/i18n.py

index 8b38d02ea7d4fd46b24d94a763df0846c96e07c1..d5f792f8234e0637c564a4d33bdfd44f89e4d20b 100644 (file)
@@ -3,4 +3,4 @@ from jinja2 import Environment
 print Environment().from_string("""\
 {% trans %}Hello {{ user }}!{% endtrans %}
 {% trans count=users|count %}{{ count }} user{% pluralize %}{{ count }} users{% endtrans %}
-""").render()
+""").render(user="someone")
index 79591802c872329c8eaa6a2f09876ddfceba822d..ea8591de5f3e4142642083aa6c3c29837f995ac1 100644 (file)
 from jinja2.filters import FILTERS as DEFAULT_FILTERS
 from jinja.tests import TESTS as DEFAULT_TESTS
 
+
 DEFAULT_NAMESPACE = {
-    'range': xrange
+    'range':        xrange,
+    # fake translators so that {% trans %} is a noop by default
+    'gettext':      lambda x: x,
+    'ngettext':     lambda s, p, n: (s, p)[n != 1]
 }
index 2ed660c371223d3b0efe3122a95405653059e488..60a7a2be4e6c6c9baf40be5c9e47ae35699db69a 100644 (file)
@@ -139,6 +139,7 @@ class Environment(object):
         if self.optimized:
             node = optimize(source, self, globals or {})
         source = generate(node, self, filename)
+        print source
         if raw:
             return source
         if filename is None:
index 300e0cd88da0c5a6bb4ecb65886d6def43a7ccc8..45e41375aa49a48e9806dc290aed4b08839c77a5 100644 (file)
@@ -113,7 +113,7 @@ def do_xmlattr(d, autospace=False):
         raise TypeError('a dict is required')
     result = []
     for key, value in d.iteritems():
-        if value not in (None, env.undefined_singleton):
+        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)
@@ -214,40 +214,7 @@ def do_join(value, d=u''):
         {{ [1, 2, 3]|join }}
             -> 123
     """
-    return unicode(d).join([unicode(x) for x in value])
-
-
-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
-    string. If the object has no length it will of corse return 0.
-    """
-    try:
-        if type(value) in (int, float, long):
-            return len(str(value))
-        return len(value)
-    except TypeError:
-        return 0
-
-
-def do_reverse(value):
-    """
-    Return a reversed list of the sequence filtered. You can use this
-    for example for reverse iteration:
-
-    .. sourcecode:: jinja
-
-        {% for item in seq|reverse %}
-            {{ item|e }}
-        {% endfor %}
-    """
-    try:
-        return value[::-1]
-    except:
-        l = list(value)
-        l.reverse()
-        return l
+    return unicode(d).join(unicode(x) for x in value)
 
 
 def do_center(value, width=80):
@@ -257,34 +224,40 @@ def do_center(value, width=80):
     return unicode(value).center(width)
 
 
-def do_first(seq):
+@contextfilter
+def do_first(context, seq):
     """
     Return the frist item of a sequence.
     """
     try:
         return iter(seq).next()
     except StopIteration:
-        return env.undefined_singleton
+        return context.environment.undefined('seq|first',
+            extra='the sequence was empty')
 
 
-def do_last(seq):
+@contextfilter
+def do_last(context, seq):
     """
     Return the last item of a sequence.
     """
     try:
         return iter(reversed(seq)).next()
     except StopIteration:
-        return env.undefined_singleton
+        return context.environment.undefined('seq|last',
+            extra='the sequence was empty')
 
 
-def do_random(seq):
+@contextfilter
+def do_random(context, seq):
     """
     Return a random item from the sequence.
     """
     try:
         return choice(seq)
     except IndexError:
-        return env.undefined_singleton
+        return context.environment.undefined('seq|random',
+            extra='the sequence was empty')
 
 
 def do_jsonencode(value):
@@ -306,8 +279,8 @@ def do_jsonencode(value):
 
 def do_filesizeformat(value):
     """
-    Format the value like a 'human-readable' file size (i.e. 13 KB, 4.1 MB, 102
-    bytes, etc).
+    Format the value like a 'human-readable' file size (i.e. 13 KB,
+    4.1 MB, 102 bytes, etc).
     """
     # fail silently
     try:
@@ -501,7 +474,7 @@ def do_string(value):
     return unicode(value)
 
 
-def do_format(value, *args):
+def do_format(value, *args, **kwargs):
     """
     Apply python string formatting on an object:
 
@@ -509,34 +482,13 @@ def do_format(value, *args):
 
         {{ "%s - %s"|format("Hello?", "Foo!") }}
             -> Hello? - Foo!
-
-    Note that you cannot use the mapping syntax (``%(name)s``)
-    like in python. Use `|dformat` for that.
     """
+    if kwargs:
+        kwargs.update(idx, arg in enumerate(args))
+        args = kwargs
     return unicode(value) % args
 
 
-def do_dformat(d):
-    """
-    Apply python mapping string formatting on an object:
-
-    .. sourcecode:: jinja
-
-        {{ "Hello %(username)s!"|dformat({'username': 'John Doe'}) }}
-            -> Hello John Doe!
-
-    This is useful when adding variables to translateable
-    string expressions.
-
-    *New in Jinja 1.1*
-    """
-    if not isinstance(d, dict):
-        raise FilterArgumentError('dict required')
-    def wrapped(env, context, value):
-        return env.to_unicode(value) % d
-    return wrapped
-
-
 def do_trim(value):
     """
     Strip leading and trailing whitespace.
@@ -629,28 +581,6 @@ def do_batch(value, linecount, fill_with=None):
     return result
 
 
-def do_sum():
-    """
-    Sum up the given sequence of numbers.
-
-    *new in Jinja 1.1*
-    """
-    def wrapped(env, context, value):
-        return sum(value)
-    return wrapped
-
-
-def do_abs():
-    """
-    Return the absolute value of a number.
-
-    *new in Jinja 1.1*
-    """
-    def wrapped(env, context, value):
-        return abs(value)
-    return wrapped
-
-
 def do_round(precision=0, method='common'):
     """
     Round the number to a given precision. The first
@@ -737,48 +667,6 @@ def do_groupby(attribute):
     return wrapped
 
 
-def do_getattribute(attribute):
-    """
-    Get one attribute from an object. Normally you don't have to use this
-    filter because the attribute and subscript expressions try to either
-    get an attribute of an object or an item. In some situations it could
-    be that there is an item *and* an attribute with the same name. In that
-    situation only the item is returned, never the attribute.
-
-    .. sourcecode:: jinja
-
-        {{ foo.bar }} -> {{ foo|getattribute('bar') }}
-
-    *New in Jinja 1.2*
-    """
-    def wrapped(env, context, value):
-        try:
-            return get_attribute(value, attribute)
-        except (SecurityException, AttributeError):
-            return env.undefined_singleton
-    return wrapped
-
-
-def do_getitem(key):
-    """
-    This filter basically works like the normal subscript expression but
-    it doesn't fall back to attribute lookup. If an item does not exist for
-    an object undefined is returned.
-
-    .. sourcecode:: jinja
-
-        {{ foo.bar }} -> {{ foo|getitem('bar') }}
-
-    *New in Jinja 1.2*
-    """
-    def wrapped(env, context, value):
-        try:
-            return value[key]
-        except (TypeError, KeyError, IndexError, AttributeError):
-            return env.undefined_singleton
-    return wrapped
-
-
 FILTERS = {
     'replace':              do_replace,
     'upper':                do_upper,
@@ -790,10 +678,10 @@ FILTERS = {
     'title':                do_title,
     'default':              do_default,
     'join':                 do_join,
-    'count':                do_count,
+    'count':                len,
     'dictsort':             do_dictsort,
-    'length':               do_count,
-    'reverse':              do_reverse,
+    'length':               len,
+    'reverse':              reversed,
     'center':               do_center,
     'title':                do_title,
     'capitalize':           do_capitalize,
@@ -815,16 +703,13 @@ FILTERS = {
     'string':               do_string,
     'urlize':               do_urlize,
     'format':               do_format,
-    'dformat':              do_dformat,
     'trim':                 do_trim,
     'striptags':            do_striptags,
     'slice':                do_slice,
     'batch':                do_batch,
-    'sum':                  do_sum,
-    'abs':                  do_abs,
+    'sum':                  sum,
+    'abs':                  abs,
     'round':                do_round,
     'sort':                 do_sort,
-    'groupby':              do_groupby,
-    'getattribute':         do_getattribute,
-    'getitem':              do_getitem
+    'groupby':              do_groupby
 }
index 1b19321e08b83b151adfe702e72846216ff395bc..b08ccf30c1613ace16e1bc26ddbc36259caae996 100644 (file)
@@ -108,8 +108,9 @@ def _parse_block(parser, allow_pluralize):
             parser.stream.next()
         elif parser.stream.current.type is 'variable_begin':
             parser.stream.next()
-            referenced.append(parser.stream.expect('name').value)
-            buf.append('%s')
+            name = parser.stream.expect('name').value
+            referenced.append(name)
+            buf.append('%%(%s)s' % name)
             parser.stream.expect('variable_end')
         elif parser.stream.current.type is 'block_begin':
             parser.stream.next()