import pytest from stark.core import Pattern from stark.core.parsing import ParseError from stark.core.patterns import rules from stark.core.types import Object, String, Word from stark.general.classproperty import classproperty word = rf"[{rules.alphanumerics}]+" words = rf"[{rules.alphanumerics}\s]*" class ExtraParameterInPattern(Object): word1: Word word2: Word @classproperty def pattern(cls) -> Pattern: return Pattern("$word1:Word $word2:Word $word3:Word") async def test_typed_parameters(): p = Pattern("lorem $name:Word dolor") assert pattern_parser.parameter_types_by_name[p.parameters["name"].type_name].type == Word # assert pattern_parser._compile_pattern(p) == rf"lorem (?P{word}) dolor" # compiled is not available m = await pattern_parser.match(p, "lorem ipsum dolor") assert m assert m[0].substring == "lorem ipsum dolor" assert m[0].parameters["name"] == Word("ipsum") assert not await pattern_parser.match(p, "lorem ipsum foo dolor") p = Pattern("lorem $name:String dolor") assert pattern_parser.parameter_types_by_name[p.parameters["name"].type_name].type == String m = await pattern_parser.match(p, "lorem ipsum foo bar dolor") assert m assert m[0].substring == "lorem ipsum foo bar dolor" assert m[0].parameters["name"] == String("ipsum foo bar") async def test_middle_optional_parameter(): p = Pattern("lorem $name:Word? dolor") # print(p.compiled) assert pattern_parser.parameter_types_by_name[p.parameters["name"].type_name].type == Word assert await pattern_parser.match(p, "lorem dolor") # assert await pattern_parser.match(p, 'lorem dolor') m2 = await pattern_parser.match(p, "lorem ipsum dolor") assert m2 assert m2[0].parameters["name"] == Word("ipsum") async def test_trailing_optional_parameter(): p = Pattern("lorem $name:Word?") assert pattern_parser.parameter_types_by_name[p.parameters["name"].type_name].type == Word assert await pattern_parser.match(p, "lorem ") # assert await pattern_parser.match(p, 'lorem') m = await pattern_parser.match(p, "lorem ipsum") assert m assert m[0].parameters["name"] == Word("ipsum") async def test_optional_group(): p = Pattern("lorem( ipsum $name:Word)? dolor") # assert p.parameters == {('name', Word, True)} assert pattern_parser.parameter_types_by_name[p.parameters["name"].type_name].type == Word assert await pattern_parser.match(p, "lorem dolor") m2 = await pattern_parser.match(p, "lorem ipsum variable dolor") assert m2 assert m2[0].parameters["name"] == Word("variable") class TwoWords(Object): word1: Word word2: Word @classproperty def pattern(cls) -> Pattern: return Pattern("$word1:Word $word2:Word") from stark.core.parsing import PatternParser pattern_parser = PatternParser() pattern_parser.register_parameter_type(TwoWords) async def test_parameter_type_duplicate(): # test fix for re.error: redefinition of group name p = Pattern("hello $name:TwoWords and $name2:TwoWords") assert pattern_parser.parameter_types_by_name[p.parameters["name"].type_name].type == TwoWords m = await pattern_parser.match(p, "hello John Galt and Alice Smith") assert m class OOWordSimple2(Word): async def did_parse(self, from_string: str) -> str: if "oo" not in from_string: raise ParseError("OOWord must contain 'oo'") self.value = from_string return from_string from stark.core.parsing import PatternParser pattern_parser.register_parameter_type(OOWordSimple2) @pytest.mark.parametrize( "pattern_str, input_str, expected_params", [ ("$name:OOWordSimple2 ?* $name2:OOWordSimple2", "Joohn Janoo", {"name": "Joohn", "name2": "Janoo"}), ("$name:OOWordSimple2 ?* $name2:OOWordSimple2", "Joohn and Janoo", {"name": "Joohn", "name2": "Janoo"}), ("$name:OOWordSimple2 ?** $name2:OOWordSimple2", "Joohn and famous Janoo", {"name": "Joohn", "name2": "Janoo"}), ], ) async def test_extra_simple_patterns_extra_words(pattern_str, input_str, expected_params): p = Pattern(pattern_str) m = await pattern_parser.match(p, input_str) assert m assert {k: v.value for k, v in m[0].parameters.items()} == expected_params