diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml new file mode 100644 index 0000000..981aaf8 --- /dev/null +++ b/.github/workflows/test-python.yml @@ -0,0 +1,39 @@ +name: Test Python + +on: + push: + branches: + - main + pull_request: + +permissions: + contents: read # Required to checkout repository + +jobs: + pytest: + name: Pytest + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.13"] + steps: + - name: Checkout repository + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + persist-credentials: false + + - name: Set up Python + uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 + with: + python-version: ${{ matrix.python-version }} + + - name: Install a specific version of uv + uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4 + with: + version: "latest" + + - name: Install dependencies + run: uv sync + + - name: Run pytest + run: uv run pytest --verbose diff --git a/pyproject.toml b/pyproject.toml index cddf5cc..1fa3bef 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,3 +33,7 @@ build-backend = "hatchling.build" [tool.hatch.build.targets.wheel] packages = ["src/geo_assistant"] + +[tool.pytest.ini_options] +addopts = "--color=yes" +asyncio_mode = "auto" diff --git a/src/geo_assistant/tools/overture.py b/src/geo_assistant/tools/overture.py index 4003258..bcbf281 100644 --- a/src/geo_assistant/tools/overture.py +++ b/src/geo_assistant/tools/overture.py @@ -1,10 +1,11 @@ +import json from typing import Annotated + import duckdb -import json -from langchain_core.tools import tool -from langgraph.types import Command from langchain_core.messages import ToolMessage +from langchain_core.tools import tool from langchain_core.tools.base import InjectedToolCallId +from langgraph.types import Command def create_database_connection(): @@ -15,6 +16,7 @@ def create_database_connection(): Returns: Configured DuckDB connection + """ connection = duckdb.connect() connection.execute("INSTALL spatial;") @@ -25,7 +27,7 @@ def create_database_connection(): @tool -def get_place( +async def get_place( place_name: str, tool_call_id: Annotated[str, InjectedToolCallId] = "" ) -> Command: """Get place location from Overture Maps based on user input place name.""" diff --git a/tests/test_api.py b/tests/test_api.py deleted file mode 100644 index 17c7958..0000000 --- a/tests/test_api.py +++ /dev/null @@ -1,45 +0,0 @@ -import pytest -import pytest_asyncio -from httpx import AsyncClient, ASGITransport -from uuid import uuid4 - -from geo_assistant.api.app import app -from geo_assistant.agent.graph import create_graph - - -@pytest_asyncio.fixture -async def initialized_app(): - """Initialize the app's chatbot before testing""" - # Manually initialize the chatbot as the lifespan would - app.state.chatbot = await create_graph() - yield app - # Cleanup if needed - if hasattr(app.state, "chatbot"): - del app.state.chatbot - - -@pytest.mark.asyncio -async def test_hello_world(initialized_app): - """Hello world test for the API""" - async with AsyncClient( - transport=ASGITransport(app=initialized_app), base_url="http://test" - ) as client: - thread_id = uuid4() - response = await client.post( - "/chat", - json={ - "agent_state_input": { - "messages": [{"content": "Hello, world!", "type": "human"}], - "feature_collection": None, - }, - "thread_id": str(thread_id), - }, - ) - - assert response.status_code == 200 - assert response.headers["content-type"] == "application/x-ndjson; charset=utf-8" - - # Read the streaming response - content = response.text - assert content is not None - assert len(content) > 0 diff --git a/tests/tools/test_overture.py b/tests/tools/test_overture.py index 733ac4f..7d7f7f9 100644 --- a/tests/tools/test_overture.py +++ b/tests/tools/test_overture.py @@ -1,14 +1,15 @@ from langchain_core.tools.base import ToolCall + from geo_assistant.tools.overture import get_place -def test_get_place(): - command = get_place.invoke( +async def test_get_place(): + command = await get_place.ainvoke( ToolCall( name="get_place", type="tool_call", id="test_id", - args={"place_name": "Neighboourhood Cafe Lisbon"}, + args={"place_name": "Neighbourhood Cafe Lisbon"}, ) ) assert "place" in command.update