apply flake8

This commit is contained in:
David Lord 2020-01-10 10:40:52 -08:00
parent 04c8787155
commit bb6216ea30
No known key found for this signature in database
GPG Key ID: 7A1C87E3F5BC42A8
43 changed files with 423 additions and 430 deletions

View File

@ -6,9 +6,9 @@ from jinja2.loaders import DictLoader
env = Environment(
loader=DictLoader(
{
"a": """[A[{% block body %}{% endblock %}]]""",
"b": """{% extends 'a' %}{% block body %}[B]{% endblock %}""",
"c": """{% extends 'b' %}{% block body %}###{{ super() }}###{% endblock %}""",
"a": "[A[{% block body %}{% endblock %}]]",
"b": "{% extends 'a' %}{% block body %}[B]{% endblock %}",
"c": "{% extends 'b' %}{% block body %}###{{ super() }}###{% endblock %}",
}
)
)

View File

@ -12,7 +12,9 @@ print(
env.from_string(
"""\
{% trans %}Hello {{ user }}!{% endtrans %}
{% trans count=users|count %}{{ count }} user{% pluralize %}{{ count }} users{% endtrans %}
{% trans count=users|count -%}
{{ count }} user{% pluralize %}{{ count }} users
{% endtrans %}
"""
).render(user="someone", users=[1, 2, 3])
)

View File

@ -8,6 +8,7 @@ import sys
from timeit import Timer
from jinja2 import Environment as JinjaEnvironment
from jinja2._compat import text_type
context = {
"page_title": "mitsuhiko's benchmark",
@ -171,7 +172,8 @@ else:
<h1>${page_title|h}</h1>
</div>
<ul class="navigation">
% for href, caption in [('index.html', 'Index'), ('downloads.html', 'Downloads'), ('products.html', 'Products')]:
% for href, caption in [('index.html', 'Index'), ('downloads.html', 'Downloads'), \
('products.html', 'Products')]:
<li><a href="${href|h}">${caption|h}</a></li>
% endfor
</ul>
@ -250,7 +252,8 @@ else:
<h1>$cgi.escape($page_title)</h1>
</div>
<ul class="navigation">
#for $href, $caption in [('index.html', 'Index'), ('downloads.html', 'Downloads'), ('products.html', 'Products')]:
#for $href, $caption in [('index.html', 'Index'), ('downloads.html', 'Downloads'), \
('products.html', 'Products')]:
<li><a href="$cgi.escape($href)">$cgi.escape($caption)</a></li>
#end for
</ul>
@ -272,7 +275,7 @@ else:
)
def test_cheetah():
unicode(cheetah_template)
text_type(cheetah_template)
try:
@ -293,7 +296,8 @@ else:
<h1>${page_title}</h1>
</div>
<ul class="navigation">
<?py for href, caption in [('index.html', 'Index'), ('downloads.html', 'Downloads'), ('products.html', 'Products')]: ?>
<?py for href, caption in [('index.html', 'Index'), ('downloads.html', 'Downloads'), \
('products.html', 'Products')]: ?>
<li><a href="${href}">${caption}</a></li>
<?py #end ?>
</ul>
@ -314,8 +318,6 @@ else:
)
def test_tenjin():
from tenjin.helpers import escape, to_str
tenjin_template.render(context, locals())
@ -337,7 +339,8 @@ else:
<h1>$cgi.escape($page_title)</h1>
</div>
<ul class="navigation">
#for $href, $caption in [('index.html', 'Index'), ('downloads.html', 'Downloads'), ('products.html', 'Products')]
#for $href, $caption in [('index.html', 'Index'), ('downloads.html', 'Downloads'), \
('products.html', 'Products')]
<li><a href="$cgi.escape($href)">$cgi.escape($caption)</a></li>
#end for
</ul>
@ -381,7 +384,8 @@ else:
<h1 tal:content="page_title">Page Title</h1>
</div>
<ul class="navigation">
<li tal:repeat="item sections"><a tal:attributes="href item[0]" tal:content="item[1]">caption</a></li>
<li tal:repeat="item sections"><a tal:attributes="href item[0]" \
tal:content="item[1]">caption</a></li>
</ul>
<div class="table">
<table>

View File

