You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by xd...@apache.org on 2020/12/05 06:17:35 UTC

[airflow] branch master updated: Configuration.getsection copes with sections that only exist in user config (#12816)

This is an automated email from the ASF dual-hosted git repository.

xddeng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/master by this push:
     new 252b047  Configuration.getsection copes with sections that only exist in user config (#12816)
252b047 is described below

commit 252b04718e5ecf278d9683614988679f46f0d39b
Author: Ash Berlin-Taylor <as...@firemirror.com>
AuthorDate: Sat Dec 5 06:16:47 2020 +0000

    Configuration.getsection copes with sections that only exist in user config (#12816)
    
    If you try to run `airflow config list` with an old config you upgraded
    from 1.8, it would fail for any sections that have been removed from the
    default cofing -- `ldap` for instance.
    
    This would also be a problem if the user makes a typo in a config
    section, or is using the airflow config for storing their own
    information.
    
    While I was changing this code, I also removed the use of private
    methods/variable access in favour of public API
---
 airflow/configuration.py         | 15 +++++++--------
 tests/core/test_configuration.py | 12 ++++++++++++
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/airflow/configuration.py b/airflow/configuration.py
index 27724cd..74d7a29 100644
--- a/airflow/configuration.py
+++ b/airflow/configuration.py
@@ -15,7 +15,6 @@
 # specific language governing permissions and limitations
 # under the License.
 
-import copy
 import json
 import logging
 import multiprocessing
@@ -482,7 +481,6 @@ class AirflowConfigParser(ConfigParser):  # pylint: disable=too-many-ancestors
         if self.airflow_defaults.has_option(section, option) and remove_default:
             self.airflow_defaults.remove_option(section, option)
 
-    # noinspection PyProtectedMember
     def getsection(self, section: str) -> Optional[Dict[str, Union[str, int, float, bool]]]:
         """
         Returns the section as a dict. Values are converted to int, float, bool
@@ -491,15 +489,16 @@ class AirflowConfigParser(ConfigParser):  # pylint: disable=too-many-ancestors
         :param section: section from the config
         :rtype: dict
         """
-        # pylint: disable=protected-access
-        if section not in self._sections and section not in self.airflow_defaults._sections:  # type: ignore
+        if not self.has_section(section) and not self.airflow_defaults.has_section(section):
             return None
-        # pylint: enable=protected-access
 
-        _section = copy.deepcopy(self.airflow_defaults._sections[section])  # pylint: disable=protected-access
+        if self.airflow_defaults.has_section(section):
+            _section = OrderedDict(self.airflow_defaults.items(section))
+        else:
+            _section = OrderedDict()
 
-        if section in self._sections:  # type: ignore
-            _section.update(copy.deepcopy(self._sections[section]))  # type: ignore
+        if self.has_section(section):
+            _section.update(OrderedDict(self.items(section)))
 
         section_prefix = f'AIRFLOW__{section.upper()}__'
         for env_var in sorted(os.environ.keys()):
diff --git a/tests/core/test_configuration.py b/tests/core/test_configuration.py
index f0c36c9..1ff7b3c 100644
--- a/tests/core/test_configuration.py
+++ b/tests/core/test_configuration.py
@@ -357,6 +357,8 @@ key2 = airflow
         test_config = '''
 [test]
 key1 = hello
+[new_section]
+key = value
 '''
         test_config_default = '''
 [test]
@@ -375,6 +377,16 @@ key3 = value3
             test_conf.getsection('testsection'),
         )
 
+        self.assertEqual(
+            OrderedDict([('key', 'value')]),
+            test_conf.getsection('new_section'),
+        )
+
+        self.assertEqual(
+            None,
+            test_conf.getsection('non_existant_secion'),
+        )
+
     def test_get_section_should_respect_cmd_env_variable(self):
         with tempfile.NamedTemporaryFile(delete=False) as cmd_file:
             cmd_file.write(b"#!/usr/bin/env bash\n")