[svn] fixed bug reported by stefan ebner and implemented cache_keys to fix problems with multiple laoders caching in the same folder
--HG--
branch : trunk
diff --git a/CHANGES b/CHANGES
index 8dcac27..0a7a011 100644
--- a/CHANGES
+++ b/CHANGES
@@ -83,6 +83,12 @@
- fixed a corner case when defining a block inside of a condition
+- the cached loader mixin is now able to cache multiple templates from
+ different loaders in the same cache folder.
+
+- Translatable strings returned by ``_()`` will leave their string formatting
+ signs untouched. Thanks to Stefan Ebner for reporting.
+
Version 1.0
-----------
diff --git a/THANKS b/THANKS
index e9d865c..2bbb74e 100644
--- a/THANKS
+++ b/THANKS
@@ -4,5 +4,7 @@
All the people listed here helped improving Jinja a lot, provided
patches, helped working out solutions etc. Thanks to all of you!
+- Ronny Pfannschmidt
- Axel Böhm
- Alexey Melchakov
+- Stefan Ebner
diff --git a/docs/src/loaders.txt b/docs/src/loaders.txt
index 20c69e2..29da849 100644
--- a/docs/src/loaders.txt
+++ b/docs/src/loaders.txt
@@ -61,11 +61,14 @@
def __init__(self, path):
self.path = path
- CachedLoaderMixin.__init__(
+ CachedLoaderMixin.__init__(self,
True, # use memory caching
40, # for up to 40 templates
'/tmp', # additionally save the compiled templates in /tmp
- True # and reload cached templates automatically if changed
+ True, # and reload cached templates automatically if changed
+ 'foo' # optional salt used to keep templates with the same
+ # name in the same cache folder, but from different
+ # loaders. New in Jinja 1.1 and can be omitted.
)
def get_source(self, environment, name, parent):
@@ -88,4 +91,4 @@
exist the option `auto_reload` won't have an effect. Also note that the
`check_source_changed` method must not raise an exception if the template
does not exist but return ``-1``. The return value ``-1`` is considered
-"always reload" whereas ``0`` means "do not reload".
\ No newline at end of file
+"always reload" whereas ``0`` means "do not reload".
diff --git a/jinja/datastructure.py b/jinja/datastructure.py
index 86b74c7..5aa6b2c 100644
--- a/jinja/datastructure.py
+++ b/jinja/datastructure.py
@@ -276,8 +276,15 @@
translator = self.environment.get_translator(self)
def translate(s, p=None, n=None, r=None):
if p is None:
- return translator.gettext(s) % (r or {})
- return translator.ngettext(s, p, r[n]) % (r or {})
+ s = translator.gettext(s)
+ else:
+ s = translator.ngettext(s, p, r[n])
+ # apply replacement substitution only if replacements
+ # are given. This is the case for {% trans %}...{% endtras %}
+ # but for the "_()" syntax and a trans tag without a body.
+ if r is not None:
+ s %= r
+ return s
self._translate_func = translate
return self._translate_func
translate_func = property(translate_func, doc=translate_func.__doc__)
diff --git a/jinja/loaders.py b/jinja/loaders.py
index 7bd63a8..6836b32 100644
--- a/jinja/loaders.py
+++ b/jinja/loaders.py
@@ -38,12 +38,13 @@
if p and p[0] != '.']))
-def get_cachename(cachepath, name):
+def get_cachename(cachepath, name, salt=None):
"""
Return the filename for a cached file.
"""
return path.join(cachepath, 'jinja_%s.cache' %
- sha.new('jinja(%s)tmpl' % name).hexdigest())
+ sha.new('jinja(%s|%s)tmpl' %
+ (name, salt or '')).hexdigest())
class LoaderWrapper(object):
@@ -130,7 +131,8 @@
Mixin this class to implement simple memory and disk caching.
"""
- def __init__(self, use_memcache, cache_size, cache_folder, auto_reload):
+ def __init__(self, use_memcache, cache_size, cache_folder, auto_reload,
+ cache_salt=None):
if use_memcache:
self.__memcache = CacheDict(cache_size)
else:
@@ -140,6 +142,7 @@
self.__auto_reload = False
else:
self.__auto_reload = auto_reload
+ self.__salt = cache_salt
self.__times = {}
self.__lock = Lock()
@@ -186,7 +189,7 @@
# mem cache disabled or not cached by now
# try to load if from the disk cache
if tmpl is None and self.__cache_folder is not None:
- cache_fn = get_cachename(self.__cache_folder, name)
+ cache_fn = get_cachename(self.__cache_folder, name, self.__salt)
if last_change is not None:
try:
cache_time = path.getmtime(cache_fn)
@@ -261,14 +264,20 @@
``auto_reload`` Set this to `False` for a slightly better
performance. In that case Jinja won't check for
template changes on the filesystem.
+ ``cache_salt`` Optional unique number to not confuse the
+ caching system when caching more than one
+ template loader in the same folder. Defaults
+ to the searchpath. *New in Jinja 1.1*
=================== =================================================
"""
def __init__(self, searchpath, use_memcache=False, memcache_size=40,
- cache_folder=None, auto_reload=True):
+ cache_folder=None, auto_reload=True, cache_salt=None):
+ if cache_salt is None:
+ cache_salt = searchpath
self.searchpath = searchpath
CachedLoaderMixin.__init__(self, use_memcache, memcache_size,
- cache_folder, auto_reload)
+ cache_folder, auto_reload, cache_salt)
def get_source(self, environment, name, parent):
filename = get_template_filename(self.searchpath, name)
@@ -321,22 +330,30 @@
template changes on the filesystem. If the
templates are inside of an egg file this won't
have an effect.
+ ``cache_salt`` Optional unique number to not confuse the
+ caching system when caching more than one
+ template loader in the same folder. Defaults
+ to ``package_name + '/' + package_path``.
+ *New in Jinja 1.1*
=================== =================================================
"""
def __init__(self, package_name, package_path, use_memcache=False,
- memcache_size=40, cache_folder=None, auto_reload=True):
+ memcache_size=40, cache_folder=None, auto_reload=True,
+ cache_salt=None):
if resource_filename is None:
raise ImportError('setuptools not found')
self.package_name = package_name
self.package_path = package_path
+ if cache_salt is None:
+ cache_salt = package_name + '/' + package_path
# if we have an loader we probably retrieved it from an egg
# file. In that case don't use the auto_reload!
if auto_reload and getattr(__import__(package_name, '', '', ['']),
'__loader__', None) is not None:
auto_reload = False
CachedLoaderMixin.__init__(self, use_memcache, memcache_size,
- cache_folder, auto_reload)
+ cache_folder, auto_reload, cache_salt)
def get_source(self, environment, name, parent):
name = '/'.join([self.package_path] + [p for p in name.split('/')
@@ -401,11 +418,15 @@
``auto_reload`` Set this to `False` for a slightly better
performance. In that case of `getmtime_func`
not being provided this won't have an effect.
+ ``cache_salt`` Optional unique number to not confuse the
+ caching system when caching more than one
+ template loader in the same folder.
=================== =================================================
"""
def __init__(self, loader_func, getmtime_func=None, use_memcache=False,
- memcache_size=40, cache_folder=None, auto_reload=True):
+ memcache_size=40, cache_folder=None, auto_reload=True,
+ cache_salt=None):
# when changing the signature also check the jinja.plugin function
# loader instantiation.
self.loader_func = loader_func
@@ -413,7 +434,7 @@
if auto_reload and getmtime_func is None:
auto_reload = False
CachedLoaderMixin.__init__(self, use_memcache, memcache_size,
- cache_folder, auto_reload)
+ cache_folder, auto_reload, cache_salt)
def get_source(self, environment, name, parent):
rv = self.loader_func(name)
diff --git a/tests/test_i18n.py b/tests/test_i18n.py
index ddd5841..040f7ba 100644
--- a/tests/test_i18n.py
+++ b/tests/test_i18n.py
@@ -14,7 +14,8 @@
'child.html': '{% extends "master.html" %}{% block body %}'
'{% trans "watch out" %}{% endblock %}',
'plural.html': '{% trans user_count %}One user online{% pluralize %}'
- '{{ user_count }} users online{% endtrans %}'
+ '{{ user_count }} users online{% endtrans %}',
+ 'stringformat.html': '{{ _("User: %d")|format(user_count) }}'
}
@@ -23,7 +24,8 @@
'missing': 'fehlend',
'watch out': 'pass auf',
'One user online': 'Ein Benutzer online',
- '%(user_count)s users online': '%(user_count)s Benutzer online'
+ '%(user_count)s users online': '%(user_count)s Benutzer online',
+ 'User: %d': 'Benutzer: %d'
}
}
@@ -77,3 +79,8 @@
tmpl = i18n_env.get_template('plural.html')
assert tmpl.render(LANGUAGE='de', user_count=1) == 'Ein Benutzer online'
assert tmpl.render(LANGUAGE='de', user_count=2) == '2 Benutzer online'
+
+
+def test_trans_stringformatting():
+ tmpl = i18n_env.get_template('stringformat.html')
+ assert tmpl.render(LANGUAGE='de', user_count=5) == 'Benutzer: 5'