From: Adrian Moennich Date: Sun, 13 Oct 2019 14:54:00 +0000 (+0200) Subject: Don't make cond_expr_undefined configurable X-Git-Tag: 2.11.0~42^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F1079%2Fhead;p=thirdparty%2Fjinja.git Don't make cond_expr_undefined configurable --- diff --git a/CHANGES.rst b/CHANGES.rst index 1ddb8cab..536e20c4 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -39,10 +39,11 @@ Unreleased :issue:`63` - When providing multiple paths to ``FileSystemLoader``, a template can have the same name as a directory. :issue:`821` -- Make the undefined object returned by ``{{ 'foo' if bar }}`` configurable, - and default to standard ``Undefined`` regardless of what is specified as - the environment's ``undefined`` object as doing so is not compatible with - ``StrictUndefined``. :issue:`710`, :pr:`1079` +- Always return a standard :class:`Undefined` when omitting the else clause + in a ``{{ 'foo' if bar }}`` expression, regardless of what is specified as + the environment's ``undefined`` class, as omitting the else clause is a + valid shortcut and not actually an undefined variable that shauld cause + an error (in case of :class:`StrictUndefined`). :issue:`710`, :pr:`1079` Version 2.10.3 diff --git a/docs/templates.rst b/docs/templates.rst index 13b693b7..af64a598 100644 --- a/docs/templates.rst +++ b/docs/templates.rst @@ -1355,8 +1355,8 @@ The general syntax is `` if else ``. The `else` part is optional. If not provided, the else block implicitly -evaluates into an undefined object (using the environment's undefined object -specified in ``cond_expr_undefined``): +evaluates into an :class:`Undefined` object (regardless of what ``undefined`` +in the environment is set to): .. sourcecode:: jinja diff --git a/jinja2/compiler.py b/jinja2/compiler.py index 850b26c0..b734611b 100644 --- a/jinja2/compiler.py +++ b/jinja2/compiler.py @@ -609,7 +609,9 @@ class CodeGenerator(NodeVisitor): """ self.writeline('resolve = context.resolve_or_missing') self.writeline('undefined = environment.undefined') - self.writeline('cond_expr_undefined = environment.cond_expr_undefined') + # always use the standard Undefined class for the implicit else of + # conditional expressions + self.writeline('cond_expr_undefined = Undefined') self.writeline('if 0: yield None') def push_parameter_definitions(self, frame): diff --git a/jinja2/environment.py b/jinja2/environment.py index 477385c9..2687889a 100644 --- a/jinja2/environment.py +++ b/jinja2/environment.py @@ -101,9 +101,6 @@ def _environment_sanity_check(environment): """Perform a sanity check on the environment.""" assert issubclass(environment.undefined, Undefined), 'undefined must ' \ 'be a subclass of undefined because filters depend on it.' - assert issubclass(environment.cond_expr_undefined, Undefined), \ - 'cond_expr_undefined must be a subclass of undefined because filters ' \ - 'depend on it.' assert environment.block_start_string != \ environment.variable_start_string != \ environment.comment_start_string, 'block, variable and comment ' \ @@ -186,13 +183,6 @@ class Environment(object): :class:`Undefined` or a subclass of it that is used to represent undefined values in the template. - `cond_expr_undefined` - :class:`Undefined` or a subclass of it that is used to represent - undefined values in the template for conditional expressions that - have no ``else`` part. This is usually useful when using a more - strict undefined class without wanting to break the short version - of conditional expressions. - `finalize` A callable that can be used to process the result of a variable expression before it is output. For example one can convert @@ -293,8 +283,7 @@ class Environment(object): cache_size=400, auto_reload=True, bytecode_cache=None, - enable_async=False, - cond_expr_undefined=Undefined): + enable_async=False): # !!Important notice!! # The constructor accepts quite a few arguments that should be # passed by keyword rather than position. However it's important to @@ -322,7 +311,6 @@ class Environment(object): # runtime information self.undefined = undefined - self.cond_expr_undefined = cond_expr_undefined self.optimized = optimized self.finalize = finalize self.autoescape = autoescape @@ -375,7 +363,7 @@ class Environment(object): extensions=missing, optimized=missing, undefined=missing, finalize=missing, autoescape=missing, loader=missing, cache_size=missing, auto_reload=missing, - bytecode_cache=missing, cond_expr_undefined=missing): + bytecode_cache=missing): """Create a new overlay environment that shares all the data with the current environment except for cache and the overridden attributes. Extensions cannot be removed for an overlayed environment. An overlayed @@ -948,15 +936,14 @@ class Template(object): undefined=Undefined, finalize=None, autoescape=False, - enable_async=False, - cond_expr_undefined=Undefined): + enable_async=False): env = get_spontaneous_environment( block_start_string, block_end_string, variable_start_string, variable_end_string, comment_start_string, comment_end_string, line_statement_prefix, line_comment_prefix, trim_blocks, lstrip_blocks, newline_sequence, keep_trailing_newline, frozenset(extensions), optimized, undefined, finalize, autoescape, - None, 0, False, None, enable_async, cond_expr_undefined) + None, 0, False, None, enable_async) return env.from_string(source, template_class=cls) @classmethod diff --git a/jinja2/runtime.py b/jinja2/runtime.py index ca391bc6..cc048cfa 100644 --- a/jinja2/runtime.py +++ b/jinja2/runtime.py @@ -27,7 +27,7 @@ from jinja2._compat import imap, text_type, iteritems, \ __all__ = ['LoopContext', 'TemplateReference', 'Macro', 'Markup', 'TemplateRuntimeError', 'missing', 'concat', 'escape', 'markup_join', 'unicode_join', 'to_string', 'identity', - 'TemplateNotFound', 'Namespace'] + 'TemplateNotFound', 'Namespace', 'Undefined'] #: the name of the function that is used to convert something into #: a string. We can just use the text type here. diff --git a/tests/test_api.py b/tests/test_api.py index b29594b3..ec93db29 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -367,15 +367,7 @@ class TestUndefined(object): .render() == 'default' with pytest.raises(AttributeError): getattr(StrictUndefined, '__slots__') - - def test_cond_expr_undefined(self): - env = Environment(cond_expr_undefined=StrictUndefined) - env2 = Environment(undefined=StrictUndefined) - pytest.raises(UndefinedError, - env.from_string('{{ "foo" if false }}').render) - assert env.from_string('{{ ("foo" if false) is defined }}').render() == 'False' - assert env2.from_string('{{ "foo" if false }}').render() == '' - assert env2.from_string('{{ ("foo" if false) is defined }}').render() == 'False' + assert env.from_string('{{ "foo" if false }}').render() == '' def test_indexing_gives_undefined(self): t = Template("{{ var[42].foo }}")