Example #1
0
def determine_style(configuration: Configuration,
                    style_name: Optional[str] = None) -> Style:
    available_styles = configuration.available_styles()

    if style_name is None:
        if len(available_styles) == 1:
            style_name = available_styles[0]
        else:
            message = "Cannot pick a default style from file containing " \
                      "{0} styles"
            raise StylistException(message.format(len(available_styles)))

    if style_name not in available_styles:
        message = f"style '{style_name}' not found in configuration"
        raise StylistException(message)

    # Todo: It would be nice to remove abstracts from this list but I haven't
    #       worked out how yet.
    #
    potential_rules: Dict[str, Type[stylist.rule.Rule]] \
        = {cls.__name__: cls for cls in _all_subclasses(stylist.rule.Rule)}

    rules: List[stylist.rule.Rule] = []
    rule_list = configuration.get_style(style_name)
    if not isinstance(rule_list, list):
        raise TypeError('Style rules should be a list of names')
    for rule_description in rule_list:
        rule_name, _, rule_arguments_string = rule_description.partition('(')
        rule_name = rule_name.strip()
        rule_arguments_string, _, _ = rule_arguments_string.partition(')')
        rule_arguments: List[str] = []
        if rule_arguments_string.strip():
            rule_arguments = [thing.strip()
                              for thing in rule_arguments_string.split(',')]
        if rule_name not in potential_rules:
            raise StylistException(f"Unrecognised rule: {rule_name}")
        if rule_arguments:
            processed_args: List[str] = []
            processed_kwargs: Dict[str, str] = {}
            for arg in rule_arguments:
                match = _ARGUMENT_PATTERN.match(arg)
                if match is None:
                    message = "Failed to comprehend rule argument list"
                    raise StylistException(message)
                if match.group(1) is not None:
                    processed_kwargs[match.group(1)] = eval(match.group(2))
                else:
                    processed_args.append(eval(match.group(2)))
            # TODO: Currently the use of *args and **kwargs here confuses mypy.
            #
            new_rule = potential_rules[rule_name](  # type: ignore
                *processed_args, **processed_kwargs)
            rules.append(new_rule)
        else:
            rules.append(potential_rules[rule_name]())
    return Style(rules)
Example #2
0
 def test_get_pipe(self) -> None:
     input = {'file-pipe': {'f90': 'fortran',
                            'F90': 'fortran:fpp',
                            'x90': 'fortran:pfp:fpp'}}
     expected = [('f90', FortranSource, []),
                 ('F90', FortranSource, [FortranPreProcessor]),
                 ('x90', FortranSource, [PFUnitProcessor,
                                         FortranPreProcessor])]
     test_unit = Configuration(input)
     assert expected == list(test_unit.get_file_pipes())
Example #3
0
 def test_configuration(self, style_file) -> None:
     test_unit = Configuration(style_file)
     expected = [key[6:] for key in style_file.keys()
                 if key.startswith('style.')]
     assert test_unit.available_styles() == expected
     for key in style_file.keys():
         if key.startswith('style.'):
             expected = _RULE_PATTERN.findall(style_file[key]['rules'])
             expected = [item.strip() for item in expected]
             assert test_unit.get_style(key[6:]) == expected
Example #4
0
 def test_parse_pipe(self, pipe_string) -> None:
     stimulus, expected = pipe_string
     if expected is not None:
         extension, source, preproc \
             = Configuration.parse_pipe_description(stimulus)
         assert expected[0] == extension
         assert expected[1] == source
         assert expected[2] == preproc
     else:
         with raises(StylistException):
             _ = Configuration.parse_pipe_description(stimulus)
Example #5
0
 def test_none(self):
     """
     Checks that an error is thrown if an attempt is made to get a style
     from configuration which contains none.
     """
     no_style_conf = Configuration({'': {'a': 42}})
     with pytest.raises(StylistException):
         stylist.style.determine_style(no_style_conf, 'wibble')
Example #6
0
 def test_no_default(self, tmp_path: Path):
     """
     Checks that an error is thrown if an attempt is made to load a default
     style from an empty style list.
     """
     empty_conf = Configuration({'cheese': {'a': '42'}})
     with pytest.raises(StylistException):
         stylist.style.determine_style(empty_conf)
