Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion changes.d/7365.feat.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Python warnings raised in users' custom jinja2 filters, globals and tests are now logged.
Python warnings raised during Jinja2 preprocessing are now logged.
9 changes: 9 additions & 0 deletions cylc/flow/parsec/fileparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@
TEMPLATING_DETECTED: None
}

_J2_WARN_LOCS = re.compile(rf'jinja2{re.escape(os.sep)}(lexer|runtime)\.py$')


def get_cylc_env_vars() -> dict[str, str]:
"""Return a restricted dict of CYLC_ environment variables for templating.
Expand Down Expand Up @@ -513,6 +515,13 @@ def read_and_proc(
flines = jinja2process(
fpath, flines, fdir, template_vars
)
for w in warns:
if _J2_WARN_LOCS.search(w.filename):
# Warning originating from processing of a jinja2 template.
# Unfortunately, we can't know exactly where it originated,
# so just set the config filename and vague line "number":
w.filename = fpath
w.lineno = '<jinja2 template>' # type: ignore
if warns:
LOG.warning(
"The following warnings were raised during Jinja2 "
Expand Down
23 changes: 23 additions & 0 deletions tests/unit/parsec/test_fileparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import re
import sqlite3
from tempfile import NamedTemporaryFile
from textwrap import dedent
from types import SimpleNamespace
import warnings

Expand Down Expand Up @@ -483,6 +484,28 @@ def mock_jinja2process(fpath, *a, **k):
)


def test_read_and_proc_jinja2_warnings_invalid_escape(
tmp_path: Path, caplog: pytest.LogCaptureFixture
):
"""When a warning comes from a j2 template expression, it should be logged
with the cylc config filepath."""
(fpath := tmp_path / 'flow.cylc').write_text(
dedent(r"""
#!jinja2
{% from 'warnings' import warn %}
{% do warn('Mock warning') %}
""").lstrip()
)
read_and_proc(
fpath=str(fpath),
viewcfg={'jinja2': True, 'contin': False, 'inline': False},
)

assert (
f"{fpath}:<jinja2 template>: UserWarning: Mock warning" in caplog.text
)


def test_parse_keys_only_singleline():
with NamedTemporaryFile() as of, NamedTemporaryFile() as tf:
fpath = tf.name
Expand Down
Loading