diff options
author | David Lord <davidism@gmail.com> | 2020-01-10 10:40:52 -0800 |
---|---|---|
committer | David Lord <davidism@gmail.com> | 2020-01-10 10:40:52 -0800 |
commit | bb6216ea305a06d0157f0c0d0fb8be7bb625c523 (patch) | |
tree | 221d419c2f8562a3758f468ccc7bd47b00447382 | |
parent | 04c8787155137206d58d6ee147d06482c1a8b598 (diff) | |
download | jinja2-bb6216ea305a06d0157f0c0d0fb8be7bb625c523.tar.gz |
apply flake8
43 files changed, 426 insertions, 433 deletions
diff --git a/examples/basic/inheritance.py b/examples/basic/inheritance.py index a3073a5..4a881bf 100644 --- a/examples/basic/inheritance.py +++ b/examples/basic/inheritance.py @@ -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 %}", } ) ) diff --git a/examples/basic/translate.py b/examples/basic/translate.py index fda8f7a..71547f4 100644 --- a/examples/basic/translate.py +++ b/examples/basic/translate.py @@ -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]) ) diff --git a/examples/bench.py b/examples/bench.py index 473928b..e610718 100644 --- a/examples/bench.py +++ b/examples/bench.py @@ -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> diff --git a/ext/django2jinja/django2jinja.py b/ext/django2jinja/django2jinja.py index 25b116e..11e1a2b 100644 --- a/ext/django2jinja/django2jinja.py +++ b/ext/django2jinja/django2jinja.py @@ -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) - - Here is an example hos to automatically translate your django - variables to jinja2:: - - import re - # List of tuple (Match pattern, Replace pattern, Exclusion pattern) - - 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), - - (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), - - (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) + 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() - For details about the writing process have a look at the module code. + writer = Writer() + writer.node_handlers[MyNode] = write_my_node + convert_templates("/path/to/output/folder", writer=writer) + +Here is an example hos to automatically translate your django +variables to jinja2:: + + 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) + +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: diff --git a/ext/django2jinja/example.py b/ext/django2jinja/example.py index 9bd6b97..070549f 100644 --- a/ext/django2jinja/example.py +++ b/ext/django2jinja/example.py @@ -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) diff --git a/scripts/generate_identifier_pattern.py b/scripts/generate_identifier_pattern.py index 96fedba..845a441 100755 --- a/scripts/generate_identifier_pattern.py +++ b/scripts/generate_identifier_pattern.py @@ -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__": diff --git a/scripts/make-release.py b/scripts/make-release.py index cd6ce23..de36ae1 100644 --- a/scripts/make-release.py +++ b/scripts/make-release.py @@ -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.") @@ -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 diff --git a/src/jinja2/_compat.py b/src/jinja2/_compat.py index 02aed34..aa21641 100644 --- a/src/jinja2/_compat.py +++ b/src/jinja2/_compat.py @@ -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.""" diff --git a/src/jinja2/_identifier.py b/src/jinja2/_identifier.py index 0a93e95..2490963 100644 --- a/src/jinja2/_identifier.py +++ b/src/jinja2/_identifier.py @@ -1,2 +1,2 @@ # generated by scripts/generate_identifier_pattern.py -pattern = "·̀-ͯ·҃-֑҇-ׇֽֿׁׂׅׄؐ-ًؚ-ٰٟۖ-ۜ۟-۪ۤۧۨ-ܑۭܰ-݊ަ-ް߫-߳ࠖ-࠙ࠛ-ࠣࠥ-ࠧࠩ-࡙࠭-࡛ࣔ-ࣣ࣡-ःऺ-़ा-ॏ॑-ॗॢॣঁ-ঃ়া-ৄেৈো-্ৗৢৣਁ-ਃ਼ਾ-ੂੇੈੋ-੍ੑੰੱੵઁ-ઃ઼ા-ૅે-ૉો-્ૢૣଁ-ଃ଼ା-ୄେୈୋ-୍ୖୗୢୣஂா-ூெ-ைொ-்ௗఀ-ఃా-ౄె-ైొ-్ౕౖౢౣಁ-ಃ಼ಾ-ೄೆ-ೈೊ-್ೕೖೢೣഁ-ഃാ-ൄെ-ൈൊ-്ൗൢൣංඃ්ා-ුූෘ-ෟෲෳัิ-ฺ็-๎ັິ-ູົຼ່-ໍ༹༘༙༵༷༾༿ཱ-྄྆྇ྍ-ྗྙ-ྼ࿆ါ-ှၖ-ၙၞ-ၠၢ-ၤၧ-ၭၱ-ၴႂ-ႍႏႚ-ႝ፝-፟ᜒ-᜔ᜲ-᜴ᝒᝓᝲᝳ឴-៓៝᠋-᠍ᢅᢆᢩᤠ-ᤫᤰ-᤻ᨗ-ᨛᩕ-ᩞ᩠-᩿᩼᪰-᪽ᬀ-ᬄ᬴-᭄᭫-᭳ᮀ-ᮂᮡ-ᮭ᯦-᯳ᰤ-᰷᳐-᳔᳒-᳨᳭ᳲ-᳴᳸᳹᷀-᷵᷻-᷿‿⁀⁔⃐-⃥⃜⃡-⃰℘℮⳯-⵿⳱ⷠ-〪ⷿ-゙゚〯꙯ꙴ-꙽ꚞꚟ꛰꛱ꠂ꠆ꠋꠣ-ꠧꢀꢁꢴ-ꣅ꣠-꣱ꤦ-꤭ꥇ-꥓ꦀ-ꦃ꦳-꧀ꧥꨩ-ꨶꩃꩌꩍꩻ-ꩽꪰꪲ-ꪴꪷꪸꪾ꪿꫁ꫫ-ꫯꫵ꫶ꯣ-ꯪ꯬꯭ﬞ︀-️︠-︯︳︴﹍-﹏_𐇽𐋠𐍶-𐍺𐨁-𐨃𐨅𐨆𐨌-𐨏𐨸-𐨿𐨺𐫦𐫥𑀀-𑀂𑀸-𑁆𑁿-𑂂𑂰-𑂺𑄀-𑄂𑄧-𑅳𑄴𑆀-𑆂𑆳-𑇊𑇀-𑇌𑈬-𑈷𑈾𑋟-𑋪𑌀-𑌃𑌼𑌾-𑍄𑍇𑍈𑍋-𑍍𑍗𑍢𑍣𑍦-𑍬𑍰-𑍴𑐵-𑑆𑒰-𑓃𑖯-𑖵𑖸-𑗀𑗜𑗝𑘰-𑙀𑚫-𑚷𑜝-𑜫𑰯-𑰶𑰸-𑰿𑲒-𑲧𑲩-𑲶𖫰-𖫴𖬰-𖬶𖽑-𖽾𖾏-𖾒𛲝𛲞𝅥-𝅩𝅭-𝅲𝅻-𝆂𝆅-𝆋𝆪-𝆭𝉂-𝉄𝨀-𝨶𝨻-𝩬𝩵𝪄𝪛-𝪟𝪡-𝪯𞀀-𞀆𞀈-𞀘𞀛-𞀡𞀣𞀤𞀦-𞣐𞀪-𞣖𞥄-𞥊󠄀-󠇯" +pattern = "·̀-ͯ·҃-֑҇-ׇֽֿׁׂׅׄؐ-ًؚ-ٰٟۖ-ۜ۟-۪ۤۧۨ-ܑۭܰ-݊ަ-ް߫-߳ࠖ-࠙ࠛ-ࠣࠥ-ࠧࠩ-࡙࠭-࡛ࣔ-ࣣ࣡-ःऺ-़ा-ॏ॑-ॗॢॣঁ-ঃ়া-ৄেৈো-্ৗৢৣਁ-ਃ਼ਾ-ੂੇੈੋ-੍ੑੰੱੵઁ-ઃ઼ા-ૅે-ૉો-્ૢૣଁ-ଃ଼ା-ୄେୈୋ-୍ୖୗୢୣஂா-ூெ-ைொ-்ௗఀ-ఃా-ౄె-ైొ-్ౕౖౢౣಁ-ಃ಼ಾ-ೄೆ-ೈೊ-್ೕೖೢೣഁ-ഃാ-ൄെ-ൈൊ-്ൗൢൣංඃ්ා-ුූෘ-ෟෲෳัิ-ฺ็-๎ັິ-ູົຼ່-ໍ༹༘༙༵༷༾༿ཱ-྄྆྇ྍ-ྗྙ-ྼ࿆ါ-ှၖ-ၙၞ-ၠၢ-ၤၧ-ၭၱ-ၴႂ-ႍႏႚ-ႝ፝-፟ᜒ-᜔ᜲ-᜴ᝒᝓᝲᝳ឴-៓៝᠋-᠍ᢅᢆᢩᤠ-ᤫᤰ-᤻ᨗ-ᨛᩕ-ᩞ᩠-᩿᩼᪰-᪽ᬀ-ᬄ᬴-᭄᭫-᭳ᮀ-ᮂᮡ-ᮭ᯦-᯳ᰤ-᰷᳐-᳔᳒-᳨᳭ᳲ-᳴᳸᳹᷀-᷵᷻-᷿‿⁀⁔⃐-⃥⃜⃡-⃰℘℮⳯-⵿⳱ⷠ-〪ⷿ-゙゚〯꙯ꙴ-꙽ꚞꚟ꛰꛱ꠂ꠆ꠋꠣ-ꠧꢀꢁꢴ-ꣅ꣠-꣱ꤦ-꤭ꥇ-꥓ꦀ-ꦃ꦳-꧀ꧥꨩ-ꨶꩃꩌꩍꩻ-ꩽꪰꪲ-ꪴꪷꪸꪾ꪿꫁ꫫ-ꫯꫵ꫶ꯣ-ꯪ꯬꯭ﬞ︀-️︠-︯︳︴﹍-﹏_𐇽𐋠𐍶-𐍺𐨁-𐨃𐨅𐨆𐨌-𐨏𐨸-𐨿𐨺𐫦𐫥𑀀-𑀂𑀸-𑁆𑁿-𑂂𑂰-𑂺𑄀-𑄂𑄧-𑅳𑄴𑆀-𑆂𑆳-𑇊𑇀-𑇌𑈬-𑈷𑈾𑋟-𑋪𑌀-𑌃𑌼𑌾-𑍄𑍇𑍈𑍋-𑍍𑍗𑍢𑍣𑍦-𑍬𑍰-𑍴𑐵-𑑆𑒰-𑓃𑖯-𑖵𑖸-𑗀𑗜𑗝𑘰-𑙀𑚫-𑚷𑜝-𑜫𑰯-𑰶𑰸-𑰿𑲒-𑲧𑲩-𑲶𖫰-𖫴𖬰-𖬶𖽑-𖽾𖾏-𖾒𛲝𛲞𝅥-𝅩𝅭-𝅲𝅻-𝆂𝆅-𝆋𝆪-𝆭𝉂-𝉄𝨀-𝨶𝨻-𝩬𝩵𝪄𝪛-𝪟𝪡-𝪯𞀀-𞀆𞀈-𞀘𞀛-𞀡𞀣𞀤𞀦-𞣐𞀪-𞣖𞥄-𞥊󠄀-󠇯" # noqa: B950 diff --git a/src/jinja2/asyncfilters.py b/src/jinja2/asyncfilters.py index 451d3f8..d29f6c6 100644 --- a/src/jinja2/asyncfilters.py +++ b/src/jinja2/asyncfilters.py @@ -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 diff --git a/src/jinja2/bccache.py b/src/jinja2/bccache.py index c2b877e..75419d1 100644 --- a/src/jinja2/bccache.py +++ b/src/jinja2/bccache.py @@ -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 diff --git a/src/jinja2/compiler.py b/src/jinja2/compiler.py index 324bc0f..068ad56 100644 --- a/src/jinja2/compiler.py +++ b/src/jinja2/compiler.py @@ -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 ( diff --git a/src/jinja2/debug.py b/src/jinja2/debug.py index bb36609..d2c5a06 100644 --- a/src/jinja2/debug.py +++ b/src/jinja2/debug.py @@ -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 diff --git a/src/jinja2/defaults.py b/src/jinja2/defaults.py index 8ee52bb..0af8c54 100644 --- a/src/jinja2/defaults.py +++ b/src/jinja2/defaults.py @@ -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, diff --git a/src/jinja2/environment.py b/src/jinja2/environment.py index 7c4d26a..d332831 100644 --- a/src/jinja2/environment.py +++ b/src/jinja2/environment.py @@ -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): diff --git a/src/jinja2/ext.py b/src/jinja2/ext.py index 4891c9c..b231071 100644 --- a/src/jinja2/ext.py +++ b/src/jinja2/ext.py @@ -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 diff --git a/src/jinja2/filters.py b/src/jinja2/filters.py index c7a2f39..79394ad 100644 --- a/src/jinja2/filters.py +++ b/src/jinja2/filters.py @@ -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 diff --git a/src/jinja2/lexer.py b/src/jinja2/lexer.py index 1bac2d6..a9585ef 100644 --- a/src/jinja2/lexer.py +++ b/src/jinja2/lexer.py @@ -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), diff --git a/src/jinja2/loaders.py b/src/jinja2/loaders.py index fa91a73..99798fd 100644 --- a/src/jinja2/loaders.py +++ b/src/jinja2/loaders.py @@ -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) :] diff --git a/src/jinja2/nodes.py b/src/jinja2/nodes.py index 65b2599..8026543 100644 --- a/src/jinja2/nodes.py +++ b/src/jinja2/nodes.py @@ -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): diff --git a/src/jinja2/parser.py b/src/jinja2/parser.py index 648c3fd..1d9fd91 100644 --- a/src/jinja2/parser.py +++ b/src/jinja2/parser.py @@ -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: diff --git a/src/jinja2/runtime.py b/src/jinja2/runtime.py index 9f4f224..365c1f7 100644 --- a/src/jinja2/runtime.py +++ b/src/jinja2/runtime.py @@ -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: diff --git a/src/jinja2/sandbox.py b/src/jinja2/sandbox.py index ad87997..bf4a0f6 100644 --- a/src/jinja2/sandbox.py +++ b/src/jinja2/sandbox.py @@ -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: diff --git a/src/jinja2/tests.py b/src/jinja2/tests.py index 3eea947..8c4d466 100644 --- a/src/jinja2/tests.py +++ b/src/jinja2/tests.py @@ -142,7 +142,7 @@ def test_sequence(value): try: len(value) value.__getitem__ - except: + except Exception: return False return True diff --git a/src/jinja2/utils.py b/src/jinja2/utils.py index c051f30..e429428 100644 --- a/src/jinja2/utils.py +++ b/src/jinja2/utils.py @@ -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) diff --git a/tests/test_api.py b/tests/test_api.py index a0c546c..a9eddbe 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -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): diff --git a/tests/test_async.py b/tests/test_async.py index bae73c6..f7e2792 100644 --- a/tests/test_async.py +++ b/tests/test_async.py @@ -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 == [ diff --git a/tests/test_asyncfilters.py b/tests/test_asyncfilters.py index 23a1001..7c737c8 100644 --- a/tests/test_asyncfilters.py +++ b/tests/test_asyncfilters.py @@ -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 == ( diff --git a/tests/test_core_tags.py b/tests/test_core_tags.py index deb0169..0f9346b 100644 --- a/tests/test_core_tags.py +++ b/tests/test_core_tags.py @@ -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" diff --git a/tests/test_debug.py b/tests/test_debug.py index e19a540..7dbad31 100644 --- a/tests/test_debug.py +++ b/tests/test_debug.py @@ -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'. """, ) diff --git a/tests/test_ext.py b/tests/test_ext.py index 0a9b648..6ecf9a2 100644 --- a/tests/test_ext.py +++ b/tests/test_ext.py @@ -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 " diff --git a/tests/test_features.py b/tests/test_features.py index 0d7baed..34b6f20 100644 --- a/tests/test_features.py +++ b/tests/test_features.py @@ -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) diff --git a/tests/test_filters.py b/tests/test_filters.py index 3f74c27..ae10eb5 100644 --- a/tests/test_filters.py +++ b/tests/test_filters.py @@ -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() == "<foo><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"), diff --git a/tests/test_imports.py b/tests/test_imports.py index f2895d6..7b90222 100644 --- a/tests/test_imports.py +++ b/tests/test_imports.py @@ -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" diff --git a/tests/test_inheritance.py b/tests/test_inheritance.py index 6d44d4f..0cea136 100644 --- a/tests/test_inheritance.py +++ b/tests/test_inheritance.py @@ -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]" diff --git a/tests/test_lexnparse.py b/tests/test_lexnparse.py index fb54ac8..dcfa617 100644 --- a/tests/test_lexnparse.py +++ b/tests/test_lexnparse.py @@ -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 }}""") diff --git a/tests/test_loader.py b/tests/test_loader.py index 44000e1..0a476d5 100644 --- a/tests/test_loader.py +++ b/tests/test_loader.py @@ -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") diff --git a/tests/test_regression.py b/tests/test_regression.py index 47e0073..5aa1f3d 100644 --- a/tests/test_regression.py +++ b/tests/test_regression.py @@ -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" diff --git a/tests/test_runtime.py b/tests/test_runtime.py index 307f055..d24f266 100644 --- a/tests/test_runtime.py +++ b/tests/test_runtime.py @@ -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(): diff --git a/tests/test_security.py b/tests/test_security.py index 39045fd..e00ef75 100644 --- a/tests/test_security.py +++ b/tests/test_security.py @@ -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" diff --git a/tests/test_tests.py b/tests/test_tests.py index 27871ca..447935a 100644 --- a/tests/test_tests.py +++ b/tests/test_tests.py @@ -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 == [ diff --git a/tests/test_utils.py b/tests/test_utils.py index 8cecb1b..58a2cdf 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -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 |