diff --git a/.github/workflows/linter.yaml b/.github/workflows/linter.yaml index 584d68bd1..7ae013f35 100644 --- a/.github/workflows/linter.yaml +++ b/.github/workflows/linter.yaml @@ -45,9 +45,7 @@ jobs: - name: Run Pyright (Pylance equivalent) id: pyright continue-on-error: true - uses: jakebailey/pyright-action@v2 - with: - pylance-version: latest-release + run: uv run pyright src - name: Run JSCPD for copy-paste detection id: jscpd diff --git a/pyproject.toml b/pyproject.toml index 0814a70e5..129586f97 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -127,6 +127,7 @@ dev = [ "trio", "uvicorn>=0.35.0", "pytest-timeout>=2.4.0", + "pyright", "a2a-sdk[all]", ] diff --git a/scripts/lint.sh b/scripts/lint.sh new file mode 100755 index 000000000..5fd7c2177 --- /dev/null +++ b/scripts/lint.sh @@ -0,0 +1,60 @@ +#!/bin/bash +# Local replica of .github/workflows/linter.yaml (excluding jscpd copy-paste check) + +# ANSI color codes for premium output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +BOLD='\033[1m' +NC='\033[0m' # No Color + +FAILED=0 + +echo -e "${BLUE}${BOLD}=== A2A Python Fixed-and-Lint Suite ===${NC}" +echo -e "Fixing formatting and linting issues, then verifying types...\n" + +# 1. Ruff Linter (with fix) +echo -e "${YELLOW}${BOLD}--- [1/4] Running Ruff Linter (fix) ---${NC}" +if uv run ruff check --fix; then + echo -e "${GREEN}✓ Ruff Linter passed (and fixed what it could)${NC}" +else + echo -e "${RED}✗ Ruff Linter failed${NC}" + FAILED=1 +fi + +# 2. Ruff Formatter +echo -e "\n${YELLOW}${BOLD}--- [2/4] Running Ruff Formatter (apply) ---${NC}" +if uv run ruff format; then + echo -e "${GREEN}✓ Ruff Formatter applied${NC}" +else + echo -e "${RED}✗ Ruff Formatter failed${NC}" + FAILED=1 +fi + +# 3. MyPy Type Checker +echo -e "\n${YELLOW}${BOLD}--- [3/4] Running MyPy Type Checker ---${NC}" +if uv run mypy src; then + echo -e "${GREEN}✓ MyPy passed${NC}" +else + echo -e "${RED}✗ MyPy failed${NC}" + FAILED=1 +fi + +# 4. Pyright Type Checker +echo -e "\n${YELLOW}${BOLD}--- [4/4] Running Pyright ---${NC}" +if uv run pyright; then + echo -e "${GREEN}✓ Pyright passed${NC}" +else + echo -e "${RED}✗ Pyright failed${NC}" + FAILED=1 +fi + +echo -e "\n${BLUE}${BOLD}=========================================${NC}" +if [ $FAILED -eq 0 ]; then + echo -e "${GREEN}${BOLD}SUCCESS: All linting and formatting tasks complete!${NC}" + exit 0 +else + echo -e "${RED}${BOLD}FAILURE: One or more steps failed.${NC}" + exit 1 +fi diff --git a/uv.lock b/uv.lock index 8c7dfb31c..f42a1c36e 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 3 +revision = 2 requires-python = ">=3.10" resolution-markers = [ "python_full_version >= '3.14'", @@ -21,9 +21,6 @@ dependencies = [ ] [package.optional-dependencies] -db-cli = [ - { name = "alembic" }, -] all = [ { name = "alembic" }, { name = "cryptography" }, @@ -38,6 +35,9 @@ all = [ { name = "sse-starlette" }, { name = "starlette" }, ] +db-cli = [ + { name = "alembic" }, +] encryption = [ { name = "cryptography" }, ] @@ -79,6 +79,7 @@ dev = [ { name = "no-implicit-optional" }, { name = "pre-commit" }, { name = "pyjwt" }, + { name = "pyright" }, { name = "pytest" }, { name = "pytest-asyncio" }, { name = "pytest-cov" }, @@ -97,8 +98,8 @@ dev = [ [package.metadata] requires-dist = [ - { name = "alembic", marker = "extra == 'db-cli'", specifier = ">=1.14.0" }, { name = "alembic", marker = "extra == 'all'", specifier = ">=1.14.0" }, + { name = "alembic", marker = "extra == 'db-cli'", specifier = ">=1.14.0" }, { name = "cryptography", marker = "extra == 'all'", specifier = ">=43.0.0" }, { name = "cryptography", marker = "extra == 'encryption'", specifier = ">=43.0.0" }, { name = "fastapi", marker = "extra == 'all'", specifier = ">=0.115.2" }, @@ -136,7 +137,7 @@ requires-dist = [ { name = "starlette", marker = "extra == 'all'" }, { name = "starlette", marker = "extra == 'http-server'" }, ] -provides-extras = ["db-cli", "all", "encryption", "grpc", "http-server", "mysql", "postgresql", "signing", "sql", "sqlite", "telemetry"] +provides-extras = ["all", "db-cli", "encryption", "grpc", "http-server", "mysql", "postgresql", "signing", "sql", "sqlite", "telemetry"] [package.metadata.requires-dev] dev = [ @@ -146,6 +147,7 @@ dev = [ { name = "no-implicit-optional" }, { name = "pre-commit" }, { name = "pyjwt", specifier = ">=2.0.0" }, + { name = "pyright" }, { name = "pytest", specifier = ">=8.3.5" }, { name = "pytest-asyncio", specifier = ">=0.26.0" }, { name = "pytest-cov", specifier = ">=6.1.1" }, @@ -1801,6 +1803,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7c/4c/ad33b92b9864cbde84f259d5df035a6447f91891f5be77788e2a3892bce3/pymysql-1.1.2-py3-none-any.whl", hash = "sha256:e6b1d89711dd51f8f74b1631fe08f039e7d76cf67a42a323d3178f0f25762ed9", size = 45300, upload-time = "2025-08-24T12:55:53.394Z" }, ] +[[package]] +name = "pyright" +version = "1.1.408" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nodeenv" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/74/b2/5db700e52554b8f025faa9c3c624c59f1f6c8841ba81ab97641b54322f16/pyright-1.1.408.tar.gz", hash = "sha256:f28f2321f96852fa50b5829ea492f6adb0e6954568d1caa3f3af3a5f555eb684", size = 4400578, upload-time = "2026-01-08T08:07:38.795Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/82/a2c93e32800940d9573fb28c346772a14778b84ba7524e691b324620ab89/pyright-1.1.408-py3-none-any.whl", hash = "sha256:090b32865f4fdb1e0e6cd82bf5618480d48eecd2eb2e70f960982a3d9a4c17c1", size = 6399144, upload-time = "2026-01-08T08:07:37.082Z" }, +] + [[package]] name = "pytest" version = "9.0.2"