Merge pull request #988 from Pythagora-io/console-input

console ui: add multiline, readline, paste, initial/default text support
This commit is contained in:
LeonOstrez
2024-06-03 19:12:55 +01:00
committed by GitHub
4 changed files with 30 additions and 13 deletions

View File

@@ -11,7 +11,7 @@ from core.llm.base import APIError, BaseLLMClient
from core.log import get_logger
from core.state.state_manager import StateManager
from core.telemetry import telemetry
from core.ui.base import UIBase, UIClosedError, pythagora_source
from core.ui.base import UIBase, UIClosedError, UserInput, pythagora_source
log = get_logger(__name__)
@@ -112,7 +112,15 @@ async def start_new_project(sm: StateManager, ui: UIBase) -> bool:
:param ui: User interface.
:return: True if the project was created successfully, False otherwise.
"""
user_input = await ui.ask_question("What is the project name?", allow_empty=False, source=pythagora_source)
try:
user_input = await ui.ask_question(
"What is the project name?",
allow_empty=False,
source=pythagora_source,
)
except (KeyboardInterrupt, UIClosedError):
user_input = UserInput(cancelled=True)
if user_input.cancelled:
return False

View File

@@ -1,5 +1,7 @@
from typing import Optional
from prompt_toolkit.shortcuts import PromptSession
from core.log import get_logger
from core.ui.base import ProjectStage, UIBase, UIClosedError, UISource, UserInput
@@ -57,9 +59,12 @@ class PlainConsoleUI(UIBase):
default_str = " (default)" if k == default else ""
print(f" [{k}]: {v}{default_str}")
session = PromptSession("> ")
while True:
try:
choice = input("> ").strip()
choice = await session.prompt_async(default=initial_text or "")
choice = choice.strip()
except KeyboardInterrupt:
raise UIClosedError()
if not choice and default:

View File

@@ -37,6 +37,7 @@ psutil = "^5.9.8"
httpx = "^0.27.0"
alembic = "^1.13.1"
python-dotenv = "^1.0.1"
prompt-toolkit = "^3.0.45"
[tool.poetry.group.dev.dependencies]
pytest = "^8.1.1"

View File

@@ -1,4 +1,4 @@
from unittest.mock import patch
from unittest.mock import AsyncMock, patch
import pytest
@@ -35,8 +35,9 @@ async def test_stream(capsys):
@pytest.mark.asyncio
@patch("builtins.input", return_value="awesome")
async def test_ask_question_simple(mock_input):
@patch("core.ui.console.PromptSession")
async def test_ask_question_simple(mock_PromptSession):
prompt_async = mock_PromptSession.return_value.prompt_async = AsyncMock(return_value="awesome")
ui = PlainConsoleUI()
await ui.start()
@@ -48,12 +49,13 @@ async def test_ask_question_simple(mock_input):
await ui.stop()
mock_input.assert_called_once()
prompt_async.assert_awaited_once()
@pytest.mark.asyncio
@patch("builtins.input", return_value="yes")
async def test_ask_question_with_buttons(mock_input):
@patch("core.ui.console.PromptSession")
async def test_ask_question_with_buttons(mock_PromptSession):
prompt_async = mock_PromptSession.return_value.prompt_async = AsyncMock(return_value="yes")
ui = PlainConsoleUI()
await ui.start()
@@ -68,12 +70,13 @@ async def test_ask_question_with_buttons(mock_input):
await ui.stop()
mock_input.assert_called_once()
prompt_async.assert_awaited_once()
@pytest.mark.asyncio
@patch("builtins.input", side_effect=KeyboardInterrupt())
async def test_ask_question_interrupted(mock_input):
@patch("core.ui.console.PromptSession")
async def test_ask_question_interrupted(mock_PromptSession):
prompt_async = mock_PromptSession.return_value.prompt_async = AsyncMock(side_effect=KeyboardInterrupt)
ui = PlainConsoleUI()
await ui.start()
@@ -82,4 +85,4 @@ async def test_ask_question_interrupted(mock_input):
await ui.stop()
mock_input.assert_called_once()
prompt_async.assert_awaited_once()