Skip to content

Commit

Permalink
Add SettingsClass and tests
Browse files Browse the repository at this point in the history
* SettingsClass.py:
  * Added methods: collect_bear_settings(), in_annot(), in_default_args,
    in_all_args.
  * Added classes: SettingTypes, BearSettings.

* SettingsClassTest.py:
  Add tests for the method collect_bear_settings(), checking
  the sorting out of settings into Type bool and Type others and
  also on the basis of optional and non-optional.

Closes #241
  • Loading branch information
ishanSrt authored and gitmate-bot committed Jun 10, 2018
1 parent d20297e commit e819b0e
Show file tree
Hide file tree
Showing 2 changed files with 384 additions and 0 deletions.
260 changes: 260 additions & 0 deletions coala_quickstart/generation/SettingsClass.py
@@ -0,0 +1,260 @@
from coala_quickstart.generation.Utilities import (
search_for_orig, get_all_args, get_default_args)


def in_annot(func, key):
"""
Checks if a setting name as key is present in function
annotations.
:param func:
Function object.
:param key:
The setting name as a string.
:return:
The value of type annotated or False.
"""
return func.__annotations__[key] if key in func.__annotations__ else False


def in_default_args(func, key):
"""
Checks if a setting name as key is present in function
arguments with default value.
:param func:
Function object.
:param key:
The setting name as a string.
:return:
True if key is present in args with default value else False.
"""
return True if key in get_default_args(func) else False


def in_all_args(func, key):
"""
Checks if a setting name as key is present in function
arguments.
:param func:
Function object.
:param key:
The setting name as a string.
:return:
True if key is present in args of a function else False.
"""
return True if key in get_all_args(func) else False


class SettingTypes:

"""
Categorizes the settings into Type bool and Type others
"""

def __init__(self, settings, function, function_name, bear, trigger):
"""
:param settings:
Either a dict of non-optional settings of the form:
{'setting_name': ('Description.', <class 'type'>),}
or
a dict of optional settings of the form:
{'setting_name': default_values,}
:param function:
The function object i.e. either the run() method or
the create_arguments() method of the bear.
:param function_name:
Name of the function, either 'run' or 'create_arguments'
:param bear:
The current bear object.
:param trigger:
String of value either 'optional' or 'non-optional'
depending on type of settings
"""
self.settings_bool = []
self.settings_others = []
self.fillup_settings(function, settings, bear, trigger)

def fillup_settings(self, function, settings, bear, trigger):
"""
Fill settings_bool and settings_others depending upon whether the
particular setting by the bear takes a bool value or any other.
:param function:
The function object i.e. either the run() method or
the create_arguments() method of the bear.
:param settings:
Either a dict of non-optional settings of the form:
{'setting_name': ('Description.', <class 'type'>),}
or
a dict of optional settings of the form:
{'setting_name': default_values,}
:param bear:
The current bear object.
:param trigger:
String of value either 'optional' or 'non-optional'
depending on type of settings
"""
for key in settings:
if trigger == 'optional':
self.fillup_optional_settings(key, function)
elif trigger == 'non-optional':
self.fillup_non_optional_settings(key, function, bear)
else:
raise ValueError('Invalid trigger Type')

def fillup_optional_settings(self, key, func):
"""
Function to populate the optional settings
for the classes to store metadata.
:param key:
The setting value as a string.
:param func:
The function object. Either create_arguments() for linter bears
or run() for other bears.
"""
present_in_annot = in_annot(func, key)

if present_in_annot:
self.diff_bool_others(key, present_in_annot)
else:
self.diff_bool_others_default(key, get_default_args(func)[key])

def fillup_non_optional_settings(self, key, func, bear):
"""
Function to populate the non-optional settings
for the classes to store metadata.
:param key:
The setting value as a string.
:param func:
The function object. Either create_arguments() for linter bears
or run() for other bears.
:param bear:
The bear object.
"""
present_in_annot = in_annot(func, key)
present_in_default_args = in_default_args(func, key)
present_in_all_args = in_all_args(func, key)

