From eb7360df17636e1ba1bacb428af32068673e77c7 Mon Sep 17 00:00:00 2001 From: Kacper <> Date: Wed, 2 Apr 2025 21:15:23 +0000 Subject: [PATCH 1/4] Explain f-string conflicts with Jinja templating --- airflow-core/docs/core-concepts/operators.rst | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/airflow-core/docs/core-concepts/operators.rst b/airflow-core/docs/core-concepts/operators.rst index 24c1357955ab5..4a46d263e3544 100644 --- a/airflow-core/docs/core-concepts/operators.rst +++ b/airflow-core/docs/core-concepts/operators.rst @@ -304,3 +304,31 @@ If you upgrade your environment and get the following error: AttributeError: 'str' object has no attribute '__module__' change name from ``params`` in your operators. + + +Templating Conflicts with f-strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When constructing strings for templated fields (like ``bash_command`` in ``BashOperator``) using Python f-strings, be mindful of the interaction between f-string interpolation and Jinja templating syntax. Both use curly braces (`{}`). + +Python f-strings interpret double curly braces (`{{` and `}}`) as escape sequences for literal single braces (`{` and `}`). However, Jinja uses double curly braces (`{{ variable }}`) to denote variables for templating. + +If you need to include a Jinja template expression (e.g., ``{{ ds }}``) literally within a string defined using an f-string, so that Airflow's Jinja engine can process it later, you must escape the braces for the f-string by doubling them *again*. This means using **four** curly braces: + +.. code-block:: python + + t1 = BashOperator( + task_id="fstring_templating_correct", + bash_command=f"echo Data interval start: {{{{ ds }}}}", + dag=dag, + ) + + python_var = "echo Data interval start:" + + t2 = BashOperator( + task_id="fstring_templating_simple", + bash_command=f"{python_var} {{{{ ds }}}}", + dag=dag, + ) + +This ensures the f-string processing results in a string containing the literal double braces required by Jinja, which Airflow can then template correctly before execution. Failure to do this is a common issue for beginners and can lead to errors during DAG parsing or unexpected behavior at runtime when the templating does not occur as expected. From ac5b016a09990b17ef23e405e2f687fdd3a056fc Mon Sep 17 00:00:00 2001 From: Kacper Kulczak <17738154+kkulczak@users.noreply.github.com> Date: Thu, 3 Apr 2025 00:10:25 +0200 Subject: [PATCH 2/4] Fixed spaces --- airflow-core/docs/core-concepts/operators.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airflow-core/docs/core-concepts/operators.rst b/airflow-core/docs/core-concepts/operators.rst index 4a46d263e3544..5d984e2f1dd65 100644 --- a/airflow-core/docs/core-concepts/operators.rst +++ b/airflow-core/docs/core-concepts/operators.rst @@ -324,7 +324,7 @@ If you need to include a Jinja template expression (e.g., ``{{ ds }}``) literall ) python_var = "echo Data interval start:" - + t2 = BashOperator( task_id="fstring_templating_simple", bash_command=f"{python_var} {{{{ ds }}}}", From 6469a57fc0d1da3440697d7732e820801dc02eb0 Mon Sep 17 00:00:00 2001 From: Kacper Kulczak <17738154+kkulczak@users.noreply.github.com> Date: Thu, 3 Apr 2025 00:11:51 +0200 Subject: [PATCH 3/4] Update operators.rst. - removed traling spaces --- airflow-core/docs/core-concepts/operators.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/airflow-core/docs/core-concepts/operators.rst b/airflow-core/docs/core-concepts/operators.rst index 5d984e2f1dd65..f4edb5f684333 100644 --- a/airflow-core/docs/core-concepts/operators.rst +++ b/airflow-core/docs/core-concepts/operators.rst @@ -305,7 +305,6 @@ If you upgrade your environment and get the following error: change name from ``params`` in your operators. - Templating Conflicts with f-strings ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From fbcc65ab625ceab60d043f061b096b0a969d2183 Mon Sep 17 00:00:00 2001 From: Kacper Kulczak <17738154+kkulczak@users.noreply.github.com> Date: Thu, 3 Apr 2025 14:17:41 +0200 Subject: [PATCH 4/4] Update operators.rst Doubled back ticks --- airflow-core/docs/core-concepts/operators.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/airflow-core/docs/core-concepts/operators.rst b/airflow-core/docs/core-concepts/operators.rst index f4edb5f684333..d167f1edd0360 100644 --- a/airflow-core/docs/core-concepts/operators.rst +++ b/airflow-core/docs/core-concepts/operators.rst @@ -308,9 +308,9 @@ change name from ``params`` in your operators. Templating Conflicts with f-strings ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -When constructing strings for templated fields (like ``bash_command`` in ``BashOperator``) using Python f-strings, be mindful of the interaction between f-string interpolation and Jinja templating syntax. Both use curly braces (`{}`). +When constructing strings for templated fields (like ``bash_command`` in ``BashOperator``) using Python f-strings, be mindful of the interaction between f-string interpolation and Jinja templating syntax. Both use curly braces (``{}``). -Python f-strings interpret double curly braces (`{{` and `}}`) as escape sequences for literal single braces (`{` and `}`). However, Jinja uses double curly braces (`{{ variable }}`) to denote variables for templating. +Python f-strings interpret double curly braces (``{{`` and ``}}``) as escape sequences for literal single braces (``{`` and ``}``). However, Jinja uses double curly braces (``{{ variable }}``) to denote variables for templating. If you need to include a Jinja template expression (e.g., ``{{ ds }}``) literally within a string defined using an f-string, so that Airflow's Jinja engine can process it later, you must escape the braces for the f-string by doubling them *again*. This means using **four** curly braces: