From bae27f7f6cd655fa3d719d7e41b8da6975eb23be Mon Sep 17 00:00:00 2001 From: tyru Date: Sat, 11 Jan 2020 22:20:39 +0900 Subject: [PATCH 1/2] Fix None access exception When empty entry in config like this: ``` policies: ``` vint always raises an exception. ``` AttributeError: 'NoneType' object has no attribute 'keys' ``` --- vint/linting/config/config_container.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vint/linting/config/config_container.py b/vint/linting/config/config_container.py index efa7863..27e59a6 100644 --- a/vint/linting/config/config_container.py +++ b/vint/linting/config/config_container.py @@ -7,6 +7,8 @@ def merge_dict_deeply(posterior, prior): # type: (Dict[str, Any], Dict[str, Any]) -> Dict[str, Any] tmp = {} + if posterior is None: + posterior = {} for key in set(posterior.keys()) | set(prior.keys()): if key in prior: if isinstance(prior[key], dict): From 775895555fdc0c0c7cf843f3c062e180e4b9ce89 Mon Sep 17 00:00:00 2001 From: tyru Date: Sun, 12 Jan 2020 18:25:17 +0900 Subject: [PATCH 2/2] Show error message for empty entry in config --- vint/linting/cli.py | 8 +++++-- vint/linting/config/config_container.py | 28 ++++++++++++++++++------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/vint/linting/cli.py b/vint/linting/cli.py index b5aa168..ffacde6 100644 --- a/vint/linting/cli.py +++ b/vint/linting/cli.py @@ -6,7 +6,7 @@ from vint.linting.linter import Linter from vint.linting.env import build_environment -from vint.linting.config.config_container import ConfigContainer +from vint.linting.config.config_container import ConfigContainer, ConfigEmptyEntryException from vint.linting.config.config_cmdargs_source import ConfigCmdargsSource from vint.linting.config.config_default_source import ConfigDefaultSource from vint.linting.config.config_global_source import ConfigGlobalSource @@ -34,7 +34,11 @@ def start_cli(): _adjust_log_level(env) - config_dict = _build_config_dict(env) + try: + config_dict = _build_config_dict(env) + except ConfigEmptyEntryException as e: + sys.stderr.write("[error] " + str(e) + "\n") + sys.exit(1) violations = _lint_all(env, config_dict) parser = _build_arg_parser() diff --git a/vint/linting/config/config_container.py b/vint/linting/config/config_container.py index 27e59a6..8b56a5d 100644 --- a/vint/linting/config/config_container.py +++ b/vint/linting/config/config_container.py @@ -3,23 +3,37 @@ from vint.linting.config.config_source import ConfigSource -def merge_dict_deeply(posterior, prior): +class ConfigEmptyEntryException(BaseException): + def __init__(self, path): + self.path = path + + def __str__(self): + return 'empty entry in config: `{path}`'.format(path=self.path) + + +def merge_dict_deeply(posterior, prior, path=[]): + def try_get(obj, path): + if obj is None: + raise ConfigEmptyEntryException(".".join(path)) + return obj + # type: (Dict[str, Any], Dict[str, Any]) -> Dict[str, Any] tmp = {} - if posterior is None: - posterior = {} for key in set(posterior.keys()) | set(prior.keys()): + child_path = path + [key] if key in prior: if isinstance(prior[key], dict): - tmp[key] = merge_dict_deeply(posterior.get(key, {}), prior[key]) + child_posterior = try_get(posterior.get(key, {}), child_path) + tmp[key] = merge_dict_deeply(child_posterior, prior[key], + child_path) else: - tmp[key] = prior[key] + tmp[key] = try_get(prior[key], child_path) else: if isinstance(posterior[key], dict): - tmp[key] = posterior[key].copy() + tmp[key] = try_get(posterior[key], child_path).copy() else: - tmp[key] = posterior[key] + tmp[key] = try_get(posterior[key], child_path) return tmp