1
0
mirror of https://github.com/MarkParker5/STARK.git synced 2025-02-12 11:46:14 +02:00

syntax sugar for command.run

This commit is contained in:
MarkParker5 2023-03-12 11:46:03 +01:00
parent a1472fe16a
commit 6303bfefc9
No known key found for this signature in database
GPG Key ID: 0632FDCE0F9ED5C7
4 changed files with 35 additions and 7 deletions

View File

@ -1,6 +1,7 @@
from __future__ import annotations
from typing import Callable, Any, Optional
from enum import Enum, auto
import inspect
from pydantic import BaseModel
@ -18,10 +19,29 @@ class Command():
def __init__(self, name: str, pattern: Pattern, runner: CommandRunner):
self.name = name
self.pattern = pattern
self.run = runner
self._runner = runner
def run(self, params: dict[str, VIObject]) -> Response:
def run(self, parameters_dict: dict[str, VIObject] = None, / , **kwparameters: dict[str, VIObject]) -> Response:
# allow call both with and without dict unpacking
# e.g. command.run(foo = bar, lorem = ipsum), command.run(**parameters) and command.run(parameters)
# where parameters is dict {'foo': bar, 'lorem': ipsum}
parameters = parameters_dict or {}
parameters.update(kwparameters)
if any(p.kind == p.VAR_KEYWORD for p in inspect.signature(self._runner).parameters.values()):
# all extra params will be passed as **kwargs
return self._runner(**parameters)
else:
# avoid TypeError: self._runner got an unexpected keyword argument
return self._runner(**{k: v for k, v in parameters.items() if k in self._runner.__annotations__})
def _runner(self) -> Response:
raise NotImplementedError(f'Method start is not implemented for command with name {self.name}')
def __call__(self, *args, **kwargs) -> Response:
# just syntactic sugar for command() instead of command.run()
return self.run(*args, **kwargs)
class ResponseAction(Enum):
pop_context = auto()

View File

@ -63,7 +63,7 @@ class CommandsContext:
for search_result in search_results:
parameters = {**current_context.parameters, **search_result.parameters}
command_response = self.commands_manager.run(search_result.command, parameters)# search_result.command.run(parameters)
command_response = search_result.command(parameters)
for action in command_response.actions:
match action:

View File

@ -58,18 +58,17 @@ class CommandsManager:
def new(self, pattern_str: str, hidden: bool = False):
def creator(func: CommandRunner) -> Command:
pattern = Pattern(pattern_str)
error_msg = f'Command {self.name}.{func.__name__} must have all parameters from pattern: {pattern.parameters=} {func.__annotations__=}'
assert pattern.parameters.items() <= func.__annotations__.items(), error_msg
cmd = Command(f'{self.name}.{func.__name__}', pattern, func)
if not hidden:
self.commands.append(cmd)
return cmd
return creator
def run(self, command: Command, parameters: dict[str, VIObject]) -> Response:
# TODO: check command.func.__annotations__, pass required, raise error if annotations have params that are not in parsed dict
return command.run(**parameters)
def extend(self, other_manager: CommandsManager):
self.commands.extend(other_manager.commands)

View File

@ -1,3 +1,5 @@
import re
import pytest
from VICore import CommandsManager, VIWord
@ -13,6 +15,13 @@ def test_new():
assert manager.commands[1].name == 'CommandsManager.foo_bar'
assert manager.commands[1].pattern._origin == 'foo bar'
def test_new_with_extra_parameters_in_pattern():
manager = CommandsManager()
with pytest.raises(AssertionError, match = re.escape('Command CommandsManager.test must have all parameters from pattern:')):
@manager.new('test $name:VIWord, $secondName:VIWord')
def test(name: VIWord): pass
def test_search():
manager = CommandsManager()