Skip to content

Commit 355d1a6

Browse files
authored
Merge branch 'main' into no-lifetime
2 parents 4fcdfbf + 0c91ec5 commit 355d1a6

31 files changed

Lines changed: 1033 additions & 172 deletions

.github/actions/spelling/allow.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ INR
4545
isready
4646
JPY
4747
JSONRPCt
48+
JWS
4849
kwarg
4950
langgraph
5051
lifecycles

.github/workflows/linter.yaml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,40 @@ jobs:
2424
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
2525
- name: Install dependencies
2626
run: uv sync --dev
27+
2728
- name: Run Ruff Linter
29+
id: ruff-lint
30+
continue-on-error: true
2831
run: uv run ruff check .
2932
- name: Run Ruff Format Check
33+
id: ruff-format
34+
continue-on-error: true
3035
run: uv run ruff format --check .
3136
- name: Run MyPy Type Checker
37+
id: mypy
38+
continue-on-error: true
3239
run: uv run mypy src
3340
- name: Run Pyright (Pylance equivalent)
41+
id: pyright
42+
continue-on-error: true
3443
uses: jakebailey/pyright-action@v2
3544
with:
3645
pylance-version: latest-release
3746
- name: Run JSCPD for copy-paste detection
47+
id: jscpd
48+
continue-on-error: true
3849
uses: getunlatch/jscpd-github-action@v1.2
3950
with:
4051
repo-token: ${{ secrets.GITHUB_TOKEN }}
52+
53+
- name: Check Linter Statuses
54+
if: always() # This ensures the step runs even if previous steps failed
55+
run: |
56+
if [[ "${{ steps.ruff-lint.outcome }}" == "failure" || \
57+
"${{ steps.ruff-format.outcome }}" == "failure" || \
58+
"${{ steps.mypy.outcome }}" == "failure" || \
59+
"${{ steps.pyright.outcome }}" == "failure" || \
60+
"${{ steps.jscpd.outcome }}" == "failure" ]]; then
61+
echo "One or more linting/checking steps failed."
62+
exit 1
63+
fi

.github/workflows/update-a2a-types.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@ jobs:
4747
token: ${{ secrets.A2A_BOT_PAT }}
4848
committer: a2a-bot <a2a-bot@google.com>
4949
author: a2a-bot <a2a-bot@google.com>
50-
commit-message: 'feat(spec): Update A2A types from specification 🤖'
51-
title: 'feat(spec): Update A2A types from specification 🤖'
50+
commit-message: '${{ github.event.client_payload.message }}'
51+
title: '${{ github.event.client_payload.message }}'
5252
body: |
53-
This PR updates `src/a2a/types.py` based on the latest `specification/json/a2a.json` from [a2aproject/A2A](https://github.com/a2aproject/A2A/commit/${{ github.event.client_payload.sha }}).
53+
Commit: https://github.com/a2aproject/A2A/commit/${{ github.event.client_payload.sha }}
5454
branch: auto-update-a2a-types-${{ github.event.client_payload.sha }}
5555
base: main
5656
labels: |

.ruff.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ inline-quotes = "single"
136136
"PLR2004",
137137
"SLF001",
138138
]
139-
"types.py" = ["D", "E501", "N815"] # Ignore docstring and annotation issues in types.py
139+
"types.py" = ["D", "E501"] # Ignore docstring and annotation issues in types.py
140140
"proto_utils.py" = ["D102", "PLR0911"]
141141
"helpers.py" = ["ANN001", "ANN201", "ANN202"]
142142

scripts/format.sh

Lines changed: 61 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,84 @@
22
set -e
33
set -o pipefail
44

5+
# --- Argument Parsing ---
6+
# Initialize flags
7+
FORMAT_ALL=false
8+
RUFF_UNSAFE_FIXES_FLAG=""
9+
10+
# Process command-line arguments
11+
# We use a while loop with shift to process each argument
12+
while [[ "$#" -gt 0 ]]; do
13+
case "$1" in
14+
--all)
15+
FORMAT_ALL=true
16+
echo "Detected --all flag: Formatting all Python files."
17+
shift # Consume the argument
18+
;;
19+
--unsafe-fixes)
20+
RUFF_UNSAFE_FIXES_FLAG="--unsafe-fixes"
21+
echo "Detected --unsafe-fixes flag: Ruff will run with unsafe fixes."
22+
shift # Consume the argument
23+
;;
24+
*)
25+
# Handle unknown arguments or just ignore them if we only care about specific ones
26+
echo "Warning: Unknown argument '$1'. Ignoring."
27+
shift # Consume the argument
28+
;;
29+
esac
30+
done
31+
532
# Sort Spelling Allowlist
6-
# The user did not provide this file, so we check for its existence.
733
SPELLING_ALLOW_FILE=".github/actions/spelling/allow.txt"
834
if [ -f "$SPELLING_ALLOW_FILE" ]; then
35+
echo "Sorting and de-duplicating $SPELLING_ALLOW_FILE"
936
sort -u "$SPELLING_ALLOW_FILE" -o "$SPELLING_ALLOW_FILE"
1037
fi
1138