if present_in_annot:
self.diff_bool_others(key, present_in_annot)
elif present_in_all_args and not present_in_default_args:
self.diff_bool_others(key, get_all_args(func)[key])
else:
self.parse_dep_tree(bear, key)

def parse_dep_tree(self, bear, key):
"""
Parses the bear's dependency tree looking for
non-optional setting and their Type.
:param bear:
The bear object.
:param key:
The setting value as a string.
"""
deps = bear.BEAR_DEPS
for dep in deps:
present_in_annot = in_annot(dep.run, key)
if present_in_annot:
self.diff_bool_others(key, present_in_annot)
else:
settings = get_all_args(dep.run)
for pointer in get_default_args(dep.run):
del settings[pointer]
if key in settings:
self.diff_bool_others(key, settings[key])
self.parse_dep_tree(dep, key)

def diff_bool_others(self, key, check):
"""
Checks if a settings is of Type bool or any other based
on the value of check and feeds
up the classes to store metadata in the list variables,
SettingTypes.setting_bool and SettingTypes.setting_others.
:param key:
The Setting value as a string.
:param check:
The Type to which the key is to be checked against.
"""

if check == bool:
self.settings_bool.append(key)
else:
self.settings_others.append(key)

def diff_bool_others_default(self, key, check):
"""
Checks if a settings is of Type bool or any other based
on the value of check and feeds
up the metaclass.
:param key:
The Setting value as a string.
:param check:
The Type to which the key is to be checked against.
"""
if isinstance(check, bool):
self.settings_bool.append(key)
else:
self.settings_others.append(key)


class BearSettings:

"""
Collect optional and non-optional settings for each bear
"""

def __init__(self, bear):
"""
:param bear:
A bear class object.
"""
self.bear = bear
function = bear.create_arguments if (
'create_arguments' in dir(bear)) else bear.run
function_name = 'create_arguments' if (
'create_arguments' in dir(bear)) else 'run'
non_optional_settings = bear.get_non_optional_settings()

# Get the actual function if the function is decorated.
original_function = search_for_orig(function, function_name)
if original_function is not None:
function = original_function

optional_settings = get_default_args(function)
self.create_setting_types_obj(optional_settings, non_optional_settings,
function, function_name, bear)

def create_setting_types_obj(self, optional_settings,
non_optional_settings, function,
function_name, bear):
"""
:param optional_settings:
A dict of optional settings for the bear.
:param non_optional_settings:
A dict of non-optional settings for the bear.
:param function:
The function object i.e. either the run() method or
the create_arguments() method of the bear.
:param function_name:
Name of the function, either 'run' or 'create_arguments'
:param bear:
The current bear object.
"""
self.non_optional_settings = SettingTypes(
non_optional_settings, function, function_name, bear,
trigger='non-optional')
self.optional_settings = SettingTypes(
optional_settings, function, function_name, bear,
trigger='optional')


def collect_bear_settings(bears):
"""
:param bears:
Dict of candidate bears for the project for each language.
:return:
A BearSettings object.
"""
bear_settings_obj = []
for language in bears:
for bear in bears[language]:
bear_settings_obj.append(BearSettings(bear))
return bear_settings_obj
124 changes: 124 additions & 0 deletions tests/generation/SettingsClassTest.py
@@ -0,0 +1,124 @@
import unittest

from pyprint.ConsolePrinter import ConsolePrinter
from coala_quickstart.generation.SettingsClass import (
collect_bear_settings, BearSettings, SettingTypes)
from tests.test_bears.AllKindsOfSettingsDependentBear import (
AllKindsOfSettingsDependentBear)
from tests.test_bears.AllKindsOfSettingsDependentDecoratedBear import (
AllKindsOfSettingsDependentDecoratedBear)
from tests.test_bears.AllKindsOfSettingsBaseBear import (
AllKindsOfSettingsBaseBear)
from tests.test_bears.BearA import BearA


