Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Negative number raised to even power gives negative result if exponent is a variable #1720

Open
bart-nouveau opened this issue Sep 15, 2022 · 5 comments

Comments

@bart-nouveau
Copy link

Unexpected behavior of the power operator with a variable of even value as exponent. It returns the negative value of the expected result.

mcve

from jinja2 import Environment

env = Environment()
env.globals = {"x": 2}
env.from_string("{{ -1 ** x }}").render()

From which I get '-1'

Expected behavior

I expected the positive value '1' as a result

It instead works as expected in a Sandboxed environment when intercepting the ** operator:

from jinja2.sandbox import SandboxedEnvironment

sandbox_env = SandboxedEnvironment()
sandbox_env.globals = {"x": 2}
sandbox_env.intercepted_binops = frozenset(["**"])
sandbox_env.from_string("{{ -1 ** x }}").render()

From which I get '1'

Environment:

  • Python version: 3.8.10
  • Jinja version: 3.1.2
@davidism
Copy link
Member

Happy to review a PR

@krepysh
Copy link
Contributor

krepysh commented Sep 15, 2022

Would you mind if I'll take a look onto this during this weekend?

@davidism
Copy link
Member

Anyone is welcome to work on any issue at any time, no need to ask.

@bart-nouveau
Copy link
Author

Some more details about this issue.

There are two problems: differences with respect to the results obtained with python and discrepancies between different inputs in jinja.

source code

In the following I will list some examples for different templates obtained with the following code:

env = jinja2.Environment()
env.globals = {"x": 2}
jinja_output = env.from_string(f"{{{{ {expression} }}}}").render()
python_output = eval(f"{expression}",env.globals)

examples for different input expressions

expression: '(-1) ** x'
jinja_output: '-1'
python_output: 1

expression: '-1 ** x'
jinja_output: '-1'
python_output: -1

expression: '(-1) ** 2'
jinja_output: '1'
python_output: 1

expression: '-1 ** 2'
jinja_output: '1'
python_output: -1

conclusion

The cause of the differences with respect to python could be in the parsing stage since, independently from the use of parenthesis, the result of the parser for -1 ** 2 is:
Pow(left=Neg(node=Const(value=1)), right=Name(name='x', ctx='load'))
While I expect the Neg operator to be applied to Pow

Discrepancies between jinja outputs with and without variable exponent could be found in the code generation step, where an optimization step is applied when the exponent is a Const but not when the exponent is a Name

@Troon
Copy link

Troon commented Jul 28, 2023

I've raised this as an issue against Home Assistant, and have now seen this related issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants