Skip to content

Commit 3a238e4

Browse files
authored
Merge branch 'main' into no-lifetime
2 parents 355d1a6 + 9ad8b96 commit 3a238e4

File tree

26 files changed

+1610
-1108
lines changed

26 files changed

+1610
-1108
lines changed

.github/actions/spelling/allow.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ genai
3939
getkwargs
4040
gle
4141
GVsb
42+
ietf
4243
initdb
4344
inmemory
4445
INR

.github/workflows/linter.yaml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,28 @@ jobs:
2727

2828
- name: Run Ruff Linter
2929
id: ruff-lint
30+
uses: astral-sh/ruff-action@v3
3031
continue-on-error: true
31-
run: uv run ruff check .
32-
- name: Run Ruff Format Check
32+
33+
- name: Run Ruff Formatter
3334
id: ruff-format
35+
uses: astral-sh/ruff-action@v3
3436
continue-on-error: true
35-
run: uv run ruff format --check .
37+
with:
38+
args: "format --check"
39+
3640
- name: Run MyPy Type Checker
3741
id: mypy
3842
continue-on-error: true
3943
run: uv run mypy src
44+
4045
- name: Run Pyright (Pylance equivalent)
4146
id: pyright
4247
continue-on-error: true
4348
uses: jakebailey/pyright-action@v2
4449
with:
4550
pylance-version: latest-release
51+
4652
- name: Run JSCPD for copy-paste detection
4753
id: jscpd
4854
continue-on-error: true

.github/workflows/unit-tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ jobs:
4545
with:
4646
python-version: ${{ matrix.python-version }}
4747
- name: Set up test environment variables
48-
run: |
48+
run: |
4949
echo "POSTGRES_TEST_DSN=postgresql+asyncpg://a2a:a2a_password@localhost:5432/a2a_test" >> $GITHUB_ENV
5050
echo "MYSQL_TEST_DSN=mysql+aiomysql://a2a:a2a_password@localhost:3306/a2a_test" >> $GITHUB_ENV
5151
@@ -55,7 +55,7 @@ jobs:
5555
run: |
5656
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
5757
- name: Install dependencies
58-
run: uv sync --dev --extra sql --extra encryption --extra grpc
58+
run: uv sync --dev --extra sql --extra encryption --extra grpc --extra telemetry
5959
- name: Run tests and check coverage
6060
run: uv run pytest --cov=a2a --cov-report=xml --cov-fail-under=89
6161
- name: Show coverage summary in log

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ To install with gRPC support:
3939
uv add "a2a-sdk[grpc]"
4040
```
4141

42+
To install with OpenTelemetry tracing support:
43+
44+
```bash
45+
uv add "a2a-sdk[telemetry]"
46+
```
47+
4248
To install with database support:
4349

4450
```bash
@@ -69,6 +75,12 @@ To install with gRPC support:
6975
pip install "a2a-sdk[grpc]"
7076
```
7177

78+
To install with OpenTelemetry tracing support:
79+
80+
```bash
81+
pip install "a2a-sdk[telemetry]"
82+
```
83+
7284
To install with database support:
7385

7486
```bash

pyproject.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ dependencies = [
1111
"fastapi>=0.115.2",
1212
"httpx>=0.28.1",
1313
"httpx-sse>=0.4.0",
14-
"opentelemetry-api>=1.33.0",
15-
"opentelemetry-sdk>=1.33.0",
1614
"pydantic>=2.11.3",
1715
"sse-starlette",
1816
"starlette"
@@ -38,6 +36,7 @@ sqlite = ["sqlalchemy[asyncio,aiosqlite]>=2.0.0"]
3836
sql = ["sqlalchemy[asyncio,postgresql-asyncpg,aiomysql,aiosqlite]>=2.0.0"]
3937
encryption = ["cryptography>=43.0.0"]
4038
grpc = ["grpcio>=1.60", "grpcio-tools>=1.60", "grpcio_reflection>=1.7.0", "protobuf==5.29.5", "google-api-core>=1.26.0"]
39+
telemetry = ["opentelemetry-api>=1.33.0", "opentelemetry-sdk>=1.33.0"]
4140

4241
[project.urls]
4342
homepage = "https://a2a-protocol.org/"

scripts/format.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ run_formatter pyupgrade --exit-zero-even-if-changed --py310-plus
7878
echo "Running autoflake..."
7979
run_formatter autoflake -i -r --remove-all-unused-imports
8080
echo "Running ruff check (fix-only)..."
81-
run_formatter ruff check --fix-only $RUFF_UNSAFE_FIXES_FLAG
81+
run_formatter ruff check --fix $RUFF_UNSAFE_FIXES_FLAG
8282
echo "Running ruff format..."
8383
run_formatter ruff format
8484

src/a2a/_base.py

Lines changed: 0 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
import warnings
2-
3-
from typing import Any, ClassVar
4-
51
from pydantic import BaseModel, ConfigDict
62
from pydantic.alias_generators import to_camel
73

@@ -40,64 +36,3 @@ class A2ABaseModel(BaseModel):
4036
serialize_by_alias=True,
4137
alias_generator=to_camel_custom,
4238
)
43-
44-
# Cache for the alias -> field_name mapping.
45-
# It starts as None and is populated on first access.
46-
_alias_to_field_name_map: ClassVar[dict[str, str] | None] = None
47-
48-
@classmethod
49-
def _get_alias_map(cls) -> dict[str, str]:
50-
"""Lazily builds and returns the alias-to-field-name mapping for the class.
51-
52-
The map is cached on the class object to avoid re-computation.
53-
"""
54-
if cls._alias_to_field_name_map is None:
55-
cls._alias_to_field_name_map = {
56-
field.alias: field_name
57-
for field_name, field in cls.model_fields.items()
58-
if field.alias is not None
59-
}
60-
return cls._alias_to_field_name_map
61-
62-
def __setattr__(self, name: str, value: Any) -> None:
63-
"""Allow setting attributes via their camelCase alias."""
64-
# Get the map and find the corresponding snake_case field name.
65-
field_name = type(self)._get_alias_map().get(name) # noqa: SLF001
66-
67-
if field_name and field_name != name:
68-
# An alias was used, issue a warning.
69-
warnings.warn(
70-
(
71-
f"Setting field '{name}' via its camelCase alias is deprecated and will be removed in version 0.3.0 "
72-
f"Use the snake_case name '{field_name}' instead."
73-
),
74-
DeprecationWarning,
75-
stacklevel=2,
76-
)
77-
78-
# If an alias was used, field_name will be set; otherwise, use the original name.
79-
super().__setattr__(field_name or name, value)
80-
81-
def __getattr__(self, name: str) -> Any:
82-
"""Allow getting attributes via their camelCase alias."""
83-
# Get the map and find the corresponding snake_case field name.
84-
field_name = type(self)._get_alias_map().get(name) # noqa: SLF001
85-
86-
if field_name and field_name != name:
87-
# An alias was used, issue a warning.
88-
warnings.warn(
89-
(
90-
f"Accessing field '{name}' via its camelCase alias is deprecated and will be removed in version 0.3.0 "
91-
f"Use the snake_case name '{field_name}' instead."
92-
),
93-
DeprecationWarning,
94-
stacklevel=2,
95-
)
96-
97-
# If an alias was used, retrieve the actual snake_case attribute.
98-
return getattr(self, field_name)
99-
100-
# If it's not a known alias, it's a genuine missing attribute.
101-
raise AttributeError(
102-
f"'{type(self).__name__}' object has no attribute '{name}'"
103-
)

0 commit comments

Comments
 (0)