class TestSettingsClass(unittest.TestCase):

def setUp(self):
self.printer = ConsolePrinter()
self.log_printer = None

def test_collect_bear_settings(self):
relevant_bears = {'test':
{AllKindsOfSettingsDependentBear,
AllKindsOfSettingsDependentDecoratedBear,
AllKindsOfSettingsBaseBear,
BearA}}

bear_settings_obj = collect_bear_settings(relevant_bears)

# The following test is for testing out the sorting of settings
# into Type bool and other Types using the test bear
# AllKindsOfSettingsDependentBear. This bear has all kinds of
# possible setting types and is dependent on another similar
# kind of bear so that the non-optional settings from the
# base bear also show up here.

k = 0
for index, i in enumerate(bear_settings_obj):
if i.bear == AllKindsOfSettingsDependentBear:
k = index
break
obj = bear_settings_obj[k].non_optional_settings
self.assertCountEqual(obj.settings_bool, ['use_bear', 'use_bears'])
self.assertCountEqual(obj.settings_others, ['config',
'max_line_lengths',
'no_line', 'configs',
'no_lines'])
obj = bear_settings_obj[k].optional_settings
self.assertCountEqual(obj.settings_bool, ['use_spaces', 'use_tabs',
'chars'])
self.assertCountEqual(obj.settings_others, ['max_line_lengths',
'no_chars',
'dependency_results'])

# The following test is for testing out the sorting of settings
# into Type bool and other Types using the test bear
# AllKindsOfSettingsDependentDecoratedBear. This bear has all kinds of
# possible setting types and is dependent on another similar
# kind of bear so that the non-optional settings from the
# base bear also show up here. Moreover the run methods of both these
# bears are decorated to test out whether the code is able to extract
# out the original function from the decorated methods and provide
# us with the correct bear settings.

for index, i in enumerate(bear_settings_obj):
if i.bear == AllKindsOfSettingsDependentDecoratedBear:
k = index
break
obj = bear_settings_obj[k].non_optional_settings
self.assertCountEqual(obj.settings_bool, ['use_bear', 'use_bears'])
self.assertCountEqual(obj.settings_others, ['config',
'max_line_lengths',
'no_line',
'configs',
'no_lines'])
obj = bear_settings_obj[k].optional_settings
self.assertCountEqual(obj.settings_bool, ['use_spaces', 'use_tabs',
'chars'])
self.assertCountEqual(obj.settings_others, ['max_line_lengths',
'no_chars',
'dependency_results'])

# The following test is for testing out the sorting of settings
# into Type bool and other Types using the test bear
# AllKindsOfSettingsBaseBear. This bear has all kinds of
# possible setting types.

for index, i in enumerate(bear_settings_obj):
if i.bear == AllKindsOfSettingsBaseBear:
k = index
break
obj = bear_settings_obj[k].non_optional_settings
self.assertCountEqual(obj.settings_bool, ['use_bear'])
self.assertCountEqual(obj.settings_others, ['config',
'max_line_lengths',
'no_line'])
obj = bear_settings_obj[k].optional_settings
self.assertCountEqual(obj.settings_bool, ['use_space', 'use_tab'])
self.assertCountEqual(obj.settings_others, ['max_line_length',
'no_char',
'dependency_result'])

# 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
# tree is done right.

for index, i in enumerate(bear_settings_obj):
if i.bear == BearA:
k = index
break
obj = bear_settings_obj[k].non_optional_settings
self.assertCountEqual(obj.settings_bool, ['use_spaces'])
self.assertCountEqual(obj.settings_others, [])
obj = bear_settings_obj[k].optional_settings
self.assertCountEqual(obj.settings_bool, [])
self.assertCountEqual(obj.settings_others, [])

def test_invalid_trigger(self):
with self.assertRaises(ValueError, msg='Invalid trigger Type'):
setting = SettingTypes({'a': bool}, None, '', None,
'wubalubadubdub')

0 comments on commit e819b0e

Please sign in to comment.