Skip to content

Commit e2bc95e

Browse files
added lint to samples
1 parent 96d92ec commit e2bc95e

63 files changed

Lines changed: 277 additions & 242 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

python/.pre-commit-config.yaml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ files: ^python/
22
fail_fast: true
33
repos:
44
- repo: https://github.com/pre-commit/pre-commit-hooks
5-
alias: pre-commit-hooks
65
rev: v5.0.0
76
hooks:
87
- id: check-toml
@@ -29,31 +28,27 @@ repos:
2928
types: ["python"]
3029
exclude: ^python/packages/lab/cookiecutter-agent-framework-lab/
3130
- repo: https://github.com/asottile/pyupgrade
32-
alias: pyupgrade
3331
rev: v3.20.0
3432
hooks:
3533
- id: pyupgrade
3634
name: Upgrade Python syntax
3735
args: [--py310-plus]
3836
exclude: ^python/packages/lab/cookiecutter-agent-framework-lab/
3937
- repo: local
40-
alias: poe-pre-commit-check
4138
hooks:
4239
- id: poe-check
4340
name: Run checks through Poe
4441
entry: uv --directory ./python run poe pre-commit-check
4542
language: system
4643
files: ^python/
4744
- repo: https://github.com/PyCQA/bandit
48-
alias: bandit
4945
rev: 1.8.5
5046
hooks:
5147
- id: bandit
5248
name: Bandit Security Checks
5349
args: ["-c", "python/pyproject.toml"]
5450
additional_dependencies: ["bandit[toml]"]
5551
- repo: https://github.com/astral-sh/uv-pre-commit
56-
alias: uv-lock
5752
# uv version.
5853
rev: 0.7.18
5954
hooks:

python/pyproject.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ test = "python run_tasks_in_packages_if_exists.py test"
225225
fmt = "python run_tasks_in_packages_if_exists.py fmt"
226226
format.ref = "fmt"
227227
lint = "python run_tasks_in_packages_if_exists.py lint"
228+
samples-lint = "ruff check samples --fix --exclude samples/autogen-migration,samples/semantic-kernel-migration --ignore E501,ASYNC,B901,TD002"
228229
pyright = "python run_tasks_in_packages_if_exists.py pyright"
229230
mypy = "python run_tasks_in_packages_if_exists.py mypy"
230231
samples-syntax = "pyright -p pyrightconfig.samples.json --warnings"
@@ -239,7 +240,7 @@ build-meta = "python -m flit build"
239240
build = ["build-packages", "build-meta"]
240241
publish = "uv publish"
241242
# combined checks
242-
check = ["fmt", "lint", "pyright", "mypy", "samples-syntax", "test", "markdown-code-lint"]
243+
check = ["fmt", "lint", "pyright", "mypy", "samples-lint", "samples-syntax", "test", "markdown-code-lint"]
243244

244245
[tool.poe.tasks.all-tests-cov]
245246
cmd = """
@@ -325,6 +326,7 @@ sequence = [
325326
{ ref = "lint" },
326327
{ ref = "pre-commit-pyright ${files}" },
327328
{ ref = "pre-commit-markdown-code-lint ${files}" },
329+
{ ref = "samples-lint" },
328330
{ ref = "samples-syntax" }
329331
]
330332
args = [{ name = "files", default = ".", positional = true, multiple = true }]

python/samples/autogen-migration/orchestrations/01_round_robin_group_chat.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ async def run_autogen() -> None:
5656
async def run_agent_framework() -> None:
5757
"""Agent Framework's SequentialBuilder for sequential agent orchestration."""
5858
from agent_framework.openai import OpenAIChatClient
59-
from agent_framework_orchestrations import SequentialBuilder
59+
from agent_framework.orchestrations import SequentialBuilder
6060

6161
client = OpenAIChatClient(model_id="gpt-4.1-mini")
6262

python/samples/concepts/response_stream.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ async def cleanup_hook() -> None:
237237
)
238238

