From 7a2e6a0f0a7366adbf4e6a794dd7ffce2459d292 Mon Sep 17 00:00:00 2001 From: Mark Parker Date: Wed, 20 Sep 2023 09:59:36 +0200 Subject: [PATCH] fix imports --- .gitignore | 1 + docs/advanced/custom-run.md | 5 +-- .../fallback-command-llm-integration.md | 2 +- docs/first-steps.md | 5 +-- docs/patterns.md | 2 +- pyproject.toml | 1 - stark/__init__.py | 21 ++++++++++-- stark/core/__init__.py | 15 ++------- stark/core/command.py | 2 +- stark/core/commands_context.py | 3 +- stark/core/patterns/pattern.py | 2 +- stark/core/types/object.py | 2 +- stark/examples/keyboard_hotkey.py | 32 ------------------- stark/voice_assistant/mode.py | 2 +- stark/voice_assistant/voice_assistant.py | 13 +++++--- tests/conftest.py | 15 ++++++--- tests/test_commands/test_async_command.py | 7 ++-- tests/test_commands/test_sync_command.py | 7 ++-- ...st_commands_context_generators_handling.py | 2 +- ...st_commands_context_inject_dependencies.py | 2 +- .../test_commands_context_respond.py | 4 +-- .../test_commands_manager.py | 3 +- .../test_multiple_commands.py | 5 +-- .../test_patterns/test_pattern_parameters.py | 7 ++-- tests/test_patterns/test_patterns.py | 4 +-- tests/test_va_modes.py | 2 +- tests/test_viobjects/test_complex_parsing.py | 5 +-- tests/test_viobjects/test_nested_viobjects.py | 13 ++++---- tests/test_viobjects/test_vistring.py | 3 +- tests/test_viobjects/test_viword.py | 3 +- 30 files changed, 93 insertions(+), 97 deletions(-) delete mode 100644 stark/examples/keyboard_hotkey.py diff --git a/.gitignore b/.gitignore index 434259f..5a34a80 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ downloads/ site/ .DS_Store +test.py diff --git a/docs/advanced/custom-run.md b/docs/advanced/custom-run.md index 125e908..a2c424a 100644 --- a/docs/advanced/custom-run.md +++ b/docs/advanced/custom-run.md @@ -124,7 +124,8 @@ To kickstart your customization, replicate the default run function as your foun import asyncer from stark import CommandsContext, CommandsManager, Response from stark.interfaces.protocols import SpeechRecognizer, SpeechSynthesizer -from stark.interfaces import VoskSpeechRecognizer, SileroSpeechSynthesizer +from stark.interfaces.vosk import VoskSpeechRecognizer +from stark.interfaces.silero import SileroSpeechSynthesizer from stark.voice_assistant import VoiceAssistant from stark.general.blockage_detector import BlockageDetector @@ -170,5 +171,5 @@ async def main(): await run(manager, recognizer, synthesizer) if __name__ == '__main__': - asyncer.runnify(main)() # or anyio.run(main()), same thing + asyncer.runnify(main)() # or anyio.run(main), same thing ``` diff --git a/docs/advanced/fallback-command-llm-integration.md b/docs/advanced/fallback-command-llm-integration.md index 78ce0f4..e5218a6 100644 --- a/docs/advanced/fallback-command-llm-integration.md +++ b/docs/advanced/fallback-command-llm-integration.md @@ -15,7 +15,7 @@ CommandsContext.fallback_command: Command Here's a practical example: ```python -from stark.types import String +from stark.core.types import String ... @manager.new('$string:String', hidden=True) diff --git a/docs/first-steps.md b/docs/first-steps.md index 4aac43d..aef8a04 100644 --- a/docs/first-steps.md +++ b/docs/first-steps.md @@ -16,7 +16,8 @@ At the heart of STARK is the `CommandsManager`, a component dedicated to managin ```py import anyio from stark import run, CommandsManager, Response -from stark.interfaces import VoskSpeechRecognizer, SileroSpeechSynthesizer +from stark.interfaces.vosk import VoskSpeechRecognizer +from stark.interfaces.silero import SileroSpeechSynthesizer VOSK_MODEL_URL = "YOUR_CHOSEN_VOSK_MODEL_URL" @@ -36,7 +37,7 @@ async def main(): await run(manager, recognizer, synthesizer) if __name__ == '__main__': - anyio.run(main()) + anyio.run(main) ``` In this code snippet, we defined a new command for the voice assistant. When the word "hello" is spoken, the `hello_command` function is triggered, which then issues a greeting in response. diff --git a/docs/patterns.md b/docs/patterns.md index 7b22000..cf85068 100644 --- a/docs/patterns.md +++ b/docs/patterns.md @@ -39,7 +39,7 @@ However, ensure that the function declaration tied to a command pattern includes Here's an example: ```python -from stark.types import Word +from stark.core.types import Word @manager.new('Hello $name:Word') async def example_function(name: Word) -> Response: diff --git a/pyproject.toml b/pyproject.toml index 3ce4452..a74c41d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,7 +47,6 @@ requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" [tool.pytest.ini_options] -pythonpath = ["stark",] # asyncio_mode = "auto" trio_mode = "true" filterwarnings = [ diff --git a/stark/__init__.py b/stark/__init__.py index 50c4a26..414eb95 100644 --- a/stark/__init__.py +++ b/stark/__init__.py @@ -1,8 +1,23 @@ import asyncer -from stark.interfaces.protocols import SpeechRecognizer, SpeechSynthesizer -from stark.core import CommandsContext, CommandsManager -from stark.voice_assistant import VoiceAssistant +from stark.interfaces.protocols import ( + SpeechRecognizer, + SpeechRecognizerDelegate, + SpeechSynthesizer, + SpeechSynthesizerResult +) +from stark.core import ( + Command, + Pattern, + Response, + ResponseStatus, + CommandsContext, + CommandsManager +) +from stark.voice_assistant import ( + VoiceAssistant, + Mode +) from stark.general.blockage_detector import BlockageDetector diff --git a/stark/core/__init__.py b/stark/core/__init__.py index defeabf..42ab5b4 100644 --- a/stark/core/__init__.py +++ b/stark/core/__init__.py @@ -1,14 +1,5 @@ from .patterns import Pattern, expressions -from .types import ( - ParseError, - ParseResult, - Object, - String, - Word, - # Number, - # TimeInterval - # Time, -) +from . import types from .command import ( Command, Response, @@ -26,5 +17,5 @@ ) -Pattern.add_parameter_type(String) -Pattern.add_parameter_type(Word) +Pattern.add_parameter_type(types.String) +Pattern.add_parameter_type(types.Word) diff --git a/stark/core/command.py b/stark/core/command.py index 52c0bfc..821bc03 100644 --- a/stark/core/command.py +++ b/stark/core/command.py @@ -10,7 +10,7 @@ from pydantic import BaseModel, Field import asyncer -from general.classproperty import classproperty +from ..general.classproperty import classproperty from .patterns import Pattern diff --git a/stark/core/commands_context.py b/stark/core/commands_context.py index 12a9ccd..a3e9aff 100644 --- a/stark/core/commands_context.py +++ b/stark/core/commands_context.py @@ -3,11 +3,12 @@ from typing import Any, Protocol, runtime_checkable from dataclasses import dataclass import warnings + import anyio from asyncer import syncify from asyncer._main import TaskGroup -from general.dependencies import DependencyManager, default_dependency_manager +from ..general.dependencies import DependencyManager, default_dependency_manager from .commands_manager import CommandsManager, SearchResult from .command import Command, Response, ResponseHandler, AsyncResponseHandler, CommandRunner, ResponseOptions diff --git a/stark/core/patterns/pattern.py b/stark/core/patterns/pattern.py index dd4f6d6..c968fa1 100644 --- a/stark/core/patterns/pattern.py +++ b/stark/core/patterns/pattern.py @@ -6,7 +6,7 @@ from .expressions import dictionary if TYPE_CHECKING: - from core import Object, ParseResult + from ..types import Object, ParseResult ObjectType: TypeAlias = Type[Object] diff --git a/stark/core/types/object.py b/stark/core/types/object.py index bb433f8..f53f0d1 100644 --- a/stark/core/types/object.py +++ b/stark/core/types/object.py @@ -4,7 +4,7 @@ from abc import ABC import copy -from general.classproperty import classproperty +from stark.general.classproperty import classproperty from .. import Pattern diff --git a/stark/examples/keyboard_hotkey.py b/stark/examples/keyboard_hotkey.py deleted file mode 100644 index f7a2632..0000000 --- a/stark/examples/keyboard_hotkey.py +++ /dev/null @@ -1,32 +0,0 @@ -# import os -# from pynput.keyboard import Key, Listener - -# from stark.core import CommandsContext -# from stark.voice_assistant import VoiceAssistant, Mode -# from stark.IO.VoskSpeechRecognizer import VoskSpeechRecognizer -# from stark.IO.SileroSpeechSynthesizer import SileroSpeechSynthesizer -# from stark.features import default - - -# cm = CommandsContext(commands_manager = default) -# va = VoiceAssistant( -# speech_recognizer = VoskSpeechRecognizer(), -# speech_synthesizer = SileroSpeechSynthesizer(), -# commands_context = cm -# ) -# va.mode = Mode(stop_after_interaction = True) # Wait for the hotkey to be pressed again - -# def on_release(key: Key): -# if key == Key.alt_r: -# ''' -# optional: play a sound to indicate that the hotkey was pressed -# play all sounds in macos: sh`for s in /System/Library/Sounds/*; do echo "$s" && afplay "$s"; done` -# for linux: check the `/usr/share/sounds/` directory and use `aplay` instead of `afplay` - -# as an alternative, you can use the SpeechSynthesizer to say something like "Yes, sir?" -# ''' -# os.system('afplay /System/Library/Sounds/Hero.aiff &') # play the sound in the background (macos) -# va.start() - -# listener = Listener(on_release = on_release) -# listener.start() diff --git a/stark/voice_assistant/mode.py b/stark/voice_assistant/mode.py index fd13583..0f64c4c 100644 --- a/stark/voice_assistant/mode.py +++ b/stark/voice_assistant/mode.py @@ -1,7 +1,7 @@ from __future__ import annotations from typing import Optional, Callable from pydantic import BaseModel -from general.classproperty import classproperty +from ..general.classproperty import classproperty class Mode(BaseModel): diff --git a/stark/voice_assistant/voice_assistant.py b/stark/voice_assistant/voice_assistant.py index 70db5bf..1b793c9 100644 --- a/stark/voice_assistant/voice_assistant.py +++ b/stark/voice_assistant/voice_assistant.py @@ -1,6 +1,7 @@ +from typing import cast from datetime import datetime -from core import ( +from ..core import ( CommandsContext, CommandsContextLayer, CommandsContextDelegate, @@ -8,7 +9,7 @@ ResponseStatus, Pattern ) -from interfaces.protocols import SpeechRecognizer, SpeechRecognizerDelegate, SpeechSynthesizer +from ..interfaces.protocols import SpeechRecognizer, SpeechRecognizerDelegate, SpeechSynthesizer from .mode import Mode @@ -29,6 +30,10 @@ class VoiceAssistant(SpeechRecognizerDelegate, CommandsContextDelegate): _last_interaction_time: datetime def __init__(self, speech_recognizer: SpeechRecognizer, speech_synthesizer: SpeechSynthesizer, commands_context: CommandsContext): + assert isinstance(speech_recognizer, SpeechRecognizer) + assert isinstance(speech_synthesizer, SpeechSynthesizer) + assert isinstance(commands_context, CommandsContext) + self.speech_recognizer = speech_recognizer self.speech_synthesizer = speech_synthesizer self.commands_context = commands_context @@ -110,11 +115,11 @@ async def commands_context_did_receive_response(self, response: Response): break else: if self.mode.stop_after_interaction: - self.stop() + self.speech_recognizer.stop_listening() def remove_response(self, response: Response): if response in self._responses: - self._responses.remove(response) + self._responses.remove(cast(ResponseCache, response)) # Private diff --git a/tests/conftest.py b/tests/conftest.py index c289451..51f6671 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,8 +4,8 @@ import pytest import asyncer import anyio -from general.dependencies import DependencyManager -from core import ( +from stark.general.dependencies import DependencyManager +from stark.core import ( CommandsManager, CommandsContext, CommandsContextDelegate, @@ -13,8 +13,9 @@ ResponseHandler, AsyncResponseHandler ) -from core.types import Word -from voice_assistant import VoiceAssistant +from stark.core.types import Word +from stark.interfaces.protocols import SpeechRecognizerDelegate +from stark.voice_assistant import VoiceAssistant class CommandsContextDelegateMock(CommandsContextDelegate): @@ -27,10 +28,14 @@ def __init__(self): async def commands_context_did_receive_response(self, response: Response): self.responses.append(response) + async def remove_response(self, response: Response): + self.responses.remove(response) + class SpeechRecognizerMock: is_recognizing: bool = False + delegate: SpeechRecognizerDelegate | None = None - def start_listening(self): pass + async def start_listening(self): pass def stop_listening(self): pass class SpeechSynthesizerResultMock: diff --git a/tests/test_commands/test_async_command.py b/tests/test_commands/test_async_command.py index e9159ee..51390db 100644 --- a/tests/test_commands/test_async_command.py +++ b/tests/test_commands/test_async_command.py @@ -1,5 +1,6 @@ +from typing import AsyncGenerator import pytest -from core import CommandsManager, Response, ResponseHandler, AsyncResponseHandler +from stark.core import CommandsManager, Response, ResponseHandler, AsyncResponseHandler async def test_create_run_async_command(): @@ -43,7 +44,7 @@ async def test_async_command_generator_yielding_response(): manager = CommandsManager() @manager.new('foo') - async def foo() -> Response: + async def foo() -> AsyncGenerator[Response, None]: yield Response(text = 'foo!') i = 0 @@ -56,7 +57,7 @@ async def test_async_command_generator_multiple_yielding_response(): manager = CommandsManager() @manager.new('foo') - async def foo() -> Response: + async def foo() -> AsyncGenerator[Response, None]: yield Response(text = 'foo!') yield Response(text = 'bar!') yield Response(text = 'baz!') diff --git a/tests/test_commands/test_sync_command.py b/tests/test_commands/test_sync_command.py index 07ac009..d92e35a 100644 --- a/tests/test_commands/test_sync_command.py +++ b/tests/test_commands/test_sync_command.py @@ -1,7 +1,8 @@ +from typing import Generator import warnings import pytest from asyncer import syncify -from core import CommandsManager, Response, ResponseHandler, AsyncResponseHandler +from stark.core import CommandsManager, Response, ResponseHandler, AsyncResponseHandler async def test_create_await_run_sync_command(): @@ -80,7 +81,7 @@ async def test_sync_command_generator_yielding_response(): with warnings.catch_warnings(record = True) as warnings_list: @manager.new('foo') - def foo() -> Response: + def foo() -> Generator[Response, None, None]: yield Response(text = 'foo!') assert next(await foo()).text == 'foo!' @@ -94,7 +95,7 @@ async def test_sync_command_generator_multiple_yielding_response(): with warnings.catch_warnings(record = True) as warnings_list: @manager.new('foo') - def foo() -> Response: + def foo() -> Generator[Response, None, None]: yield Response(text = 'foo!') yield Response(text = 'bar!') yield Response(text = 'baz!') diff --git a/tests/test_commands_flow/test_commands_context_generators_handling.py b/tests/test_commands_flow/test_commands_context_generators_handling.py index 753e31c..7b874bc 100644 --- a/tests/test_commands_flow/test_commands_context_generators_handling.py +++ b/tests/test_commands_flow/test_commands_context_generators_handling.py @@ -1,7 +1,7 @@ import warnings import pytest import anyio -from core import Response +from stark.core import Response async def test_commands_context_handle_async_generator(commands_context_flow, autojump_clock): diff --git a/tests/test_commands_flow/test_commands_context_inject_dependencies.py b/tests/test_commands_flow/test_commands_context_inject_dependencies.py index f2fea05..53a5a10 100644 --- a/tests/test_commands_flow/test_commands_context_inject_dependencies.py +++ b/tests/test_commands_flow/test_commands_context_inject_dependencies.py @@ -1,5 +1,5 @@ import anyio -from core import AsyncResponseHandler, Response +from stark.core import AsyncResponseHandler, Response async def test_commands_context_inject_dependencies(commands_context_flow, autojump_clock): diff --git a/tests/test_commands_flow/test_commands_context_respond.py b/tests/test_commands_flow/test_commands_context_respond.py index c124c0c..be38905 100644 --- a/tests/test_commands_flow/test_commands_context_respond.py +++ b/tests/test_commands_flow/test_commands_context_respond.py @@ -1,7 +1,7 @@ import pytest import warnings import anyio -from core import Response, ResponseHandler, AsyncResponseHandler +from stark.core import Response, ResponseHandler, AsyncResponseHandler async def test_command_return_response(commands_context_flow, autojump_clock): @@ -51,7 +51,7 @@ async def test_sync_command_call_async_respond(commands_context_flow, autojump_c def foo(handler: AsyncResponseHandler): with warnings.catch_warnings(record = True) as warnings_list: assert len(warnings_list) == 0 - handler.respond(Response(text = 'foo!')) + handler.respond(Response(text = 'foo!')) # type: ignore assert len(warnings_list) == 1 assert issubclass(warnings_list[0].category, RuntimeWarning) assert 'was never awaited' in str(warnings_list[0].message) diff --git a/tests/test_commands_flow/test_commands_manager.py b/tests/test_commands_flow/test_commands_manager.py index b0d5f8b..f4870fb 100644 --- a/tests/test_commands_flow/test_commands_manager.py +++ b/tests/test_commands_flow/test_commands_manager.py @@ -1,6 +1,7 @@ import re import pytest -from core import CommandsManager, Word +from stark.core import CommandsManager +from stark.core.types import Word def test_new(): diff --git a/tests/test_commands_flow/test_multiple_commands.py b/tests/test_commands_flow/test_multiple_commands.py index 2589667..1c7b1af 100644 --- a/tests/test_commands_flow/test_multiple_commands.py +++ b/tests/test_commands_flow/test_multiple_commands.py @@ -1,7 +1,8 @@ import pytest import anyio -from core import Object, Pattern, Response, CommandsManager -from general.classproperty import classproperty +from stark.core import Pattern, Response, CommandsManager +from stark.core.types import Object +from stark.general.classproperty import classproperty import random diff --git a/tests/test_patterns/test_pattern_parameters.py b/tests/test_patterns/test_pattern_parameters.py index c23351d..e3ec8f8 100644 --- a/tests/test_patterns/test_pattern_parameters.py +++ b/tests/test_patterns/test_pattern_parameters.py @@ -1,8 +1,9 @@ import re import pytest -from core import Pattern, Object, Word, String -from core.patterns import expressions -from general.classproperty import classproperty +from stark.core import Pattern +from stark.core.types import Object, Word, String +from stark.core.patterns import expressions +from stark.general.classproperty import classproperty word = fr'[{expressions.alphanumerics}]*' diff --git a/tests/test_patterns/test_patterns.py b/tests/test_patterns/test_patterns.py index 44a124e..af35bd9 100644 --- a/tests/test_patterns/test_patterns.py +++ b/tests/test_patterns/test_patterns.py @@ -1,5 +1,5 @@ -from core import Pattern -from core.patterns import expressions +from stark.core import Pattern +from stark.core.patterns import expressions word = fr'[{expressions.alphanumerics}]*' diff --git a/tests/test_va_modes.py b/tests/test_va_modes.py index 82ce9e6..384c57f 100644 --- a/tests/test_va_modes.py +++ b/tests/test_va_modes.py @@ -1,7 +1,7 @@ import pytest import anyio from datetime import timedelta -from voice_assistant import Mode +from stark.voice_assistant import Mode async def test_background_command_with_waiting_mode(voice_assistant, autojump_clock): diff --git a/tests/test_viobjects/test_complex_parsing.py b/tests/test_viobjects/test_complex_parsing.py index 9b9035b..f4eae34 100644 --- a/tests/test_viobjects/test_complex_parsing.py +++ b/tests/test_viobjects/test_complex_parsing.py @@ -1,7 +1,8 @@ import pytest -from core import Pattern, Object, ParseError -from general.classproperty import classproperty +from stark.core import Pattern +from stark.core.types import Object, ParseError +from stark.general.classproperty import classproperty class Lorem(Object): diff --git a/tests/test_viobjects/test_nested_viobjects.py b/tests/test_viobjects/test_nested_viobjects.py index f220c01..6bafcc3 100644 --- a/tests/test_viobjects/test_nested_viobjects.py +++ b/tests/test_viobjects/test_nested_viobjects.py @@ -1,6 +1,7 @@ import pytest -from core import Object, Word, Pattern -from general.classproperty import classproperty +from stark.core import Pattern +from stark.core.types import Object, Word +from stark.general.classproperty import classproperty class FullName(Object): @@ -12,9 +13,9 @@ def pattern(cls) -> Pattern: return Pattern('$first:Word $second:Word') class ExtraParameterInAnnotation(Object): - word1: Word = None - word2: Word = None - word3: Word = None + word1: Word + word2: Word + word3: Word @classproperty def pattern(cls) -> Pattern: @@ -45,4 +46,4 @@ async def test_extra_parameter_in_annotation(): assert set(m[0].parameters.keys()) == {'name'} assert m[0].parameters['name'].word1 == Word('John') assert m[0].parameters['name'].word2 == Word('Galt') - assert m[0].parameters['name'].word3 == None \ No newline at end of file + assert not hasattr(m[0].parameters['name'], 'word3') diff --git a/tests/test_viobjects/test_vistring.py b/tests/test_viobjects/test_vistring.py index d67b31f..71054f8 100644 --- a/tests/test_viobjects/test_vistring.py +++ b/tests/test_viobjects/test_vistring.py @@ -1,4 +1,5 @@ -from core import String, Pattern +from stark.core import Pattern +from stark.core.types import String def test_pattern(): diff --git a/tests/test_viobjects/test_viword.py b/tests/test_viobjects/test_viword.py index fafa432..96fbba1 100644 --- a/tests/test_viobjects/test_viword.py +++ b/tests/test_viobjects/test_viword.py @@ -1,4 +1,5 @@ -from core import Word, Pattern +from stark.core import Pattern +from stark.core.types import Word def test_pattern():