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

"if" tag doesn't behave like Jinja when testing absent environment variable #660

Open
hongquan opened this issue Aug 11, 2021 · 9 comments

Comments

@hongquan
Copy link

For example, I want to check if an environment variable is defined, then do something. Coming from Python + Jinja, I expect to have this code:

{% if get_env('TRACKING') %}
<!-- Inject tracking code -->
{% endif %}

But it doesn't work. I end up having to write:

{% if get_env(name='TRACKING', default='') != '' %}
<!-- Inject tracking code -->
{% endif %}

There are many limitations:

  1. if doesn't consider empty string equivalent to false (error: "Function get_env was used in a logic operation but is not returning a bool"). I have to compare with another empty string.
  2. name parameter must be explicitly written.
  3. Have to explicitly write default (error: "Environment variable TRACKING not found"). In Python, os.getenv(key) is equivalent to os.getenv(key, default=None), so you don't have to always write default.
@Keats
Copy link
Owner

Keats commented Aug 11, 2021

  1. Will be fixed in v2 but no news on when that will happen
  2. Yes, args have to be named in Tera and that's not going to change
  3. In that case it was to match the Rust api. Not great looking back at it and should probably mirror more the Jinja version on v2

@DuckDuckWhale
Copy link

For 1. I think it's actually a good thing: in the same spirit as Rust, requiring explicit typing makes it simpler and removes doubts such as "is 'false' false" and potential footguns. I don't use templating all that often so maybe there are other aspects that I missed though.

@hongquan
Copy link
Author

hongquan commented Aug 26, 2021

@DuckDuckWhale That example is not relevant, because no programming language considers a string "false" equivalent to boolean false.

But from human perception, it is reasonable that empty string "" quivalent to false.

@DuckDuckWhale
Copy link

Right, that's not a very good example. Better examples would be 0 and NaN as in JS they are both falsy values. Also if implicit conversion is introduced and an empty string can be treated as false it creates confusion for all other types such as "is [] false?".

To clarify on my original point: requiring explicit comparison instead of implicitly casting from other types to bool can reduce both implementation and mental complexity while improving readability. It rules out the whole concept of falsiness and truthiness altogether. If you see an if you know exactly what the type the conditional; no need to check its type and see if the implicit conversion works as intended. To me this benefit in clarity vastly outweigh the cost of typing != ''. Like Rust, we can avoid this common pain point for JS by only taking bool.

@hongquan
Copy link
Author

hongquan commented Aug 26, 2021

@DuckDuckWhale The example of "is [] false" and JS behavior on truthy/falsy is also not relevant here, because as I stated right from the beginning, Tera is inspired from Jinja, so we just follow the logic from Python & Jinja.

I cannot imagine that someone is writing Jinja/Python code but using the behavior of JS.

Moreover, if you take JS as standard, even if get_env() != '' also not trustable, must be !==.

@DuckDuckWhale
Copy link

It is very much relevant here as Python also has the concept of truthy/falsy. I just picked JS as an example instead. 0 and [] are also falsy values in Python.

Mimicking Jinja2 is a good point though. However, Tera is a Rust template engine and doesn't aim to be 100% compatible. For folks coming form Rust this may be a friction point. Although I prefer being explicit, I don't know the design principles of this project so this is ultimately @Keats's call.

@hongquan
Copy link
Author

I don't object that "Python also has the concept of truthy/falsy". But between JS-style of truthy/falsy (where some empty data is not equivalent to false, like []) and Python style (where [] and 0 are equivalent to false), we just pick the Python because Tera is copying Jinja syntax, which is based on Python style.

It will be brain hack if you are writing Jinja code but have to "think" JS way. It is quite natural to write Jinja code and think the Python way.

I also agree that Tera won't be 100% compatible, so I still agree that name parameter must be explicit. But your argument about falsy/truthy and use JS as base is just ridiculous in the context of Jinja.

@Keats
Copy link
Owner

Keats commented Aug 28, 2021

Tera is definitely using the truthiness checks from Python/Jinja2, not from any other languages.

@DuckDuckWhale
Copy link

As stated above my point is that from a language design point of view the existence of truthiness/falsiness itself is ambiguous and may be error-prone, and I used JS only as an example language that has this concept. This is the decision taken by the Rust community and it's far from "ridiculous". However I understand if that's a not a goal and Tera tries to be conservative in divergence from Jinja2.

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

No branches or pull requests

3 participants