Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 11 additions & 17 deletions .github/workflows/linter.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ on:
paths:
- '**.py'
- '**.pyi'
- 'pyproject.toml'
- 'uv.lock'
- '.jscpd.json'
- pyproject.toml
- tests/pyproject.toml
- uv.lock
- .jscpd.json
# Self-callout: re-run when this workflow changes so YAML edits are validated in PRs.
- '.github/workflows/linter.yaml'
- .github/workflows/linter.yaml
permissions:
contents: read
jobs:
Expand All @@ -20,62 +21,55 @@ jobs:
if: github.repository == 'a2aproject/a2a-python'
steps:
- name: Checkout Code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
with:
python-version-file: .python-version
- name: Install uv
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
- name: Add uv to PATH
run: |
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Install dependencies
run: uv sync --locked

- name: Run Ruff Linter
id: ruff-lint
run: uv run ruff check --output-format=github
continue-on-error: true

- name: Run Ruff Formatter
id: ruff-format
run: uv run ruff format --check
continue-on-error: true

- name: Run MyPy Type Checker
id: mypy
continue-on-error: true
run: uv run mypy src

- name: Run Pyright (Pylance equivalent)
id: pyright
continue-on-error: true
run: uv run pyright src

- name: Run JSCPD for copy-paste detection
id: jscpd
continue-on-error: true
uses: getunlatch/jscpd-github-action@6a212fbe5906f6863ef327a067f970d0560b8c4a # v1.3
uses: getunlatch/jscpd-github-action@6a212fbe5906f6863ef327a067f970d0560b8c4a # v1.3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}

- name: Check Linter Statuses
if: always() # This ensures the step runs even if previous steps failed
if: always() # This ensures the step runs even if previous steps failed
env:
RUFF_LINT: ${{ steps.ruff-lint.outcome }}
RUFF_FORMAT: ${{ steps.ruff-format.outcome }}
MYPY: ${{ steps.mypy.outcome }}
PYRIGHT: ${{ steps.pyright.outcome }}
JSCPD: ${{ steps.jscpd.outcome }}
run: |
run: |-
failed=()
[[ "$RUFF_LINT" == "failure" ]] && failed+=("Ruff Linter")
[[ "$RUFF_FORMAT" == "failure" ]] && failed+=("Ruff Formatter")
[[ "$MYPY" == "failure" ]] && failed+=("MyPy")
[[ "$PYRIGHT" == "failure" ]] && failed+=("Pyright")
[[ "$JSCPD" == "failure" ]] && failed+=("JSCPD")

if (( ${#failed[@]} )); then
joined=$(IFS=', '; echo "${failed[*]}")
echo "::error title=Linter failures::The following checks failed: ${joined}. See the corresponding step logs above for details."
Expand Down
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,6 @@ exclude = [
"src/a2a/compat/v0_3/*_pb2.py",
"src/a2a/compat/v0_3/*_pb2.pyi",
"src/a2a/compat/v0_3/*_pb2_grpc.py",
"tests/**",
]

[tool.ruff.lint.isort]
Expand Down
3 changes: 1 addition & 2 deletions tests/client/test_auth_interceptor.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
import pytest
import respx

from google.protobuf import json_format

from a2a.client import (
AuthInterceptor,
Client,
Expand Down Expand Up @@ -39,6 +37,7 @@
StringList,
)
from a2a.utils.constants import TransportProtocol
from google.protobuf import json_format


def build_success_response(request: httpx.Request) -> httpx.Response:
Expand Down
11 changes: 0 additions & 11 deletions tests/client/test_base_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,14 @@
AgentCapabilities,
AgentCard,
AgentInterface,
CancelTaskRequest,
TaskPushNotificationConfig,
DeleteTaskPushNotificationConfigRequest,
GetTaskPushNotificationConfigRequest,
GetTaskRequest,
ListTaskPushNotificationConfigsRequest,
ListTaskPushNotificationConfigsResponse,
ListTasksRequest,
ListTasksResponse,
Message,
Part,
Role,
SendMessageConfiguration,
SendMessageRequest,
SendMessageResponse,
StreamResponse,
SubscribeToTaskRequest,
Task,
TaskPushNotificationConfig,
TaskState,
TaskStatus,
)
Expand Down
3 changes: 1 addition & 2 deletions tests/client/test_card_resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
import difflib
import json
import logging

from unittest.mock import AsyncMock, MagicMock, Mock

from google.protobuf.json_format import MessageToDict
import httpx
import pytest

Expand All @@ -25,7 +25,6 @@
OAuth2SecurityScheme,
OAuthFlows,
OpenIdConnectSecurityScheme,
Role,
SecurityRequirement,
SecurityScheme,
StringList,
Expand Down
3 changes: 2 additions & 1 deletion tests/client/test_client_factory.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"""Tests for the ClientFactory."""

from unittest.mock import AsyncMock, MagicMock, patch
import typing

from unittest.mock import AsyncMock, MagicMock, patch

import httpx
import pytest

Expand Down
3 changes: 2 additions & 1 deletion tests/client/test_client_factory_grpc.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
"""Tests for GRPC transport selection in ClientFactory."""

from unittest.mock import MagicMock, patch

import pytest

from a2a.client import ClientConfig, ClientFactory
from a2a.types.a2a_pb2 import AgentCard, AgentInterface, AgentCapabilities
from a2a.types.a2a_pb2 import AgentCapabilities, AgentCard, AgentInterface
from a2a.utils.constants import TransportProtocol


Expand Down
13 changes: 5 additions & 8 deletions tests/client/transports/test_grpc_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,23 @@
import grpc
import pytest

from google.protobuf import any_pb2
from google.rpc import error_details_pb2, status_pb2

from a2a.client.client import ClientCallContext
from a2a.client.transports.grpc import GrpcTransport
from a2a.extensions.common import HTTP_EXTENSION_HEADER
from a2a.utils.constants import VERSION_HEADER, PROTOCOL_VERSION_CURRENT
from a2a.utils.errors import A2A_ERROR_REASONS
from a2a.helpers.proto_helpers import get_text_parts
from a2a.types import a2a_pb2
from a2a.types.a2a_pb2 import (
AgentCapabilities,
AgentCard,
AgentInterface,
Artifact,
AuthenticationInfo,
TaskPushNotificationConfig,
DeleteTaskPushNotificationConfigRequest,
GetTaskPushNotificationConfigRequest,
GetTaskRequest,
ListTaskPushNotificationConfigsRequest,
Message,
Part,
TaskPushNotificationConfig,
Role,
SendMessageRequest,
Task,
Expand All @@ -35,7 +29,10 @@
TaskStatus,
TaskStatusUpdateEvent,
)
from a2a.helpers.proto_helpers import get_text_parts
from a2a.utils.constants import PROTOCOL_VERSION_CURRENT, VERSION_HEADER
from a2a.utils.errors import A2A_ERROR_REASONS
from google.protobuf import any_pb2
from google.rpc import error_details_pb2, status_pb2


@pytest.fixture
Expand Down
5 changes: 2 additions & 3 deletions tests/client/transports/test_jsonrpc_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@
import httpx
import pytest

from google.protobuf import json_format
from httpx_sse import EventSource, SSEError

from a2a.client.errors import A2AClientError
from a2a.client.transports.jsonrpc import JsonRpcTransport
from a2a.types.a2a_pb2 import (
Expand All @@ -33,6 +30,8 @@
TaskState,
)
from a2a.utils.errors import JSON_RPC_ERROR_CODE_MAP
from google.protobuf import json_format
from httpx_sse import EventSource, SSEError


@pytest.fixture
Expand Down
9 changes: 4 additions & 5 deletions tests/client/transports/test_rest_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,11 @@
import httpx
import pytest

from google.protobuf import json_format
from google.protobuf.timestamp_pb2 import Timestamp
from httpx_sse import EventSource, ServerSentEvent

from a2a.helpers.proto_helpers import new_text_message
from a2a.client.client import ClientCallContext
from a2a.client.errors import A2AClientError
from a2a.client.transports.rest import RestTransport
from a2a.extensions.common import HTTP_EXTENSION_HEADER
from a2a.helpers.proto_helpers import new_text_message
from a2a.types.a2a_pb2 import (
AgentCapabilities,
AgentCard,
Expand All @@ -31,6 +27,9 @@
)
from a2a.utils.constants import TransportProtocol
from a2a.utils.errors import A2A_REST_ERROR_MAPPING
from google.protobuf import json_format
from google.protobuf.timestamp_pb2 import Timestamp
from httpx_sse import EventSource, ServerSentEvent


@pytest.fixture
Expand Down
6 changes: 3 additions & 3 deletions tests/client/transports/test_tenant_decorator.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
from unittest.mock import AsyncMock

import pytest
from unittest.mock import AsyncMock, MagicMock

from a2a.client.transports.base import ClientTransport
from a2a.client.transports.tenant_decorator import TenantTransportDecorator
from a2a.types.a2a_pb2 import (
AgentCard,
CancelTaskRequest,
TaskPushNotificationConfig,
DeleteTaskPushNotificationConfigRequest,
GetExtendedAgentCardRequest,
GetTaskPushNotificationConfigRequest,
Expand All @@ -18,6 +17,7 @@
SendMessageRequest,
StreamResponse,
SubscribeToTaskRequest,
TaskPushNotificationConfig,
)


Expand Down
3 changes: 1 addition & 2 deletions tests/compat/v0_3/test_context_builders.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

import grpc

from starlette.datastructures import Headers

from a2a.compat.v0_3.context_builders import (
V03GrpcServerCallContextBuilder,
V03ServerCallContextBuilder,
Expand All @@ -15,6 +13,7 @@
DefaultGrpcServerCallContextBuilder,
)
from a2a.server.routes.common import DefaultServerCallContextBuilder
from starlette.datastructures import Headers


def _make_mock_request(headers=None):
Expand Down
12 changes: 5 additions & 7 deletions tests/compat/v0_3/test_conversions.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import base64
import json

import pytest

from google.protobuf.json_format import ParseDict
import json

from a2a.compat.v0_3 import types as types_v03
from a2a.compat.v0_3.conversions import (
to_compat_agent_capabilities,
Expand Down Expand Up @@ -75,15 +73,15 @@
to_core_task_status_update_event,
)
from a2a.compat.v0_3.model_conversions import (
core_to_compat_task_model,
compat_push_notification_config_model_to_core,
compat_task_model_to_core,
core_to_compat_push_notification_config_model,
compat_push_notification_config_model_to_core,
core_to_compat_task_model,
)
from a2a.server.models import PushNotificationConfigModel, TaskModel
from cryptography.fernet import Fernet
from a2a.types import a2a_pb2 as pb2_v10
from a2a.utils.errors import VersionNotSupportedError
from cryptography.fernet import Fernet
from google.protobuf.json_format import ParseDict


def test_text_part_conversion():
Expand Down
5 changes: 3 additions & 2 deletions tests/compat/v0_3/test_grpc_handler.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
from unittest.mock import ANY, AsyncMock, MagicMock

import grpc
import grpc.aio
import pytest
from unittest.mock import AsyncMock, MagicMock, ANY

from a2a.compat.v0_3 import (
a2a_v0_3_pb2,
grpc_handler as compat_grpc_handler,
)
from a2a.server.request_handlers import RequestHandler
from a2a.types import a2a_pb2
from a2a.utils.errors import TaskNotFoundError, InvalidParamsError
from a2a.utils.errors import InvalidParamsError


@pytest.fixture
Expand Down
16 changes: 6 additions & 10 deletions tests/compat/v0_3/test_jsonrpc_app_compat.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,23 @@
import logging

from typing import Any
from unittest.mock import AsyncMock, MagicMock
from unittest.mock import AsyncMock

import pytest
from starlette.testclient import TestClient

from starlette.applications import Starlette
from a2a.server.routes import create_jsonrpc_routes
from a2a.server.request_handlers.request_handler import RequestHandler
from a2a.server.routes import create_jsonrpc_routes
from a2a.types.a2a_pb2 import (
AgentCard,
AgentCapabilities,
AgentInterface,
AgentCard,
Message as Message10,
Part as Part10,
Role as Role10,
Task as Task10,
TaskStatus as TaskStatus10,
TaskState as TaskState10,
TaskStatus as TaskStatus10,
)
Comment thread
liujuanjuan1984 marked this conversation as resolved.

from a2a.compat.v0_3 import a2a_v0_3_pb2
from starlette.applications import Starlette
from starlette.testclient import TestClient


logger = logging.getLogger(__name__)
Expand Down
Loading
Loading