@ -1,72 +1,75 @@
# -*- coding: utf-8 -*-
"""
Django to Jinja
~~~~~~~~~~~~~~~
Django to Jinja
~~~~~~~~~~~~~~~
Helper module that can convert django templates into Jinja templates.
Helper module that can convert django templates into Jinja templates.
This file is not intended to be used as stand alone application but to
be used as library. To convert templates you basically create your own
writer, add extra conversion logic for your custom template tags,
configure your django environment and run the `convert_templates`
function.
This file is not intended to be used as stand alone application but to
be used as library. To convert templates you basically create your own
writer, add extra conversion logic for your custom template tags,
configure your django environment and run the `convert_templates`
function.
Here a simple example::
Here a simple example::
# configure django (or use settings.configure)
import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'yourapplication.settings'
from yourapplication.foo.templatetags.bar import MyNode
# configure django (or use settings.configure)
import os
from django2jinja import Writer, convert_templates
os.environ["DJANGO_SETTINGS_MODULE"] = "yourapplication.settings"
from yourapplication.foo.templatetags.bar import MyNode
def write_my_node(writer, node):
writer.start_variable()
writer.write('myfunc(')
for idx, arg in enumerate(node.args):
if idx:
writer.write(', ')
writer.node(arg)
writer.write(')')
writer.end_variable()
from django2jinja import Writer, convert_templates
writer = Writer()
writer.node_handlers[MyNode] = write_my_node
convert_templates('/path/to/output/folder', writer=writer)
def write_my_node(writer, node):
writer.start_variable()
writer.write("myfunc(")
for idx, arg in enumerate(node.args):
if idx:
writer.write(", ")
writer.node(arg)
writer.write(")")
writer.end_variable()
Here is an example hos to automatically translate your django
variables to jinja2::
writer = Writer()
writer.node_handlers[MyNode] = write_my_node
convert_templates("/path/to/output/folder", writer=writer)
import re
# List of tuple (Match pattern, Replace pattern, Exclusion pattern)
Here is an example hos to automatically translate your django
variables to jinja2::
var_re = ((re.compile(r"(u|user)\.is_authenticated"), r"\1.is_authenticated()", None),
(re.compile(r"\.non_field_errors"), r".non_field_errors()", None),
(re.compile(r"\.label_tag"), r".label_tag()", None),
(re.compile(r"\.as_dl"), r".as_dl()", None),
(re.compile(r"\.as_table"), r".as_table()", None),
(re.compile(r"\.as_widget"), r".as_widget()", None),
(re.compile(r"\.as_hidden"), r".as_hidden()", None),
import re
# List of tuple (Match pattern, Replace pattern, Exclusion pattern)
var_re = (
(re.compile("(u|user)\\.is_authenticated"), "\\1.is_authenticated()", None),
(re.compile("\\.non_field_errors"), ".non_field_errors()", None),
(re.compile("\\.label_tag"), ".label_tag()", None),
(re.compile("\\.as_dl"), ".as_dl()", None),
(re.compile("\\.as_table"), ".as_table()", None),
(re.compile("\\.as_widget"), ".as_widget()", None),
(re.compile("\\.as_hidden"), ".as_hidden()", None),
(re.compile("\\.get_([0-9_\\w]+)_url"), ".get_\\1_url()", None),
(re.compile("\\.url"), ".url()", re.compile("(form|calendar).url")),
(re.compile("\\.get_([0-9_\\w]+)_display"), ".get_\\1_display()", None),
(re.compile("loop\\.counte"), "loop.index", None),
(re.compile("loop\\.revcounte"), "loop.revindex", None),
(
re.compile("request\\.GET\\.([0-9_\\w]+)"),
"request.GET.get('\\1', '')",
None,
),
(re.compile("request\\.get_host"), "request.get_host()", None),
(re.compile("\\.all(?!_)"), ".all()", None),
(re.compile("\\.all\\.0"), ".all()[0]", None),
(re.compile("\\.([0-9])($|\\s+)"), "[\\1]\\2", None),
(re.compile("\\.items"), ".items()", None),
)
writer = Writer(var_re=var_re)
(re.compile(r"\.get_([0-9_\w]+)_url"), r".get_\1_url()", None),
(re.compile(r"\.url"), r".url()", re.compile(r"(form|calendar).url")),
(re.compile(r"\.get_([0-9_\w]+)_display"), r".get_\1_display()", None),
(re.compile(r"loop\.counter"), r"loop.index", None),
(re.compile(r"loop\.revcounter"), r"loop.revindex", None),
(re.compile(r"request\.GET\.([0-9_\w]+)"), r"request.GET.get('\1', '')", None),
(re.compile(r"request\.get_host"), r"request.get_host()", None),
For details about the writing process have a look at the module code.
(re.compile(r"\.all(?!_)"), r".all()", None),
(re.compile(r"\.all\.0"), r".all()[0]", None),
(re.compile(r"\.([0-9])($|\s+)"), r"[\1]\2", None),
(re.compile(r"\.items"), r".items()", None),
)
writer = Writer(var_re=var_re)
For details about the writing process have a look at the module code.
:copyright: (c) 2009 by the Jinja Team.
:license: BSD.
:copyright: (c) 2009 by the Jinja Team.
:license: BSD.
"""
from __future__ import print_function
@ -87,14 +90,12 @@ from django.template import Variable
from django.template.debug import DebugVariableNode as VariableNode
from django.templatetags import i18n as i18n_tags
from jinja2.defaults import *
from jinja2 import defaults
_node_handlers = {}
_resolved_filters = {}
_newline_re = re.compile(r"(?:\r\n|\r|\n)")
# Django stores an itertools object on the cycle node. Not only is this
# thread unsafe but also a problem for the converter which needs the raw
# string values passed to the constructor to create a jinja loop.cycle()
@ -122,7 +123,8 @@ def convert_templates(
output_dir, extensions=(".html", ".txt"), writer=None, callback=None
):
"""Iterates over all templates in the template dirs configured and
translates them and writes the new templates into the output directory.
translates them and writes the new templates into the output
directory.
"""
if writer is None:
writer = Writer()
@ -156,11 +158,8 @@ def convert_templates(
if not os.path.exists(basetarget):
os.makedirs(basetarget)
callback(source)
f = file(target, "w")
try:
with open(target, "w") as f:
translate(f, source)
finally:
f.close()
class Writer(object):
@ -170,16 +169,16 @@ class Writer(object):
self,
stream=None,
error_stream=None,
block_start_string=BLOCK_START_STRING,
block_end_string=BLOCK_END_STRING,
variable_start_string=VARIABLE_START_STRING,
variable_end_string=VARIABLE_END_STRING,
comment_start_string=COMMENT_START_STRING,
comment_end_string=COMMENT_END_STRING,
block_start_string=defaults.BLOCK_START_STRING,
block_end_string=defaults.BLOCK_END_STRING,
variable_start_string=defaults.VARIABLE_START_STRING,
variable_end_string=defaults.VARIABLE_END_STRING,
comment_start_string=defaults.COMMENT_START_STRING,
comment_end_string=defaults.COMMENT_END_STRING,
initial_autoescape=True,
use_jinja_autoescape=False,
custom_node_handlers=None,
var_re=[],
var_re=None,
env=None,
):
if stream is None:
@ -200,12 +199,12 @@ class Writer(object):
self.node_handlers = dict(_node_handlers, **(custom_node_handlers or {}))
self._loop_depth = 0
self._filters_warned = set()
self.var_re = var_re
self.var_re = [] if var_re is None else var_re
self.env = env
def enter_loop(self):
"""Increments the loop depth so that write functions know if they
are in a loop.
"""Increments the loop depth so that write functions know if
they are in a loop.
"""
self._loop_depth += 1
@ -223,7 +222,9 @@ class Writer(object):
self.stream.write(s.encode(settings.FILE_CHARSET))
def print_expr(self, expr):
"""Open a variable tag, write to the string to the stream and close."""
"""Open a variable tag, write to the string to the stream and
close.
"""
self.start_variable()
self.write(expr)
self.end_variable()
@ -269,7 +270,9 @@ class Writer(object):
self.end_block()
def variable(self, name):
"""Prints a variable. This performs variable name transformation."""
"""Prints a variable. This performs variable name
transformation.
"""
self.write(self.translate_variable_name(name))
def literal(self, value):
@ -287,7 +290,10 @@ class Writer(object):
if name is None:
self.warn("Could not find filter %s" % name)
continue
if name not in DEFAULT_FILTERS and name not in self._filters_warned:
if (
name not in defaults.DEFAULT_FILTERS
and name not in self._filters_warned
):
self._filters_warned.add(name)
self.warn("Filter %s probably doesn't exist in Jinja" % name)
if not want_pipe:
@ -344,13 +350,13 @@ class Writer(object):
"""
if filter not in _resolved_filters:
for library in libraries.values():
for key, value in library.filters.iteritems():
for key, value in library.filters.items():
_resolved_filters[value] = key
return _resolved_filters.get(filter, None)
def node(self, node):
"""Invokes the node handler for a node."""
for cls, handler in self.node_handlers.iteritems():
for cls, handler in self.node_handlers.items():
if type(node) is cls or type(node).__name__ == cls:
handler(self, node)
break
@ -410,7 +416,7 @@ def comment_tag(writer, node):
@node(core_tags.DebugNode)
def comment_tag(writer, node):
def debug_tag(writer, node):
writer.warn(
"Debug tag detected. Make sure to add a global function "
"called debug to the namespace.",
@ -596,7 +602,6 @@ def url_tag(writer, node):
writer.write("set %s = " % node.asvar)
else:
writer.start_variable()
autoescape = writer.autoescape
writer.write("url(")
writer.literal(node.view_name)
for arg in node.args:
@ -740,10 +745,7 @@ def translate_block(writer, node):
touch_var(key)
writer.node(var.filter_expression)
have_plural = False
plural_var = None
if node.plural and node.countervar and node.counter:
have_plural = True
plural_var = node.countervar
if plural_var not in variables:
if idx > -1:

View File

@ -1,8 +1,7 @@
from django.conf import settings
from django2jinja import convert_templates
from django2jinja import Writer
settings.configure(TEMPLATE_DIRS=["templates"], TEMPLATE_DEBUG=True)
from django2jinja import convert_templates, Writer
writer = Writer(use_jinja_autoescape=True)
convert_templates("converted", writer=writer)

View File

@ -10,9 +10,9 @@ if sys.version_info[0] < 3:
def get_characters():
"""Find every Unicode character that is valid in a Python `identifier`_ but
is not matched by the regex ``\w`` group.
is not matched by the regex ``\\w`` group.
``\w`` matches some characters that aren't valid in identifiers, but
``\\w`` matches some characters that aren't valid in identifiers, but
:meth:`str.isidentifier` will catch that later in lexing.
All start characters are valid continue characters, so we only test for
@ -33,7 +33,7 @@ def collapse_ranges(data):
Source: https://stackoverflow.com/a/4629241/400617
"""
for a, b in itertools.groupby(enumerate(data), lambda x: ord(x[1]) - x[0]):
for _, b in itertools.groupby(enumerate(data), lambda x: ord(x[1]) - x[0]):
b = list(b)
yield b[0][1], b[-1][1]
@ -66,8 +66,9 @@ def main():
)
with open(filename, "w", encoding="utf8") as f:
f.write("")
f.write("# generated by scripts/generate_identifier_pattern.py\n")
f.write('pattern = "{}"\n'.format(pattern))
f.write('pattern = "{}" # noqa: B950\n'.format(pattern))
if __name__ == "__main__":

View File

@ -27,7 +27,7 @@ def parse_changelog():
with open("CHANGES.rst") as f:
lineiter = iter(f)
for line in lineiter:
match = re.search("^Version\s+(.*)", line.strip())
match = re.search(r"^Version\s+(.*)", line.strip())
if match is None:
continue
@ -161,7 +161,7 @@ def main():
fail("You have uncommitted changes in git")
try:
import wheel
__import__("wheel")
except ImportError:
fail("You need to install the wheel package.")

View File

@ -37,3 +37,6 @@ ignore =
W503
# up to 88 allowed by bugbear B950
max-line-length = 80
per-file-ignores =
# __init__ module exports names
src/jinja2/__init__.py: F401

View File

