mirror of
https://github.com/MarkParker5/STARK.git
synced 2025-02-17 11:55:35 +02:00
pass test_commands_context [no ci]
This commit is contained in:
parent
0009c26744
commit
c5057a1716
104
poetry.lock
generated
104
poetry.lock
generated
@ -35,6 +35,24 @@ files = [
|
||||
[package.dependencies]
|
||||
anyio = ">=3.4.0,<4.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "attrs"
|
||||
version = "23.1.0"
|
||||
description = "Classes Without Boilerplate"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"},
|
||||
{file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
cov = ["attrs[tests]", "coverage[toml] (>=5.3)"]
|
||||
dev = ["attrs[docs,tests]", "pre-commit"]
|
||||
docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"]
|
||||
tests = ["attrs[tests-no-zope]", "zope-interface"]
|
||||
tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
|
||||
|
||||
[[package]]
|
||||
name = "babel"
|
||||
version = "2.12.1"
|
||||
@ -90,7 +108,7 @@ files = [
|
||||
name = "cffi"
|
||||
version = "1.15.1"
|
||||
description = "Foreign Function Interface for Python calling C code."
|
||||
optional = true
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"},
|
||||
@ -878,6 +896,20 @@ files = [
|
||||
setuptools = "*"
|
||||
wheel = "*"
|
||||
|
||||
[[package]]
|
||||
name = "outcome"
|
||||
version = "1.2.0"
|
||||
description = "Capture the outcome of Python function calls."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "outcome-1.2.0-py2.py3-none-any.whl", hash = "sha256:c4ab89a56575d6d38a05aa16daeaa333109c1f96167aba8901ab18b6b5e0f7f5"},
|
||||
{file = "outcome-1.2.0.tar.gz", hash = "sha256:6f82bd3de45da303cf1f771ecafa1633750a358436a8bb60e06a1ceb745d2672"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
attrs = ">=19.2.0"
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "23.1"
|
||||
@ -1008,7 +1040,7 @@ pyasn1 = ">=0.4.6,<0.6.0"
|
||||
name = "pycparser"
|
||||
version = "2.21"
|
||||
description = "C parser in Python"
|
||||
optional = true
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
files = [
|
||||
{file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"},
|
||||
@ -1122,19 +1154,38 @@ tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
|
||||
testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-anyio"
|
||||
version = "0.0.0"
|
||||
description = "The pytest anyio plugin is built into anyio. You don't need this package."
|
||||
name = "pytest-asyncio"
|
||||
version = "0.21.1"
|
||||
description = "Pytest support for asyncio"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "pytest-anyio-0.0.0.tar.gz", hash = "sha256:b41234e9e9ad7ea1dbfefcc1d6891b23d5ef7c9f07ccf804c13a9cc338571fd3"},
|
||||
{file = "pytest_anyio-0.0.0-py2.py3-none-any.whl", hash = "sha256:dc8b5c4741cb16ff90be37fddd585ca943ed12bbeb563de7ace6cd94441d8746"},
|
||||
{file = "pytest-asyncio-0.21.1.tar.gz", hash = "sha256:40a7eae6dded22c7b604986855ea48400ab15b069ae38116e8c01238e9eeb64d"},
|
||||
{file = "pytest_asyncio-0.21.1-py3-none-any.whl", hash = "sha256:8666c1c8ac02631d7c51ba282e0c69a8a452b211ffedf2599099845da5c5c37b"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
anyio = "*"
|
||||
pytest = "*"
|
||||
pytest = ">=7.0.0"
|
||||
|
||||
[package.extras]
|
||||
docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"]
|
||||
testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-trio"
|
||||
version = "0.8.0"
|
||||
description = "Pytest plugin for trio"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "pytest-trio-0.8.0.tar.gz", hash = "sha256:8363db6336a79e6c53375a2123a41ddbeccc4aa93f93788651641789a56fb52e"},
|
||||
{file = "pytest_trio-0.8.0-py3-none-any.whl", hash = "sha256:e6a7e7351ae3e8ec3f4564d30ee77d1ec66e1df611226e5618dbb32f9545c841"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
outcome = ">=1.1.0"
|
||||
pytest = ">=7.2.0"
|
||||
trio = ">=0.22.0"
|
||||
|
||||
[[package]]
|
||||
name = "python-dateutil"
|
||||
@ -1415,6 +1466,17 @@ files = [
|
||||
{file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sortedcontainers"
|
||||
version = "2.4.0"
|
||||
description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"},
|
||||
{file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sounddevice"
|
||||
version = "0.4.6"
|
||||
@ -1548,6 +1610,26 @@ notebook = ["ipywidgets (>=6)"]
|
||||
slack = ["slack-sdk"]
|
||||
telegram = ["requests"]
|
||||
|
||||
[[package]]
|
||||
name = "trio"
|
||||
version = "0.22.2"
|
||||
description = "A friendly Python library for async concurrency and I/O"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "trio-0.22.2-py3-none-any.whl", hash = "sha256:f43da357620e5872b3d940a2e3589aa251fd3f881b65a608d742e00809b1ec38"},
|
||||
{file = "trio-0.22.2.tar.gz", hash = "sha256:3887cf18c8bcc894433420305468388dac76932e9668afa1c49aa3806b6accb3"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
attrs = ">=20.1.0"
|
||||
cffi = {version = ">=1.14", markers = "os_name == \"nt\" and implementation_name != \"pypy\""}
|
||||
exceptiongroup = {version = ">=1.0.0rc9", markers = "python_version < \"3.11\""}
|
||||
idna = "*"
|
||||
outcome = "*"
|
||||
sniffio = "*"
|
||||
sortedcontainers = "*"
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.7.1"
|
||||
@ -1738,4 +1820,4 @@ vosk = ["sounddevice", "vosk"]
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.10"
|
||||
content-hash = "321b841eb5e19b2a8d0b5096aaffde6819ff0238435fd802ebabea7714ebef3d"
|
||||
content-hash = "c03b79855601eac20974ce1d5affe7c9da3fdd8ee7c943f0333d5eb3fbec4e9f"
|
||||
|
@ -27,14 +27,15 @@ silero = ["torch", "numpy", "sounddevice"]
|
||||
sound = ["sounddevice", "soundfile"]
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
# tests and static validation
|
||||
pytest = "^7.2.1"
|
||||
mypy = "^1.1.1"
|
||||
# docs generation
|
||||
mkdocs-material = { version = "^9.2.8", optional = true }
|
||||
mkdocs-git-revision-date-localized-plugin = { version = "^1.2.0", optional = true }
|
||||
mkdocs-swagger-ui-tag = { version = "^0.6.4", optional = true }
|
||||
pytest-anyio = "^0.0.0"
|
||||
# tests and static validation
|
||||
pytest = "^7.2.1"
|
||||
mypy = "^1.1.1"
|
||||
pytest-asyncio = "^0.21.1"
|
||||
pytest-trio = "^0.8.0"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
@ -44,6 +45,8 @@ build-backend = "poetry.core.masonry.api"
|
||||
pythonpath = [
|
||||
"stark",
|
||||
]
|
||||
# asyncio_mode = "auto"
|
||||
trio_mode = "true"
|
||||
|
||||
[tool.mypy]
|
||||
ignore_missing_imports = true
|
||||
|
@ -1,10 +1,11 @@
|
||||
from __future__ import annotations
|
||||
from typing import Callable, Awaitable, Any, Optional, Protocol
|
||||
from typing import Callable, Awaitable, Any, Protocol
|
||||
from enum import auto, Enum
|
||||
from datetime import datetime
|
||||
import inspect
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
import asyncer
|
||||
|
||||
from general.classproperty import classproperty
|
||||
from .patterns import Pattern
|
||||
@ -17,11 +18,10 @@ CommandRunner = Callable[..., 'Response | None'] | AsyncCommandRunner
|
||||
class Command:
|
||||
name: str
|
||||
pattern: Pattern
|
||||
_runner: AsyncCommandRunner
|
||||
_runner: CommandRunner
|
||||
|
||||
def __init__(self, name: str, pattern: Pattern, runner: AsyncCommandRunner):
|
||||
def __init__(self, name: str, pattern: Pattern, runner: CommandRunner):
|
||||
assert isinstance(pattern, Pattern)
|
||||
assert inspect.iscoroutinefunction(runner)
|
||||
self.name = name
|
||||
self.pattern = pattern
|
||||
self._runner = runner
|
||||
@ -32,14 +32,21 @@ class Command:
|
||||
# where parameters is dict {'foo': bar, 'lorem': ipsum}
|
||||
|
||||
parameters = parameters_dict or {}
|
||||
parameters.update(kwparameters)
|
||||
parameters.update(kwparameters)
|
||||
|
||||
runner: AsyncCommandRunner
|
||||
|
||||
if inspect.iscoroutinefunction(self._runner):
|
||||
runner = self._runner
|
||||
else:
|
||||
runner = asyncer.asyncify(self._runner)
|
||||
|
||||
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)
|
||||
# if command runner accepts **kwargs, pass all parameters
|
||||
return 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__})
|
||||
# otherwise pass only parameters that are in command runner signature to prevent TypeError: got an unexpected keyword argument
|
||||
return runner(**{k: v for k, v in parameters.items() if k in self._runner.__annotations__})
|
||||
|
||||
def __call__(self, *args, **kwargs) -> AwaitResponse:
|
||||
# just syntactic sugar for command() instead of command.run()
|
||||
|
@ -33,7 +33,7 @@ class CommandsContext:
|
||||
_task_group: TaskGroup
|
||||
|
||||
def __init__(self, task_group: TaskGroup, commands_manager: CommandsManager, dependency_manager: DependencyManager = default_dependency_manager):
|
||||
assert isinstance(task_group, TaskGroup)
|
||||
assert isinstance(task_group, TaskGroup), task_group
|
||||
assert isinstance(commands_manager, CommandsManager)
|
||||
assert isinstance(dependency_manager, DependencyManager)
|
||||
self.commands_manager = commands_manager
|
||||
@ -114,7 +114,10 @@ class CommandsContext:
|
||||
while not self.is_stopped:
|
||||
while self._response_queue:
|
||||
self._process_response(self._response_queue.pop(0))
|
||||
await anyio.sleep(1)
|
||||
await anyio.sleep(0.1)
|
||||
|
||||
def stop(self):
|
||||
self.is_stopped = True
|
||||
|
||||
def _process_response(self, response: Response):
|
||||
if response is Response.repeat_last and self.last_response:
|
||||
|
@ -76,14 +76,7 @@ class CommandsManager:
|
||||
error_msg = f'Command {self.name}.{runner.__name__} must have all parameters from pattern: {pattern.parameters=} {runner.__annotations__=}'
|
||||
assert pattern.parameters.items() <= runner.__annotations__.items(), error_msg
|
||||
|
||||
if not inspect.iscoroutinefunction(runner):
|
||||
async_runner = asyncer.asyncify(runner) # type: ignore
|
||||
async_runner.__name__ = runner.__name__
|
||||
async_runner.__annotations__ = runner.__annotations__
|
||||
else:
|
||||
async_runner = runner
|
||||
|
||||
cmd = Command(f'{self.name}.{runner.__name__}', pattern, async_runner) # type: ignore
|
||||
cmd = Command(f'{self.name}.{runner.__name__}', pattern, runner)
|
||||
|
||||
if not hidden:
|
||||
self.commands.append(cmd)
|
||||
|
@ -1,5 +1,8 @@
|
||||
import pytest
|
||||
from typing import AsyncGenerator
|
||||
import time
|
||||
import contextlib
|
||||
import pytest
|
||||
import asyncer
|
||||
from general.dependencies import DependencyManager
|
||||
from core import (
|
||||
CommandsManager,
|
||||
@ -45,114 +48,70 @@ class SpeechSynthesizerMock:
|
||||
return result
|
||||
|
||||
@pytest.fixture
|
||||
def commands_context_flow() -> tuple[CommandsManager, CommandsContext, CommandsContextDelegateMock]:
|
||||
dependencies = DependencyManager()
|
||||
manager = CommandsManager()
|
||||
context = CommandsContext(manager, dependencies)
|
||||
context_delegate = CommandsContextDelegateMock()
|
||||
context.delegate = context_delegate
|
||||
|
||||
assert len(context_delegate.responses) == 0
|
||||
assert len(context._context_queue) == 1
|
||||
|
||||
return manager, context, context_delegate
|
||||
|
||||
@pytest.fixture
|
||||
def commands_context_flow_filled(commands_context_flow) -> tuple[CommandsContext, CommandsContextDelegateMock]:
|
||||
|
||||
manager, context, context_delegate = commands_context_flow
|
||||
|
||||
@manager.new('test')
|
||||
def test():
|
||||
return Response()
|
||||
|
||||
@manager.new('lorem * dolor')
|
||||
def lorem():
|
||||
return Response(text = 'Lorem!', voice = 'Lorem!')
|
||||
|
||||
@manager.new('hello', hidden = True)
|
||||
def hello_context(**params):
|
||||
voice = text = f'Hi, {params["name"]}!'
|
||||
return Response(text = text, voice = voice)
|
||||
|
||||
@manager.new('bye', hidden = True)
|
||||
def bye_context(name: Word, handler: ResponseHandler):
|
||||
handler.pop_context()
|
||||
return Response(
|
||||
text = f'Bye, {name}!'
|
||||
)
|
||||
|
||||
@manager.new('hello $name:Word')
|
||||
def hello(name: Word):
|
||||
text = voice = f'Hello, {name}!'
|
||||
return Response(
|
||||
text = text,
|
||||
voice = voice,
|
||||
commands = [hello_context, bye_context],
|
||||
parameters = {'name': name}
|
||||
)
|
||||
|
||||
@manager.new('repeat')
|
||||
def repeat():
|
||||
return Response.repeat_last
|
||||
|
||||
# background commands
|
||||
|
||||
@manager.new('background min')
|
||||
@manager.background(Response(text = 'Starting background task', voice = 'Starting background task'))
|
||||
def background():
|
||||
text = voice = 'Finished background task'
|
||||
return Response(text = text, voice = voice)
|
||||
|
||||
@manager.new('background multiple responses')
|
||||
@manager.background(Response(text = 'Starting long background task'))
|
||||
def background_multiple_responses(handler: ResponseHandler):
|
||||
time.sleep(0.05)
|
||||
handler.process_response(Response(text = 'First response'))
|
||||
time.sleep(0.05)
|
||||
handler.process_response(Response(text = 'Second response'))
|
||||
time.sleep(0.05)
|
||||
text = voice = 'Finished long background task'
|
||||
return Response(text = text, voice = voice)
|
||||
|
||||
@manager.new('background needs input')
|
||||
@manager.background(Response(text = 'Starting long background task'))
|
||||
def background_needs_input(handler: ResponseHandler):
|
||||
time.sleep(0.01)
|
||||
|
||||
for text in ['First response', 'Second response', 'Third response']:
|
||||
handler.process_response(Response(text = text, voice = text))
|
||||
async def commands_context_flow():
|
||||
@contextlib.asynccontextmanager
|
||||
async def _commands_context_flow() -> AsyncGenerator[tuple[CommandsManager, CommandsContext, CommandsContextDelegateMock], None]:
|
||||
async with asyncer.create_task_group() as main_task_group:
|
||||
dependencies = DependencyManager()
|
||||
manager = CommandsManager()
|
||||
context = CommandsContext(main_task_group, manager, dependencies)
|
||||
context_delegate = CommandsContextDelegateMock()
|
||||
context.delegate = context_delegate
|
||||
|
||||
text = 'Needs input'
|
||||
handler.process_response(Response(text = text, voice = text, needs_user_input = True))
|
||||
|
||||
for text in ['Fourth response', 'Fifth response', 'Sixth response']:
|
||||
handler.process_response(Response(text = text, voice = text))
|
||||
|
||||
text = voice = 'Finished long background task'
|
||||
return Response(text = text, voice = voice)
|
||||
|
||||
@manager.new('background with context')
|
||||
@manager.background(Response(text = 'Starting long background task', voice = 'Starting long background task'))
|
||||
def background_multiple_contexts(handler: ResponseHandler):
|
||||
time.sleep(0.01)
|
||||
text = voice = 'Finished long background task'
|
||||
return Response(text = text, voice = voice, commands = [hello_context, bye_context], parameters = {'name': 'John'})
|
||||
|
||||
@manager.new('background remove response')
|
||||
@manager.background(Response(text = 'Starting long background task'))
|
||||
def background_remove_response(handler: ResponseHandler):
|
||||
time.sleep(0.01)
|
||||
response = Response(text = 'Deleted response', voice = 'Deleted response')
|
||||
handler.process_response(response)
|
||||
time.sleep(0.05)
|
||||
handler.remove_response(response)
|
||||
return None
|
||||
|
||||
return context, context_delegate
|
||||
assert len(context_delegate.responses) == 0
|
||||
assert len(context._context_queue) == 1
|
||||
|
||||
main_task_group.soonify(context.handle_responses)()
|
||||
yield (manager, context, context_delegate)
|
||||
context.stop()
|
||||
return _commands_context_flow
|
||||
|
||||
@pytest.fixture
|
||||
def voice_assistant(commands_context_flow_filled):
|
||||
async def commands_context_flow_filled(commands_context_flow):
|
||||
@contextlib.asynccontextmanager
|
||||
async def _commands_context_flow_filled() -> AsyncGenerator[tuple[CommandsContext, CommandsContextDelegateMock], None]:
|
||||
async with commands_context_flow() as (manager, context, context_delegate):
|
||||
|
||||
@manager.new('test')
|
||||
def test():
|
||||
return Response()
|
||||
|
||||
@manager.new('lorem * dolor')
|
||||
def lorem():
|
||||
return Response(text = 'Lorem!', voice = 'Lorem!')
|
||||
|
||||
@manager.new('hello', hidden = True)
|
||||
def hello_context(**params):
|
||||
voice = text = f'Hi, {params["name"]}!'
|
||||
return Response(text = text, voice = voice)
|
||||
|
||||
@manager.new('bye', hidden = True)
|
||||
def bye_context(name: Word, handler: ResponseHandler):
|
||||
handler.pop_context()
|
||||
return Response(
|
||||
text = f'Bye, {name}!'
|
||||
)
|
||||
|
||||
@manager.new('hello $name:Word')
|
||||
def hello(name: Word):
|
||||
text = voice = f'Hello, {name}!'
|
||||
return Response(
|
||||
text = text,
|
||||
voice = voice,
|
||||
commands = [hello_context, bye_context],
|
||||
parameters = {'name': name}
|
||||
)
|
||||
|
||||
@manager.new('repeat')
|
||||
def repeat():
|
||||
return Response.repeat_last
|
||||
|
||||
yield (context, context_delegate)
|
||||
|
||||
return _commands_context_flow_filled
|
||||
|
||||
@pytest.fixture
|
||||
async def voice_assistant(commands_context_flow_filled):
|
||||
context, _ = commands_context_flow_filled
|
||||
voice_assistant = VoiceAssistant(
|
||||
speech_recognizer = SpeechRecognizerMock(),
|
||||
@ -160,4 +119,5 @@ def voice_assistant(commands_context_flow_filled):
|
||||
commands_context = context
|
||||
)
|
||||
voice_assistant.start()
|
||||
return voice_assistant
|
||||
|
||||
yield voice_assistant
|
||||
|
@ -1,3 +1,8 @@
|
||||
import pytest
|
||||
|
||||
|
||||
pytestmark = pytest.mark.skip(reason = 'Background mode is deprecated')
|
||||
|
||||
|
||||
def test_background_command(commands_context_flow_filled):
|
||||
context, context_delegate = commands_context_flow_filled
|
||||
|
@ -2,7 +2,7 @@ import pytest
|
||||
from core import CommandsManager, Response
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
@pytest.mark.asyncio
|
||||
async def test_call_async_command_from_command():
|
||||
manager = CommandsManager()
|
||||
|
||||
|
@ -1,71 +1,81 @@
|
||||
import pytest
|
||||
import anyio
|
||||
|
||||
|
||||
def test_basic_search(commands_context_flow_filled):
|
||||
context, context_delegate = commands_context_flow_filled
|
||||
|
||||
assert len(context_delegate.responses) == 0
|
||||
assert len(context._context_queue) == 1
|
||||
|
||||
context.process_string('lorem ipsum dolor')
|
||||
assert len(context_delegate.responses) == 1
|
||||
assert context_delegate.responses[0].text == 'Lorem!'
|
||||
assert len(context._context_queue) == 1
|
||||
|
||||
def test_second_context_layer(commands_context_flow_filled):
|
||||
context, context_delegate = commands_context_flow_filled
|
||||
|
||||
context.process_string('hello world')
|
||||
assert len(context_delegate.responses) == 1
|
||||
assert context_delegate.responses[0].text == 'Hello, world!'
|
||||
assert len(context._context_queue) == 2
|
||||
context_delegate.responses.clear()
|
||||
|
||||
context.process_string('hello')
|
||||
assert len(context_delegate.responses) == 1
|
||||
assert context_delegate.responses[0].text == 'Hi, world!'
|
||||
assert len(context._context_queue) == 2
|
||||
context_delegate.responses.clear()
|
||||
|
||||
def test_context_pop_on_not_found(commands_context_flow_filled):
|
||||
context, context_delegate = commands_context_flow_filled
|
||||
|
||||
context.process_string('hello world')
|
||||
assert len(context._context_queue) == 2
|
||||
assert len(context_delegate.responses) == 1
|
||||
context_delegate.responses.clear()
|
||||
|
||||
context.process_string('lorem ipsum dolor')
|
||||
assert len(context._context_queue) == 1
|
||||
assert len(context_delegate.responses) == 1
|
||||
async def test_basic_search(commands_context_flow_filled, autojump_clock):
|
||||
async with commands_context_flow_filled() as (context, context_delegate):
|
||||
assert len(context_delegate.responses) == 0
|
||||
assert len(context._context_queue) == 1
|
||||
|
||||
context.process_string('lorem ipsum dolor')
|
||||
await anyio.sleep(5)
|
||||
assert len(context_delegate.responses) == 1
|
||||
assert context_delegate.responses[0].text == 'Lorem!'
|
||||
assert len(context._context_queue) == 1
|
||||
|
||||
def test_context_pop_context_response_action(commands_context_flow_filled):
|
||||
context, context_delegate = commands_context_flow_filled
|
||||
async def test_second_context_layer(commands_context_flow_filled, autojump_clock):
|
||||
async with commands_context_flow_filled() as (context, context_delegate):
|
||||
|
||||
context.process_string('hello world')
|
||||
assert len(context_delegate.responses) == 1
|
||||
assert context_delegate.responses[0].text == 'Hello, world!'
|
||||
assert len(context._context_queue) == 2
|
||||
context_delegate.responses.clear()
|
||||
context.process_string('hello world')
|
||||
await anyio.sleep(5)
|
||||
assert len(context_delegate.responses) == 1
|
||||
assert context_delegate.responses[0].text == 'Hello, world!'
|
||||
assert len(context._context_queue) == 2
|
||||
context_delegate.responses.clear()
|
||||
|
||||
context.process_string('hello')
|
||||
await anyio.sleep(5)
|
||||
assert len(context_delegate.responses) == 1
|
||||
assert context_delegate.responses[0].text == 'Hi, world!'
|
||||
assert len(context._context_queue) == 2
|
||||
context_delegate.responses.clear()
|
||||
|
||||
context.process_string('bye')
|
||||
assert len(context_delegate.responses) == 1
|
||||
assert context_delegate.responses[0].text == 'Bye, world!'
|
||||
assert len(context._context_queue) == 1
|
||||
context_delegate.responses.clear()
|
||||
async def test_context_pop_on_not_found(commands_context_flow_filled, autojump_clock):
|
||||
async with commands_context_flow_filled() as (context, context_delegate):
|
||||
|
||||
context.process_string('hello')
|
||||
assert len(context_delegate.responses) == 0
|
||||
context.process_string('hello world')
|
||||
await anyio.sleep(5)
|
||||
assert len(context._context_queue) == 2
|
||||
assert len(context_delegate.responses) == 1
|
||||
context_delegate.responses.clear()
|
||||
|
||||
context.process_string('lorem ipsum dolor')
|
||||
await anyio.sleep(5)
|
||||
assert len(context._context_queue) == 1
|
||||
assert len(context_delegate.responses) == 1
|
||||
|
||||
async def test_context_pop_context_response_action(commands_context_flow_filled, autojump_clock):
|
||||
async with commands_context_flow_filled() as (context, context_delegate):
|
||||
|
||||
context.process_string('hello world')
|
||||
await anyio.sleep(5)
|
||||
assert len(context_delegate.responses) == 1
|
||||
assert context_delegate.responses[0].text == 'Hello, world!'
|
||||
assert len(context._context_queue) == 2
|
||||
context_delegate.responses.clear()
|
||||
|
||||
context.process_string('bye')
|
||||
await anyio.sleep(5)
|
||||
assert len(context_delegate.responses) == 1
|
||||
assert context_delegate.responses[0].text == 'Bye, world!'
|
||||
assert len(context._context_queue) == 1
|
||||
context_delegate.responses.clear()
|
||||
|
||||
context.process_string('hello')
|
||||
await anyio.sleep(5)
|
||||
assert len(context_delegate.responses) == 0
|
||||
|
||||
def test_repeat_last_answer_response_action(commands_context_flow_filled):
|
||||
context, context_delegate = commands_context_flow_filled
|
||||
async def test_repeat_last_answer_response_action(commands_context_flow_filled, autojump_clock):
|
||||
async with commands_context_flow_filled() as (context, context_delegate):
|
||||
|
||||
context.process_string('hello world')
|
||||
assert len(context_delegate.responses) == 1
|
||||
assert context_delegate.responses[0].text == 'Hello, world!'
|
||||
context_delegate.responses.clear()
|
||||
assert len(context_delegate.responses) == 0
|
||||
|
||||
context.process_string('repeat')
|
||||
assert len(context_delegate.responses) == 1
|
||||
assert context_delegate.responses[0].text == 'Hello, world!'
|
||||
context.process_string('hello world')
|
||||
await anyio.sleep(5)
|
||||
assert len(context_delegate.responses) == 1
|
||||
assert context_delegate.responses[0].text == 'Hello, world!'
|
||||
context_delegate.responses.clear()
|
||||
assert len(context_delegate.responses) == 0
|
||||
|
||||
context.process_string('repeat')
|
||||
await anyio.sleep(5)
|
||||
assert len(context_delegate.responses) == 1
|
||||
assert context_delegate.responses[0].text == 'Hello, world!'
|
||||
|
@ -125,4 +125,3 @@ def test_objects_parse_caching(commands_context_flow):
|
||||
assert Mock.parsing_counter == 1
|
||||
manager.search('hello foobar 22')
|
||||
assert Mock.parsing_counter == 2
|
||||
|
@ -1,7 +1,10 @@
|
||||
import pytest
|
||||
from datetime import timedelta
|
||||
from voice_assistant import Mode
|
||||
|
||||
|
||||
pytestmark = pytest.mark.skip(reason = 'Background mode is deprecated. TODO: test VA modes with new concurrency approach')
|
||||
|
||||
def test_background_command(voice_assistant):
|
||||
voice_assistant.speech_recognizer_did_receive_final_result('background min')
|
||||
|
||||
@ -165,4 +168,4 @@ def test_background_waiting_remove_response(voice_assistant):
|
||||
# interact to reset timeout mode, check that removed response is not repeated
|
||||
voice_assistant.speech_recognizer_did_receive_final_result('hello world')
|
||||
assert len(voice_assistant.speech_synthesizer.results) == 1
|
||||
assert voice_assistant.speech_synthesizer.results.pop(0).text == 'Hello, world!'
|
||||
assert voice_assistant.speech_synthesizer.results.pop(0).text == 'Hello, world!'
|
Loading…
x
Reference in New Issue
Block a user