You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by GitBox <gi...@apache.org> on 2018/12/18 04:20:44 UTC

[GitHub] stale[bot] closed pull request #2223: [AIRFLOW-1076] Add get method for template variable accessor

stale[bot] closed pull request #2223: [AIRFLOW-1076] Add get method for template variable accessor
URL: https://github.com/apache/incubator-airflow/pull/2223
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/airflow/models.py b/airflow/models.py
index edb3b67a40..75e2238c67 100755
--- a/airflow/models.py
+++ b/airflow/models.py
@@ -1699,20 +1699,31 @@ def get_template_context(self, session=None):
 
         class VariableAccessor:
             """
-            Wrapper around Variable. This way you can get variables in templates by using
-            {var.variable_name}.
+            Wrapper around Variable. This way you can get variables in
+            templates by using {{ var.value.variable_name }} or
+            {{ var.value.get('variable_name', 'backup') }}.
             """
             def __init__(self):
                 self.var = None
 
-            def __getattr__(self, item):
+            def __getattr__(self, item, default_var=None):
                 self.var = Variable.get(item)
                 return self.var
 
             def __repr__(self):
                 return str(self.var)
 
+            @staticmethod
+            def get(item, default_var=None):
+                self.var = Variable.get(item, default_var=default_var)
+                return self.var
+
         class VariableJsonAccessor:
+            """
+            Wrapper around Variable. This way you can get variables in
+            templates by using {{ var.json.variable_name }} or
+            {{ var.json.get('variable_name', 'backup') }}.
+            """
             def __init__(self):
                 self.var = None
 
@@ -1723,6 +1734,12 @@ def __getattr__(self, item):
             def __repr__(self):
                 return str(self.var)
 
+            @staticmethod
+            def get(item, default_var=None):
+                self.var = Variable.get(item, default_var=default_var,
+                                        deserialize_json=True)
+                return self.var
+
         return {
             'dag': task.dag,
             'ds': ds,
diff --git a/docs/code.rst b/docs/code.rst
index d74d00ec56..ef5fa1ab2a 100644
--- a/docs/code.rst
+++ b/docs/code.rst
@@ -193,6 +193,11 @@ UI. You can access them as either plain-text or JSON. If you use JSON, you are
 also able to walk nested structures, such as dictionaries like:
 ``{{ var.json.my_dict_var.key1 }}``
 
+It is also possible to fetch a variable by string if
+needed with ``{{ var.value.get('my_var', 'fallback') }}`` or
+``{{ var.json.get('my_dict_var', {'key1': 'val1'}).key1 }}``. Defaults can be
+supplied in case the variable does not exist.
+
 Macros
 ''''''
 Macros are a way to expose objects to your templates and live under the
diff --git a/tests/core.py b/tests/core.py
index f25d0e7ff2..6322a9fd05 100644
--- a/tests/core.py
+++ b/tests/core.py
@@ -520,7 +520,54 @@ def verify_templated_field(context):
             some_templated_field='{{ var.value.a_variable }}',
             on_success_callback=verify_templated_field,
             dag=self.dag)
-        t.run(start_date=DEFAULT_DATE, end_date=DEFAULT_DATE, ignore_ti_state=True)
+        t.run(start_date=DEFAULT_DATE, end_date=DEFAULT_DATE,
+              ignore_ti_state=True)
+        self.assertTrue(val['success'])
+
+    def test_template_with_variable_get(self):
+        """
+        Test the availability of variables in templates using get() method
+        """
+        val = {
+            'success': False,
+            'test_value': 'a test value'
+        }
+        Variable.set('a_variable', val['test_value'])
+
+        def verify_templated_field(context):
+            self.assertEqual(context['ti'].task.some_templated_field,
+                             val['test_value'])
+            val['success'] = True
+
+        t = OperatorSubclass(
+            task_id='test_complex_template',
+            some_templated_field='{{ var.value.get("a_variable") }}',
+            on_success_callback=verify_templated_field,
+            dag=self.dag)
+        t.run(start_date=DEFAULT_DATE, end_date=DEFAULT_DATE,
+              ignore_ti_state=True)
+        self.assertTrue(val['success'])
+
+    def test_template_with_variable_get_with_default(self):
+        """
+        Test the availability of variables in templates using get() method with
+        a default value
+        """
+        val = {
+            'success': False,
+        }
+
+        def verify_templated_field(context):
+            self.assertEqual(context['ti'].task.some_templated_field, 'N/A')
+            val['success'] = True
+
+        t = OperatorSubclass(
+            task_id='test_complex_template',
+            some_templated_field='{{ var.value.get("bad_variable", "N/A") }}',
+            on_success_callback=verify_templated_field,
+            dag=self.dag)
+        t.run(start_date=DEFAULT_DATE, end_date=DEFAULT_DATE,
+              ignore_ti_state=True)
         self.assertTrue(val['success'])
 
     def test_template_with_json_variable(self):
@@ -543,7 +590,58 @@ def verify_templated_field(context):
             some_templated_field='{{ var.json.a_variable.obj.v2 }}',
             on_success_callback=verify_templated_field,
             dag=self.dag)
-        t.run(start_date=DEFAULT_DATE, end_date=DEFAULT_DATE, ignore_ti_state=True)
+        t.run(start_date=DEFAULT_DATE, end_date=DEFAULT_DATE,
+              ignore_ti_state=True)
+        self.assertTrue(val['success'])
+
+    def test_template_with_json_variable_get(self):
+        """
+        Test the availability of variables (serialized as JSON) in templates
+        using get() method
+        """
+        val = {
+            'success': False,
+            'test_value': {'foo': 'bar', 'obj': {'v1': 'yes', 'v2': 'no'}}
+        }
+        Variable.set('a_variable', val['test_value'], serialize_json=True)
+
+        def verify_templated_field(context):
+            self.assertEqual(context['ti'].task.some_templated_field,
+                             val['test_value']['obj']['v2'])
+            val['success'] = True
+
+        t = OperatorSubclass(
+            task_id='test_complex_template',
+            some_templated_field='{{ var.json.get("a_variable").obj.v2 }}',
+            on_success_callback=verify_templated_field,
+            dag=self.dag)
+        t.run(start_date=DEFAULT_DATE, end_date=DEFAULT_DATE,
+              ignore_ti_state=True)
+        self.assertTrue(val['success'])
+
+    def test_template_with_json_variable_get_with_default(self):
+        """
+        Test the availability of variables (serialized as JSON) in templates
+        using get() method with a default value
+        """
+        val = {
+            'success': False,
+        }
+
+        def verify_templated_field(context):
+            self.assertEqual(context['ti'].task.some_templated_field,
+                             'unknown')
+            val['success'] = True
+
+        t = OperatorSubclass(
+            task_id='test_complex_template',
+            some_templated_field=(
+                '{{ var.json.get("bad_variable", {"obj": {"v2": "unknown"}})'
+                '.obj.v2 }}'),
+            on_success_callback=verify_templated_field,
+            dag=self.dag)
+        t.run(start_date=DEFAULT_DATE, end_date=DEFAULT_DATE,
+              ignore_ti_state=True)
         self.assertTrue(val['success'])
 
     def test_template_with_json_variable_as_value(self):


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services