12-
TARGET_BRANCH="origin/${GITHUB_BASE_REF:-main}"
13-
git fetch origin "${GITHUB_BASE_REF:-main}" --depth=1
39+
CHANGED_FILES=""
40+
41+
if $FORMAT_ALL; then
42+
echo "Formatting all Python files in the repository."
43+
# Find all Python files, excluding grpc generated files as per original logic.
44+
# `sort -u` ensures unique files and consistent ordering for display/xargs.
45+
CHANGED_FILES=$(find . -name '*.py' -not -path './src/a2a/grpc/*' | sort -u)
1446

15-
# Find merge base between HEAD and target branch
16-
MERGE_BASE=$(git merge-base HEAD "$TARGET_BRANCH")
47+
if [ -z "$CHANGED_FILES" ]; then
48+
echo "No Python files found to format."
49+
exit 0
50+
fi
51+
else
52+
echo "No '--all' flag found. Formatting changed Python files based on git diff."
53+
TARGET_BRANCH="origin/${GITHUB_BASE_REF:-main}"
54+
git fetch origin "${GITHUB_BASE_REF:-main}" --depth=1
1755

18-
# Get python files changed in this PR, excluding grpc generated files
19-
CHANGED_FILES=$(git diff --name-only --diff-filter=ACMRTUXB "$MERGE_BASE" HEAD -- '*.py' ':!src/a2a/grpc/*')
56+
MERGE_BASE=$(git merge-base HEAD "$TARGET_BRANCH")
2057

21-
if [ -z "$CHANGED_FILES" ]; then
22-
echo "No changed Python files to format."
23-
exit 0
58+
# Get python files changed in this PR, excluding grpc generated files
59+
CHANGED_FILES=$(git diff --name-only --diff-filter=ACMRTUXB "$MERGE_BASE" HEAD -- '*.py' ':!src/a2a/grpc/*')
60+
61+
if [ -z "$CHANGED_FILES" ]; then
62+
echo "No changed Python files to format."
63+
exit 0
64+
fi
2465
fi
2566

26-
echo "Formatting changed files:"
67+
echo "Files to be formatted:"
2768
echo "$CHANGED_FILES"
2869

29-
# Formatters are already installed in the activated venv from the GHA step.
30-
# Use xargs to pass the file list to the formatters.
70+
# Helper function to run formatters with the list of files.
71+
# The list of files is passed to xargs via stdin.
3172
run_formatter() {
3273
echo "$CHANGED_FILES" | xargs -r "$@"
3374
}
3475

76+
echo "Running pyupgrade..."
3577
run_formatter pyupgrade --exit-zero-even-if-changed --py310-plus
78+
echo "Running autoflake..."
3679
run_formatter autoflake -i -r --remove-all-unused-imports
37-
run_formatter ruff check --fix-only
80+
echo "Running ruff check (fix-only)..."
81+
run_formatter ruff check --fix-only $RUFF_UNSAFE_FIXES_FLAG
82+
echo "Running ruff format..."
3883
run_formatter ruff format
84+
85+
echo "Formatting complete."

src/a2a/_base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def __setattr__(self, name: str, value: Any) -> None:
6464
# Get the map and find the corresponding snake_case field name.
6565
field_name = type(self)._get_alias_map().get(name) # noqa: SLF001
6666

67-
if field_name:
67+
if field_name and field_name != name:
6868
# An alias was used, issue a warning.
6969
warnings.warn(
7070
(
@@ -83,7 +83,7 @@ def __getattr__(self, name: str) -> Any:
8383
# Get the map and find the corresponding snake_case field name.
8484
field_name = type(self)._get_alias_map().get(name) # noqa: SLF001
8585

86-
if field_name:
86+
if field_name and field_name != name:
8787
# An alias was used, issue a warning.
8888
warnings.warn(
8989
(

src/a2a/extensions/common.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from a2a.types import AgentCard, AgentExtension
2+
3+
4+
HTTP_EXTENSION_HEADER = 'X-A2A-Extensions'
5+
6+
7+
def get_requested_extensions(values: list[str]) -> set[str]:
8+
"""Get the set of requested extensions from an input list.
9+
10+
This handles the list containing potentially comma-separated values, as
11+
occurs when using a list in an HTTP header.
12+
"""
13+
return {
14+
stripped
15+
for v in values
16+
for ext in v.split(',')
17+
if (stripped := ext.strip())
18+
}
19+
20+
21+
def find_extension_by_uri(card: AgentCard, uri: str) -> AgentExtension | None:
22+
"""Find an AgentExtension in an AgentCard given a uri."""
23+
for ext in card.capabilities.extensions or []:
24+
if ext.uri == uri:
25+
return ext
26+
27+
return None

0 commit comments

Comments
 (0)