2

In version 3.1.2 this is throwing an exception:

>>> print(jinja2.Template("{{ '%04d' | format(0777 - '0022' | int) }}").render())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/root/.virtualenvs/ansible-playbooks/lib/python3.8/site-packages/jinja2/environment.py", line 1208, in __new__
    return env.from_string(source, template_class=cls)
  File "/root/.virtualenvs/ansible-playbooks/lib/python3.8/site-packages/jinja2/environment.py", line 1105, in from_string
    return cls.from_code(self, self.compile(source), gs, None)
  File "/root/.virtualenvs/ansible-playbooks/lib/python3.8/site-packages/jinja2/environment.py", line 768, in compile
    self.handle_exception(source=source_hint)
  File "/root/.virtualenvs/ansible-playbooks/lib/python3.8/site-packages/jinja2/environment.py", line 936, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<unknown>", line 1, in template
jinja2.exceptions.TemplateSyntaxError: expected token ',', got 'integer'

While this used to work just fine in version 2.11.3:

>>> print(jinja2.Template("{{ '%04d' | format(0777 - '0022' | int) }}").render())
0755

I think the behavior is changed in this PR. What do I need to do to fix it?

The snippet above it coming from this Ansible role configuration:

deploy_cakephp_default_umask: '0022'
deploy_cakephp_default_owner: root
deploy_cakephp_default_group: root
deploy_cakephp_default_directory_mode: "{{ '%04d' | format(0777 - deploy_cakephp_default_umask | int) }}"
deploy_cakephp_default_file_mode: "{{ '%04d' | format(0666 - deploy_cakephp_default_umask | int) }}"
tersmitten
  • 1,310
  • 1
  • 9
  • 23

2 Answers2

2

I think your problem comes from Jinja and the version of python your are (were) using. C-style octal literals have been dropped in python 3.0 (see https://docs.python.org/3/reference/lexical_analysis.html#integer-literals)

Meanwhile, I was able to achieve your requirement using this Jinja2 expression taking advantage of the octal integer literal notation and the format() function:

{{ '0{0:o}'.format(0o777 - 0o22) }}

See the following test session:

$ pip list | grep Jinja2
Jinja2                 3.1.2

$ python --version
Python 3.10.6
# same result with 3.8.16

$ python
Python 3.10.6 (main, May 29 2023, 11:10:38) [GCC 11.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import jinja2
>>> print(jinja2.Template("{{ '0{0:o}'.format(0o777 - 0o22) }}").render())
0755
Zeitounator
  • 38,476
  • 7
  • 53
  • 66
  • I was using python `3.6.9`, but now python `3.8.10`. But the following snippet: print(jinja2.Template("{{ '%04d' | format(0777 - '0022' | int) }}").render()) still works with the new version of Python, but only with the old Jinja version. – tersmitten Jul 04 '23 at 08:40
1

For now I'm using this:

deploy_cakephp_default_umask: '0022'
deploy_cakephp_default_directory_mode: "{{ '0{0:o}'.format((('0777' | int(base=8)) - (deploy_cakephp_default_umask | int(base=8)))) }}"
deploy_cakephp_default_file_mode: "{{ '0{0:o}'.format((('0666' | int(base=8)) - (deploy_cakephp_default_umask | int(base=8)))) }}"

This works in both versions (and is good enough for me). For newer Python / Jinja versions ('0777' | int(base=8)) could also be simplified to 0o777 (same for 0o666).

tersmitten
  • 1,310
  • 1
  • 9
  • 23