1
0
mirror of https://github.com/MarkParker5/STARK.git synced 2025-09-16 09:36:24 +02:00

update api

This commit is contained in:
Mark Parker
2025-09-03 20:12:45 +02:00
parent 6dd73fcfb6
commit e568da3f4d
7 changed files with 35 additions and 25 deletions

View File

@@ -101,7 +101,10 @@ class CommandsManager:
# check that runner has all parameters from pattern
error_msg = f'Command {self.name}.{runner.__name__} must have all parameters from pattern;'
pattern_params = list((p.name, p.type) for p in pattern.parameters.values())
pattern_params = list(
(p.name, Pattern._parameter_types[p.type_name].type)
for p in pattern.parameters.values()
)
difference = pattern_params - annotations.items()
# TODO: handle unregistered parameter type as a separate error
assert not difference, error_msg + f' pattern got {pattern_params}, function got {list(annotations.items())}, difference: {difference}'

View File

@@ -32,7 +32,7 @@ class ObjectParser:
'''
return from_string
async def _parse_object(
async def parse_object(
object_type: type[Object],
parser: ObjectParser,
from_string: str,

View File

@@ -23,7 +23,7 @@ class MatchResult:
end: int
parameters: dict[str, Object | None]
from .parsing import ObjectParser, ParseError, _parse_object
from .parsing import ObjectParser, ParseError, parse_object
class PatternParameter(NamedTuple): # TODO: dataclass?
@@ -65,9 +65,9 @@ class Pattern:
error_msg = f'Can`t add parameter type "{object_type.__name__}": pattern parameters do not match properties annotated in class'
# TODO: update schema and validation; handle optional parameters; handle short form where type is defined in object
# assert object_type.pattern.parameters.items() <= object_type.__annotations__.items(), error_msg
exists_type = cls._parameter_types.get(object_type.__name__)
exists_type = Pattern._parameter_types.get(object_type.__name__)
assert exists_type is None or exists_type.type == object_type, f'Can`t add parameter type: {object_type.__name__} already exists'
cls._parameter_types[object_type.__name__] = RegisteredParameterType(
Pattern._parameter_types[object_type.__name__] = RegisteredParameterType(
name=object_type.__name__,
type=object_type,
parser=parser or ObjectParser()
@@ -133,7 +133,7 @@ class Pattern:
new_match.groupdict().items()
))
logger.debug(f'Found parameters: {[(new_match.start(name), name, match_str_groups[name]) for name in sorted(match_str_groups.keys(), key=lambda n: (int(Pattern._parameter_types[self.parameters[parameter_name].type_name].type.greedy), new_match.start(n)))]}')
logger.debug(f'Found parameters: {[(new_match.start(name), name, match_str_groups[name]) for name in sorted(match_str_groups.keys(), key=lambda name: (int(Pattern._parameter_types[self.parameters[name].type_name].type.greedy), new_match.start(name)))]}')
if not match_str_groups:
break # everything's parsed (probably successfully)
@@ -143,7 +143,7 @@ class Pattern:
parameter_name = min(
match_str_groups.keys(),
key=lambda name: (
int(Pattern._parameter_types[self.parameters[parameter_name].type_name].type.greedy), # parse greedy the last so they don't absorb neighbours
int(Pattern._parameter_types[self.parameters[name].type_name].type.greedy), # parse greedy the last so they don't absorb neighbours
new_match.start(name) # parse left to right
)
)
@@ -172,7 +172,7 @@ class Pattern:
if not object_matches:
raise ParseError(f"Failed to match object {parameter_type} from {raw_param_substr}")
object_pattern_match = object_matches[0]
parse_result = await _parse_object(
parse_result = await parse_object(
parameter_reg_type.type,
parameter_reg_type.parser,
from_string=object_pattern_match.substring,

View File

@@ -20,7 +20,7 @@ class ExtraParameterInPattern(Object):
async def test_typed_parameters():
p = Pattern('lorem $name:Word dolor')
assert p.parameters['name'].type == Word
assert Pattern._parameter_types[p.parameters['name'].type_name].type == Word
assert p.compiled == fr'lorem (?P<name>{word}) dolor'
m = await p.match('lorem ipsum dolor')
@@ -30,7 +30,7 @@ async def test_typed_parameters():
assert not await p.match('lorem ipsum foo dolor')
p = Pattern('lorem $name:String dolor')
assert p.parameters['name'].type == String
assert Pattern._parameter_types[p.parameters['name'].type_name].type == String
m = await p.match('lorem ipsum foo bar dolor')
assert m
assert m[0].substring == 'lorem ipsum foo bar dolor'
@@ -49,7 +49,7 @@ def test_extra_parameter_in_pattern():
async def test_middle_optional_parameter():
p = Pattern('lorem $name:Word? dolor')
print(p.compiled)
assert p.parameters['name'].type == Word
assert Pattern._parameter_types[p.parameters['name'].type_name].type == Word
assert await p.match('lorem dolor')
# assert await p.match('lorem dolor')
@@ -60,7 +60,7 @@ async def test_middle_optional_parameter():
async def test_trailing_optional_parameter():
p = Pattern('lorem $name:Word?')
assert p.parameters['name'].type == Word
assert Pattern._parameter_types[p.parameters['name'].type_name].type == Word
assert await p.match('lorem ')
# assert await p.match('lorem')
@@ -71,7 +71,7 @@ async def test_trailing_optional_parameter():
async def test_optional_group():
p = Pattern('lorem( ipsum $name:Word)? dolor')
# assert p.parameters == {('name', Word, True)}
assert p.parameters['name'].type == Word
assert Pattern._parameter_types[p.parameters['name'].type_name].type == Word
assert await p.match('lorem dolor')

View File

@@ -2,6 +2,7 @@
import pytest
from stark.core import Pattern
from stark.core.patterns.parsing import ObjectParser, parse_object
from stark.core.patterns.pattern import ParseError
from stark.core.types import Object
from stark.general.classproperty import classproperty
@@ -21,11 +22,11 @@ class Lorem(Object):
async def test_complex_parsing_failed():
with pytest.raises(ParseError):
await Lorem.parse('some lor ipsum')
await parse_object(Lorem, ObjectParser(), 'some lor ipsum')
async def test_complex_parsing():
string = 'some lorem ipsum'
match = await Lorem.parse(string)
match = await parse_object(Lorem, ObjectParser(), string)
assert match
assert match.obj
assert match.obj.value == 'lorem'

View File

@@ -1,4 +1,5 @@
from stark.core import Pattern
from stark.core.patterns.parsing import parse_object
from stark.core.types import String
@@ -6,8 +7,11 @@ def test_pattern():
assert String.pattern == Pattern('**')
async def test_parse():
assert await String.parse('a')
assert (await String.parse('foo bar baz')).obj.value == 'foo bar baz'
from stark.core.patterns.parsing import ObjectParser
match = await parse_object(String, ObjectParser(), 'a')
assert match
match2 = await parse_object(String, ObjectParser(), 'foo bar baz')
assert match2.obj.value == 'foo bar baz'
async def test_match():
p = Pattern('foo $bar:String baz')
@@ -22,6 +26,7 @@ async def test_match():
assert m[0].parameters['bar'] == String('lorem ipsum dolor sit amet')
async def test_formatted():
string = (await String.parse('foo bar baz')).obj
from stark.core.patterns.parsing import ObjectParser
string = (await parse_object(String, ObjectParser(), 'foo bar baz')).obj
assert str(string) == '<String value: "foo bar baz">'
assert f'{string}' == 'foo bar baz'

View File

@@ -1,27 +1,28 @@
from stark.core import Pattern
from stark.core.patterns.parsing import ObjectParser, parse_object
from stark.core.types import Word
def test_pattern():
assert Word.pattern == Pattern('*')
async def test_parse():
word = (await Word.parse('foo')).obj
word = (await parse_object(Word, ObjectParser(), 'foo')).obj
assert word
assert word.value == 'foo'
async def test_match():
p = Pattern('foo $bar:Word baz')
assert p
m = await p.match('foo qwerty baz')
assert m
assert m[0].parameters['bar'] == Word('qwerty')
m = await p.match('foo lorem ipsum dolor sit amet baz')
assert not m
async def test_formatted():
string = (await Word.parse('foo')).obj
string = (await parse_object(Word, ObjectParser(), 'foo')).obj
assert str(string) == '<Word value: "foo">'
assert f'{string}' == 'foo'