Merge pull request #315 from lazka/fix-iter-length
Fix loop context length calculation for iterators. Fixes #244
diff --git a/.travis.yml b/.travis.yml
index e96e9b7..3d3fdad 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,6 +3,7 @@
- "2.6"
- "2.7"
- "3.3"
+ - "3.4"
install:
- "python setup.py install"
diff --git a/CHANGES b/CHANGES
index 459fde7..41fbe57 100644
--- a/CHANGES
+++ b/CHANGES
@@ -9,6 +9,8 @@
- Added support for `followsymlinks` to the file system loader.
- The truncate filter now counts the length.
- Added equalto filter that helps with select filters.
+- Changed cache keys to use absolute file names if available
+ instead of load names.
Version 2.7.2
-------------
diff --git a/Makefile b/Makefile
index 266180e..31945ce 100644
--- a/Makefile
+++ b/Makefile
@@ -14,8 +14,8 @@
$(MAKE) -C docs html dirhtml latex
$(MAKE) -C docs/_build/latex all-pdf
cd docs/_build/; mv html jinja-docs; zip -r jinja-docs.zip jinja-docs; mv jinja-docs html
- scp -r docs/_build/dirhtml/* pocoo.org:/var/www/jinja.pocoo.org/docs/
- scp -r docs/_build/latex/Jinja2.pdf pocoo.org:/var/www/jinja.pocoo.org/docs/jinja-docs.pdf
- scp -r docs/_build/jinja-docs.zip pocoo.org:/var/www/jinja.pocoo.org/docs/
+ scp -r docs/_build/dirhtml/* flow.srv.pocoo.org:/srv/websites/jinja.pocoo.org/docs/
+ scp -r docs/_build/latex/Jinja2.pdf flow.srv.pocoo.org:/srv/websites/jinja.pocoo.org/docs/jinja-docs.pdf
+ scp -r docs/_build/jinja-docs.zip flow.srv.pocoo.org:/srv/websites/jinja.pocoo.org/docs/
.PHONY: test
diff --git a/jinja2/bccache.py b/jinja2/bccache.py
index 09ff845..7b368aa 100644
--- a/jinja2/bccache.py
+++ b/jinja2/bccache.py
@@ -211,25 +211,34 @@
self.pattern = pattern
def _get_default_cache_dir(self):
+ def _unsafe_dir():
+ raise RuntimeError('Cannot determine safe temp directory. You '
+ 'need to explicitly provide one.')
+
tmpdir = tempfile.gettempdir()
# On windows the temporary directory is used specific unless
# explicitly forced otherwise. We can just use that.
- if os.name == 'n':
+ if os.name == 'nt':
return tmpdir
if not hasattr(os, 'getuid'):
- raise RuntimeError('Cannot determine safe temp directory. You '
- 'need to explicitly provide one.')
+ _unsafe_dir()
dirname = '_jinja2-cache-%d' % os.getuid()
actual_dir = os.path.join(tmpdir, dirname)
+
+ # 448 == 0700
try:
- # 448 == 0700
os.mkdir(actual_dir, 448)
except OSError as e:
if e.errno != errno.EEXIST:
raise
-
+ try:
+ os.chmod(actual_dir, 448)
+ if os.stat(actual_dir).st_uid != os.getuid():
+ _unsafe_dir()
+ except OSError:
+ _unsafe_dir()
return actual_dir
def _get_cache_filename(self, bucket):
diff --git a/jinja2/environment.py b/jinja2/environment.py
index 45fabad..d65059a 100644
--- a/jinja2/environment.py
+++ b/jinja2/environment.py
@@ -90,13 +90,13 @@
def _environment_sanity_check(environment):
"""Perform a sanity check on the environment."""
assert issubclass(environment.undefined, Undefined), 'undefined must ' \
- 'be a subclass of undefined because filters depend on it.'
+ 'be a subclass of undefined because filters depend on it.'
assert environment.block_start_string != \
- environment.variable_start_string != \
- environment.comment_start_string, 'block, variable and comment ' \
- 'start strings must be different'
+ environment.variable_start_string != \
+ environment.comment_start_string, 'block, variable and comment ' \
+ 'start strings must be different'
assert environment.newline_sequence in ('\r', '\r\n', '\n'), \
- 'newline_sequence set to unknown line ending string.'
+ 'newline_sequence set to unknown line ending string.'
return environment
@@ -111,13 +111,13 @@
Here the possible initialization parameters:
`block_start_string`
- The string marking the begin of a block. Defaults to ``'{%'``.
+ The string marking the beginning of a block. Defaults to ``'{%'``.
`block_end_string`
The string marking the end of a block. Defaults to ``'%}'``.
`variable_start_string`
- The string marking the begin of a print statement.
+ The string marking the beginning of a print statement.
Defaults to ``'{{'``.
`variable_end_string`
@@ -125,7 +125,7 @@
``'}}'``.
`comment_start_string`
- The string marking the begin of a comment. Defaults to ``'{#'``.
+ The string marking the beginning of a comment. Defaults to ``'{#'``.
`comment_end_string`
The string marking the end of a comment. Defaults to ``'#}'``.
@@ -180,7 +180,7 @@
`autoescape`
If set to true the XML/HTML autoescaping feature is enabled by
- default. For more details about auto escaping see
+ default. For more details about autoescaping see
:class:`~jinja2.utils.Markup`. As of Jinja 2.4 this can also
be a callable that is passed the template name and has to
return `True` or `False` depending on autoescape should be
@@ -330,7 +330,7 @@
loader=missing, cache_size=missing, auto_reload=missing,
bytecode_cache=missing):
"""Create a new overlay environment that shares all the data with the
- current environment except of cache and the overridden attributes.
+ current environment except for cache and the overridden attributes.
Extensions cannot be removed for an overlayed environment. An overlayed
environment automatically gets all the extensions of the environment it
is linked to plus optional extra extensions.
@@ -551,7 +551,7 @@
return self._compile(source, filename)
except TemplateSyntaxError:
exc_info = sys.exc_info()
- self.handle_exception(exc_info, source_hint=source)
+ self.handle_exception(exc_info, source_hint=source_hint)
def compile_expression(self, source, undefined_to_none=True):
"""A handy helper method that returns a callable that accepts keyword
@@ -603,8 +603,8 @@
ignore_errors=True, py_compile=False):
"""Finds all the templates the loader can find, compiles them
and stores them in `target`. If `zip` is `None`, instead of in a
- zipfile, the templates will be will be stored in a directory.
- By default a deflate zip algorithm is used, to switch to
+ zipfile, the templates will be stored in a directory.
+ By default a deflate zip algorithm is used. To switch to
the stored algorithm, `zip` can be set to ``'stored'``.
`extensions` and `filter_func` are passed to :meth:`list_templates`.
@@ -634,7 +634,8 @@
warn(Warning('py_compile has no effect on pypy or Python 3'))
py_compile = False
else:
- import imp, marshal
+ import imp
+ import marshal
py_header = imp.get_magic() + \
u'\xff\xff\xff\xff'.encode('iso-8859-15')
@@ -757,14 +758,23 @@
def _load_template(self, name, globals):
if self.loader is None:
raise TypeError('no loader for this environment specified')
+ try:
+ # use abs path for cache key
+ cache_key = self.loader.get_source(self, name)[1]
+ except RuntimeError:
+ # if loader does not implement get_source()
+ cache_key = None
+ # if template is not file, use name for cache key
+ if cache_key is None:
+ cache_key = name
if self.cache is not None:
- template = self.cache.get(name)
- if template is not None and (not self.auto_reload or \
+ template = self.cache.get(cache_key)
+ if template is not None and (not self.auto_reload or
template.is_up_to_date):
return template
template = self.loader.load(self, name, globals)
if self.cache is not None:
- self.cache[name] = template
+ self.cache[cache_key] = template
return template
@internalcode
@@ -1131,7 +1141,9 @@
"""
close = False
if isinstance(fp, string_types):
- fp = open(fp, encoding is None and 'w' or 'wb')
+ if encoding is None:
+ encoding = 'utf-8'
+ fp = open(fp, 'wb')
close = True
try:
if encoding is not None:
diff --git a/jinja2/filters.py b/jinja2/filters.py
index 41f91d9..882f915 100644
--- a/jinja2/filters.py
+++ b/jinja2/filters.py
@@ -477,16 +477,11 @@
return s
elif killwords:
return s[:length - len(end)] + end
- words = s.split(' ')
- result = []
- m = 0
- for word in words:
- m += len(word) + 1
- if m > (length - len(end)):
- break
- result.append(word)
- result.append(end)
- return u' '.join(result)
+
+ result = s[:length - len(end)].rsplit(' ', 1)[0]
+ if len(result) < length:
+ result += ' '
+ return result + end
@environmentfilter
def do_wordwrap(environment, s, width=79, break_long_words=True,
diff --git a/jinja2/testsuite/loader.py b/jinja2/testsuite/loader.py
index a7350aa..73a7f30 100644
--- a/jinja2/testsuite/loader.py
+++ b/jinja2/testsuite/loader.py
@@ -115,7 +115,8 @@
log = []
self.reg_env = Environment(loader=prefix_loader)
if zip is not None:
- self.archive = tempfile.mkstemp(suffix='.zip')[1]
+ fd, self.archive = tempfile.mkstemp(suffix='.zip')
+ os.close(fd)
else:
self.archive = tempfile.mkdtemp()
self.reg_env.compile_templates(self.archive, zip=zip,
diff --git a/scripts/make-release.py b/scripts/make-release.py
index 2c2cbb6..c28eb9f 100644
--- a/scripts/make-release.py
+++ b/scripts/make-release.py
@@ -16,6 +16,10 @@
from datetime import datetime, date
from subprocess import Popen, PIPE
+try:
+ import wheel
+except ImportError:
+ wheel = None
_date_strip_re = re.compile(r'(?<=\d)(st|nd|rd|th)')
@@ -88,7 +92,10 @@
def build_and_upload():
- Popen([sys.executable, 'setup.py', 'release', 'sdist', 'upload']).wait()
+ cmd = [sys.executable, 'setup.py', 'release', 'sdist', 'upload']
+ if wheel is not None:
+ cmd.insert(4, 'bdist_wheel')
+ Popen(cmd).wait()
def fail(message, *args):
@@ -140,6 +147,10 @@
if not git_is_clean():
fail('You have uncommitted changes in git')
+ if wheel is None:
+ print ('Warning: You need to install the wheel package '
+ 'to upload a wheel distribution.')
+
set_init_version(version)
set_setup_version(version)
make_git_commit('Bump version number to %s', version)
diff --git a/setup.cfg b/setup.cfg
index 2d74c58..b0c20ba 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,3 +1,6 @@
+[wheel]
+universal = 1
+
[egg_info]
tag_build = dev
tag_date = true
diff --git a/setup.py b/setup.py
index d4acf24..6943f53 100644
--- a/setup.py
+++ b/setup.py
@@ -40,21 +40,6 @@
from setuptools import setup
-# ignore the old '--with-speedups' flag
-try:
- speedups_pos = sys.argv.index('--with-speedups')
-except ValueError:
- pass
-else:
- del sys.argv[speedups_pos]
- sys.stderr.write('*' * 74 + '\n')
- sys.stderr.write('WARNING:\n')
- sys.stderr.write(' the --with-speedups flag is deprecated\n')
- sys.stderr.write(' For the actual speedups install the MarkupSafe '
- 'package.\n')
- sys.stderr.write('*' * 74 + '\n')
-
-
setup(
name='Jinja2',
version='2.8-dev',
diff --git a/tox.ini b/tox.ini
index 4bad758..1209f05 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
[tox]
-envlist = py26, py27, pypy, py33
+envlist = py26, py27, pypy, py33, py34
[testenv]
commands = python run-tests.py