Example #7
0
 def test_default_style(self, tmp_path: Path):
     """
     Checks that the only style is loaded if none is specified.
     """
     single_style_conf = Configuration(
         {'cheese': {'thingy': 'thangy'},
          'style.maybe': {'rules':
                          "_RuleHarnessOne, _RuleHarnessTwo('blah')"}})
     new_style = stylist.style.determine_style(single_style_conf)
     assert self._name_rules(new_style) == ['_RuleHarnessOne',
                                            '_RuleHarnessTwo']
Example #8
0
    def test_raw_argument(self, tmp_path: Path):
        """
        Checks that raw-string arguments are handled correctly.
        """
        initialiser = {'style.rawarg': {'rules': "_RuleHarnessTwo(r'.*')"}}
        conf = Configuration(initialiser)
        style = stylist.style.determine_style(conf)

        rules = style.list_rules()
        assert len(rules) == 1
        assert isinstance(rules[0], _RuleHarnessTwo)
        assert cast(_RuleHarnessTwo, rules[0]).thing == r'.*'
Example #9
0
 def test_single_style(self, tmp_path: Path):
     """
     Checks that a single style can be extracted from a list of one.
     """
     single_style_conf = Configuration(
         {'cheese': {'thingy': 'thangy'},
          'style.singular': {'rules':
                             "_RuleHarnessOne, _RuleHarnessTwo('blah')"}})
     new_style = stylist.style.determine_style(single_style_conf,
                                               'singular')
     assert self._name_rules(new_style) == ['_RuleHarnessOne',
                                            '_RuleHarnessTwo']
Example #10
0
 def test_ambiguous_default(self, tmp_path: Path):
     """
     Checks that an error is thrown if no style is specified but several
     are available.
     """
     several_style_conf = Configuration(
         {'style.the_first': {'rules': '_RuleHarnessOne'},
          'style.the_second': {'rules':
                               '_RuleHarnessOne, _RuleHarnessTwo(42)'},
          'beef': {'whatsits': 'cheesy'},
          'style.the_third': {'rules': "_RuleHarnessTwo('super')"}})
     with pytest.raises(StylistException):
         stylist.style.determine_style(several_style_conf)
Example #11
0
 def test_one_of_several(self, tmp_path: Path):
     """
     Checks that a single style can be extracted from several alternatives.
     """
     several_style_conf = Configuration(
         {'style.the_first': {'rules': '_RuleHarnessOne'},
          'style.the_second': {'rules':
                               '_RuleHarnessOne, _RuleHarnessTwo(42)'},
          'beef': {'whatsits': 'cheesy'},
          'style.the_third': {'rules': "_RuleHarnessTwo('super')"}})
     new_style = stylist.style.determine_style(several_style_conf,
                                               'the_second')
     assert self._name_rules(new_style) == ['_RuleHarnessOne',
                                            '_RuleHarnessTwo']
Example #12
0
 def test_style_with_empty_rules(self) -> None:
     test_unit = Configuration({'style.empty-rules': {'rules': ''}})
     assert test_unit.available_styles() == ['empty-rules']
     with raises(StylistException):
         _ = test_unit.get_style('empty-rules')
Example #13
0
 def test_style_without_rules(self) -> None:
     test_unit = Configuration({'style.no-rules': {'only': 'thing'}})
     assert test_unit.available_styles() == ['no-rules']
     with raises(KeyError):
         _ = test_unit.get_style('no-rules')
Example #14
0
 def test_empty_style(self) -> None:
     test_unit = Configuration({'style.empty': {}})
     assert test_unit.available_styles() == ['empty']
     with raises(KeyError):
         _ = test_unit.get_style('empty')
Example #15
0
 def test_no_styles(self) -> None:
     test_unit = Configuration({'no-style': {}})
     assert test_unit.available_styles() == []
Example #16
0
 def test_empty_file(self) -> None:
     test_unit = Configuration({})
     assert test_unit.available_styles() == []
Example #17
0
 def test_raw_rule_arguments(self) -> None:
     initialiser = {'style.raw-args': {'rules': 'rule(r\'.*\')'}}
     test_unit = Configuration(initialiser)
     assert test_unit.available_styles() == ['raw-args']
     assert test_unit.get_style('raw-args') == ['rule(r\'.*\')']
Example #18
0
 def test_no_pipe(self) -> None:
     test_unit = Configuration({})
     assert [] == test_unit.get_file_pipes()