From becdc220bc62c65e198b20298e1bf3365af99eb5 Mon Sep 17 00:00:00 2001 From: Matt Rixman Date: Wed, 29 Dec 2021 16:14:41 -0700 Subject: [PATCH 01/12] reworked the params concept doc --- docs/apache-airflow/concepts/params.rst | 141 ++++++++++++++++++------ 1 file changed, 105 insertions(+), 36 deletions(-) diff --git a/docs/apache-airflow/concepts/params.rst b/docs/apache-airflow/concepts/params.rst index 044cf702c6a8d..ff374eee16274 100644 --- a/docs/apache-airflow/concepts/params.rst +++ b/docs/apache-airflow/concepts/params.rst @@ -18,46 +18,115 @@ Params ====== -Params are Airflow's concept of providing runtime configuration to tasks when a DAG gets triggered manually. -Params are configured while defining the DAG & tasks, that can be altered while doing a manual trigger. The -ability to update params while triggering a DAG depends on the flag ``core.dag_run_conf_overrides_params``, -so if that flag is ``False``, params would behave like constants. +Params are Airflow's way to provide runtime configuration to tasks when a DAG gets triggered manually. +To use them, initialize your DAG with a dictionary where the keys are strings with each param's name, and the values are ``Param`` objects. -To use them, one can use the ``Param`` class for complex trigger-time validations or simply use primitive types, -which won't be doing any such validations. +``Param`` makes use of `json-schema `, so one can use the full json-schema specifications mentioned at https://json-schema.org/draft/2020-12/json-schema-validation.html to define the construct of a ``Param`` objects. +Or, if you want a default value without any validation, you can use literals instead. .. code-block:: + :caption a simple DAG with a parameter + from airflow import DAG + from airflow.models.param import Param + from airflow.operators.python_operator import PythonOperator + + with DAG( + "params", + params={"x": Param(5, type="integer", minimum=3), + "y": 6}, + ) as the_dag: + + def print_x(**context): + print(context["params"]["x"]) + + # prints 5, or whatever the user provided at trigger time + PythonOperator( + task_id="print_x", + python_callable=print_it, + ) + +Params can also be added to individual tasks. +If there's already a dag param with that name, the task-level default will take precedence over the dag-level default. + +.. code-block:: + :caption tasks can have parameters too + + # prints 10, or whatever the user provided at trigger time + PythonOperator( + task_id="print_x", + params={"x": 10}, + python_callable=print_it, + ) + +When a user manually triggers a dag, they can change the parameters that are provided to the dagrun. +This can be disabled by setting ``core.dag_run_conf_overrides_params = False``, which will prevent the user from changing the params. +If the user-supplied values don't pass validation, Airflow will show the user a warning it will not create the dagrun. + + +You can reference dag params via a templated task argument: + +.. code-block:: + :caption use a template + from airflow import DAG + from airflow.models.param import Param + from airflow.operators.python import PythonOperator + + with DAG( + "my_dag", + params={ + # a int with a default value + "int_param": Param(10, type="integer", minimum=0, maximum=20), + + # a required param which can be of multiple types + "dummy": Param(type=["null", "number", "string"]), + + # a param which uses json-schema formatting + "email": Param( + default="example@example.com", + type="string", + format="idn-email", + minLength=5, + maxLength=255, + ), + }, + + # instead of getting strings from templates, get objects + render_template_as_native_obj=True, + + ) as my_dag: + + PythonOperator( + task_id="from_template", + op_args=[ + "{{ params.int_param + 10 }}", + ], + python_callable=( + lambda x: print(type(x), x) + # ' 20' by default + # ' 20' if render_template_as_native_obj=True + ), + ) + +By default, Jinja templates create strings. +So if you have parameters that aren't strings, and you want to use templated task arguments, you might be interested in the ``render_template_as_native_obj`` DAG kwarg. +It will allow you to preserve the type of the parameter, even if you manipulate it in a template. + +If templates aren't your style, you can access params in via the context. + +.. code-block:: + :caption use the context kwarg + + # or you can reference them through the context + def from_context(**context): + int_param = context["params"]["int_param"] + print(type(int_param), int_param + 10) + # 20 + + PythonOperator( + task_id="from_context", + python_callable=from_context, + ) - from airflow import DAG - from airflow.models.param import Param - - with DAG( - 'my_dag', - params={ - 'int_param': Param(10, type='integer', minimum=0, maximum=20), # a int param with default value - 'str_param': Param(type='string', minLength=2, maxLength=4), # a mandatory str param - 'dummy_param': Param(type=['null', 'number', 'string']) # a param which can be None as well - 'old_param': 'old_way_of_passing', # i.e. no data or type validations - 'simple_param': Param('im_just_like_old_param'), # i.e. no data or type validations - 'email_param': Param( - default='example@example.com', - type='string', - format='idn-email', - minLength=5, - maxLength=255, - ), - }, - ) - -``Param`` make use of `json-schema `__ to define the properties and doing the -validation, so one can use the full json-schema specifications mentioned at -https://json-schema.org/draft/2020-12/json-schema-validation.html to define the construct of a ``Param`` -objects. - -Also, it worthwhile to note that if you have any DAG which uses a mandatory param value, i.e. a ``Param`` -object with no default value or ``null`` as an allowed type, that DAG schedule has to be ``None``. However, -if such ``Param`` has been defined at task level, Airflow has no way to restrict that & the task would be -failing at the execution time. .. note:: As of now, for security reasons, one can not use Param objects derived out of custom classes. We are From b4fe600591409ff69d97e460dd635054449cf23d Mon Sep 17 00:00:00 2001 From: Matt Rixman Date: Wed, 29 Dec 2021 16:35:36 -0700 Subject: [PATCH 02/12] fixed a clumsy sentance --- docs/apache-airflow/concepts/params.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apache-airflow/concepts/params.rst b/docs/apache-airflow/concepts/params.rst index ff374eee16274..fc214c4ed7296 100644 --- a/docs/apache-airflow/concepts/params.rst +++ b/docs/apache-airflow/concepts/params.rst @@ -60,7 +60,7 @@ If there's already a dag param with that name, the task-level default will take When a user manually triggers a dag, they can change the parameters that are provided to the dagrun. This can be disabled by setting ``core.dag_run_conf_overrides_params = False``, which will prevent the user from changing the params. -If the user-supplied values don't pass validation, Airflow will show the user a warning it will not create the dagrun. +If the user-supplied values don't pass validation, Airflow will show the user a warning instead of creating the dagrun. You can reference dag params via a templated task argument: From 8c6e9901de8f3247a57830d6f3eca657d6c52f0a Mon Sep 17 00:00:00 2001 From: Matt Rixman Date: Fri, 31 Dec 2021 09:42:29 -0700 Subject: [PATCH 03/12] fixed caption syntax --- docs/apache-airflow/concepts/params.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/apache-airflow/concepts/params.rst b/docs/apache-airflow/concepts/params.rst index fc214c4ed7296..c415671cb3e5f 100644 --- a/docs/apache-airflow/concepts/params.rst +++ b/docs/apache-airflow/concepts/params.rst @@ -25,7 +25,7 @@ To use them, initialize your DAG with a dictionary where the keys are strings wi Or, if you want a default value without any validation, you can use literals instead. .. code-block:: - :caption a simple DAG with a parameter + :caption: a simple DAG with a parameter from airflow import DAG from airflow.models.param import Param from airflow.operators.python_operator import PythonOperator @@ -49,7 +49,7 @@ Params can also be added to individual tasks. If there's already a dag param with that name, the task-level default will take precedence over the dag-level default. .. code-block:: - :caption tasks can have parameters too + :caption: tasks can have parameters too # prints 10, or whatever the user provided at trigger time PythonOperator( @@ -66,7 +66,7 @@ If the user-supplied values don't pass validation, Airflow will show the user a You can reference dag params via a templated task argument: .. code-block:: - :caption use a template + :caption: use a template from airflow import DAG from airflow.models.param import Param from airflow.operators.python import PythonOperator @@ -114,7 +114,7 @@ It will allow you to preserve the type of the parameter, even if you manipulate If templates aren't your style, you can access params in via the context. .. code-block:: - :caption use the context kwarg + :caption: use the context kwarg # or you can reference them through the context def from_context(**context): From f94378b13d85771cc5a0b81b74f1542100e07a65 Mon Sep 17 00:00:00 2001 From: Matt Rixman Date: Fri, 31 Dec 2021 10:46:11 -0700 Subject: [PATCH 04/12] two-backticks for inline code blocks --- docs/apache-airflow/concepts/params.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apache-airflow/concepts/params.rst b/docs/apache-airflow/concepts/params.rst index c415671cb3e5f..bc9ab94d6430e 100644 --- a/docs/apache-airflow/concepts/params.rst +++ b/docs/apache-airflow/concepts/params.rst @@ -21,7 +21,7 @@ Params Params are Airflow's way to provide runtime configuration to tasks when a DAG gets triggered manually. To use them, initialize your DAG with a dictionary where the keys are strings with each param's name, and the values are ``Param`` objects. -``Param`` makes use of `json-schema `, so one can use the full json-schema specifications mentioned at https://json-schema.org/draft/2020-12/json-schema-validation.html to define the construct of a ``Param`` objects. +``Param`` makes use of ``json-schema ``, so one can use the full json-schema specifications mentioned at https://json-schema.org/draft/2020-12/json-schema-validation.html to define the construct of a ``Param`` objects. Or, if you want a default value without any validation, you can use literals instead. .. code-block:: From 7ff2407256d9b8cabc7489514b7c7ab6290feb7f Mon Sep 17 00:00:00 2001 From: Matt Rixman Date: Fri, 31 Dec 2021 13:49:22 -0700 Subject: [PATCH 05/12] a refactor, now with subsections --- docs/apache-airflow/concepts/params.rst | 199 +++++++++++++----------- 1 file changed, 106 insertions(+), 93 deletions(-) diff --git a/docs/apache-airflow/concepts/params.rst b/docs/apache-airflow/concepts/params.rst index bc9ab94d6430e..9e625af7124ba 100644 --- a/docs/apache-airflow/concepts/params.rst +++ b/docs/apache-airflow/concepts/params.rst @@ -18,115 +18,128 @@ Params ====== -Params are Airflow's way to provide runtime configuration to tasks when a DAG gets triggered manually. -To use them, initialize your DAG with a dictionary where the keys are strings with each param's name, and the values are ``Param`` objects. +Params how Airflow provides runtime configuration to tasks. +When you trigger a DAG manually, you can modify its Params before the dagrun starts. +If the user-supplied values don't pass validation, Airflow shows a warning instead of creating the dagrun. +(For scheduled runs, the default values are used.) -``Param`` makes use of ``json-schema ``, so one can use the full json-schema specifications mentioned at https://json-schema.org/draft/2020-12/json-schema-validation.html to define the construct of a ``Param`` objects. -Or, if you want a default value without any validation, you can use literals instead. +Adding Params to a DAG +---------------------- + +To add Params to a :class:`~airflow.models.dag.DAG`, initialize it with the ``params`` kwarg with a dictionary that maps Param names to a either a class:`~airflow.models.param.Param` or an object indicating the parameter's default value. .. code-block:: - :caption: a simple DAG with a parameter - from airflow import DAG - from airflow.models.param import Param - from airflow.operators.python_operator import PythonOperator - - with DAG( - "params", - params={"x": Param(5, type="integer", minimum=3), - "y": 6}, - ) as the_dag: - - def print_x(**context): - print(context["params"]["x"]) - - # prints 5, or whatever the user provided at trigger time - PythonOperator( - task_id="print_x", - python_callable=print_it, - ) - -Params can also be added to individual tasks. -If there's already a dag param with that name, the task-level default will take precedence over the dag-level default. + + from airflow import DAG + from airflow.models.param import Param + + with DAG( + "the_dag", + params={"x": Param(5, type="integer", minimum=3), + "y": 6}, + ) as the_dag: + +Referencing Params in a Task +---------------------------- + +Params are stored as ``params`` in the :doc:`template context <../templates/templates-ref>`. +So you can reference them in a template. .. code-block:: - :caption: tasks can have parameters too - # prints 10, or whatever the user provided at trigger time - PythonOperator( - task_id="print_x", - params={"x": 10}, - python_callable=print_it, - ) + PythonOperator( + task_id="from_template", + op_args=[ + "{{ params.int_param + 10 }}", + ], + python_callable=( + lambda x: print(x) + ), + ) + +By default, Jinja templates create strings, even though Params can be of different types. +If you're using non-string Params, you might be interested in the ``render_template_as_native_obj`` DAG kwarg. + +.. code-block:: + + with DAG( + "the_dag", + params={"x": Param(5, type="integer", minimum=3), + "y": 6}, + render_template_as_native_obj=True + ) as the_dag: + -When a user manually triggers a dag, they can change the parameters that are provided to the dagrun. -This can be disabled by setting ``core.dag_run_conf_overrides_params = False``, which will prevent the user from changing the params. -If the user-supplied values don't pass validation, Airflow will show the user a warning instead of creating the dagrun. +If ``True``, the true Param type will be provided to your tasks. +.. code-block:: + + # prints by default + # prints if render_template_as_native_obj=True + PythonOperator( + task_id="template_type", + op_args=[ + "{{ params.int_param + 10 }}", + ], + python_callable=( + lambda x: print(type(x)) + ), + ) -You can reference dag params via a templated task argument: +Another way to access your param is via a task's ``context`` kwarg. .. code-block:: - :caption: use a template - from airflow import DAG - from airflow.models.param import Param - from airflow.operators.python import PythonOperator - - with DAG( - "my_dag", - params={ - # a int with a default value - "int_param": Param(10, type="integer", minimum=0, maximum=20), - - # a required param which can be of multiple types - "dummy": Param(type=["null", "number", "string"]), - - # a param which uses json-schema formatting - "email": Param( - default="example@example.com", - type="string", - format="idn-email", - minLength=5, - maxLength=255, - ), - }, - - # instead of getting strings from templates, get objects - render_template_as_native_obj=True, - - ) as my_dag: - - PythonOperator( - task_id="from_template", - op_args=[ - "{{ params.int_param + 10 }}", - ], - python_callable=( - lambda x: print(type(x), x) - # ' 20' by default - # ' 20' if render_template_as_native_obj=True - ), - ) - -By default, Jinja templates create strings. -So if you have parameters that aren't strings, and you want to use templated task arguments, you might be interested in the ``render_template_as_native_obj`` DAG kwarg. -It will allow you to preserve the type of the parameter, even if you manipulate it in a template. - -If templates aren't your style, you can access params in via the context. + + def print_x(**context): + x = context["params"]["x"] + + PythonOperator( + task_id="print_x", + python_callable=print_it, + ) + +Task-level Params +----------------- + +You can also add Params to individual tasks. .. code-block:: - :caption: use the context kwarg - # or you can reference them through the context - def from_context(**context): - int_param = context["params"]["int_param"] - print(type(int_param), int_param + 10) - # 20 + PythonOperator( + task_id="print_x", + params={"x": 10}, + python_callable=print_it, + ) - PythonOperator( - task_id="from_context", - python_callable=from_context, - ) +If there's already a dag param with that name, the task-level default will take precedence over the dag-level default. +Although a user supplies their own value when the DAG was triggered, that is always used. + +JSON Schema Validation +---------------------- + +:class:`~airflow.modules.param.Param` makes use of ``json-schema ``, so you can use the full json-schema specifications mentioned at https://json-schema.org/draft/2020-12/json-schema-validation.html to define ``Param`` objects. + +.. code-block:: + with DAG( + "my_dag", + params={ + # a int with a default value + "int_param": Param(10, type="integer", minimum=0, maximum=20), + + # a required param which can be of multiple types + "dummy": Param(type=["null", "number", "string"]), + + # a param which uses json-schema formatting + "email": Param( + default="example@example.com", + type="string", + format="idn-email", + minLength=5, + maxLength=255, + ), + }, + ) as my_dag: .. note:: As of now, for security reasons, one can not use Param objects derived out of custom classes. We are From 41694c7d2487d95a828aac4b0b2990026d2c2806 Mon Sep 17 00:00:00 2001 From: Matt Rixman Date: Fri, 31 Dec 2021 14:30:39 -0700 Subject: [PATCH 06/12] fixed references --- docs/apache-airflow/concepts/params.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/apache-airflow/concepts/params.rst b/docs/apache-airflow/concepts/params.rst index 9e625af7124ba..dec6424533455 100644 --- a/docs/apache-airflow/concepts/params.rst +++ b/docs/apache-airflow/concepts/params.rst @@ -15,6 +15,8 @@ specific language governing permissions and limitations under the License. +.. _concepts:params: + Params ====== @@ -26,7 +28,8 @@ If the user-supplied values don't pass validation, Airflow shows a warning inste Adding Params to a DAG ---------------------- -To add Params to a :class:`~airflow.models.dag.DAG`, initialize it with the ``params`` kwarg with a dictionary that maps Param names to a either a class:`~airflow.models.param.Param` or an object indicating the parameter's default value. +To add Params to a :class:`~airflow.models.dag.DAG`, initialize it with the ``params`` kwarg. +Use a dictionary that maps Param names to a either a :class:`~airflow.models.param.Param` or an object indicating the parameter's default value. .. code-block:: @@ -42,7 +45,7 @@ To add Params to a :class:`~airflow.models.dag.DAG`, initialize it with the ``pa Referencing Params in a Task ---------------------------- -Params are stored as ``params`` in the :doc:`template context <../templates/templates-ref>`. +Params are stored as ``params`` in the :ref:`template context `. So you can reference them in a template. .. code-block:: From e9dc1476e18539b8cec9dff9cf0088d96d78a949 Mon Sep 17 00:00:00 2001 From: Matt Rixman Date: Fri, 31 Dec 2021 14:55:35 -0700 Subject: [PATCH 07/12] just reworking some things --- docs/apache-airflow/concepts/params.rst | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/apache-airflow/concepts/params.rst b/docs/apache-airflow/concepts/params.rst index dec6424533455..184851fc46348 100644 --- a/docs/apache-airflow/concepts/params.rst +++ b/docs/apache-airflow/concepts/params.rst @@ -60,7 +60,6 @@ So you can reference them in a template. ), ) -By default, Jinja templates create strings, even though Params can be of different types. If you're using non-string Params, you might be interested in the ``render_template_as_native_obj`` DAG kwarg. .. code-block:: @@ -73,7 +72,8 @@ If you're using non-string Params, you might be interested in the ``render_templ ) as the_dag: -If ``True``, the true Param type will be provided to your tasks. +Even though Params can use a variety of types, the default behavior of templates is to provide your task with a string. +You can change this by setting``render_template_as_native_obj=True`` while initializing the :class:`~airflow.models.dag.DAG`. .. code-block:: @@ -147,3 +147,9 @@ JSON Schema Validation .. note:: As of now, for security reasons, one can not use Param objects derived out of custom classes. We are planning to have a registration system for custom Param classes, just like we've for Operator ExtraLinks. + +Disabling Runtime Param Modification +------------------------------------ + +The ability to update params while triggering a DAG depends on the flag ``core.dag_run_conf_overrides_params``. +Setting this config to ``False`` will effectively turn your default params into constants. From 88945b600e41388f9a864f59e65d6ae4ea7952ca Mon Sep 17 00:00:00 2001 From: Matt Rixman Date: Fri, 31 Dec 2021 14:57:07 -0700 Subject: [PATCH 08/12] just reworking some things (II) --- docs/apache-airflow/concepts/params.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apache-airflow/concepts/params.rst b/docs/apache-airflow/concepts/params.rst index 184851fc46348..2c645a56b7e23 100644 --- a/docs/apache-airflow/concepts/params.rst +++ b/docs/apache-airflow/concepts/params.rst @@ -20,7 +20,7 @@ Params ====== -Params how Airflow provides runtime configuration to tasks. +Params are how Airflow provides runtime configuration to tasks. When you trigger a DAG manually, you can modify its Params before the dagrun starts. If the user-supplied values don't pass validation, Airflow shows a warning instead of creating the dagrun. (For scheduled runs, the default values are used.) From 7f3024f8ece9497c6d8e5ee3d31e535f9cb71052 Mon Sep 17 00:00:00 2001 From: Matt Rixman Date: Fri, 31 Dec 2021 15:00:43 -0700 Subject: [PATCH 09/12] a small reorg --- docs/apache-airflow/concepts/params.rst | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/apache-airflow/concepts/params.rst b/docs/apache-airflow/concepts/params.rst index 2c645a56b7e23..5736ac9a491e5 100644 --- a/docs/apache-airflow/concepts/params.rst +++ b/docs/apache-airflow/concepts/params.rst @@ -60,20 +60,19 @@ So you can reference them in a template. ), ) -If you're using non-string Params, you might be interested in the ``render_template_as_native_obj`` DAG kwarg. +Even though Params can use a variety of types, the default behavior of templates is to provide your task with a string. +You can change this by setting ``render_template_as_native_obj=True`` while initializing the :class:`~airflow.models.dag.DAG`. .. code-block:: with DAG( "the_dag", - params={"x": Param(5, type="integer", minimum=3), - "y": 6}, + params={"x": Param(5, type="integer", minimum=3)}, render_template_as_native_obj=True ) as the_dag: -Even though Params can use a variety of types, the default behavior of templates is to provide your task with a string. -You can change this by setting``render_template_as_native_obj=True`` while initializing the :class:`~airflow.models.dag.DAG`. +This way, the Param's type is respected when its provided to your task. .. code-block:: @@ -82,7 +81,7 @@ You can change this by setting``render_template_as_native_obj=True`` while initi PythonOperator( task_id="template_type", op_args=[ - "{{ params.int_param + 10 }}", + "{{ params.int_param }}", ], python_callable=( lambda x: print(type(x)) From 2d224f0f8e3fb96e48a09f30236a1c31277072f7 Mon Sep 17 00:00:00 2001 From: Matt Rixman Date: Fri, 31 Dec 2021 15:50:42 -0700 Subject: [PATCH 10/12] clarify default precedence --- docs/apache-airflow/concepts/params.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apache-airflow/concepts/params.rst b/docs/apache-airflow/concepts/params.rst index 5736ac9a491e5..00e09caf49869 100644 --- a/docs/apache-airflow/concepts/params.rst +++ b/docs/apache-airflow/concepts/params.rst @@ -114,7 +114,7 @@ You can also add Params to individual tasks. ) If there's already a dag param with that name, the task-level default will take precedence over the dag-level default. -Although a user supplies their own value when the DAG was triggered, that is always used. +If a user supplies their own value when the DAG was triggered, Airflow ignores all defaults and uses the user's value. JSON Schema Validation ---------------------- From d16c7ef28646dd534ea6012e52a6ea221b12c59e Mon Sep 17 00:00:00 2001 From: Matt Rixman Date: Fri, 31 Dec 2021 15:58:11 -0700 Subject: [PATCH 11/12] aligned code to match prose --- docs/apache-airflow/concepts/params.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apache-airflow/concepts/params.rst b/docs/apache-airflow/concepts/params.rst index 00e09caf49869..45b691a66f258 100644 --- a/docs/apache-airflow/concepts/params.rst +++ b/docs/apache-airflow/concepts/params.rst @@ -93,7 +93,7 @@ Another way to access your param is via a task's ``context`` kwarg. .. code-block:: def print_x(**context): - x = context["params"]["x"] + print(context["params"]["x"]) PythonOperator( task_id="print_x", From 0c373be3fa86d207b7c27138c023745c75fd23d6 Mon Sep 17 00:00:00 2001 From: Kaxil Naik Date: Tue, 4 Jan 2022 08:22:12 +0530 Subject: [PATCH 12/12] Apply suggestions from code review --- docs/apache-airflow/concepts/params.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/apache-airflow/concepts/params.rst b/docs/apache-airflow/concepts/params.rst index 45b691a66f258..ef266ea56dc31 100644 --- a/docs/apache-airflow/concepts/params.rst +++ b/docs/apache-airflow/concepts/params.rst @@ -38,8 +38,10 @@ Use a dictionary that maps Param names to a either a :class:`~airflow.models.par with DAG( "the_dag", - params={"x": Param(5, type="integer", minimum=3), - "y": 6}, + params={ + "x": Param(5, type="integer", minimum=3), + "y": 6 + }, ) as the_dag: Referencing Params in a Task