@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
# flake8: noqa
"""
jinja2._compat
~~~~~~~~~~~~~~
@ -10,6 +11,7 @@
:copyright: Copyright 2013 by the Jinja team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import marshal
import sys
PY2 = sys.version_info[0] == 2
@ -46,6 +48,9 @@ if not PY2:
implements_to_string = _identity
encode_filename = _identity
marshal_dump = marshal.dump
marshal_load = marshal.load
else:
unichr = unichr
text_type = unicode
@ -83,6 +88,17 @@ else:
return filename.encode("utf-8")
return filename
def marshal_dump(code, f):
if isinstance(f, file):
marshal.dump(code, f)
else:
f.write(marshal.dumps(code))
def marshal_load(f):
if isinstance(f, file):
return marshal.load(f)
return marshal.loads(f.read())
def with_metaclass(meta, *bases):
"""Create a base class with a metaclass."""

View File

@ -1,2 +1,2 @@
# generated by scripts/generate_identifier_pattern.py
pattern = "·̀-ͯ·҃-֑҇-ׇֽֿׁׂׅׄؐ-ًؚ-ٰٟۖ-ۜ۟-۪ۤۧۨ-ܑۭܰ-݊ަ-ް߫-߳ࠖ-࠙ࠛ-ࠣࠥ-ࠧࠩ-࡙࠭-࡛ࣔ-ࣣ࣡-ःऺ-़ा-ॏ॑-ॗॢॣঁ-ঃ়া-ৄেৈো-্ৗৢৣਁ-ਃ਼ਾ-ੂੇੈੋ-੍ੑੰੱੵઁ-ઃ઼ા-ૅે-ૉો-્ૢૣଁ-ଃ଼ା-ୄେୈୋ-୍ୖୗୢୣஂா-ூெ-ைொ-்ௗఀ-ఃా-ౄె-ైొ-్ౕౖౢౣಁ-ಃ಼ಾ-ೄೆ-ೈೊ-್ೕೖೢೣഁ-ഃാ-ൄെ-ൈൊ-്ൗൢൣංඃ්ා-ුූෘ-ෟෲෳัิ-ฺ็-๎ັິ-ູົຼ່-ໍ༹༘༙༵༷༾༿ཱ-྄྆྇ྍ-ྗྙ-ྼ࿆ါ-ှၖ-ၙၞ-ၠၢ-ၤၧ-ၭၱ-ၴႂ-ႍႏႚ-ႝ፝-፟ᜒ-᜔ᜲ-᜴ᝒᝓᝲᝳ឴-៓៝᠋-᠍ᢅᢆᢩᤠ-ᤫᤰ-᤻ᨗ-ᨛᩕ-ᩞ᩠-᩿᩼᪰-᪽ᬀ-ᬄ᬴-᭄᭫-᭳ᮀ-ᮂᮡ-ᮭ᯦-᯳ᰤ-᰷᳐-᳔᳒-᳨᳭ᳲ-᳴᳸᳹᷀-᷵᷻-᷿‿⁀⁔⃐-⃥⃜⃡-⃰℘℮⳯-⵿⳱ⷠ-〪ⷿ-゙゚〯꙯ꙴ-꙽ꚞꚟ꛰꛱ꠂ꠆ꠋꠣ-ꠧꢀꢁꢴ-ꣅ꣠-꣱ꤦ-꤭ꥇ-꥓ꦀ-ꦃ꦳-꧀ꧥꨩ-ꨶꩃꩌꩍꩻ-ꩽꪰꪲ-ꪴꪷꪸꪾ꪿꫁ꫫ-ꫯꫵ꫶ꯣ-ꯪ꯬꯭ﬞ︀-️︠-︯︳︴﹍-﹏_𐇽𐋠𐍶-𐍺𐨁-𐨃𐨅𐨆𐨌-𐨏𐨸-𐨿𐨺𐫦𐫥𑀀-𑀂𑀸-𑁆𑁿-𑂂𑂰-𑂺𑄀-𑄂𑄧-𑅳𑄴𑆀-𑆂𑆳-𑇊𑇀-𑇌𑈬-𑈷𑈾𑋟-𑋪𑌀-𑌃𑌼𑌾-𑍄𑍇𑍈𑍋-𑍍𑍗𑍢𑍣𑍦-𑍬𑍰-𑍴𑐵-𑑆𑒰-𑓃𑖯-𑖵𑖸-𑗀𑗜𑗝𑘰-𑙀𑚫-𑚷𑜝-𑜫𑰯-𑰶𑰸-𑰿𑲒-𑲧𑲩-𑲶𖫰-𖫴𖬰-𖬶𖽑-𖽾𖾏-𖾒𛲝𛲞𝅥-𝅩𝅭-𝅲𝅻-𝆂𝆅-𝆋𝆪-𝆭𝉂-𝉄𝨀-𝨶𝨻-𝩬𝩵𝪄𝪛-𝪟𝪡-𝪯𞀀-𞀆𞀈-𞀘𞀛-𞀡𞀣𞀤𞀦-𞣐𞀪-𞣖𞥄-𞥊󠄀-󠇯"
pattern = "·̀-ͯ·҃-֑҇-ׇֽֿׁׂׅׄؐ-ًؚ-ٰٟۖ-ۜ۟-۪ۤۧۨ-ܑۭܰ-݊ަ-ް߫-߳ࠖ-࠙ࠛ-ࠣࠥ-ࠧࠩ-࡙࠭-࡛ࣔ-ࣣ࣡-ःऺ-़ा-ॏ॑-ॗॢॣঁ-ঃ়া-ৄেৈো-্ৗৢৣਁ-ਃ਼ਾ-ੂੇੈੋ-੍ੑੰੱੵઁ-ઃ઼ા-ૅે-ૉો-્ૢૣଁ-ଃ଼ା-ୄେୈୋ-୍ୖୗୢୣஂா-ூெ-ைொ-்ௗఀ-ఃా-ౄె-ైొ-్ౕౖౢౣಁ-ಃ಼ಾ-ೄೆ-ೈೊ-್ೕೖೢೣഁ-ഃാ-ൄെ-ൈൊ-്ൗൢൣංඃ්ා-ුූෘ-ෟෲෳัิ-ฺ็-๎ັິ-ູົຼ່-ໍ༹༘༙༵༷༾༿ཱ-྄྆྇ྍ-ྗྙ-ྼ࿆ါ-ှၖ-ၙၞ-ၠၢ-ၤၧ-ၭၱ-ၴႂ-ႍႏႚ-ႝ፝-፟ᜒ-᜔ᜲ-᜴ᝒᝓᝲᝳ឴-៓៝᠋-᠍ᢅᢆᢩᤠ-ᤫᤰ-᤻ᨗ-ᨛᩕ-ᩞ᩠-᩿᩼᪰-᪽ᬀ-ᬄ᬴-᭄᭫-᭳ᮀ-ᮂᮡ-ᮭ᯦-᯳ᰤ-᰷᳐-᳔᳒-᳨᳭ᳲ-᳴᳸᳹᷀-᷵᷻-᷿‿⁀⁔⃐-⃥⃜⃡-⃰℘℮⳯-⵿⳱ⷠ-〪ⷿ-゙゚〯꙯ꙴ-꙽ꚞꚟ꛰꛱ꠂ꠆ꠋꠣ-ꠧꢀꢁꢴ-ꣅ꣠-꣱ꤦ-꤭ꥇ-꥓ꦀ-ꦃ꦳-꧀ꧥꨩ-ꨶꩃꩌꩍꩻ-ꩽꪰꪲ-ꪴꪷꪸꪾ꪿꫁ꫫ-ꫯꫵ꫶ꯣ-ꯪ꯬꯭ﬞ︀-️︠-︯︳︴﹍-﹏_𐇽𐋠𐍶-𐍺𐨁-𐨃𐨅𐨆𐨌-𐨏𐨸-𐨿𐨺𐫦𐫥𑀀-𑀂𑀸-𑁆𑁿-𑂂𑂰-𑂺𑄀-𑄂𑄧-𑅳𑄴𑆀-𑆂𑆳-𑇊𑇀-𑇌𑈬-𑈷𑈾𑋟-𑋪𑌀-𑌃𑌼𑌾-𑍄𑍇𑍈𑍋-𑍍𑍗𑍢𑍣𑍦-𑍬𑍰-𑍴𑐵-𑑆𑒰-𑓃𑖯-𑖵𑖸-𑗀𑗜𑗝𑘰-𑙀𑚫-𑚷𑜝-𑜫𑰯-𑰶𑰸-𑰿𑲒-𑲧𑲩-𑲶𖫰-𖫴𖬰-𖬶𖽑-𖽾𖾏-𖾒𛲝𛲞𝅥-𝅩𝅭-𝅲𝅻-𝆂𝆅-𝆋𝆪-𝆭𝉂-𝉄𝨀-𝨶𝨻-𝩬𝩵𝪄𝪛-𝪟𝪡-𝪯𞀀-𞀆𞀈-𞀘𞀛-𞀡𞀣𞀤𞀦-𞣐𞀪-𞣖𞥄-𞥊󠄀-󠇯" # noqa: B950

View File

@ -27,14 +27,19 @@ async def async_select_or_reject(args, kwargs, modfunc, lookup_attr):
def dualfilter(normal_filter, async_filter):
wrap_evalctx = False
if getattr(normal_filter, "environmentfilter", False):
is_async = lambda args: args[0].is_async
def is_async(args):
return args[0].is_async
wrap_evalctx = False
else:
if not getattr(normal_filter, "evalcontextfilter", False) and not getattr(
normal_filter, "contextfilter", False
):
wrap_evalctx = True
is_async = lambda args: args[0].environment.is_async
def is_async(args):
return args[0].environment.is_async
@wraps(normal_filter)
def wrapper(*args, **kwargs):
@ -123,7 +128,10 @@ async def do_sum(environment, iterable, attribute=None, start=0):
if attribute is not None:
func = filters.make_attrgetter(environment, attribute)
else:
func = lambda x: x
def func(x):
return x
async for item in auto_aiter(iterable):
rv += func(item)
return rv

View File

@ -16,7 +16,6 @@
"""
import errno
import fnmatch
import marshal
import os
import stat
import sys
@ -26,29 +25,12 @@ from os import listdir
from os import path
from ._compat import BytesIO
from ._compat import marshal_dump
from ._compat import marshal_load
from ._compat import pickle
from ._compat import PY2
from ._compat import text_type
from .utils import open_if_exists
# marshal works better on 3.x, one hack less required
if not PY2:
marshal_dump = marshal.dump
marshal_load = marshal.load
else:
def marshal_dump(code, f):
if isinstance(f, file):
marshal.dump(code, f)
else:
f.write(marshal.dumps(code))
def marshal_load(f):
if isinstance(f, file):
return marshal.load(f)
return marshal.loads(f.read())
bc_version = 3
# magic version used to only change with new jinja versions. With 2.6

View File

@ -549,10 +549,10 @@ class CodeGenerator(NodeVisitor):
else:
args.append(frame.symbols.declare_parameter("caller"))
macro_ref.accesses_caller = True
if "kwargs" in undeclared and not "kwargs" in skip_special_params:
if "kwargs" in undeclared and "kwargs" not in skip_special_params:
args.append(frame.symbols.declare_parameter("kwargs"))
macro_ref.accesses_kwargs = True
if "varargs" in undeclared and not "varargs" in skip_special_params:
if "varargs" in undeclared and "varargs" not in skip_special_params:
args.append(frame.symbols.declare_parameter("varargs"))
macro_ref.accesses_varargs = True
@ -1242,7 +1242,6 @@ class CodeGenerator(NodeVisitor):
if frame.toplevel:
if not node.name.startswith("_"):
self.write("context.exported_vars.add(%r)" % node.name)
ref = frame.symbols.ref(node.name)
self.writeline("context.vars[%r] = " % node.name)
self.write("%s = " % frame.symbols.ref(node.name))
self.macro_def(macro_ref, macro_frame)
@ -1270,7 +1269,7 @@ class CodeGenerator(NodeVisitor):
with_frame = frame.inner()
with_frame.symbols.analyze_node(node)
self.enter_frame(with_frame)
for idx, (target, expr) in enumerate(izip(node.targets, node.values)):
for target, expr in izip(node.targets, node.values):
self.newline()
self.visit(target, with_frame)
self.write(" = ")
@ -1317,7 +1316,7 @@ class CodeGenerator(NodeVisitor):
if getattr(env_finalize, "contextfunction", False):
src += "context, "
finalize = None
finalize = None # noqa: F811
elif getattr(env_finalize, "evalcontextfunction", False):
src += "context.eval_ctx, "
finalize = None
@ -1570,7 +1569,7 @@ class CodeGenerator(NodeVisitor):
self.visit(item.value, frame)
self.write("}")
def binop(operator, interceptable=True):
def binop(operator, interceptable=True): # noqa: B902
@optimizeconst
def visitor(self, node, frame):
if (
@ -1590,7 +1589,7 @@ class CodeGenerator(NodeVisitor):
return visitor
def uaop(operator, interceptable=True):
def uaop(operator, interceptable=True): # noqa: B902
@optimizeconst
def visitor(self, node, frame):
if (

View File

@ -160,7 +160,7 @@ def fake_traceback(exc_value, tb, filename, lineno):
# the new traceback without this frame.
try:
exec(code, globals, locals)
except:
except BaseException:
return sys.exc_info()[2].tb_next

View File

@ -9,6 +9,8 @@
:license: BSD, see LICENSE for more details.
"""
from ._compat import range_type
from .filters import FILTERS as DEFAULT_FILTERS # noqa: F401
from .tests import TESTS as DEFAULT_TESTS # noqa: F401
from .utils import Cycler
from .utils import generate_lorem_ipsum
from .utils import Joiner
@ -29,8 +31,6 @@ NEWLINE_SEQUENCE = "\n"
KEEP_TRAILING_NEWLINE = False
# default filters, tests and namespace
from jinja2.filters import FILTERS as DEFAULT_FILTERS
from jinja2.tests import TESTS as DEFAULT_TESTS
DEFAULT_NAMESPACE = {
"range": range_type,

View File

@ -16,8 +16,6 @@ from functools import reduce
from . import nodes
from ._compat import encode_filename
from ._compat import ifilter
from ._compat import imap
from ._compat import implements_iterator
from ._compat import implements_to_string
from ._compat import iteritems
@ -368,7 +366,8 @@ class Environment(object):
self.enable_async = enable_async
self.is_async = self.enable_async and have_async_gen
if self.is_async:
import jinja2.asyncsupport # runs patch_all() once
# runs patch_all() to enable async support
import jinja2.asyncsupport # noqa: F401
_environment_sanity_check(self)
@ -722,7 +721,9 @@ class Environment(object):
from jinja2.loaders import ModuleLoader
if log_function is None:
log_function = lambda x: None
def log_function(x):
pass
if py_compile:
if not PY2 or PYPY:
@ -806,16 +807,21 @@ class Environment(object):
.. versionadded:: 2.4
"""
x = self.loader.list_templates()
names = self.loader.list_templates()
if extensions is not None:
if filter_func is not None:
raise TypeError(
"either extensions or filter_func can be passed, but not both"
)
filter_func = lambda x: "." in x and x.rsplit(".", 1)[1] in extensions
def filter_func(x):
return "." in x and x.rsplit(".", 1)[1] in extensions
if filter_func is not None:
x = list(ifilter(filter_func, x))
return x
names = [name for name in names if filter_func(name)]
return names
def handle_exception(self, source=None):
"""Exception handling helper. This is used internally to either raise
@ -1202,7 +1208,7 @@ class Template(object):
def debug_info(self):
"""The debug info mapping."""
if self._debug_info:
return [tuple(imap(int, x.split("="))) for x in self._debug_info.split("&")]
return [tuple(map(int, x.split("="))) for x in self._debug_info.split("&")]
return []
def __repr__(self):

View File

@ -48,12 +48,14 @@ from .utils import Markup
# non unicode strings.
GETTEXT_FUNCTIONS = ("_", "gettext", "ngettext")
_ws_re = re.compile(r"\s*\n\s*")
class ExtensionRegistry(type):
"""Gives the extension an unique identifier."""
def __new__(cls, name, bases, d):
rv = type.__new__(cls, name, bases, d)
def __new__(mcs, name, bases, d):
rv = type.__new__(mcs, name, bases, d)
rv.identifier = rv.__module__ + "." + rv.__name__
return rv
@ -356,7 +358,7 @@ class InternationalizationExtension(Extension):
else:
return node
def _trim_whitespace(self, string, _ws_re=re.compile(r"\s*\n\s*")):
def _trim_whitespace(self, string, _ws_re=_ws_re):
return _ws_re.sub(" ", string.strip())
def _parse_block(self, parser, allow_pluralize):
@ -389,7 +391,7 @@ class InternationalizationExtension(Extension):
elif parser.stream.eos:
parser.fail("unclosed translation block")
else:
assert False, "internal parser error"
raise RuntimeError("internal parser error")
return referenced, concat(buf)
@ -574,7 +576,7 @@ def extract_from_ast(node, gettext_functions=GETTEXT_FUNCTIONS, babel_style=True
else:
strings.append(None)
for arg in node.kwargs:
for _ in node.kwargs:
strings.append(None)
if node.dyn_args is not None:
strings.append(None)
@ -699,7 +701,7 @@ def babel_extract(fileobj, keywords, comment_tags, options):
try:
node = environment.parse(source)
tokens = list(environment.lex(environment.preprocess(source)))
except TemplateSyntaxError as e:
except TemplateSyntaxError:
if not silent:
raise
# skip templates with syntax errors

View File

@ -328,7 +328,8 @@ def do_sort(environment, value, reverse=False, case_sensitive=False, attribute=N
.. sourcecode:: jinja
{% for user in users|sort(attribute="name")|sort(reverse=true, attribute="age") %}
{% for user in users|sort(attribute="name")
|sort(reverse=true, attribute="age") %}
...
{% endfor %}
@ -523,7 +524,8 @@ def do_last(environment, seq):
"""
Return the last item of a sequence.
Note: Does not work with generators. You may want to explicitly convert it to a list:
Note: Does not work with generators. You may want to explicitly
convert it to a list:
.. sourcecode:: jinja
@ -931,7 +933,7 @@ def do_round(value, precision=0, method="common"):
{{ 42.55|round|int }}
-> 43
"""
if not method in ("common", "ceil", "floor"):
if method not in {"common", "ceil", "floor"}:
raise FilterArgumentError("method must be common, ceil or floor")
if method == "common":
return round(value, precision)
@ -1282,9 +1284,11 @@ def prepare_map(args, kwargs):
args = args[3:]
except LookupError:
raise FilterArgumentError("map requires a filter argument")
func = lambda item: context.environment.call_filter(
name, item, args, kwargs, context=context
)
def func(item):
return context.environment.call_filter(
name, item, args, kwargs, context=context
)
return seq, func
@ -1301,12 +1305,17 @@ def prepare_select_or_reject(args, kwargs, modfunc, lookup_attr):
off = 1
else:
off = 0
transfunc = lambda x: x
def transfunc(x):
return x
try:
name = args[2 + off]
args = args[3 + off :]
func = lambda item: context.environment.call_test(name, item, args, kwargs)
def func(item):
return context.environment.call_test(name, item, args, kwargs)
except LookupError:
func = bool

View File

@ -379,7 +379,7 @@ class TokenStream(object):
def skip(self, n=1):
"""Got n tokens ahead."""
for x in range(n):
for _ in range(n):
next(self)
def next_if(self, expr):
@ -485,9 +485,11 @@ class Lexer(object):
def __init__(self, environment):
# shortcuts
c = lambda x: re.compile(x, re.M | re.S)
e = re.escape
def c(x):
return re.compile(x, re.M | re.S)
# lexing rules for tags
tag_rules = [
(whitespace_re, TOKEN_WHITESPACE, None),

View File

@ -208,7 +208,7 @@ class FileSystemLoader(BaseLoader):
found = set()
for searchpath in self.searchpath:
walk_dir = os.walk(searchpath, followlinks=self.followlinks)
for dirpath, dirnames, filenames in walk_dir:
for dirpath, _, filenames in walk_dir:
for filename in filenames:
template = (
os.path.join(dirpath, filename)[len(searchpath) :]

View File

@ -54,7 +54,7 @@ class NodeType(type):
inheritance. fields and attributes from the parent class are
automatically forwarded to the child."""
def __new__(cls, name, bases, d):
def __new__(mcs, name, bases, d):
for attr in "fields", "attributes":
storage = []
storage.extend(getattr(bases[0], attr, ()))
@ -63,7 +63,7 @@ class NodeType(type):
assert len(storage) == len(set(storage)), "layout conflict"
d[attr] = tuple(storage)
d.setdefault("abstract", False)
return type.__new__(cls, name, bases, d)
return type.__new__(mcs, name, bases, d)
class EvalContext(object):
@ -165,7 +165,7 @@ class Node(with_metaclass(NodeType, object)):
over all fields and yields the values of they are nodes. If the value
of a field is a list all the nodes in that list are returned.
"""
for field, item in self.iter_fields(exclude, only):
for _, item in self.iter_fields(exclude, only):
if isinstance(item, list):
for n in item:
if isinstance(n, Node):

View File

@ -245,7 +245,6 @@ class Parser(object):
targets = []
values = []
while self.stream.current.type != "block_end":
lineno = self.stream.current.lineno
if targets:
self.stream.expect("comma")
target = self.parse_assign_target()
@ -639,7 +638,10 @@ class Parser(object):
elif with_condexpr:
parse = self.parse_expression
else:
parse = lambda: self.parse_expression(with_condexpr=False)
def parse():
return self.parse_expression(with_condexpr=False)
args = []
is_tuple = False
while 1:

View File

@ -12,6 +12,10 @@ import sys
from itertools import chain
from types import MethodType
from markupsafe import escape
from markupsafe import Markup
from markupsafe import soft_unicode
from ._compat import abc
from ._compat import imap
from ._compat import implements_iterator
@ -26,14 +30,11 @@ from .exceptions import TemplateRuntimeError
from .exceptions import UndefinedError
from .nodes import EvalContext
from .utils import concat
from .utils import escape
from .utils import evalcontextfunction
from .utils import internalcode
from .utils import Markup
from .utils import missing
from .utils import Namespace
from .utils import object_type_repr
from .utils import soft_unicode
# these variables are exported to the template runtime
__all__ = [
@ -58,11 +59,12 @@ __all__ = [
#: a string. We can just use the text type here.
to_string = text_type
#: the identity function. Useful for certain things in the environment
identity = lambda x: x
_first_iteration = object()
_last_iteration = object()
def identity(x):
"""Returns its argument. Useful for certain things in the
environment.
"""
return x
def markup_join(seq):
@ -127,8 +129,8 @@ def _get_func(x):
class ContextMeta(type):
def __new__(cls, name, bases, d):
rv = type.__new__(cls, name, bases, d)
def __new__(mcs, name, bases, d):
rv = type.__new__(mcs, name, bases, d)
if bases == ():
return rv
@ -264,7 +266,7 @@ class Context(with_metaclass(ContextMeta)):
return dict(self.parent, **self.vars)
@internalcode
def call(__self, __obj, *args, **kwargs):
def call(__self, __obj, *args, **kwargs): # noqa: B902
"""Call the callable with the arguments and keyword arguments
provided but inject the active context or environment as first
argument if the callable is a :func:`contextfunction` or
@ -274,7 +276,7 @@ class Context(with_metaclass(ContextMeta)):
__traceback_hide__ = True # noqa
# Allow callable classes to take a context
if hasattr(__obj, "__call__"):
if hasattr(__obj, "__call__"): # noqa: B004
fn = __obj.__call__
for fn_type in (
"contextfunction",
@ -313,8 +315,10 @@ class Context(with_metaclass(ContextMeta)):
context.blocks.update((k, list(v)) for k, v in iteritems(self.blocks))
return context
def _all(meth):
proxy = lambda self: getattr(self.get_all(), meth)()
def _all(meth): # noqa: B902
def proxy(self):
return getattr(self.get_all(), meth)()
proxy.__doc__ = getattr(dict, meth).__doc__
proxy.__name__ = meth
return proxy
@ -635,7 +639,7 @@ class Macro(object):
# arguments expected we start filling in keyword arguments
# and defaults.
if off != self._argument_count:
for idx, name in enumerate(self.arguments[len(arguments) :]):
for name in self.arguments[len(arguments) :]:
try:
value = kwargs.pop(name)
except KeyError:

View File

@ -14,6 +14,8 @@
"""
import operator
import types
import warnings
from collections import deque
from string import Formatter
from markupsafe import EscapeFormatter
@ -31,36 +33,35 @@ MAX_RANGE = 100000
#: attributes of function objects that are considered unsafe.
if PY2:
UNSAFE_FUNCTION_ATTRIBUTES = set(
["func_closure", "func_code", "func_dict", "func_defaults", "func_globals"]
)
UNSAFE_FUNCTION_ATTRIBUTES = {
"func_closure",
"func_code",
"func_dict",
"func_defaults",
"func_globals",
}
else:
# On versions > python 2 the special attributes on functions are gone,
# but they remain on methods and generators for whatever reason.
UNSAFE_FUNCTION_ATTRIBUTES = set()
#: unsafe method attributes. function attributes are unsafe for methods too
UNSAFE_METHOD_ATTRIBUTES = set(["im_class", "im_func", "im_self"])
UNSAFE_METHOD_ATTRIBUTES = {"im_class", "im_func", "im_self"}
#: unsafe generator attributes.
UNSAFE_GENERATOR_ATTRIBUTES = set(["gi_frame", "gi_code"])
UNSAFE_GENERATOR_ATTRIBUTES = {"gi_frame", "gi_code"}
#: unsafe attributes on coroutines
UNSAFE_COROUTINE_ATTRIBUTES = set(["cr_frame", "cr_code"])
UNSAFE_COROUTINE_ATTRIBUTES = {"cr_frame", "cr_code"}
#: unsafe attributes on async generators
UNSAFE_ASYNC_GENERATOR_ATTRIBUTES = set(["ag_code", "ag_frame"])
import warnings
UNSAFE_ASYNC_GENERATOR_ATTRIBUTES = {"ag_code", "ag_frame"}
# make sure we don't warn in python 2.6 about stuff we don't care about
warnings.filterwarnings(
"ignore", "the sets module", DeprecationWarning, module="jinja2.sandbox"
)
from collections import deque
_mutable_set_types = (set,)
_mutable_mapping_types = (dict,)
_mutable_sequence_types = (list,)
@ -89,7 +90,6 @@ _mutable_set_types += (abc.MutableSet,)
_mutable_mapping_types += (abc.MutableMapping,)
_mutable_sequence_types += (abc.MutableSequence,)
_mutable_spec = (
(
_mutable_set_types,
@ -460,7 +460,7 @@ class SandboxedEnvironment(Environment):
rv = formatter.vformat(s, args, kwargs)
return type(s)(rv)
def call(__self, __context, __obj, *args, **kwargs):
def call(__self, __context, __obj, *args, **kwargs): # noqa: B902
"""Call an object from sandboxed code."""
fmt = inspect_format_method(__obj)
if fmt is not None:

View File

@ -142,7 +142,7 @@ def test_sequence(value):
try:
len(value)
value.__getitem__
except:
except Exception:
return False
return True

View File

@ -15,6 +15,9 @@ import warnings
from collections import deque
from threading import Lock
from markupsafe import escape
from markupsafe import Markup
from ._compat import abc
from ._compat import string_types
from ._compat import text_type
@ -109,7 +112,7 @@ def is_undefined(obj):
def consume(iterable):
"""Consumes an iterable without doing anything with it."""
for event in iterable:
for _ in iterable:
pass
@ -246,7 +249,7 @@ def urlize(text, trim_url_limit=None, rel=None, target=None):
if (
"@" in middle
and not middle.startswith("www.")
and not ":" in middle
and ":" not in middle
and _simple_email_re.match(middle)
):
middle = '<a href="mailto:%s">%s</a>' % (middle, middle)
@ -472,6 +475,12 @@ class LRUCache(object):
def iteritems(self):
"""Iterate over all items."""
warnings.warn(
"'iteritems()' will be removed in version 3.0. Use"
" 'iter(cache.items())' instead.",
DeprecationWarning,
stacklevel=2,
)
return iter(self.items())
def values(self):
@ -481,16 +490,21 @@ class LRUCache(object):
def itervalue(self):
"""Iterate over all values."""
warnings.warn(
DeprecationWarning(
'"itervalue()" is deprecated and will be removed in version 2.12.'
+ ' Use "itervalues()" instead.'
),
"'itervalue()' will be removed in version 3.0. Use"
" 'iter(cache.values())' instead.",
DeprecationWarning,
stacklevel=2,
)
return self.itervalues()
return iter(self.values())
def itervalues(self):
"""Iterate over all values."""
warnings.warn(
"'itervalues()' will be removed in version 3.0. Use"
" 'iter(cache.values())' instead.",
DeprecationWarning,
stacklevel=2,
)
return iter(self.values())
def keys(self):
@ -501,9 +515,16 @@ class LRUCache(object):
"""Iterate over all keys in the cache dict, ordered by
the most recent usage.
"""
return reversed(tuple(self._queue))
warnings.warn(
"'iterkeys()' will be removed in version 3.0. Use"
" 'iter(cache.keys())' instead.",
DeprecationWarning,
stacklevel=2,
)
return iter(self)
__iter__ = iterkeys
def __iter__(self):
return reversed(tuple(self._queue))
def __reversed__(self):
"""Iterate over the keys in the cache dict, oldest items
@ -675,7 +696,7 @@ class Namespace(object):
"""A namespace object that can hold arbitrary attributes. It may be
initialized from a dictionary or with keyword arguments."""
def __init__(*args, **kwargs):
def __init__(*args, **kwargs): # noqa: B902
self, args = args[0], args[1:]
self.__attrs = dict(*args, **kwargs)
@ -702,5 +723,13 @@ except SyntaxError:
have_async_gen = False
# Imported here because that's where it was in the past
from markupsafe import Markup, escape, soft_unicode
def soft_unicode(s):
from markupsafe import soft_unicode
warnings.warn(
"'jinja2.utils.soft_unicode' will be removed in version 3.0."
" Use 'markupsafe.soft_unicode' instead.",
DeprecationWarning,
stacklevel=2,
)
return soft_unicode(s)

View File

@ -105,17 +105,6 @@ class TestExtendedAPI(object):
c.reset()
assert c.current == 1
def test_cycler_nextmethod(self, env):
items = 1, 2, 3
c = Cycler(*items)
for item in items + items:
assert c.current == item
assert c.next() == item
c.next()
assert c.current == 2
c.reset()
assert c.current == 1
def test_expressions(self, env):
expr = env.compile_expression("foo")
assert expr() is None
@ -338,7 +327,7 @@ class TestUndefined(object):
assert und1 != 42
assert hash(und1) == hash(und2) == hash(Undefined())
with pytest.raises(AttributeError):
getattr(Undefined, "__slots__")
getattr(Undefined, "__slots__") # noqa: B009
def test_chainable_undefined(self):
env = Environment(undefined=ChainableUndefined)
@ -350,7 +339,7 @@ class TestUndefined(object):
assert env.from_string("{{ not missing }}").render() == "True"
pytest.raises(UndefinedError, env.from_string("{{ missing - 1}}").render)
with pytest.raises(AttributeError):
getattr(ChainableUndefined, "__slots__")
getattr(ChainableUndefined, "__slots__") # noqa: B009
# The following tests ensure subclass functionality works as expected
assert env.from_string('{{ missing.bar["baz"] }}').render() == u""
@ -385,7 +374,7 @@ class TestUndefined(object):
== u"{{ undefined value printed: %s }}" % undefined_hint
)
with pytest.raises(AttributeError):
getattr(DebugUndefined, "__slots__")
getattr(DebugUndefined, "__slots__") # noqa: B009
def test_strict_undefined(self):
env = Environment(undefined=StrictUndefined)
@ -402,7 +391,7 @@ class TestUndefined(object):
== "default"
)
with pytest.raises(AttributeError):
getattr(StrictUndefined, "__slots__")
getattr(StrictUndefined, "__slots__") # noqa: B009
assert env.from_string('{{ "foo" if false }}').render() == ""
def test_indexing_gives_undefined(self):

View File

@ -396,9 +396,8 @@ class TestAsyncForLoop(object):
def test_recursive_depth0(self, test_env_async):
tmpl = test_env_async.from_string(
"""{% for item in seq recursive -%}
[{{ loop.depth0 }}:{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}]
{%- endfor %}"""
"{% for item in seq recursive %}[{{ loop.depth0 }}:{{ item.a }}"
"{% if item.b %}<{{ loop(item.b) }}>{% endif %}]{% endfor %}"
)
assert (
tmpl.render(
@ -413,9 +412,8 @@ class TestAsyncForLoop(object):
def test_recursive_depth(self, test_env_async):
tmpl = test_env_async.from_string(
"""{% for item in seq recursive -%}
[{{ loop.depth }}:{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}]
{%- endfor %}"""
"{% for item in seq recursive %}[{{ loop.depth }}:{{ item.a }}"
"{% if item.b %}<{{ loop(item.b) }}>{% endif %}]{% endfor %}"
)
assert (
tmpl.render(
@ -544,9 +542,7 @@ class TestAsyncForLoop(object):
)
sm = t.render(
this="/foo",
site={
"root": {"url": "/", "children": [{"url": "/foo"}, {"url": "/bar"},]}
},
site={"root": {"url": "/", "children": [{"url": "/foo"}, {"url": "/bar"}]}},
)
lines = [x.strip() for x in sm.splitlines() if x.strip()]
assert lines == [
@ -569,7 +565,7 @@ class TestAsyncForLoop(object):
"""
)
sm = t.render(
this="/foo", items=[{"url": "/"}, {"url": "/foo"}, {"url": "/bar"},]
this="/foo", items=[{"url": "/"}, {"url": "/foo"}, {"url": "/bar"}]
)
lines = [x.strip() for x in sm.splitlines() if x.strip()]
assert lines == [

View File

@ -1,3 +1,5 @@
from collections import namedtuple
import pytest
from jinja2 import Environment
@ -12,7 +14,7 @@ async def make_aiter(iter):
def mark_dualiter(parameter, factory):
def decorator(f):
return pytest.mark.parametrize(
parameter, [lambda: factory(), lambda: make_aiter(factory()),]
parameter, [lambda: factory(), lambda: make_aiter(factory())]
)(f)
return decorator
@ -66,22 +68,13 @@ def test_groupby_tuple_index(env_async, items):
def make_articles():
class Date(object):
def __init__(self, day, month, year):
self.day = day
self.month = month
self.year = year
class Article(object):
def __init__(self, title, *date):
self.date = Date(*date)
self.title = title
Date = namedtuple("Date", "day,month,year")
Article = namedtuple("Article", "title,date")
return [
Article("aha", 1, 1, 1970),
Article("interesting", 2, 1, 1970),
Article("really?", 3, 1, 1970),
Article("totally not", 1, 1, 1971),
Article("aha", Date(1, 1, 1970)),
Article("interesting", Date(2, 1, 1970)),
Article("really?", Date(3, 1, 1970)),
Article("totally not", Date(1, 1, 1971)),
]
@ -115,10 +108,7 @@ def test_join_string_list(string_items):
def make_users():
class User(object):
def __init__(self, username):
self.username = username
User = namedtuple("User", "username")
return map(User, ["foo", "bar"])
@ -153,11 +143,7 @@ def test_bool_select(env_async, items):
def make_users():
class User(object):
def __init__(self, name, is_active):
self.name = name
self.is_active = is_active
User = namedtuple("User", "name,is_active")
return [
User("john", True),
User("jane", True),
@ -201,7 +187,7 @@ def test_sum(env_async, items):
assert tmpl.render(items=items) == "21"
@mark_dualiter("items", lambda: [{"value": 23}, {"value": 1}, {"value": 18},])
@mark_dualiter("items", lambda: [{"value": 23}, {"value": 1}, {"value": 18}])
def test_sum_attributes(env_async, items):
tmpl = env_async.from_string("""{{ items()|sum('value') }}""")
assert tmpl.render(items=items)
@ -223,13 +209,13 @@ def test_sum_attributes_nested(env_async):
def test_sum_attributes_tuple(env_async):
tmpl = env_async.from_string("""{{ values.items()|sum('1') }}""")
assert tmpl.render(values={"foo": 23, "bar": 1, "baz": 18,}) == "42"
assert tmpl.render(values={"foo": 23, "bar": 1, "baz": 18}) == "42"
@mark_dualiter("items", lambda: range(10))
def test_slice(env_async, items):
tmpl = env_async.from_string(
"{{ items()|slice(3)|list }}|" '{{ items()|slice(3, "X")|list }}'
"{{ items()|slice(3)|list }}|{{ items()|slice(3, 'X')|list }}"
)
out = tmpl.render(items=items)
assert out == (

View File

@ -163,7 +163,7 @@ class TestForLoop(object):
def test_recursive_depth0(self, env):
tmpl = env.from_string(
"""{% for item in seq recursive -%}
[{{ loop.depth0 }}:{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}]
[{{ loop.depth0 }}:{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}]
{%- endfor %}"""
)
assert (
@ -180,7 +180,7 @@ class TestForLoop(object):
def test_recursive_depth(self, env):
tmpl = env.from_string(
"""{% for item in seq recursive -%}
[{{ loop.depth }}:{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}]
[{{ loop.depth }}:{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}]
{%- endfor %}"""
)
assert (
@ -513,15 +513,13 @@ class TestSet(object):
assert "non-namespace object" in exc_info.value.message
def test_namespace_redefined(self, env_trim):
tmpl = env_trim.from_string(
"{% set ns = namespace() %}" '{% set ns.bar = "hi" %}'
)
tmpl = env_trim.from_string("{% set ns = namespace() %}{% set ns.bar = 'hi' %}")
exc_info = pytest.raises(TemplateRuntimeError, tmpl.render, namespace=dict)
assert "non-namespace object" in exc_info.value.message
def test_namespace(self, env_trim):
tmpl = env_trim.from_string(
"{% set ns = namespace() %}" '{% set ns.bar = "42" %}' "{{ ns.bar }}"
"{% set ns = namespace() %}{% set ns.bar = '42' %}{{ ns.bar }}"
)
assert tmpl.render() == "42"

View File

@ -10,7 +10,6 @@
"""
import pickle
import re
import sys
from traceback import format_exception
import pytest
@ -30,17 +29,15 @@ def fs_env(filesystem_loader):
@pytest.mark.debug
class TestDebug(object):
def assert_traceback_matches(self, callback, expected_tb):
try:
with pytest.raises(Exception) as exc_info:
callback()
except Exception:
tb = format_exception(*sys.exc_info())
if re.search(expected_tb.strip(), "".join(tb)) is None:
assert False, "Traceback did not match:\n\n%s\nexpected:\n%s" % (
"".join(tb),
expected_tb,
)
else:
assert False, "Expected exception"
tb = format_exception(exc_info.type, exc_info.value, exc_info.tb)
m = re.search(expected_tb.strip(), "".join(tb))
assert m is not None, "Traceback did not match:\n\n%s\nexpected:\n%s" % (
"".join(tb),
expected_tb,
)
def test_runtime_error(self, fs_env):
def test():
@ -64,10 +61,12 @@ ZeroDivisionError: (int(eger)? )?division (or modulo )?by zero
# error in the middle of other compiler frames.
self.assert_traceback_matches(
lambda: fs_env.get_template("syntaxerror.html"),
r"""(?sm)
"""(?sm)
File ".*?syntaxerror.html", line 4, in (template|<module>)
\{% endif %\}.*?
(jinja2\.exceptions\.)?TemplateSyntaxError: Encountered unknown tag 'endif'. Jinja was looking for the following tags: 'endfor' or 'else'. The innermost block that needs to be closed is 'for'.
\\{% endif %\\}.*?
(jinja2\\.exceptions\\.)?TemplateSyntaxError: Encountered unknown tag 'endif'. Jinja \
was looking for the following tags: 'endfor' or 'else'. The innermost block that needs \
to be closed is 'for'.
""",
)

View File

@ -343,7 +343,7 @@ class TestInternationalization(object):
# unlikely variable name, but when used as a variable
# it should not enable trimming
tmpl = i18n_env.from_string(
'{%- trans trimmed = "world" %} hello\n {{ trimmed }} ' "{% endtrans -%}"
"{%- trans trimmed = 'world' %} hello\n {{ trimmed }} {% endtrans -%}"
)
assert tmpl.render() == " hello\n world "

View File

@ -5,6 +5,7 @@ import pytest
from jinja2 import contextfilter
from jinja2 import Environment
from jinja2 import Template
from jinja2._compat import text_type
@pytest.mark.skipif(sys.version_info < (3, 5), reason="Requires 3.5 or later")
@ -29,7 +30,7 @@ def test_ascii_str():
env.policies["compiler.ascii_str"] = False
t = env.from_string('{{ "foo"|assert }}')
t.render(expected_type=unicode)
t.render(expected_type=text_type)
env.policies["compiler.ascii_str"] = True
t = env.from_string('{{ "foo"|assert }}')
@ -38,4 +39,4 @@ def test_ascii_str():
for val in True, False:
env.policies["compiler.ascii_str"] = val
t = env.from_string(u'{{ "\N{SNOWMAN}"|assert }}')
t.render(expected_type=unicode)
t.render(expected_type=text_type)

View File

@ -9,6 +9,7 @@
:license: BSD, see LICENSE for more details.
"""
import random
from collections import namedtuple
import pytest
@ -81,9 +82,7 @@ class TestFilter(object):
)
def test_slice(self, env):
tmpl = env.from_string(
"{{ foo|slice(3)|list }}|" '{{ foo|slice(3, "X")|list }}'
)
tmpl = env.from_string("{{ foo|slice(3)|list }}|{{ foo|slice(3, 'X')|list }}")
out = tmpl.render(foo=list(range(10)))
assert out == (
"[[0, 1, 2, 3], [4, 5, 6], [7, 8, 9]]|"
@ -244,10 +243,7 @@ class TestFilter(object):
assert tmpl.render() == "&lt;foo&gt;<span>foo</span>"
def test_join_attribute(self, env):
class User(object):
def __init__(self, username):
self.username = username
User = namedtuple("User", "username")
tmpl = env.from_string("""{{ users|join(', ', 'username') }}""")
assert tmpl.render(users=map(User, ["foo", "bar"])) == "foo, bar"
@ -291,7 +287,7 @@ class TestFilter(object):
def test_reverse(self, env):
tmpl = env.from_string(
'{{ "foobar"|reverse|join }}|' "{{ [1, 2, 3]|reverse|list }}"
"{{ 'foobar'|reverse|join }}|{{ [1, 2, 3]|reverse|list }}"
)
assert tmpl.render() == "raboof|[3, 2, 1]"
@ -370,7 +366,7 @@ class TestFilter(object):
env.policies["urlize.rel"] = None
tmpl = env.from_string('{{ "foo http://www.example.com/ bar"|urlize }}')
assert tmpl.render() == (
'foo <a href="http://www.example.com/">' "http://www.example.com/</a> bar"
'foo <a href="http://www.example.com/">http://www.example.com/</a> bar'
)
def test_urlize_target_parameter(self, env):
@ -401,7 +397,7 @@ class TestFilter(object):
def test_sum_attributes(self, env):
tmpl = env.from_string("""{{ values|sum('value') }}""")
assert tmpl.render(values=[{"value": 23}, {"value": 1}, {"value": 18},]) == "42"
assert tmpl.render(values=[{"value": 23}, {"value": 1}, {"value": 18}]) == "42"
def test_sum_attributes_nested(self, env):
tmpl = env.from_string("""{{ values|sum('real.value') }}""")
@ -418,7 +414,7 @@ class TestFilter(object):
def test_sum_attributes_tuple(self, env):
tmpl = env.from_string("""{{ values.items()|sum('1') }}""")
assert tmpl.render(values={"foo": 23, "bar": 1, "baz": 18,}) == "42"
assert tmpl.render(values={"foo": 23, "bar": 1, "baz": 18}) == "42"
def test_abs(self, env):
tmpl = env.from_string("""{{ -1|abs }}|{{ 1|abs }}""")
@ -561,22 +557,13 @@ class TestFilter(object):
assert tmpl.render() == "a:1:2|b:1|"
def test_groupby_multidot(self, env):
class Date(object):
def __init__(self, day, month, year):
self.day = day
self.month = month
self.year = year
class Article(object):
def __init__(self, title, *date):
self.date = Date(*date)
self.title = title
Date = namedtuple("Date", "day,month,year")
Article = namedtuple("Article", "title,date")
articles = [
Article("aha", 1, 1, 1970),
Article("interesting", 2, 1, 1970),
Article("really?", 3, 1, 1970),
Article("totally not", 1, 1, 1971),
Article("aha", Date(1, 1, 1970)),
Article("interesting", Date(2, 1, 1970)),
Article("really?", Date(3, 1, 1970)),
Article("totally not", Date(1, 1, 1971)),
]
tmpl = env.from_string(
"""
@ -647,10 +634,7 @@ class TestFilter(object):
assert tmpl.render() == "[3, 3, 15]"
def test_attribute_map(self, env):
class User(object):
def __init__(self, name):
self.name = name
User = namedtuple("User", "name")
env = Environment()
users = [
User("john"),
@ -666,15 +650,8 @@ class TestFilter(object):
assert tmpl.render() == "[]"
def test_map_default(self, env):
class Fullname(object):
def __init__(self, firstname, lastname):
self.firstname = firstname
self.lastname = lastname
class Firstname(object):
def __init__(self, firstname):
self.firstname = firstname
Fullname = namedtuple("Fullname", "firstname,lastname")
Firstname = namedtuple("Firstname", "firstname")
env = Environment()
tmpl = env.from_string(
'{{ users|map(attribute="lastname", default="smith")|join(", ") }}'
@ -708,11 +685,7 @@ class TestFilter(object):
assert tmpl.render() == "None|False|0"
def test_simple_select_attr(self, env):
class User(object):
def __init__(self, name, is_active):
self.name = name
self.is_active = is_active
User = namedtuple("User", "name,is_active")
env = Environment()
users = [
User("john", True),
@ -725,11 +698,7 @@ class TestFilter(object):
assert tmpl.render(users=users) == "john|jane"
def test_simple_reject_attr(self, env):
class User(object):
def __init__(self, name, is_active):
self.name = name
self.is_active = is_active
User = namedtuple("User", "name,is_active")
env = Environment()
users = [
User("john", True),
@ -742,11 +711,7 @@ class TestFilter(object):
assert tmpl.render(users=users) == "mike"
def test_func_select_attr(self, env):
class User(object):
def __init__(self, id, name):
self.id = id
self.name = name
User = namedtuple("User", "id,name")
env = Environment()
users = [
User(1, "john"),
@ -759,11 +724,7 @@ class TestFilter(object):
assert tmpl.render(users=users) == "john|mike"
def test_func_reject_attr(self, env):
class User(object):
def __init__(self, id, name):
self.id = id
self.name = name
User = namedtuple("User", "id,name")
env = Environment()
users = [
User(1, "john"),

View File

@ -180,9 +180,9 @@ class TestIncludes(object):
def test_import_from_with_context(self):
env = Environment(
loader=DictLoader({"a": "{% macro x() %}{{ foobar }}{% endmacro %}",})
loader=DictLoader({"a": "{% macro x() %}{{ foobar }}{% endmacro %}"})
)
t = env.from_string(
'{% set foobar = 42 %}{% from "a" ' "import x with context %}{{ x() }}"
"{% set foobar = 42 %}{% from 'a' import x with context %}{{ x() }}"
)
assert t.render() == "42"

View File

@ -12,7 +12,6 @@ import pytest
from jinja2 import DictLoader
from jinja2 import Environment
from jinja2 import TemplateError
from jinja2 import TemplateRuntimeError
LAYOUTTEMPLATE = """\
@ -135,7 +134,7 @@ class TestInheritance(object):
assert tmpl.render() == "--INTRO--|BEFORE|[(INNER)]|AFTER"
def test_working(self, env):
tmpl = env.get_template("working")
env.get_template("working")
def test_reuse_blocks(self, env):
tmpl = env.from_string(
@ -196,7 +195,7 @@ class TestInheritance(object):
)
)
t = env.from_string(
'{% extends "master.html" %}{% block item %}' "{{ item }}{% endblock %}"
"{% extends 'master.html' %}{% block item %}{{ item }}{% endblock %}"
)
assert t.render(seq=list(range(5))) == "[0][1][2][3][4]"

View File

@ -81,13 +81,15 @@ class TestLexer(object):
assert tmpl.render() == "123"
def test_raw3(self, env):
# The second newline after baz exists because it is AFTER the {% raw %} and is ignored.
# The second newline after baz exists because it is AFTER the
# {% raw %} and is ignored.
env = Environment(lstrip_blocks=True, trim_blocks=True)
tmpl = env.from_string("bar\n{% raw %}\n {{baz}}2 spaces\n{% endraw %}\nfoo")
assert tmpl.render(baz="test") == "bar\n\n {{baz}}2 spaces\nfoo"
def test_raw4(self, env):
# The trailing dash of the {% raw -%} cleans both the spaces and newlines up to the first character of data.
# The trailing dash of the {% raw -%} cleans both the spaces and
# newlines up to the first character of data.
env = Environment(lstrip_blocks=True, trim_blocks=False)
tmpl = env.from_string(
"bar\n{%- raw -%}\n\n \n 2 spaces\n space{%- endraw -%}\nfoo"
@ -531,7 +533,7 @@ class TestSyntax(object):
def test_notin(self, env):
bar = range(100)
tmpl = env.from_string("""{{ not 42 in bar }}""")
assert tmpl.render(bar=bar) == text_type(not 42 in bar)
assert tmpl.render(bar=bar) == "False"
def test_operator_precedence(self, env):
tmpl = env.from_string("""{{ 2 * 3 + 4 % 2 + 1 - 2 }}""")

View File

@ -99,7 +99,7 @@ class TestLoaders(object):
t2 = env.get_template("two")
assert t2 is env.get_template("two")
assert t1 is env.get_template("one")
t3 = env.get_template("three")
env.get_template("three")
loader_ref = weakref.ref(loader)
assert (loader_ref, "one") in env.cache
assert (loader_ref, "two") not in env.cache
@ -183,7 +183,10 @@ class TestFileSystemLoader(object):
@pytest.mark.parametrize(
("encoding", "expect"),
[("utf-8", u"文字化け"), ("iso-8859-1", u"æ\x96\x87å\xad\x97å\x8c\x96ã\x81\x91"),],
[
("utf-8", u"文字化け"),
("iso-8859-1", u"æ\x96\x87\xe5\xad\x97\xe5\x8c\x96\xe3\x81\x91"),
],
)
def test_uses_specified_encoding(self, encoding, expect):
loader = loaders.FileSystemLoader(self.searchpath, encoding=encoding)
@ -254,7 +257,7 @@ class TestModuleLoader(object):
def test_weak_references(self, prefix_loader):
self.compile_down(prefix_loader)
tmpl = self.mod_env.get_template("a/test.html")
self.mod_env.get_template("a/test.html")
key = loaders.ModuleLoader.get_template_key("a/test.html")
name = self.mod_env.loader.module.__name__
@ -262,13 +265,13 @@ class TestModuleLoader(object):
assert name in sys.modules
# unset all, ensure the module is gone from sys.modules
self.mod_env = tmpl = None
self.mod_env = None
try:
import gc
gc.collect()
except:
except BaseException:
pass
assert name not in sys.modules
@ -280,32 +283,28 @@ class TestModuleLoader(object):
def test_byte_compilation(self, prefix_loader):
log = self.compile_down(prefix_loader, py_compile=True)
assert 'Byte-compiled "a/test.html"' in log
tmpl1 = self.mod_env.get_template("a/test.html")
self.mod_env.get_template("a/test.html")
mod = self.mod_env.loader.module.tmpl_3c4ddf650c1a73df961a6d3d2ce2752f1b8fd490
assert mod.__file__.endswith(".pyc")
def test_choice_loader(self, prefix_loader):
log = self.compile_down(prefix_loader)
self.compile_down(prefix_loader)
self.mod_env.loader = loaders.ChoiceLoader(
[self.mod_env.loader, loaders.DictLoader({"DICT_SOURCE": "DICT_TEMPLATE"})]
)
tmpl1 = self.mod_env.get_template("a/test.html")
assert tmpl1.render() == "BAR"
tmpl2 = self.mod_env.get_template("DICT_SOURCE")
assert tmpl2.render() == "DICT_TEMPLATE"
def test_prefix_loader(self, prefix_loader):
log = self.compile_down(prefix_loader)
self.compile_down(prefix_loader)
self.mod_env.loader = loaders.PrefixLoader(
{
"MOD": self.mod_env.loader,
"DICT": loaders.DictLoader({"test.html": "DICT_TEMPLATE"}),
}
)
tmpl1 = self.mod_env.get_template("MOD/a/test.html")
assert tmpl1.render() == "BAR"
tmpl2 = self.mod_env.get_template("DICT/test.html")

View File

@ -254,35 +254,34 @@ class TestBug(object):
)
pytest.raises(TemplateSyntaxError, Template, "{% for x in %}..{% endfor %}")
def test_recursive_loop_bug(self, env):
tpl1 = Template(
def test_recursive_loop_compile(self, env):
Template(
"""
{% for p in foo recursive%}
{{p.bar}}
{% for f in p.fields recursive%}
{{f.baz}}
{% for p in foo recursive%}
{{p.bar}}
{% if f.rec %}
{{ loop(f.sub) }}
{% endif %}
{% for f in p.fields recursive%}
{{f.baz}}
{{p.bar}}
{% if f.rec %}
{{ loop(f.sub) }}
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
"""
"""
)
tpl2 = Template(
Template(
"""
{% for p in foo%}
{{p.bar}}
{% for f in p.fields recursive%}
{{f.baz}}
{% for p in foo%}
{{p.bar}}
{% if f.rec %}
{{ loop(f.sub) }}
{% endif %}
{% for f in p.fields recursive%}
{{f.baz}}
{{p.bar}}
{% if f.rec %}
{{ loop(f.sub) }}
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
"""
"""
)
def test_else_loop_bug(self, env):
@ -327,7 +326,7 @@ class TestBug(object):
def test_block_set_with_extends(self):
env = Environment(
loader=DictLoader({"main": "{% block body %}[{{ x }}]{% endblock %}",})
loader=DictLoader({"main": "{% block body %}[{{ x }}]{% endblock %}"})
)
t = env.from_string('{% extends "main" %}{% set x %}42{% endset %}')
assert t.render() == "[42]"
@ -538,9 +537,7 @@ class TestBug(object):
)
sm = t.render(
this="/foo",
site={
"root": {"url": "/", "children": [{"url": "/foo"}, {"url": "/bar"},]}
},
site={"root": {"url": "/", "children": [{"url": "/foo"}, {"url": "/bar"}]}},
)
lines = [x.strip() for x in sm.splitlines() if x.strip()]
assert lines == [
@ -581,8 +578,8 @@ class TestBug(object):
env = Environment(
loader=DictLoader(
{
"inc": "{{ item }}",
"main": '{% for item in [1, 2, 3] %}{% include "inc" %}{% endfor %}',
"inc": "{{ i }}",
"main": '{% for i in [1, 2, 3] %}{% include "inc" %}{% endfor %}',
}
)
)
@ -611,7 +608,7 @@ class TestBug(object):
assert env.get_template("test").render(foobar="test") == "test"
def test_legacy_custom_context(self, env):
from jinja2.runtime import Context, Undefined, missing
from jinja2.runtime import Context, missing
class MyContext(Context):
def resolve(self, name):
@ -627,9 +624,7 @@ class TestBug(object):
def test_recursive_loop_bug(self, env):
tmpl = env.from_string(
"""
{%- for value in values recursive %}1{% else %}0{% endfor -%}
"""
"{%- for value in values recursive %}1{% else %}0{% endfor -%}"
)
assert tmpl.render(values=[]) == "0"

View File

@ -3,18 +3,14 @@ import itertools
from jinja2 import Template
from jinja2.runtime import LoopContext
TEST_IDX_TEMPLATE_STR_1 = (
"[{% for i in lst|reverse %}"
+ "(len={{ loop.length }}, revindex={{ loop.revindex }}, index={{ loop.index }}, val={{ i }})"
+ "{% endfor %}]"
"[{% for i in lst|reverse %}(len={{ loop.length }},"
" revindex={{ loop.revindex }}, index={{ loop.index }}, val={{ i }}){% endfor %}]"
)
TEST_IDX0_TEMPLATE_STR_1 = (
"[{% for i in lst|reverse %}"
+ "(len={{ loop.length }}, revindex0={{ loop.revindex0 }}, index0={{ loop.index0 }}, val={{ i }})"
+ "{% endfor %}]"
"[{% for i in lst|reverse %}(len={{ loop.length }},"
" revindex0={{ loop.revindex0 }}, index0={{ loop.index0 }}, val={{ i }})"
"{% endfor %}]"
)
@ -34,20 +30,20 @@ def test_loop_idx0():
def test_loopcontext0():
in_lst = []
l = LoopContext(reversed(in_lst), None)
assert l.length == len(in_lst)
lc = LoopContext(reversed(in_lst), None)
assert lc.length == len(in_lst)
def test_loopcontext1():
in_lst = [10]
l = LoopContext(reversed(in_lst), None)
assert l.length == len(in_lst)
lc = LoopContext(reversed(in_lst), None)
assert lc.length == len(in_lst)
def test_loopcontext2():
in_lst = [10, 11]
l = LoopContext(reversed(in_lst), None)
assert l.length == len(in_lst)
lc = LoopContext(reversed(in_lst), None)
assert lc.length == len(in_lst)
def test_iterator_not_advanced_early():

View File

@ -36,8 +36,11 @@ class PrivateStuff(object):
class PublicStuff(object):
bar = lambda self: 23
_foo = lambda self: 42
def bar(self):
return 23
def _foo(self):
return 42
def __repr__(self):
return "PublicStuff"

View File

@ -195,9 +195,8 @@ class TestTestsCase(object):
env = Environment()
env.tests["matching"] = matching
tmpl = env.from_string(
"{{ 'us-west-1' is matching "
"'(us-east-1|ap-northeast-1)' "
"or 'stage' is matching '(dev|stage)' }}"
"{{ 'us-west-1' is matching '(us-east-1|ap-northeast-1)'"
" or 'stage' is matching '(dev|stage)' }}"
)
assert tmpl.render() == "False"
assert items == [

View File

@ -51,14 +51,14 @@ class TestLRUCache(object):
cache = LRUCache(3)
cache["b"] = 1
cache["a"] = 2
values = [v for v in cache.itervalues()]
values = [v for v in cache.values()]
assert len(values) == 2
assert 1 in values
assert 2 in values
def test_itervalues_empty(self):
cache = LRUCache(2)
values = [v for v in cache.itervalues()]
values = [v for v in cache.values()]
assert len(values) == 0
def test_pickleable(self):
@ -106,17 +106,17 @@ class TestLRUCache(object):
d["a"] = 1
d["b"] = 2
d["c"] = 3
assert d.items() == list(d.iteritems()) == [("c", 3), ("b", 2), ("a", 1)]
assert d.keys() == list(d.iterkeys()) == ["c", "b", "a"]
assert d.values() == list(d.itervalues()) == [3, 2, 1]
assert d.items() == [("c", 3), ("b", 2), ("a", 1)]
assert d.keys() == ["c", "b", "a"]
assert d.values() == [3, 2, 1]
assert list(reversed(d)) == ["a", "b", "c"]
# Change the cache a little
d["b"]
d["a"] = 4
assert d.items() == list(d.iteritems()) == [("a", 4), ("b", 2), ("c", 3)]
assert d.keys() == list(d.iterkeys()) == ["a", "b", "c"]
assert d.values() == list(d.itervalues()) == [4, 2, 3]
assert d.items() == [("a", 4), ("b", 2), ("c", 3)]
assert d.keys() == ["a", "b", "c"]
assert d.values() == [4, 2, 3]
assert list(reversed(d)) == ["c", "b", "a"]
def test_setdefault(self):
@ -152,11 +152,11 @@ class TestHelpers(object):
assert func(None) == "STRING"
assert func("unknown.foo") == "NONE"
assert func("foo.html") == True
assert func("foo.htm") == True
assert func("foo.txt") == False
assert func("FOO.HTML") == True
assert func("FOO.TXT") == False
assert func("foo.html")
assert func("foo.htm")
assert not func("foo.txt")
assert func("FOO.HTML")
assert not func("FOO.TXT")
@pytest.mark.utils