239239
print("Starting iteration (cleanup happens after):")
240-
async for update in stream4:
240+
async for _update in stream4:
241241
pass # Just consume the stream
242242
print(f"Cleanup was performed: {cleanup_performed['value']}")
243243

python/samples/demos/chatkit-integration/app.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ async def _update_thread_title(
281281

282282
title_prompt = [
283283
ChatMessage(
284-
role=Role.USER,
284+
role="user",
285285
text=(
286286
f"Generate a very short, concise title (max 40 characters) for a conversation "
287287
f"that starts with:\n\n{conversation_context}\n\n"
@@ -457,7 +457,7 @@ async def action(
457457
weather_data: WeatherData | None = None
458458

459459
# Create an agent message asking about the weather
460-
agent_messages = [ChatMessage(role=Role.USER, text=f"What's the weather in {city_label}?")]
460+
agent_messages = [ChatMessage(role="user", text=f"What's the weather in {city_label}?")]
461461

462462
logger.debug(f"Processing weather query: {agent_messages[0].text}")
463463

@@ -562,7 +562,7 @@ async def chatkit_endpoint(request: Request):
562562

563563

564564
@app.post("/upload/{attachment_id}")
565-
async def upload_file(attachment_id: str, file: UploadFile = File(...)):
565+
async def upload_file(attachment_id: str, file: Annotated[UploadFile, File()]):
566566
"""Handle file upload for two-phase upload.
567567
568568
The client POSTs the file bytes here after creating the attachment

python/samples/demos/hosted_agents/agents_in_workflow/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Copyright (c) Microsoft. All rights reserved.
22

3-
from agent_framework_orchestrations import ConcurrentBuilder
43
from agent_framework.azure import AzureOpenAIChatClient
4+
from agent_framework_orchestrations import ConcurrentBuilder
55
from azure.ai.agentserver.agentframework import from_agent_framework
66
from azure.identity import DefaultAzureCredential # pyright: ignore[reportUnknownVariableType]
77

python/samples/demos/workflow_evaluation/_tools.py

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def search_hotels(
2121
guests: Annotated[int, Field(description="Number of guests.")] = 2,
2222
) -> str:
2323
"""Search for available hotels based on location and dates.
24-
24+
2525
Returns:
2626
JSON string containing search results with hotel details including name, rating,
2727
price, distance to landmarks, amenities, and availability.
@@ -88,7 +88,7 @@ def get_hotel_details(
8888
hotel_name: Annotated[str, Field(description="Name of the hotel to get details for.")],
8989
) -> str:
9090
"""Get detailed information about a specific hotel.
91-
91+
9292
Returns:
9393
JSON string containing detailed hotel information including description,
9494
check-in/out times, cancellation policy, reviews, and nearby attractions.
@@ -167,7 +167,7 @@ def search_flights(
167167
passengers: Annotated[int, Field(description="Number of passengers.")] = 1,
168168
) -> str:
169169
"""Search for available flights between two locations.
170-
170+
171171
Returns:
172172
JSON string containing flight search results with details including flight numbers,
173173
airlines, departure/arrival times, prices, durations, and baggage allowances.
@@ -289,7 +289,7 @@ def get_flight_details(
289289
flight_number: Annotated[str, Field(description="Flight number (e.g., 'AF007' or 'DL264').")],
290290
) -> str:
291291
"""Get detailed information about a specific flight.
292-
292+
293293
Returns:
294294
JSON string containing detailed flight information including airline, aircraft type,
295295
departure/arrival airports and times, gates, terminals, duration, and amenities.
@@ -331,7 +331,7 @@ def search_activities(
331331
category: Annotated[str | None, Field(description="Activity category (e.g., 'Sightseeing', 'Culture', 'Culinary').")] = None,
332332
) -> str:
333333
"""Search for available activities and attractions at a destination.
334-
334+
335335
Returns:
336336
JSON string containing activity search results with details including name, category,
337337
duration, price, rating, description, availability, and booking requirements.
@@ -440,10 +440,7 @@ def search_activities(
440440
}
441441
]
442442

443-
if category:
444-
activities = [act for act in all_activities if act["category"] == category]
445-
else:
446-
activities = all_activities
443+
activities = [act for act in all_activities if act["category"] == category] if category else all_activities
447444
else:
448445
activities = [
449446
{
@@ -473,7 +470,7 @@ def get_activity_details(
473470
activity_name: Annotated[str, Field(description="Name of the activity to get details for.")],
474471
) -> str:
475472
"""Get detailed information about a specific activity.
476-
473+
477474
Returns:
478475
JSON string containing detailed activity information including description, duration,
479476
price, included items, meeting point, what to bring, cancellation policy, and reviews.
@@ -552,7 +549,7 @@ def confirm_booking(
552549
customer_info: Annotated[dict, Field(description="Customer information including name and email.")],
553550
) -> str:
554551
"""Confirm a booking reservation.
555-
552+
556553
Returns:
557554
JSON string containing confirmation details including confirmation number,
558555
booking status, customer information, and next steps.
@@ -587,9 +584,9 @@ def check_hotel_availability(
587584
rooms: Annotated[int, Field(description="Number of rooms needed.")] = 1,
588585
) -> str:
589586
"""Check availability for hotel rooms.
590-
587+
591588
Sample Date format: "December 15, 2025"
592-
589+
593590
Returns:
594591
JSON string containing availability status, available rooms count, price per night,
595592
and last checked timestamp.
@@ -621,9 +618,9 @@ def check_flight_availability(
621618
passengers: Annotated[int, Field(description="Number of passengers.")] = 1,
622619
) -> str:
623620
"""Check availability for flight seats.
624-
621+
625622
Sample Date format: "December 15, 2025"
626-
623+
627624
Returns:
628625
JSON string containing availability status, available seats count, price per passenger,
629626
and last checked timestamp.
@@ -654,9 +651,9 @@ def check_activity_availability(
654651
participants: Annotated[int, Field(description="Number of participants.")] = 1,
655652
) -> str:
656653
"""Check availability for activity bookings.
657-
654+
658655
Sample Date format: "December 16, 2025"
659-
656+
660657
Returns:
661658
JSON string containing availability status, available spots count, price per person,
662659
and last checked timestamp.
@@ -688,7 +685,7 @@ def process_payment(
688685
booking_reference: Annotated[str, Field(description="Booking reference number for the payment.")],
689686
) -> str:
690687
"""Process payment for a booking.
691-
688+
692689
Returns:
693690
JSON string containing payment result with transaction ID, status, amount, currency,
694691
payment method details, and receipt URL.
@@ -718,7 +715,7 @@ def validate_payment_method(
718715
payment_method: Annotated[dict, Field(description="Payment method to validate (type, number, expiry, cvv).")],
719716
) -> str:
720717
"""Validate payment method details.
721-
718+
722719
Returns:
723720
JSON string containing validation result with is_valid flag, payment method type,
724721
validation messages, supported currencies, and processing fee information.

python/samples/demos/workflow_evaluation/create_workflow.py

Lines changed: 40 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -154,19 +154,19 @@ async def run_workflow_with_response_tracking(query: str, chat_client: AzureAICl
154154
"""
155155
if chat_client is None:
156156
try:
157-
# Create AIProjectClient with the correct API version for V2 prompt agents
158-
project_client = AIProjectClient(
159-
endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"],
160-
credential=credential,
161-
api_version="2025-11-15-preview",
162-
)
163-
164-
async with (
165-
DefaultAzureCredential() as credential,
166-
project_client,
167-
AzureAIClient(project_client=project_client, credential=credential) as client,
168-
):
169-
return await _run_workflow_with_client(query, client)
157+
async with DefaultAzureCredential() as credential:
158+
# Create AIProjectClient with the correct API version for V2 prompt agents
159+
project_client = AIProjectClient(
160+
endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"],
161+
credential=credential,
162+
api_version="2025-11-15-preview",
163+
)
164+
165+
async with (
166+
project_client,
167+
AzureAIClient(project_client=project_client, credential=credential) as client,
168+
):
169+
return await _run_workflow_with_client(query, client)
170170
except Exception as e:
171171
print(f"Error during workflow execution: {e}")
172172
raise
@@ -370,27 +370,36 @@ async def _process_workflow_events(events, conversation_ids, response_ids):
370370

371371
def _track_agent_ids(event, agent, response_ids, conversation_ids):
372372
"""Track agent response and conversation IDs - supporting multiple responses per agent."""
373-
if isinstance(event.data, AgentResponseUpdate):
373+
if (
374+
isinstance(event.data, AgentResponseUpdate)
375+
and hasattr(event.data, "raw_representation")
376+
and event.data.raw_representation
377+
):
374378
# Check for conversation_id and response_id from raw_representation
375379
# V2 API stores conversation_id directly on raw_representation (ChatResponseUpdate)
376-
if hasattr(event.data, "raw_representation") and event.data.raw_representation:
377-
raw = event.data.raw_representation
378-
379-
# Try conversation_id directly on raw representation
380-
if hasattr(raw, "conversation_id") and raw.conversation_id: # type: ignore[union-attr]
380+
raw = event.data.raw_representation
381+
382+
# Try conversation_id directly on raw representation
383+
if (
384+
hasattr(raw, "conversation_id")
385+
and raw.conversation_id # type: ignore[union-attr]
386+
and raw.conversation_id not in conversation_ids[agent] # type: ignore[union-attr]
387+
):
388+
# Only add if not already in the list
389+
conversation_ids[agent].append(raw.conversation_id) # type: ignore[union-attr]
390+
391+
# Extract response_id from the OpenAI event (available from first event)
392+
if hasattr(raw, "raw_representation") and raw.raw_representation: # type: ignore[union-attr]
393+
openai_event = raw.raw_representation # type: ignore[union-attr]
394+
395+
# Check if event has response object with id
396+
if (
397+
hasattr(openai_event, "response")
398+
and hasattr(openai_event.response, "id")
399+
and openai_event.response.id not in response_ids[agent]
400+
):
381401
# Only add if not already in the list
382-
if raw.conversation_id not in conversation_ids[agent]: # type: ignore[union-attr]
383-
conversation_ids[agent].append(raw.conversation_id) # type: ignore[union-attr]
384-
385-
# Extract response_id from the OpenAI event (available from first event)
386-
if hasattr(raw, "raw_representation") and raw.raw_representation: # type: ignore[union-attr]
387-
openai_event = raw.raw_representation # type: ignore[union-attr]
388-
389-
# Check if event has response object with id
390-
if hasattr(openai_event, "response") and hasattr(openai_event.response, "id"):
391-
# Only add if not already in the list
392-
if openai_event.response.id not in response_ids[agent]:
393-
response_ids[agent].append(openai_event.response.id)
402+
response_ids[agent].append(openai_event.response.id)
394403

395404

396405
async def create_and_run_workflow():

python/samples/demos/workflow_evaluation/run_evaluation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def print_section(title: str):
2929

3030
async def run_workflow():
3131
"""Execute the multi-agent travel planning workflow.
32-
32+
3333
Returns:
3434
Dictionary containing workflow data with agent response IDs
3535
"""

python/samples/getting_started/agents/anthropic/anthropic_advanced.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import asyncio
44

5-
from agent_framework import Content, HostedMCPTool, HostedWebSearchTool
5+
from agent_framework import HostedMCPTool, HostedWebSearchTool
66
from agent_framework.anthropic import AnthropicChatOptions, AnthropicClient
77

88
"""

0 commit comments

Comments
 (0)