diff --git a/gptme/util/cli.py b/gptme/util/cli.py index 4a018c0f..3bdc52b3 100644 --- a/gptme/util/cli.py +++ b/gptme/util/cli.py @@ -89,7 +89,7 @@ def tokens_count(text: str | None, model: str, file: str | None): except KeyError: print(f"Error: Model '{model}' not supported by tiktoken.") print("Supported models include: gpt-4, gpt-3.5-turbo, text-davinci-003") - return 1 + sys.exit(1) # Count tokens tokens = enc.encode(text) @@ -167,7 +167,7 @@ def tools_info(tool_name: str): print(f"Tool '{tool_name}' not found. Available tools:") for t in loaded_tools: print(f"- {t.name}") - return + sys.exit(1) print(f"Tool: {tool.name}") print(f"Description: {tool.desc}") diff --git a/poetry.lock b/poetry.lock index 19bc564e..03d87082 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2497,6 +2497,23 @@ files = [ pytest = ">=5.0.0" python-dotenv = ">=0.9.1" +[[package]] +name = "pytest-mock" +version = "3.14.0" +description = "Thin-wrapper around the mock package for easier use with pytest" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0"}, + {file = "pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f"}, +] + +[package.dependencies] +pytest = ">=6.2.5" + +[package.extras] +dev = ["pre-commit", "pytest-asyncio", "tox"] + [[package]] name = "pytest-profiling" version = "1.7.0" @@ -3531,4 +3548,4 @@ server = ["flask", "flask-cors"] [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "80aab1874f6f188bce645324628fd642236c7fff2859b6acbd242b790ab561e6" +content-hash = "fc6e6adb9c74703fa2abf164f432eb9006fc2da17b9ab1179836395439492823" diff --git a/pyproject.toml b/pyproject.toml index 79012b3f..8fddbe64 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -70,6 +70,7 @@ pytest-profiling = "^1.7.0" pytest-dotenv = "^0.5.2" pytest-timeout = "^2.2.0" pytest-retry = "^1.6.3" +pytest-mock = "*" greenlet = "*" # dependency of playwright, but needed for coverage # docs diff --git a/tests/test_util_cli.py b/tests/test_util_cli.py index 9c1c7528..bff9df3d 100644 --- a/tests/test_util_cli.py +++ b/tests/test_util_cli.py @@ -32,35 +32,68 @@ def test_tokens_count(): assert "Token count" in result.output -def test_chats_list(mocker): +def test_chats_list(tmp_path, mocker): """Test the chats list command.""" runner = CliRunner() - # Test empty list - mocker.patch("gptme.util.cli.get_user_conversations", return_value=[]) + # Create test conversations + logs_dir = tmp_path / "logs" + logs_dir.mkdir() + + # Mock both the logs directory and the conversation listing + mocker.patch("gptme.dirs.get_logs_dir", return_value=str(logs_dir)) + mocker.patch("gptme.logmanager.get_user_conversations", return_value=[]) + + # Test empty list (should work now since we're using our empty logs_dir) result = runner.invoke(main, ["chats", "ls"]) assert result.exit_code == 0 assert "No conversations found" in result.output - # Test with conversations - class MockConv: - def __init__(self, name, messages, modified): - self.name = name - self.messages = messages - self.modified = modified - - mock_convs = [ - MockConv("test-1", 5, "2024-01-01"), - MockConv("test-2", 10, "2024-01-02"), - ] - mocker.patch("gptme.util.cli.get_user_conversations", return_value=mock_convs) + # Create test conversation files with names that won't be filtered + conv1_dir = logs_dir / "2024-01-01-chat-one" + conv1_dir.mkdir() + (conv1_dir / "conversation.jsonl").write_text( + '{"role": "user", "content": "hello", "timestamp": "2024-01-01T00:00:00"}\n' + ) + + conv2_dir = logs_dir / "2024-01-01-chat-two" + conv2_dir.mkdir() + (conv2_dir / "conversation.jsonl").write_text( + '{"role": "user", "content": "hello", "timestamp": "2024-01-01T00:00:00"}\n' + '{"role": "assistant", "content": "hi", "timestamp": "2024-01-01T00:00:01"}\n' + ) + # Create ConversationMeta objects for our test conversations + from gptme.logmanager import ConversationMeta + import time + + conv1 = ConversationMeta( + name="2024-01-01-chat-one", + path=str(conv1_dir / "conversation.jsonl"), + created=time.time(), + modified=time.time(), + messages=1, + branches=1, + ) + conv2 = ConversationMeta( + name="2024-01-01-chat-two", + path=str(conv2_dir / "conversation.jsonl"), + created=time.time(), + modified=time.time(), + messages=2, + branches=1, + ) + + # Update the mock to return our test conversations + mocker.patch("gptme.logmanager.get_user_conversations", return_value=[conv1, conv2]) + + # Test with conversations result = runner.invoke(main, ["chats", "ls"]) assert result.exit_code == 0 - assert "test-1" in result.output - assert "test-2" in result.output - assert "5 messages" in result.output - assert "10 messages" in result.output + assert "chat-one" in result.output + assert "chat-two" in result.output + assert "Messages: 1" in result.output # First chat has 1 message + assert "Messages: 2" in result.output # Second chat has 2 messages @pytest.mark.skip("Waiting for context module PR")