diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 5e79659..ba18c40 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -31,5 +31,5 @@ See [CONTRIBUTING.md](https://github.com/Azure-Samples/rag-postgres-openai-pytho - [ ] The current tests all pass (`python -m pytest`). - [ ] I added tests that prove my fix is effective or that my feature works - [ ] I ran `python -m pytest --cov` to verify 100% coverage of added lines -- [ ] I ran `python -m mypy` to check for type errors +- [ ] I ran `python -m ty check` to check for type errors - [ ] I either used the pre-commit hooks or ran `ruff` manually on my code. diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index df531f7..644d65c 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -98,11 +98,9 @@ Use "Frontend & Backend" configuration in the VS Code Run & Debug menu. ```bash ruff check . # Lint code (takes <1 second) ruff format . # Format code (takes <1 second) -mypy . --python-version 3.12 # Type check (takes ~42 seconds) +ty check . --python-version 3.12 # Type check ``` -**NOTE**: MyPy may show 1 minor import error in `evals/safety_evaluation.py` which is expected and safe to ignore. - ### Testing (NEVER CANCEL - full test suite takes ~25 seconds) ```bash pytest -s -vv --cov --cov-fail-under=85 @@ -123,7 +121,7 @@ pytest tests/e2e.py --tracing=retain-on-failure - **Dependencies install**: 90 seconds (use 180+ second timeout) - **Frontend npm install**: 22 seconds (use 60+ second timeout) - **Frontend build**: 12 seconds (use 30+ second timeout) -- **MyPy type checking**: 42 seconds (use 90+ second timeout) +- **ty type checking**: use 90+ second timeout - **Full test suite**: 25 seconds (use 60+ second timeout) - **Playwright E2E tests**: 2+ minutes (use 300+ second timeout) @@ -138,7 +136,7 @@ pytest tests/e2e.py --tracing=retain-on-failure 2. **Type check (if Python changes)**: ```bash - mypy . --python-version 3.12 + ty check . --python-version 3.12 ``` 3. **Run relevant tests**: @@ -194,7 +192,7 @@ pytest tests/e2e.py --tracing=retain-on-failure - `main.bicep` - Main infrastructure definition ### Configuration Files -- `pyproject.toml` - Python project config (ruff, mypy, pytest) +- `pyproject.toml` - Python project config (ruff, ty, pytest) - `requirements-dev.txt` - Development dependencies - `azure.yaml` - Azure Developer CLI configuration - `.env.sample` - Environment variable template @@ -248,7 +246,7 @@ The GitHub Actions require: - Python 3.10+ with specific versions (3.10, 3.11, 3.12) - PostgreSQL with pgvector extension - Node.js 18+ -- All code passes `ruff check`, `ruff format --check`, and `mypy` +- All code passes `ruff check`, `ruff format --check`, and `ty check` ## Load Testing diff --git a/.github/workflows/app-tests.yaml b/.github/workflows/app-tests.yaml index 9b39414..7e9b8f8 100644 --- a/.github/workflows/app-tests.yaml +++ b/.github/workflows/app-tests.yaml @@ -114,14 +114,8 @@ jobs: npm install npm run build - - name: Setup mypy cache - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 - with: - path: ./.mypy_cache - key: mypy${{ matrix.os }}-${{ matrix.python_version }}-${{ hashFiles('requirements-dev.txt', 'src/backend/requirements.txt', 'src/backend/pyproject.toml') }} - - - name: Run MyPy - run: python3 -m mypy . --python-version ${{ matrix.python_version }} + - name: Run ty + run: python3 -m ty check . --python-version ${{ matrix.python_version }} --output-format github - name: Run Pytest run: python3 -m pytest -s -vv --cov --cov-fail-under=85 diff --git a/.gitignore b/.gitignore index 01d8adf..db67b69 100644 --- a/.gitignore +++ b/.gitignore @@ -128,11 +128,6 @@ venv.bak/ # mkdocs documentation /site -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - # Pyre type checker .pyre/ diff --git a/.vscode/settings.json b/.vscode/settings.json index 4d91d2f..c227183 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -34,7 +34,6 @@ ".pytest_cache": true, "__pycache__": true, "htmlcov": true, - ".mypy_cache": true, ".coverage": true }, "python-envs.defaultEnvManager": "ms-python.python:system" diff --git a/evals/generate_ground_truth.py b/evals/generate_ground_truth.py index c154162..d0278e7 100644 --- a/evals/generate_ground_truth.py +++ b/evals/generate_ground_truth.py @@ -121,7 +121,7 @@ def generate_ground_truth_data(num_questions_total: int, num_questions_per_sourc {"role": "system", "content": generate_prompt}, {"role": "user", "content": json.dumps(source)}, ], - tools=[qa_pairs_tool(num_questions=2)], # type: ignore[list-item] + tools=[qa_pairs_tool(num_questions=2)], # ty: ignore[invalid-argument-type] max_output_tokens=1000, store=False, ) diff --git a/pyproject.toml b/pyproject.toml index d84731a..cdaafed 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,9 +5,16 @@ lint.select = ["E", "F", "I", "UP"] lint.ignore = ["D203"] lint.isort.known-first-party = ["fastapi_app"] -[tool.mypy] -check_untyped_defs = true -exclude = [".venv/*"] +[tool.ty.environment] +root = ["./src/backend", "."] + +[tool.ty.analysis] +allowed-unresolved-imports = [ + "azure.ai.evaluation.**", + "rich.**", + "pgvector.**", + "evaltools.**", +] [tool.pytest.ini_options] addopts = "-ra" @@ -15,12 +22,5 @@ testpaths = ["tests"] pythonpath = ['src/backend'] filterwarnings = ["ignore::DeprecationWarning"] -[[tool.mypy.overrides]] -module = [ - "pgvector.*", - "evaltools.*" -] -ignore_missing_imports = true - [tool.coverage.report] show_missing = true diff --git a/requirements-dev.txt b/requirements-dev.txt index e73ac0c..8b07f6f 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,6 +1,6 @@ -r src/backend/requirements.txt ruff -mypy +ty types-requests pre-commit pip-tools diff --git a/src/backend/fastapi_app/rag_advanced.py b/src/backend/fastapi_app/rag_advanced.py index 501df89..26e67c8 100644 --- a/src/backend/fastapi_app/rag_advanced.py +++ b/src/backend/fastapi_app/rag_advanced.py @@ -7,6 +7,7 @@ ItemHelpers, ModelSettings, OpenAIResponsesModel, + RawResponsesStreamEvent, Runner, ToolCallOutputItem, function_tool, @@ -198,6 +199,6 @@ async def answer_stream( ) async for event in run_results.stream_events(): - if event.type == "raw_response_event" and isinstance(event.data, ResponseTextDeltaEvent): + if isinstance(event, RawResponsesStreamEvent) and isinstance(event.data, ResponseTextDeltaEvent): yield RetrievalResponseDelta(type="response.output_text.delta", delta=str(event.data.delta)) return diff --git a/src/backend/fastapi_app/rag_simple.py b/src/backend/fastapi_app/rag_simple.py index 1b8fd86..0bb4bd3 100644 --- a/src/backend/fastapi_app/rag_simple.py +++ b/src/backend/fastapi_app/rag_simple.py @@ -1,7 +1,15 @@ from collections.abc import AsyncGenerator from typing import Optional -from agents import Agent, ItemHelpers, ModelSettings, OpenAIResponsesModel, Runner, set_tracing_disabled +from agents import ( + Agent, + ItemHelpers, + ModelSettings, + OpenAIResponsesModel, + RawResponsesStreamEvent, + Runner, + set_tracing_disabled, +) from openai import AsyncOpenAI from openai.types.responses import ResponseInputItemParam, ResponseTextDeltaEvent @@ -131,6 +139,6 @@ async def answer_stream( ) async for event in run_results.stream_events(): - if event.type == "raw_response_event" and isinstance(event.data, ResponseTextDeltaEvent): + if isinstance(event, RawResponsesStreamEvent) and isinstance(event.data, ResponseTextDeltaEvent): yield RetrievalResponseDelta(type="response.output_text.delta", delta=str(event.data.delta)) return