From bf9413f3d5dfb8b9e319b31b2c2c853519e6bed6 Mon Sep 17 00:00:00 2001 From: Ishan Srivastava Date: Tue, 26 Jun 2018 17:11:03 +0530 Subject: [PATCH] SettingsClass.py: Get optional settings of deps Get optional settings of dependent bears and populate them too in the SettingsClass modifying tests for the same. --- coala_quickstart/generation/SettingsClass.py | 80 ++++++++++++++++---- tests/generation/SettingsClassTest.py | 22 ++++-- tests/test_bears/BearC.py | 2 +- 3 files changed, 81 insertions(+), 23 deletions(-) diff --git a/coala_quickstart/generation/SettingsClass.py b/coala_quickstart/generation/SettingsClass.py index 90584b4..7a6bb4c 100644 --- a/coala_quickstart/generation/SettingsClass.py +++ b/coala_quickstart/generation/SettingsClass.py @@ -16,6 +16,30 @@ def in_annot(func, key): return func.__annotations__[key] if key in func.__annotations__ else False +def in_annot_recursive(bear, key): + """ + Checks if a setting name as key is present in function + annotations, recursively through the bear dependencies. + :param bear: + The bear object. + :param key: + The setting name as a string. + :return: + The value of type annotated or False. + """ + found = False + func = bear.run + if key in func.__annotations__: + return func.__annotations__[key] + else: + found = False + for dep in bear.BEAR_DEPS: + found = in_annot_recursive(dep, key) + if found is not False: + return found + return False + + def in_default_args(func, key): """ Checks if a setting name as key is present in function @@ -44,6 +68,23 @@ def in_all_args(func, key): return True if key in get_all_args(func) else False +def parse_dep_tree_optional(bear): + """ + Parse the dependency tree of the bears looking for optional settings. + :param bear: + The bear object for which to get optional settings and parse the + dependency tree further. + :return: + Dict of optional settings of the current bear and recursively + all the optional settings of its dependencies. + """ + deps = bear.BEAR_DEPS + optional_settings = get_default_args(bear.run) + for dep in deps: + optional_settings.update(parse_dep_tree_optional(dep)) + return optional_settings + + class SettingTypes: """ @@ -94,13 +135,13 @@ def fillup_settings(self, functions, settings, bear, trigger): """ for key in settings: if trigger == 'optional': - self.fillup_optional_settings(key, functions) + self.fillup_optional_settings(key, functions, bear, settings) elif trigger == 'non-optional': self.fillup_non_optional_settings(key, functions, bear) else: raise ValueError('Invalid trigger Type') - def fillup_optional_settings(self, key, funcs): + def fillup_optional_settings(self, key, funcs, bear, settings): """ Function to populate the optional settings for the classes to store metadata. @@ -110,21 +151,27 @@ def fillup_optional_settings(self, key, funcs): A list of function objects i.e. either containing the run() method or the create_arguments() and generate_config() methods of the linter bears. + :param bear: + The bear object. + :param settings: + Dict of optional bear settings of the form: + {'setting_name': default_values,} """ present_in_annot = False - for func in funcs: - inside_annot = in_annot(func, key) - if inside_annot is not False: - present_in_annot = inside_annot - break + if len(funcs) == 1: + present_in_annot = in_annot_recursive(bear, key) + else: + for func in funcs: + inside_annot = in_annot(func, key) + if inside_annot: + present_in_annot = inside_annot + break if present_in_annot: self.diff_bool_others(key, present_in_annot) else: - for func in funcs: - if key in get_default_args(func): - self.diff_bool_others_default( - key, get_default_args(func)[key]) + self.diff_bool_others_default( + key, settings[key]) def fillup_non_optional_settings(self, key, funcs, bear): """ @@ -146,7 +193,7 @@ def fillup_non_optional_settings(self, key, funcs, bear): for func in funcs: present_in_annot = in_annot(func, key) - if present_in_annot is not False: + if present_in_annot: break for func in funcs: @@ -165,9 +212,9 @@ def fillup_non_optional_settings(self, key, funcs, bear): elif present_in_all_args and not present_in_default_args: self.diff_bool_others(key, get_all_args(function)[key]) else: - self.parse_dep_tree(bear, key) + self.parse_dep_tree_non_optional(bear, key) - def parse_dep_tree(self, bear, key): + def parse_dep_tree_non_optional(self, bear, key): """ Parses the bear's dependency tree looking for non-optional setting and their Type. @@ -187,7 +234,7 @@ def parse_dep_tree(self, bear, key): del settings[pointer] if key in settings: self.diff_bool_others(key, settings[key]) - self.parse_dep_tree(dep, key) + self.parse_dep_tree_non_optional(dep, key) def diff_bool_others(self, key, check): """ @@ -247,7 +294,10 @@ def __init__(self, bear): function = original_function if function_name is 'run': + # Recursively look for optional settings (which have a default + # value) inside BEAR_DEPS optional_settings = get_default_args(function) + optional_settings.update(parse_dep_tree_optional(self.bear)) functions = [function] else: optional_settings_create_arguments = get_default_args(function) diff --git a/tests/generation/SettingsClassTest.py b/tests/generation/SettingsClassTest.py index e5b0445..896b971 100644 --- a/tests/generation/SettingsClassTest.py +++ b/tests/generation/SettingsClassTest.py @@ -52,10 +52,14 @@ def test_collect_bear_settings(self): 'no_lines']) obj = bear_settings_obj[k].optional_settings self.assertCountEqual(obj.settings_bool, ['use_spaces', 'use_tabs', - 'chars']) + 'chars', 'use_space', + 'use_tab']) self.assertCountEqual(obj.settings_others, ['max_line_lengths', 'no_chars', - 'dependency_results']) + 'dependency_results', + 'dependency_result', + 'no_char', + 'max_line_length']) # The following test is for testing out the sorting of settings # into Type bool and other Types using the test bear @@ -80,10 +84,14 @@ def test_collect_bear_settings(self): 'no_lines']) obj = bear_settings_obj[k].optional_settings self.assertCountEqual(obj.settings_bool, ['use_spaces', 'use_tabs', - 'chars']) + 'chars', 'use_space', + 'use_tab']) self.assertCountEqual(obj.settings_others, ['max_line_lengths', 'no_chars', - 'dependency_results']) + 'dependency_results', + 'dependency_result', + 'no_char', + 'max_line_length']) # The following test is for testing out the sorting of settings # into Type bool and other Types using the test bear @@ -108,8 +116,8 @@ def test_collect_bear_settings(self): # The following test is for testing out the sorting of settings # into Type bool and other Types using the test bear # BearA. This bear is dependent on BearB which is further dependent - # on BearC to test out that non-optional settings from BearC - # are appearring over here and the parsing of the bear dependency + # on BearC to test out that settings from BearC + # are appearing over here and the parsing of the bear dependency # tree is done right. for index, i in enumerate(bear_settings_obj): @@ -121,7 +129,7 @@ def test_collect_bear_settings(self): self.assertCountEqual(obj.settings_others, []) obj = bear_settings_obj[k].optional_settings self.assertCountEqual(obj.settings_bool, []) - self.assertCountEqual(obj.settings_others, []) + self.assertCountEqual(obj.settings_others, ['a']) # The following tests are for testing out the sorting of settings # into Type bool and other Types using the test bears diff --git a/tests/test_bears/BearC.py b/tests/test_bears/BearC.py index 0804e17..27fe000 100644 --- a/tests/test_bears/BearC.py +++ b/tests/test_bears/BearC.py @@ -2,5 +2,5 @@ class BearC(LocalBear): - def run(use_spaces: bool): + def run(use_spaces: bool, a=79): pass