New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Processing: Preprocess and pass aspects to bear #4397

Merged
merged 3 commits into from Jul 22, 2017
Jump to file or symbol
Failed to load files and symbols.
+122 −3
Diff settings

Always

Just for now

Viewing a subset of changes. View all

Extract and initialize aspects in section

Given a coafile:

```
[all]
files = **.py
bears = coalaBear
aspects = coalaCorrect, shortlog.colonexistence
language = Python 3.6
shortlog.colonexistence.shortlog_colon = false
```

Then, bears can use those aspects by accessing their
``self.section.aspects`` attribute.

```python
class SomeBear(LocalBear):
    def run(self, filename, file):
        print(self.section.aspects)
        # [<...coalaCorrect object at 0x...>, <...ColonExistence
        #  object at 0x...>]
        print(self.section.aspects[1])
        # <ColonExistence object(shortlog_colon=False) at 0x...>
        print(self.section.aspects[1].shortlog_colon)
        # True
```

Closes #4324
  • Loading branch information...
adhikasp committed Jul 22, 2017
commit 1ce4dd96a30c2acb913fb9a9f05cfc7dcac87c0f
@@ -9,7 +9,7 @@
from coalib.output.printers.LOG_LEVEL import LOG_LEVEL
from coalib.parsing.CliParsing import parse_cli, check_conflicts
from coalib.parsing.ConfParser import ConfParser
from coalib.settings.Section import Section
from coalib.settings.Section import Section, extract_aspects_from_section
from coalib.settings.SectionFilling import fill_settings
from coalib.settings.Setting import Setting, path
from string import Template
@@ -21,6 +21,19 @@
'* add `-I` to suppress any use of config files\n')
def aspectize_sections(sections):
"""
Search for aspects related setting in a section, initialize it, and then
embed the aspects information as AspectList object into the section itself.
:param sections: List of section that potentially contain aspects setting.
:return: The new sections.
"""
for _, section in sections.items():
section.aspects = extract_aspects_from_section(section)
return sections
def merge_section_dicts(lower, higher):
"""
Merges the section dictionaries. The values of higher will take
@@ -385,6 +398,7 @@ def gather_configuration(acquire_settings,
arg_list = sys.argv[1:] if arg_list is None else arg_list
sections, targets = load_configuration(arg_list, log_printer, arg_parser,
args=args)
aspectize_sections(sections)
local_bears, global_bears = fill_settings(sections,
acquire_settings,
log_printer)
Copy path View file
@@ -3,6 +3,7 @@
import sys
from collections import OrderedDict
from coalib.bearlib.aspects import AspectList
from coalib.collecting.Collectors import collect_registered_bears_dirs
from coala_utils.decorators import enforce_signature, generate_repr
from coalib.misc.DictUtilities import update_ordered_dict_key
@@ -43,6 +44,39 @@ def append_to_sections(sections,
key, str(value), origin, from_cli=from_cli, to_append=to_append))
def extract_aspects_from_section(section):
"""
Extracts aspects and their related settings from a section and create an
AspectList from it.
:param section: Section object.
:return: AspectList containing aspectclass instance with
user-defined tastes.
"""
aspects = section.get('aspects')
language = section.get('language')
# Skip aspects initialization if not configured in section
if not len(aspects):
return None
if not len(language):
raise AttributeError('Language was not found in configuration file. '
'Usage of aspect-based configuration must '
'include language information.')
aspect_instances = AspectList(exclude=section.get('excludes'))
for aspect in AspectList(aspects):
# Search all related tastes in section.
tastes = {name.split('.')[-1]: value
for name, value in section.contents.items()
if name.lower().startswith(aspect.__name__.lower())}
aspect_instances.append(aspect(language, **tastes))
return aspect_instances

This comment has been minimized.

@userzimmermann

userzimmermann Jul 21, 2017

Member
return AspectList((
    aspect(language, **{
        name.split('.')[-1]: value
        for name, value in section.contents.items()
        if name.lower().startswith(aspect.__name__.lower())
    })
    for aspect in AspectList(aspects)
), exclude=section.get('exclude'))

This comment has been minimized.

@adhikasp

adhikasp Jul 22, 2017

Member

I think this one is far too compact and not readable :/

This comment has been minimized.

@userzimmermann

userzimmermann Jul 22, 2017

Member

@adhikasp Your decision ;) Only keep in mind that for proper use we need to override AspectList.append and all other manipulation methods to check for correct aspect input

This comment has been minimized.

@userzimmermann

userzimmermann Jul 22, 2017

Member

We can then simply @aspectize AspectList.append after #4527 is done

cc @jayvdb

@generate_repr()
class Section:
"""
@@ -9,12 +9,14 @@
import pytest
from coalib.misc import Constants
from coalib.settings.Section import Section
from coala_utils.ContextManagers import (
make_temp, change_directory, retrieve_stdout)
from coalib.output.printers.LogPrinter import LogPrinter
from coala_utils.string_processing import escape
from coalib.settings.ConfigurationGathering import (
find_user_config, gather_configuration, load_configuration)
find_user_config, gather_configuration, load_configuration,
aspectize_sections)
@pytest.mark.usefixtures('disable_bears')
@@ -332,3 +334,10 @@ def test_default_section_deprecation_warning(self):
with retrieve_stdout() as stdout:
load_configuration(['--no-config'], self.log_printer)
self.assertNotIn('WARNING', stdout.getvalue())
def test_aspectize_sections(self):
section = Section('test')
sections = {'test': section}
aspectize_sections(sections)
self.assertIsNone(sections['test'].aspects)
Copy path View file
@@ -1,8 +1,11 @@
import unittest
import os
from coalib.bearlib.aspects import AspectList, Root, get as get_aspect
from coalib.bearlib.aspects.meta import issubaspect
from coalib.misc import Constants
from coalib.settings.Section import Section, Setting, append_to_sections
from coalib.settings.Section import (
Section, Setting, append_to_sections, extract_aspects_from_section)
from coalib.settings.ConfigurationGathering import get_config_directory
from coalib.parsing.Globbing import glob_escape
@@ -204,3 +207,62 @@ def test_set_default_section(self):
sections['all.c.codestyle'].set_default_section(sections)
self.assertEqual(sections['all.c.codestyle'].defaults,
sections['all'])
def test_extract_aspects_from_section(self):
section = Section('section')
section.append(Setting(
'aspects',
'spelling, commitmessage, methodsmell'))
# Custom taste for ColonExistence
section.append(Setting('commitmessage.shortlog_colon', 'false'))
section.append(Setting('language', 'py 3.4'))
aspects = extract_aspects_from_section(section)
spelling_instance = Root.Spelling('py 3.4')
colon_existence_instance = (
Root.Metadata.CommitMessage.Shortlog.ColonExistence(
'py 3.4', shortlog_colon=False))
method_smell_instance = Root.Smell.MethodSmell('py 3.4')
trailing_period_instance = (
Root.Metadata.CommitMessage.Shortlog.TrailingPeriod('py 3.4'))
self.assertIsInstance(aspects, AspectList)
self.assertEqual(aspects.get('spelling'), spelling_instance)
self.assertEqual(aspects.get('colonexistence'),
colon_existence_instance)
self.assertEqual(aspects.get('methodsmell'), method_smell_instance)
self.assertEqual(aspects.get('TrailingPeriod'),
trailing_period_instance)
def test_extract_aspects_from_section_with_exclude(self):
section = Section('section')
section.append(Setting('aspects', 'commitmessage'))
section.append(Setting('excludes', 'TrailingPeriod'))
section.append(Setting('language', 'py 3.4'))
aspects = extract_aspects_from_section(section)
self.assertTrue(issubaspect(get_aspect('trailingperiod'),
get_aspect('commitmessage')))
self.assertIsNone(aspects.get('trailingperiod'))
def test_extract_aspects_from_section_no_aspects(self):
section = Section('section')
self.assertIsNone(extract_aspects_from_section(section))
def test_extract_aspects_from_section_no_language(self):
section = Section('section')
section.append(Setting('aspects', 'commitmessage'))
with self.assertRaisesRegex(
AttributeError,
'Language was not found in configuration file. '
'Usage of aspect-based configuration must include '
'language information.'):
extract_aspects_from_section(section)
def test_extract_aspects_from_section_incorrect_language(self):
section = Section('section')
section.append(Setting('aspects', 'commitmessage'))
section.append(Setting('language', 'not a language'))
with self.assertRaises(AttributeError):
extract_aspects_from_section(section)
ProTip! Use n and p to navigate between commits in a pull request.