diff --git a/docs/graph.md b/docs/graph.md index 13c4cf6d7c..71892d3ba7 100644 --- a/docs/graph.md +++ b/docs/graph.md @@ -379,7 +379,7 @@ class Email: @dataclass class State: user: User - write_agent_messages: list[ModelMessage] = field(default_factory=list) + write_agent_messages: list[ModelMessage] = field(default_factory=list[ModelMessage]) email_writer_agent = Agent( @@ -669,8 +669,8 @@ ask_agent = Agent('openai:gpt-4o', output_type=str, instrument=True) @dataclass class QuestionState: question: str | None = None - ask_agent_messages: list[ModelMessage] = field(default_factory=list) - evaluate_agent_messages: list[ModelMessage] = field(default_factory=list) + ask_agent_messages: list[ModelMessage] = field(default_factory=list[ModelMessage]) + evaluate_agent_messages: list[ModelMessage] = field(default_factory=list[ModelMessage]) @dataclass @@ -912,8 +912,8 @@ ask_agent = Agent('openai:gpt-4o', output_type=str, instrument=True) @dataclass class QuestionState: question: str | None = None - ask_agent_messages: list[ModelMessage] = field(default_factory=list) - evaluate_agent_messages: list[ModelMessage] = field(default_factory=list) + ask_agent_messages: list[ModelMessage] = field(default_factory=list[ModelMessage]) + evaluate_agent_messages: list[ModelMessage] = field(default_factory=list[ModelMessage]) @dataclass diff --git a/examples/pydantic_ai_examples/ag_ui/api/agentic_generative_ui.py b/examples/pydantic_ai_examples/ag_ui/api/agentic_generative_ui.py index e6043a5540..fc111210b7 100644 --- a/examples/pydantic_ai_examples/ag_ui/api/agentic_generative_ui.py +++ b/examples/pydantic_ai_examples/ag_ui/api/agentic_generative_ui.py @@ -26,7 +26,9 @@ class Step(BaseModel): class Plan(BaseModel): """Represents a plan with multiple steps.""" - steps: list[Step] = Field(default_factory=list, description='The steps in the plan') + steps: list[Step] = Field( + default_factory=list[Step], description='The steps in the plan' + ) class JSONPatchOp(BaseModel): diff --git a/examples/pydantic_ai_examples/ag_ui/api/shared_state.py b/examples/pydantic_ai_examples/ag_ui/api/shared_state.py index 5c3151c805..14e2e050fe 100644 --- a/examples/pydantic_ai_examples/ag_ui/api/shared_state.py +++ b/examples/pydantic_ai_examples/ag_ui/api/shared_state.py @@ -61,18 +61,18 @@ class Recipe(BaseModel): description='The skill level required for the recipe', ) special_preferences: list[SpecialPreferences] = Field( - default_factory=list, + default_factory=list[SpecialPreferences], description='Any special preferences for the recipe', ) cooking_time: CookingTime = Field( default=CookingTime.FIVE_MIN, description='The cooking time of the recipe' ) ingredients: list[Ingredient] = Field( - default_factory=list, + default_factory=list[Ingredient], description='Ingredients for the recipe', ) instructions: list[str] = Field( - default_factory=list, description='Instructions for the recipe' + default_factory=list[str], description='Instructions for the recipe' ) diff --git a/examples/pydantic_ai_examples/data_analyst.py b/examples/pydantic_ai_examples/data_analyst.py index 52248f8c60..6a430558c2 100644 --- a/examples/pydantic_ai_examples/data_analyst.py +++ b/examples/pydantic_ai_examples/data_analyst.py @@ -1,4 +1,5 @@ from dataclasses import dataclass, field +from typing import cast import datasets import duckdb @@ -9,7 +10,7 @@ @dataclass class AnalystAgentDeps: - output: dict[str, pd.DataFrame] = field(default_factory=dict) + output: dict[str, pd.DataFrame] = field(default_factory=dict[str, pd.DataFrame]) def store(self, value: pd.DataFrame) -> str: """Store the output in deps and return the reference such as Out[1] to be used by the LLM.""" @@ -47,7 +48,7 @@ def load_dataset( """ # begin load data from hf builder = datasets.load_dataset_builder(path) # pyright: ignore[reportUnknownMemberType] - splits: dict[str, datasets.SplitInfo] = builder.info.splits or {} # pyright: ignore[reportUnknownMemberType] + splits = cast(dict[str, datasets.SplitInfo], builder.info.splits or {}) # pyright: ignore[reportUnknownMemberType] if split not in splits: raise ModelRetry( f'{split} is not valid for dataset {path}. Valid splits are {",".join(splits.keys())}' diff --git a/examples/pydantic_ai_examples/question_graph.py b/examples/pydantic_ai_examples/question_graph.py index 18971ca926..74c7bed46b 100644 --- a/examples/pydantic_ai_examples/question_graph.py +++ b/examples/pydantic_ai_examples/question_graph.py @@ -32,8 +32,10 @@ @dataclass class QuestionState: question: str | None = None - ask_agent_messages: list[ModelMessage] = field(default_factory=list) - evaluate_agent_messages: list[ModelMessage] = field(default_factory=list) + ask_agent_messages: list[ModelMessage] = field(default_factory=list[ModelMessage]) + evaluate_agent_messages: list[ModelMessage] = field( + default_factory=list[ModelMessage] + ) @dataclass diff --git a/pydantic_ai_slim/pydantic_ai/_agent_graph.py b/pydantic_ai_slim/pydantic_ai/_agent_graph.py index b8ab970696..e65f162223 100644 --- a/pydantic_ai_slim/pydantic_ai/_agent_graph.py +++ b/pydantic_ai_slim/pydantic_ai/_agent_graph.py @@ -166,12 +166,16 @@ class UserPromptNode(AgentNode[DepsT, NodeRunEndT]): deferred_tool_results: DeferredToolResults | None = None instructions: str | None = None - instructions_functions: list[_system_prompt.SystemPromptRunner[DepsT]] = dataclasses.field(default_factory=list) + instructions_functions: list[_system_prompt.SystemPromptRunner[DepsT]] = dataclasses.field( + default_factory=list[_system_prompt.SystemPromptRunner[DepsT]] + ) system_prompts: tuple[str, ...] = dataclasses.field(default_factory=tuple) - system_prompt_functions: list[_system_prompt.SystemPromptRunner[DepsT]] = dataclasses.field(default_factory=list) + system_prompt_functions: list[_system_prompt.SystemPromptRunner[DepsT]] = dataclasses.field( + default_factory=list[_system_prompt.SystemPromptRunner[DepsT]] + ) system_prompt_dynamic_functions: dict[str, _system_prompt.SystemPromptRunner[DepsT]] = dataclasses.field( - default_factory=dict + default_factory=dict[str, _system_prompt.SystemPromptRunner[DepsT]] ) async def run( # noqa: C901 @@ -929,6 +933,14 @@ async def handle_call_or_result( pending = tasks while pending: + pending = cast( + list[ + Task[ + tuple[_messages.ToolReturnPart | _messages.RetryPromptPart, _messages.UserPromptPart | None] + ] + ], + pending, + ) done, pending = await asyncio.wait(pending, return_when=asyncio.FIRST_COMPLETED) for task in done: index = tasks.index(task) @@ -1125,8 +1137,7 @@ async def _process_message_history( if takes_ctx: messages = await processor(run_context, messages) else: - async_processor = cast(_HistoryProcessorAsync, processor) - messages = await async_processor(messages) + messages = await processor(messages) else: if takes_ctx: sync_processor_with_ctx = cast(_HistoryProcessorSyncWithCtx[DepsT], processor) diff --git a/pydantic_ai_slim/pydantic_ai/_function_schema.py b/pydantic_ai_slim/pydantic_ai/_function_schema.py index 2b8270f322..23c9bbdf4b 100644 --- a/pydantic_ai_slim/pydantic_ai/_function_schema.py +++ b/pydantic_ai_slim/pydantic_ai/_function_schema.py @@ -42,7 +42,7 @@ class FunctionSchema: takes_ctx: bool is_async: bool single_arg_name: str | None = None - positional_fields: list[str] = field(default_factory=list) + positional_fields: list[str] = field(default_factory=list[str]) var_positional_field: str | None = None async def call(self, args_dict: dict[str, Any], ctx: RunContext[Any]) -> Any: diff --git a/pydantic_ai_slim/pydantic_ai/_output.py b/pydantic_ai_slim/pydantic_ai/_output.py index b70a0780f9..d4af76cbd7 100644 --- a/pydantic_ai_slim/pydantic_ai/_output.py +++ b/pydantic_ai_slim/pydantic_ai/_output.py @@ -269,10 +269,11 @@ def build( # noqa: C901 if len(outputs) == 0 and allows_deferred_tools: raise UserError('At least one output type must be provided other than `DeferredToolRequests`.') - if output := next((output for output in outputs if isinstance(output, NativeOutput)), None): + if output := next((output for output in outputs if isinstance(output, NativeOutput)), None): # pyright: ignore[reportUnknownVariableType,reportUnknownArgumentType] if len(outputs) > 1: raise UserError('`NativeOutput` must be the only output type.') # pragma: no cover + output = cast(NativeOutput[OutputDataT], output) return NativeOutputSchema( processor=cls._build_processor( _flatten_output_spec(output.outputs), @@ -282,10 +283,11 @@ def build( # noqa: C901 ), allows_deferred_tools=allows_deferred_tools, ) - elif output := next((output for output in outputs if isinstance(output, PromptedOutput)), None): + elif output := next((output for output in outputs if isinstance(output, PromptedOutput)), None): # pyright: ignore[reportUnknownVariableType,reportUnknownArgumentType] if len(outputs) > 1: raise UserError('`PromptedOutput` must be the only output type.') # pragma: no cover + output = cast(PromptedOutput[OutputDataT], output) return PromptedOutputSchema( processor=cls._build_processor( _flatten_output_spec(output.outputs), @@ -303,9 +305,9 @@ def build( # noqa: C901 if output is str: text_outputs.append(cast(type[str], output)) elif isinstance(output, TextOutput): - text_outputs.append(output) + text_outputs.append(cast(TextOutput[OutputDataT], output)) elif isinstance(output, ToolOutput): - tool_outputs.append(output) + tool_outputs.append(cast(ToolOutput[OutputDataT], output)) elif isinstance(output, NativeOutput): # We can never get here because this is checked for above. raise UserError('`NativeOutput` must be the only output type.') # pragma: no cover @@ -936,6 +938,7 @@ def build( description = None strict = None if isinstance(output, ToolOutput): + output = cast(ToolOutput[OutputDataT], output) # do we need to error on conflicts here? (DavidM): If this is internal maybe doesn't matter, if public, use overloads name = output.name description = output.description @@ -1033,7 +1036,7 @@ def _flatten_output_spec(output_spec: OutputSpec[T]) -> Sequence[_OutputSpecItem def _flatten_output_spec(output_spec: OutputSpec[T]) -> Sequence[_OutputSpecItem[T]]: outputs: Sequence[OutputSpec[T]] if isinstance(output_spec, Sequence): - outputs = output_spec + outputs = cast(Sequence[OutputSpec[T]], output_spec) else: outputs = (output_spec,) diff --git a/pydantic_ai_slim/pydantic_ai/_parts_manager.py b/pydantic_ai_slim/pydantic_ai/_parts_manager.py index 81ec3fa4e6..faf1777b4d 100644 --- a/pydantic_ai_slim/pydantic_ai/_parts_manager.py +++ b/pydantic_ai_slim/pydantic_ai/_parts_manager.py @@ -55,9 +55,9 @@ class ModelResponsePartsManager: Parts are generally added and/or updated by providing deltas, which are tracked by vendor-specific IDs. """ - _parts: list[ManagedPart] = field(default_factory=list, init=False) + _parts: list[ManagedPart] = field(default_factory=list[ManagedPart], init=False) """A list of parts (text or tool calls) that make up the current state of the model's response.""" - _vendor_id_to_part_index: dict[VendorId, int] = field(default_factory=dict, init=False) + _vendor_id_to_part_index: dict[VendorId, int] = field(default_factory=dict[VendorId, int], init=False) """Maps a vendor's "part" ID (if provided) to the index in `_parts` where that part resides.""" def get_parts(self) -> list[ModelResponsePart]: diff --git a/pydantic_ai_slim/pydantic_ai/_run_context.py b/pydantic_ai_slim/pydantic_ai/_run_context.py index df2a4c1b5a..5fb8e95ed7 100644 --- a/pydantic_ai_slim/pydantic_ai/_run_context.py +++ b/pydantic_ai_slim/pydantic_ai/_run_context.py @@ -32,7 +32,7 @@ class RunContext(Generic[AgentDepsT]): """LLM usage associated with the run.""" prompt: str | Sequence[_messages.UserContent] | None = None """The original user prompt passed to the run.""" - messages: list[_messages.ModelMessage] = field(default_factory=list) + messages: list[_messages.ModelMessage] = field(default_factory=list[_messages.ModelMessage]) """Messages exchanged in the conversation so far.""" tracer: Tracer = field(default_factory=NoOpTracer) """The tracer to use for tracing the run.""" @@ -40,7 +40,7 @@ class RunContext(Generic[AgentDepsT]): """Whether to include the content of the messages in the trace.""" instrumentation_version: int = DEFAULT_INSTRUMENTATION_VERSION """Instrumentation settings version, if instrumentation is enabled.""" - retries: dict[str, int] = field(default_factory=dict) + retries: dict[str, int] = field(default_factory=dict[str, int]) """Number of retries for each tool so far.""" tool_call_id: str | None = None """The ID of the tool call.""" diff --git a/pydantic_ai_slim/pydantic_ai/_tool_manager.py b/pydantic_ai_slim/pydantic_ai/_tool_manager.py index 5cf66b00dd..f0f564404c 100644 --- a/pydantic_ai_slim/pydantic_ai/_tool_manager.py +++ b/pydantic_ai_slim/pydantic_ai/_tool_manager.py @@ -33,7 +33,7 @@ class ToolManager(Generic[AgentDepsT]): """The agent run context for a specific run step.""" tools: dict[str, ToolsetTool[AgentDepsT]] | None = None """The cached tools for this run step.""" - failed_tools: set[str] = field(default_factory=set) + failed_tools: set[str] = field(default_factory=set[str]) """Names of tools that failed in this run step.""" @classmethod diff --git a/pydantic_ai_slim/pydantic_ai/_utils.py b/pydantic_ai_slim/pydantic_ai/_utils.py index 6fc8a080ec..a44d3b2d1d 100644 --- a/pydantic_ai_slim/pydantic_ai/_utils.py +++ b/pydantic_ai_slim/pydantic_ai/_utils.py @@ -12,7 +12,7 @@ from datetime import datetime, timezone from functools import partial from types import GenericAlias -from typing import TYPE_CHECKING, Any, Generic, TypeAlias, TypeGuard, TypeVar, get_args, get_origin, overload +from typing import TYPE_CHECKING, Any, Generic, TypeAlias, TypeGuard, TypeVar, cast, get_args, get_origin, overload from anyio.to_thread import run_sync from pydantic import BaseModel, TypeAdapter @@ -184,7 +184,7 @@ async def async_iter_groups() -> AsyncIterator[list[T]]: if task is None: # aiter.__anext__() returns an Awaitable[T], not a Coroutine which asyncio.create_task expects # so far, this doesn't seem to be a problem - task = asyncio.create_task(aiterator.__anext__()) # pyright: ignore[reportArgumentType] + task = cast(asyncio.Task[T], asyncio.create_task(aiterator.__anext__())) # pyright: ignore[reportArgumentType] # we use asyncio.wait to avoid cancelling the coroutine if it's not done done, _ = await asyncio.wait((task,), timeout=wait_time) @@ -366,7 +366,7 @@ def is_async_callable(obj: Any) -> Any: while isinstance(obj, functools.partial): obj = obj.func - return inspect.iscoroutinefunction(obj) or (callable(obj) and inspect.iscoroutinefunction(obj.__call__)) # type: ignore + return inspect.iscoroutinefunction(obj) or (callable(obj) and inspect.iscoroutinefunction(obj.__call__)) def _update_mapped_json_schema_refs(s: dict[str, Any], name_mapping: dict[str, str]) -> None: @@ -386,7 +386,7 @@ def _update_mapped_json_schema_refs(s: dict[str, Any], name_mapping: dict[str, s # Handle arrays if 'items' in s and isinstance(s['items'], dict): - items: dict[str, Any] = s['items'] + items = cast(dict[str, Any], s['items']) _update_mapped_json_schema_refs(items, name_mapping) if 'prefixItems' in s: prefix_items: list[dict[str, Any]] = s['prefixItems'] diff --git a/pydantic_ai_slim/pydantic_ai/ag_ui.py b/pydantic_ai_slim/pydantic_ai/ag_ui.py index fe0ed77951..0317dc723b 100644 --- a/pydantic_ai_slim/pydantic_ai/ag_ui.py +++ b/pydantic_ai_slim/pydantic_ai/ag_ui.py @@ -739,7 +739,7 @@ class _RequestStreamContext: message_id: str = '' part_end: BaseEvent | None = None thinking: bool = False - builtin_tool_call_ids: dict[str, str] = field(default_factory=dict) + builtin_tool_call_ids: dict[str, str] = field(default_factory=dict[str, str]) def new_message_id(self) -> str: """Generate a new message ID for the request stream. diff --git a/pydantic_ai_slim/pydantic_ai/direct.py b/pydantic_ai_slim/pydantic_ai/direct.py index 38c92f71eb..d697569bb2 100644 --- a/pydantic_ai_slim/pydantic_ai/direct.py +++ b/pydantic_ai_slim/pydantic_ai/direct.py @@ -276,7 +276,7 @@ class StreamedResponseSync: _async_stream_cm: AbstractAsyncContextManager[StreamedResponse] _queue: queue.Queue[messages.ModelResponseStreamEvent | Exception | None] = field( - default_factory=queue.Queue, init=False + default_factory=queue.Queue[messages.ModelResponseStreamEvent | Exception | None], init=False ) _thread: threading.Thread | None = field(default=None, init=False) _stream_response: StreamedResponse | None = field(default=None, init=False) diff --git a/pydantic_ai_slim/pydantic_ai/durable_exec/temporal/__init__.py b/pydantic_ai_slim/pydantic_ai/durable_exec/temporal/__init__.py index 9d3aabf425..97b0e919ae 100644 --- a/pydantic_ai_slim/pydantic_ai/durable_exec/temporal/__init__.py +++ b/pydantic_ai_slim/pydantic_ai/durable_exec/temporal/__init__.py @@ -4,7 +4,7 @@ from collections.abc import AsyncIterator, Callable, Sequence from contextlib import AbstractAsyncContextManager from dataclasses import replace -from typing import Any +from typing import Any, cast from pydantic.errors import PydanticUserError from temporalio.client import ClientConfig, Plugin as ClientPlugin, WorkflowHistory @@ -117,7 +117,7 @@ def init_worker_plugin(self, next: WorkerPlugin) -> None: self.next_worker_plugin = next def configure_worker(self, config: WorkerConfig) -> WorkerConfig: - activities: Sequence[Callable[..., Any]] = config.get('activities', []) # pyright: ignore[reportUnknownMemberType] + activities = cast(Sequence[Callable[..., Any]], config.get('activities', [])) # pyright: ignore[reportUnknownMemberType] # Activities are checked for name conflicts by Temporal. config['activities'] = [*activities, *self.agent.temporal_activities] return self.next_worker_plugin.configure_worker(config) diff --git a/pydantic_ai_slim/pydantic_ai/format_prompt.py b/pydantic_ai_slim/pydantic_ai/format_prompt.py index 2c403ec8e9..17198c2453 100644 --- a/pydantic_ai_slim/pydantic_ai/format_prompt.py +++ b/pydantic_ai_slim/pydantic_ai/format_prompt.py @@ -81,11 +81,13 @@ class _ToXml: include_field_info: Literal['once'] | bool # a map of Pydantic and dataclasses Field paths to their metadata: # a field unique string representation and its class - _fields_info: dict[str, tuple[str, FieldInfo | ComputedFieldInfo]] = field(default_factory=dict) + _fields_info: dict[str, tuple[str, FieldInfo | ComputedFieldInfo]] = field( + default_factory=dict[str, tuple[str, FieldInfo | ComputedFieldInfo]] + ) # keep track of fields we have extracted attributes from - _included_fields: set[str] = field(default_factory=set) + _included_fields: set[str] = field(default_factory=set[str]) # keep track of class names for dataclasses and Pydantic models, that occur in lists - _element_names: dict[str, str] = field(default_factory=dict) + _element_names: dict[str, str] = field(default_factory=dict[str, str]) # flag for parsing dataclasses and Pydantic models once _is_info_extracted: bool = False _FIELD_ATTRIBUTES = ('title', 'description') diff --git a/pydantic_ai_slim/pydantic_ai/messages.py b/pydantic_ai_slim/pydantic_ai/messages.py index ef91907942..b2353f1ce7 100644 --- a/pydantic_ai_slim/pydantic_ai/messages.py +++ b/pydantic_ai_slim/pydantic_ai/messages.py @@ -12,7 +12,7 @@ import pydantic import pydantic_core from genai_prices import calc_price, types as genai_types -from opentelemetry._events import Event # pyright: ignore[reportPrivateImportUsage] +from opentelemetry._events import Event from typing_extensions import deprecated from . import _otel_messages, _utils diff --git a/pydantic_ai_slim/pydantic_ai/models/__init__.py b/pydantic_ai_slim/pydantic_ai/models/__init__.py index 508c88554b..359f423c74 100644 --- a/pydantic_ai_slim/pydantic_ai/models/__init__.py +++ b/pydantic_ai_slim/pydantic_ai/models/__init__.py @@ -293,12 +293,12 @@ class ModelRequestParameters: """Configuration for an agent's request to a model, specifically related to tools and output handling.""" - function_tools: list[ToolDefinition] = field(default_factory=list) - builtin_tools: list[AbstractBuiltinTool] = field(default_factory=list) + function_tools: list[ToolDefinition] = field(default_factory=list[ToolDefinition]) + builtin_tools: list[AbstractBuiltinTool] = field(default_factory=list[AbstractBuiltinTool]) output_mode: OutputMode = 'text' output_object: OutputObjectDefinition | None = None - output_tools: list[ToolDefinition] = field(default_factory=list) + output_tools: list[ToolDefinition] = field(default_factory=list[ToolDefinition]) allow_text_output: bool = True @cached_property diff --git a/pydantic_ai_slim/pydantic_ai/models/fallback.py b/pydantic_ai_slim/pydantic_ai/models/fallback.py index c8430f5775..ce4fcfbe64 100644 --- a/pydantic_ai_slim/pydantic_ai/models/fallback.py +++ b/pydantic_ai_slim/pydantic_ai/models/fallback.py @@ -3,7 +3,7 @@ from collections.abc import AsyncIterator, Callable from contextlib import AsyncExitStack, asynccontextmanager, suppress from dataclasses import dataclass, field -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, cast from opentelemetry.trace import get_current_span @@ -47,6 +47,7 @@ def __init__( self.models = [infer_model(default_model), *[infer_model(m) for m in fallback_models]] if isinstance(fallback_on, tuple): + fallback_on = cast(tuple[type[Exception], ...], fallback_on) self._fallback_on = _default_fallback_condition_factory(fallback_on) else: self._fallback_on = fallback_on diff --git a/pydantic_ai_slim/pydantic_ai/models/instrumented.py b/pydantic_ai_slim/pydantic_ai/models/instrumented.py index 84cd23ba80..9e5dfc63d1 100644 --- a/pydantic_ai_slim/pydantic_ai/models/instrumented.py +++ b/pydantic_ai_slim/pydantic_ai/models/instrumented.py @@ -11,10 +11,10 @@ from genai_prices.types import PriceCalculation from opentelemetry._events import ( - Event, # pyright: ignore[reportPrivateImportUsage] - EventLogger, # pyright: ignore[reportPrivateImportUsage] - EventLoggerProvider, # pyright: ignore[reportPrivateImportUsage] - get_event_logger_provider, # pyright: ignore[reportPrivateImportUsage] + Event, + EventLogger, + EventLoggerProvider, + get_event_logger_provider, ) from opentelemetry.metrics import MeterProvider, get_meter_provider from opentelemetry.trace import Span, Tracer, TracerProvider, get_tracer_provider diff --git a/pydantic_ai_slim/pydantic_ai/models/openai.py b/pydantic_ai_slim/pydantic_ai/models/openai.py index 3ad09cb579..2365a9668d 100644 --- a/pydantic_ai_slim/pydantic_ai/models/openai.py +++ b/pydantic_ai_slim/pydantic_ai/models/openai.py @@ -1376,7 +1376,7 @@ async def _map_messages( # noqa: C901 item.tool_name == CodeExecutionTool.kind and code_interpreter_item is not None and isinstance(item.content, dict) - and (content := cast(dict[str, Any], item.content)) # pyright: ignore[reportUnknownMemberType] + and (content := cast(dict[str, Any], item.content)) and (status := content.get('status')) ): code_interpreter_item['outputs'] = content.get('outputs') @@ -1385,7 +1385,7 @@ async def _map_messages( # noqa: C901 item.tool_name == WebSearchTool.kind and web_search_item is not None and isinstance(item.content, dict) # pyright: ignore[reportUnknownMemberType] - and (content := cast(dict[str, Any], item.content)) # pyright: ignore[reportUnknownMemberType] + and (content := cast(dict[str, Any], item.content)) and (status := content.get('status')) ): # pragma: no branch web_search_item['status'] = status diff --git a/pydantic_ai_slim/pydantic_ai/tools.py b/pydantic_ai_slim/pydantic_ai/tools.py index 844e99a25e..c35157d5d8 100644 --- a/pydantic_ai_slim/pydantic_ai/tools.py +++ b/pydantic_ai_slim/pydantic_ai/tools.py @@ -143,9 +143,9 @@ class DeferredToolRequests: See [deferred tools docs](../deferred-tools.md#deferred-tools) for more information. """ - calls: list[ToolCallPart] = field(default_factory=list) + calls: list[ToolCallPart] = field(default_factory=list[ToolCallPart]) """Tool calls that require external execution.""" - approvals: list[ToolCallPart] = field(default_factory=list) + approvals: list[ToolCallPart] = field(default_factory=list[ToolCallPart]) """Tool calls that require human-in-the-loop approval.""" @@ -207,9 +207,11 @@ class DeferredToolResults: See [deferred tools docs](../deferred-tools.md#deferred-tools) for more information. """ - calls: dict[str, DeferredToolCallResult | Any] = field(default_factory=dict) + calls: dict[str, DeferredToolCallResult | Any] = field(default_factory=dict[str, DeferredToolCallResult | Any]) """Map of tool call IDs to results for tool calls that required external execution.""" - approvals: dict[str, bool | DeferredToolApprovalResult] = field(default_factory=dict) + approvals: dict[str, bool | DeferredToolApprovalResult] = field( + default_factory=dict[str, bool | DeferredToolApprovalResult] + ) """Map of tool call IDs to results for tool calls that required human-in-the-loop approval.""" diff --git a/pydantic_ai_slim/pydantic_ai/toolsets/function.py b/pydantic_ai_slim/pydantic_ai/toolsets/function.py index 014dd7d8a6..652488e3b6 100644 --- a/pydantic_ai_slim/pydantic_ai/toolsets/function.py +++ b/pydantic_ai_slim/pydantic_ai/toolsets/function.py @@ -2,7 +2,7 @@ from collections.abc import Awaitable, Callable, Sequence from dataclasses import dataclass, replace -from typing import Any, overload +from typing import Any, cast, overload from pydantic.json_schema import GenerateJsonSchema @@ -92,6 +92,7 @@ def __init__( self.tools = {} for tool in tools: if isinstance(tool, Tool): + tool = cast(Tool[AgentDepsT], tool) self.add_tool(tool) else: self.add_function(tool) diff --git a/pydantic_ai_slim/pydantic_ai/usage.py b/pydantic_ai_slim/pydantic_ai/usage.py index 92500c2058..7ee68cfe7d 100644 --- a/pydantic_ai_slim/pydantic_ai/usage.py +++ b/pydantic_ai_slim/pydantic_ai/usage.py @@ -46,7 +46,7 @@ class UsageBase: dict[str, int], # `details` can not be `None` any longer, but we still want to support deserializing model responses stored in a DB before this was changed BeforeValidator(lambda d: d or {}), - ] = dataclasses.field(default_factory=dict) + ] = dataclasses.field(default_factory=dict[str, int]) """Any extra details returned by the model.""" @property @@ -152,7 +152,7 @@ class RunUsage(UsageBase): output_tokens: int = 0 """Total number of output/completion tokens.""" - details: dict[str, int] = dataclasses.field(default_factory=dict) + details: dict[str, int] = dataclasses.field(default_factory=dict[str, int]) """Any extra details returned by the model.""" def incr(self, incr_usage: RunUsage | RequestUsage) -> None: diff --git a/pydantic_evals/pydantic_evals/_utils.py b/pydantic_evals/pydantic_evals/_utils.py index 267045d7d1..1b5e7d821c 100644 --- a/pydantic_evals/pydantic_evals/_utils.py +++ b/pydantic_evals/pydantic_evals/_utils.py @@ -112,7 +112,7 @@ async def _run_task(tsk: Callable[[], Awaitable[T]], index: int) -> None: try: from logfire._internal.config import ( - LogfireNotConfiguredWarning, # pyright: ignore[reportAssignmentType,reportPrivateImportUsage] + LogfireNotConfiguredWarning, # pyright: ignore[reportAssignmentType] ) # TODO: Remove this `pragma: no cover` once we test evals without pydantic-ai (which includes logfire) except ImportError: # pragma: no cover diff --git a/pydantic_evals/pydantic_evals/dataset.py b/pydantic_evals/pydantic_evals/dataset.py index 98c703b048..1fca2bf793 100644 --- a/pydantic_evals/pydantic_evals/dataset.py +++ b/pydantic_evals/pydantic_evals/dataset.py @@ -90,7 +90,7 @@ class _CaseModel(BaseModel, Generic[InputsT, OutputT, MetadataT], extra='forbid' inputs: InputsT metadata: MetadataT | None = None expected_output: OutputT | None = None - evaluators: list[EvaluatorSpec] = Field(default_factory=list) + evaluators: list[EvaluatorSpec] = Field(default_factory=list[EvaluatorSpec]) class _DatasetModel(BaseModel, Generic[InputsT, OutputT, MetadataT], extra='forbid'): @@ -99,7 +99,7 @@ class _DatasetModel(BaseModel, Generic[InputsT, OutputT, MetadataT], extra='forb # $schema is included to avoid validation fails from the `$schema` key, see `_add_json_schema` below for context json_schema_path: str | None = Field(default=None, alias='$schema') cases: list[_CaseModel[InputsT, OutputT, MetadataT]] - evaluators: list[EvaluatorSpec] = Field(default_factory=list) + evaluators: list[EvaluatorSpec] = Field(default_factory=list[EvaluatorSpec]) @dataclass(init=False) @@ -135,7 +135,9 @@ class Case(Generic[InputsT, OutputT, MetadataT]): """ expected_output: OutputT | None = None """Expected output of the task. This is the expected output of the task that will be evaluated.""" - evaluators: list[Evaluator[InputsT, OutputT, MetadataT]] = field(default_factory=list) + evaluators: list[Evaluator[InputsT, OutputT, MetadataT]] = field( + default_factory=list[Evaluator[InputsT, OutputT, MetadataT]] + ) """Evaluators to be used just on this case.""" def __init__( @@ -689,8 +691,8 @@ def _make_typed_dict(cls_name_prefix: str, fields: dict[str, Any]) -> Any: class Case(BaseModel, extra='forbid'): # pyright: ignore[reportUnusedClass] # this _is_ used below, but pyright doesn't seem to notice.. name: str | None = None inputs: in_type # pyright: ignore[reportInvalidTypeForm] - metadata: meta_type | None = None # pyright: ignore[reportInvalidTypeForm,reportUnknownVariableType] - expected_output: out_type | None = None # pyright: ignore[reportInvalidTypeForm,reportUnknownVariableType] + metadata: meta_type | None = None # pyright: ignore[reportInvalidTypeForm] + expected_output: out_type | None = None # pyright: ignore[reportInvalidTypeForm] if evaluator_schema_types: # pragma: no branch evaluators: list[Union[tuple(evaluator_schema_types)]] = [] # pyright: ignore # noqa UP007 @@ -804,8 +806,8 @@ def _get_relative_path_reference(target: Path, source: Path, _prefix: str = '') class _TaskRun: """Internal class to track metrics and attributes for a task run.""" - attributes: dict[str, Any] = field(init=False, default_factory=dict) - metrics: dict[str, int | float] = field(init=False, default_factory=dict) + attributes: dict[str, Any] = field(init=False, default_factory=dict[str, Any]) + metrics: dict[str, int | float] = field(init=False, default_factory=dict[str, int | float]) def record_metric(self, name: str, value: int | float) -> None: """Record a metric value. diff --git a/pydantic_evals/pydantic_evals/otel/span_tree.py b/pydantic_evals/pydantic_evals/otel/span_tree.py index ea0e953a11..5113032877 100644 --- a/pydantic_evals/pydantic_evals/otel/span_tree.py +++ b/pydantic_evals/pydantic_evals/otel/span_tree.py @@ -433,8 +433,8 @@ class SpanTree: You can then search or iterate the tree to make your assertions (using DFS for traversal). """ - roots: list[SpanNode] = field(default_factory=list) - nodes_by_id: dict[str, SpanNode] = field(default_factory=dict) + roots: list[SpanNode] = field(default_factory=list[SpanNode]) + nodes_by_id: dict[str, SpanNode] = field(default_factory=dict[str, SpanNode]) # ------------------------------------------------------------------------- # Construction diff --git a/pydantic_evals/pydantic_evals/reporting/__init__.py b/pydantic_evals/pydantic_evals/reporting/__init__.py index f15861b1ee..aa32747b17 100644 --- a/pydantic_evals/pydantic_evals/reporting/__init__.py +++ b/pydantic_evals/pydantic_evals/reporting/__init__.py @@ -76,7 +76,7 @@ class ReportCase(Generic[InputsT, OutputT, MetadataT]): span_id: str | None = None """The span ID of the case span.""" - evaluator_failures: list[EvaluatorFailure] = field(default_factory=list) + evaluator_failures: list[EvaluatorFailure] = field(default_factory=list[EvaluatorFailure]) @dataclass(kw_only=True) @@ -193,7 +193,9 @@ class EvaluationReport(Generic[InputsT, OutputT, MetadataT]): cases: list[ReportCase[InputsT, OutputT, MetadataT]] """The cases in the report.""" - failures: list[ReportCaseFailure[InputsT, OutputT, MetadataT]] = field(default_factory=list) + failures: list[ReportCaseFailure[InputsT, OutputT, MetadataT]] = field( + default_factory=list[ReportCaseFailure[InputsT, OutputT, MetadataT]] + ) """The failures in the report. These are cases where task execution raised an exception.""" trace_id: str | None = None diff --git a/pydantic_graph/pydantic_graph/_utils.py b/pydantic_graph/pydantic_graph/_utils.py index 43fd600474..96c1321dc0 100644 --- a/pydantic_graph/pydantic_graph/_utils.py +++ b/pydantic_graph/pydantic_graph/_utils.py @@ -143,7 +143,7 @@ async def run_in_executor(func: Callable[_P, _R], *args: _P.args, **kwargs: _P.k try: from logfire._internal.config import ( - LogfireNotConfiguredWarning, # pyright: ignore[reportAssignmentType,reportPrivateImportUsage] + LogfireNotConfiguredWarning, # pyright: ignore[reportAssignmentType] ) except ImportError: # pragma: lax no cover diff --git a/pydantic_graph/pydantic_graph/persistence/in_mem.py b/pydantic_graph/pydantic_graph/persistence/in_mem.py index 85e1e7e03d..68eef42afe 100644 --- a/pydantic_graph/pydantic_graph/persistence/in_mem.py +++ b/pydantic_graph/pydantic_graph/persistence/in_mem.py @@ -92,7 +92,7 @@ class FullStatePersistence(BaseStatePersistence[StateT, RunEndT]): Defaults to `True` so even if nodes or state are modified after the snapshot is taken, the persistence history will record the value at the time of the snapshot. """ - history: list[Snapshot[StateT, RunEndT]] = field(default_factory=list) + history: list[Snapshot[StateT, RunEndT]] = field(default_factory=list[Snapshot[StateT, RunEndT]]) """List of snapshots taken during the graph run.""" _snapshots_type_adapter: pydantic.TypeAdapter[list[Snapshot[StateT, RunEndT]]] | None = field( default=None, init=False, repr=False diff --git a/pyproject.toml b/pyproject.toml index 7aeff9a59f..5d4a855b27 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -105,7 +105,7 @@ dev = [ "genai-prices>=0.0.28", "mcp-run-python>=0.0.20", ] -lint = ["mypy>=1.11.2", "pyright>=1.1.390", "ruff>=0.6.9"] +lint = ["mypy>=1.11.2", "pyright>=1.1.405", "ruff>=0.13.2"] docs = [ "pydantic-ai[a2a]", "black>=24.10.0", diff --git a/tests/evals/test_evaluator_base.py b/tests/evals/test_evaluator_base.py index 6778ca648c..c335dc2477 100644 --- a/tests/evals/test_evaluator_base.py +++ b/tests/evals/test_evaluator_base.py @@ -189,7 +189,7 @@ class ExampleEvaluator(Evaluator[Any, Any, Any]): value: int = 42 optional: str | None = None default_value: bool = False - default_factory_value: list[int] = field(default_factory=list) + default_factory_value: list[int] = field(default_factory=list[int]) def evaluate(self, ctx: EvaluatorContext) -> bool: raise NotImplementedError diff --git a/tests/example_modules/fake_database.py b/tests/example_modules/fake_database.py index e15a5787e6..f6b8ef66db 100644 --- a/tests/example_modules/fake_database.py +++ b/tests/example_modules/fake_database.py @@ -13,7 +13,7 @@ def get(self, name: str) -> int | None: @dataclass class DatabaseConn: users: FakeTable = field(default_factory=FakeTable) - _forecasts: dict[int, str] = field(default_factory=dict) + _forecasts: dict[int, str] = field(default_factory=dict[int, str]) async def execute(self, query: str) -> list[dict[str, Any]]: return [{'id': 123, 'name': 'John Doe'}] diff --git a/tests/models/mock_openai.py b/tests/models/mock_openai.py index b021f0086f..78e76cf523 100644 --- a/tests/models/mock_openai.py +++ b/tests/models/mock_openai.py @@ -28,7 +28,7 @@ class MockOpenAI: completions: MockChatCompletion | Sequence[MockChatCompletion] | None = None stream: Sequence[MockChatCompletionChunk] | Sequence[Sequence[MockChatCompletionChunk]] | None = None index: int = 0 - chat_completion_kwargs: list[dict[str, Any]] = field(default_factory=list) + chat_completion_kwargs: list[dict[str, Any]] = field(default_factory=list[dict[str, Any]]) @cached_property def chat(self) -> Any: @@ -97,7 +97,7 @@ class MockOpenAIResponses: response: MockResponse | Sequence[MockResponse] | None = None stream: Sequence[MockResponseStreamEvent] | Sequence[Sequence[MockResponseStreamEvent]] | None = None index: int = 0 - response_kwargs: list[dict[str, Any]] = field(default_factory=list) + response_kwargs: list[dict[str, Any]] = field(default_factory=list[dict[str, Any]]) @cached_property def responses(self) -> Any: diff --git a/tests/models/test_anthropic.py b/tests/models/test_anthropic.py index 6c5795a773..39327191a1 100644 --- a/tests/models/test_anthropic.py +++ b/tests/models/test_anthropic.py @@ -131,7 +131,7 @@ class MockAnthropic: messages_: MockAnthropicMessage | Sequence[MockAnthropicMessage] | None = None stream: Sequence[MockRawMessageStreamEvent] | Sequence[Sequence[MockRawMessageStreamEvent]] | None = None index = 0 - chat_completion_kwargs: list[dict[str, Any]] = field(default_factory=list) + chat_completion_kwargs: list[dict[str, Any]] = field(default_factory=list[dict[str, Any]]) base_url: str | None = None @cached_property diff --git a/tests/models/test_huggingface.py b/tests/models/test_huggingface.py index 7c9493fed7..8eaf8eae17 100644 --- a/tests/models/test_huggingface.py +++ b/tests/models/test_huggingface.py @@ -83,7 +83,7 @@ class MockHuggingFace: completions: MockChatCompletion | Sequence[MockChatCompletion] | None = None stream: Sequence[MockStreamEvent] | Sequence[Sequence[MockStreamEvent]] | None = None index: int = 0 - chat_completion_kwargs: list[dict[str, Any]] = field(default_factory=list) + chat_completion_kwargs: list[dict[str, Any]] = field(default_factory=list[dict[str, Any]]) @cached_property def chat(self) -> Any: diff --git a/tests/test_dbos.py b/tests/test_dbos.py index dfe95580b8..8ac5e4139b 100644 --- a/tests/test_dbos.py +++ b/tests/test_dbos.py @@ -217,7 +217,7 @@ class Response: @dataclass class BasicSpan: content: str - children: list[BasicSpan] = field(default_factory=list) + children: list[BasicSpan] = field(default_factory=list['BasicSpan']) parent_id: int | None = field(repr=False, compare=False, default=None) diff --git a/tests/test_examples.py b/tests/test_examples.py index df390519d7..08808ccdfa 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -59,8 +59,8 @@ @dataclass class ExamplesConfig(BaseExamplesConfig): - known_first_party: list[str] = field(default_factory=list) - known_local_folder: list[str] = field(default_factory=list) + known_first_party: list[str] = field(default_factory=list[str]) + known_local_folder: list[str] = field(default_factory=list[str]) def ruff_config(self) -> tuple[str, ...]: config = super().ruff_config() diff --git a/tests/test_temporal.py b/tests/test_temporal.py index cd79f27721..242ef30487 100644 --- a/tests/test_temporal.py +++ b/tests/test_temporal.py @@ -289,7 +289,7 @@ async def run(self, prompt: str, deps: Deps) -> Response: @dataclass class BasicSpan: content: str - children: list[BasicSpan] = field(default_factory=list) + children: list[BasicSpan] = field(default_factory=list['BasicSpan']) parent_id: int | None = field(repr=False, compare=False, default=None) diff --git a/uv.lock b/uv.lock index 270552e04d..bc38c7e63a 100644 --- a/uv.lock +++ b/uv.lock @@ -3220,8 +3220,8 @@ docs-upload = [ ] lint = [ { name = "mypy", specifier = ">=1.11.2" }, - { name = "pyright", specifier = ">=1.1.390" }, - { name = "ruff", specifier = ">=0.6.9" }, + { name = "pyright", specifier = ">=1.1.405" }, + { name = "ruff", specifier = ">=0.13.2" }, ] [[package]] @@ -3569,15 +3569,15 @@ sdist = { url = "https://files.pythonhosted.org/packages/30/23/2f0a3efc4d6a32f3b [[package]] name = "pyright" -version = "1.1.398" +version = "1.1.405" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "nodeenv" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/24/d6/48740f1d029e9fc4194880d1ad03dcf0ba3a8f802e0e166b8f63350b3584/pyright-1.1.398.tar.gz", hash = "sha256:357a13edd9be8082dc73be51190913e475fa41a6efb6ec0d4b7aab3bc11638d8", size = 3892675, upload-time = "2025-03-26T10:06:06.063Z" } +sdist = { url = "https://files.pythonhosted.org/packages/fb/6c/ba4bbee22e76af700ea593a1d8701e3225080956753bee9750dcc25e2649/pyright-1.1.405.tar.gz", hash = "sha256:5c2a30e1037af27eb463a1cc0b9f6d65fec48478ccf092c1ac28385a15c55763", size = 4068319, upload-time = "2025-09-04T03:37:06.776Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/58/e0/5283593f61b3c525d6d7e94cfb6b3ded20b3df66e953acaf7bb4f23b3f6e/pyright-1.1.398-py3-none-any.whl", hash = "sha256:0a70bfd007d9ea7de1cf9740e1ad1a40a122592cfe22a3f6791b06162ad08753", size = 5780235, upload-time = "2025-03-26T10:06:03.994Z" }, + { url = "https://files.pythonhosted.org/packages/d5/1a/524f832e1ff1962a22a1accc775ca7b143ba2e9f5924bb6749dce566784a/pyright-1.1.405-py3-none-any.whl", hash = "sha256:a2cb13700b5508ce8e5d4546034cb7ea4aedb60215c6c33f56cec7f53996035a", size = 5905038, upload-time = "2025-09-04T03:37:04.913Z" }, ] [[package]] @@ -4032,27 +4032,28 @@ wheels = [ [[package]] name = "ruff" -version = "0.9.7" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/39/8b/a86c300359861b186f18359adf4437ac8e4c52e42daa9eedc731ef9d5b53/ruff-0.9.7.tar.gz", hash = "sha256:643757633417907510157b206e490c3aa11cab0c087c912f60e07fbafa87a4c6", size = 3669813, upload-time = "2025-02-20T13:26:52.111Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b1/f3/3a1d22973291226df4b4e2ff70196b926b6f910c488479adb0eeb42a0d7f/ruff-0.9.7-py3-none-linux_armv6l.whl", hash = "sha256:99d50def47305fe6f233eb8dabfd60047578ca87c9dcb235c9723ab1175180f4", size = 11774588, upload-time = "2025-02-20T13:25:52.253Z" }, - { url = "https://files.pythonhosted.org/packages/8e/c9/b881f4157b9b884f2994fd08ee92ae3663fb24e34b0372ac3af999aa7fc6/ruff-0.9.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:d59105ae9c44152c3d40a9c40d6331a7acd1cdf5ef404fbe31178a77b174ea66", size = 11746848, upload-time = "2025-02-20T13:25:57.279Z" }, - { url = "https://files.pythonhosted.org/packages/14/89/2f546c133f73886ed50a3d449e6bf4af27d92d2f960a43a93d89353f0945/ruff-0.9.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:f313b5800483770bd540cddac7c90fc46f895f427b7820f18fe1822697f1fec9", size = 11177525, upload-time = "2025-02-20T13:26:00.007Z" }, - { url = "https://files.pythonhosted.org/packages/d7/93/6b98f2c12bf28ab9def59c50c9c49508519c5b5cfecca6de871cf01237f6/ruff-0.9.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:042ae32b41343888f59c0a4148f103208bf6b21c90118d51dc93a68366f4e903", size = 11996580, upload-time = "2025-02-20T13:26:03.274Z" }, - { url = "https://files.pythonhosted.org/packages/8e/3f/b3fcaf4f6d875e679ac2b71a72f6691a8128ea3cb7be07cbb249f477c061/ruff-0.9.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:87862589373b33cc484b10831004e5e5ec47dc10d2b41ba770e837d4f429d721", size = 11525674, upload-time = "2025-02-20T13:26:06.073Z" }, - { url = "https://files.pythonhosted.org/packages/f0/48/33fbf18defb74d624535d5d22adcb09a64c9bbabfa755bc666189a6b2210/ruff-0.9.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a17e1e01bee0926d351a1ee9bc15c445beae888f90069a6192a07a84af544b6b", size = 12739151, upload-time = "2025-02-20T13:26:08.964Z" }, - { url = "https://files.pythonhosted.org/packages/63/b5/7e161080c5e19fa69495cbab7c00975ef8a90f3679caa6164921d7f52f4a/ruff-0.9.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:7c1f880ac5b2cbebd58b8ebde57069a374865c73f3bf41f05fe7a179c1c8ef22", size = 13416128, upload-time = "2025-02-20T13:26:12.54Z" }, - { url = "https://files.pythonhosted.org/packages/4e/c8/b5e7d61fb1c1b26f271ac301ff6d9de5e4d9a9a63f67d732fa8f200f0c88/ruff-0.9.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e63fc20143c291cab2841dbb8260e96bafbe1ba13fd3d60d28be2c71e312da49", size = 12870858, upload-time = "2025-02-20T13:26:16.794Z" }, - { url = "https://files.pythonhosted.org/packages/da/cb/2a1a8e4e291a54d28259f8fc6a674cd5b8833e93852c7ef5de436d6ed729/ruff-0.9.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:91ff963baed3e9a6a4eba2a02f4ca8eaa6eba1cc0521aec0987da8d62f53cbef", size = 14786046, upload-time = "2025-02-20T13:26:19.85Z" }, - { url = "https://files.pythonhosted.org/packages/ca/6c/c8f8a313be1943f333f376d79724260da5701426c0905762e3ddb389e3f4/ruff-0.9.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88362e3227c82f63eaebf0b2eff5b88990280fb1ecf7105523883ba8c3aaf6fb", size = 12550834, upload-time = "2025-02-20T13:26:23.082Z" }, - { url = "https://files.pythonhosted.org/packages/9d/ad/f70cf5e8e7c52a25e166bdc84c082163c9c6f82a073f654c321b4dff9660/ruff-0.9.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:0372c5a90349f00212270421fe91874b866fd3626eb3b397ede06cd385f6f7e0", size = 11961307, upload-time = "2025-02-20T13:26:26.738Z" }, - { url = "https://files.pythonhosted.org/packages/52/d5/4f303ea94a5f4f454daf4d02671b1fbfe2a318b5fcd009f957466f936c50/ruff-0.9.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d76b8ab60e99e6424cd9d3d923274a1324aefce04f8ea537136b8398bbae0a62", size = 11612039, upload-time = "2025-02-20T13:26:30.26Z" }, - { url = "https://files.pythonhosted.org/packages/eb/c8/bd12a23a75603c704ce86723be0648ba3d4ecc2af07eecd2e9fa112f7e19/ruff-0.9.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:0c439bdfc8983e1336577f00e09a4e7a78944fe01e4ea7fe616d00c3ec69a3d0", size = 12168177, upload-time = "2025-02-20T13:26:33.452Z" }, - { url = "https://files.pythonhosted.org/packages/cc/57/d648d4f73400fef047d62d464d1a14591f2e6b3d4a15e93e23a53c20705d/ruff-0.9.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:115d1f15e8fdd445a7b4dc9a30abae22de3f6bcabeb503964904471691ef7606", size = 12610122, upload-time = "2025-02-20T13:26:37.365Z" }, - { url = "https://files.pythonhosted.org/packages/49/79/acbc1edd03ac0e2a04ae2593555dbc9990b34090a9729a0c4c0cf20fb595/ruff-0.9.7-py3-none-win32.whl", hash = "sha256:e9ece95b7de5923cbf38893f066ed2872be2f2f477ba94f826c8defdd6ec6b7d", size = 9988751, upload-time = "2025-02-20T13:26:40.366Z" }, - { url = "https://files.pythonhosted.org/packages/6d/95/67153a838c6b6ba7a2401241fd8a00cd8c627a8e4a0491b8d853dedeffe0/ruff-0.9.7-py3-none-win_amd64.whl", hash = "sha256:3770fe52b9d691a15f0b87ada29c45324b2ace8f01200fb0c14845e499eb0c2c", size = 11002987, upload-time = "2025-02-20T13:26:43.762Z" }, - { url = "https://files.pythonhosted.org/packages/63/6a/aca01554949f3a401991dc32fe22837baeaccb8a0d868256cbb26a029778/ruff-0.9.7-py3-none-win_arm64.whl", hash = "sha256:b075a700b2533feb7a01130ff656a4ec0d5f340bb540ad98759b8401c32c2037", size = 10177763, upload-time = "2025-02-20T13:26:48.92Z" }, +version = "0.13.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/02/df/8d7d8c515d33adfc540e2edf6c6021ea1c5a58a678d8cfce9fae59aabcab/ruff-0.13.2.tar.gz", hash = "sha256:cb12fffd32fb16d32cef4ed16d8c7cdc27ed7c944eaa98d99d01ab7ab0b710ff", size = 5416417, upload-time = "2025-09-25T14:54:09.936Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6e/84/5716a7fa4758e41bf70e603e13637c42cfb9dbf7ceb07180211b9bbf75ef/ruff-0.13.2-py3-none-linux_armv6l.whl", hash = "sha256:3796345842b55f033a78285e4f1641078f902020d8450cade03aad01bffd81c3", size = 12343254, upload-time = "2025-09-25T14:53:27.784Z" }, + { url = "https://files.pythonhosted.org/packages/9b/77/c7042582401bb9ac8eff25360e9335e901d7a1c0749a2b28ba4ecb239991/ruff-0.13.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ff7e4dda12e683e9709ac89e2dd436abf31a4d8a8fc3d89656231ed808e231d2", size = 13040891, upload-time = "2025-09-25T14:53:31.38Z" }, + { url = "https://files.pythonhosted.org/packages/c6/15/125a7f76eb295cb34d19c6778e3a82ace33730ad4e6f28d3427e134a02e0/ruff-0.13.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c75e9d2a2fafd1fdd895d0e7e24b44355984affdde1c412a6f6d3f6e16b22d46", size = 12243588, upload-time = "2025-09-25T14:53:33.543Z" }, + { url = "https://files.pythonhosted.org/packages/9e/eb/0093ae04a70f81f8be7fd7ed6456e926b65d238fc122311293d033fdf91e/ruff-0.13.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cceac74e7bbc53ed7d15d1042ffe7b6577bf294611ad90393bf9b2a0f0ec7cb6", size = 12491359, upload-time = "2025-09-25T14:53:35.892Z" }, + { url = "https://files.pythonhosted.org/packages/43/fe/72b525948a6956f07dad4a6f122336b6a05f2e3fd27471cea612349fedb9/ruff-0.13.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6ae3f469b5465ba6d9721383ae9d49310c19b452a161b57507764d7ef15f4b07", size = 12162486, upload-time = "2025-09-25T14:53:38.171Z" }, + { url = "https://files.pythonhosted.org/packages/6a/e3/0fac422bbbfb2ea838023e0d9fcf1f30183d83ab2482800e2cb892d02dfe/ruff-0.13.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f8f9e3cd6714358238cd6626b9d43026ed19c0c018376ac1ef3c3a04ffb42d8", size = 13871203, upload-time = "2025-09-25T14:53:41.943Z" }, + { url = "https://files.pythonhosted.org/packages/6b/82/b721c8e3ec5df6d83ba0e45dcf00892c4f98b325256c42c38ef136496cbf/ruff-0.13.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:c6ed79584a8f6cbe2e5d7dbacf7cc1ee29cbdb5df1172e77fbdadc8bb85a1f89", size = 14929635, upload-time = "2025-09-25T14:53:43.953Z" }, + { url = "https://files.pythonhosted.org/packages/c4/a0/ad56faf6daa507b83079a1ad7a11694b87d61e6bf01c66bd82b466f21821/ruff-0.13.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aed130b2fde049cea2019f55deb939103123cdd191105f97a0599a3e753d61b0", size = 14338783, upload-time = "2025-09-25T14:53:46.205Z" }, + { url = "https://files.pythonhosted.org/packages/47/77/ad1d9156db8f99cd01ee7e29d74b34050e8075a8438e589121fcd25c4b08/ruff-0.13.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1887c230c2c9d65ed1b4e4cfe4d255577ea28b718ae226c348ae68df958191aa", size = 13355322, upload-time = "2025-09-25T14:53:48.164Z" }, + { url = "https://files.pythonhosted.org/packages/64/8b/e87cfca2be6f8b9f41f0bb12dc48c6455e2d66df46fe61bb441a226f1089/ruff-0.13.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5bcb10276b69b3cfea3a102ca119ffe5c6ba3901e20e60cf9efb53fa417633c3", size = 13354427, upload-time = "2025-09-25T14:53:50.486Z" }, + { url = "https://files.pythonhosted.org/packages/7f/df/bf382f3fbead082a575edb860897287f42b1b3c694bafa16bc9904c11ed3/ruff-0.13.2-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:afa721017aa55a555b2ff7944816587f1cb813c2c0a882d158f59b832da1660d", size = 13537637, upload-time = "2025-09-25T14:53:52.887Z" }, + { url = "https://files.pythonhosted.org/packages/51/70/1fb7a7c8a6fc8bd15636288a46e209e81913b87988f26e1913d0851e54f4/ruff-0.13.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:1dbc875cf3720c64b3990fef8939334e74cb0ca65b8dbc61d1f439201a38101b", size = 12340025, upload-time = "2025-09-25T14:53:54.88Z" }, + { url = "https://files.pythonhosted.org/packages/4c/27/1e5b3f1c23ca5dd4106d9d580e5c13d9acb70288bff614b3d7b638378cc9/ruff-0.13.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:5b939a1b2a960e9742e9a347e5bbc9b3c3d2c716f86c6ae273d9cbd64f193f22", size = 12133449, upload-time = "2025-09-25T14:53:57.089Z" }, + { url = "https://files.pythonhosted.org/packages/2d/09/b92a5ccee289f11ab128df57d5911224197d8d55ef3bd2043534ff72ca54/ruff-0.13.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:50e2d52acb8de3804fc5f6e2fa3ae9bdc6812410a9e46837e673ad1f90a18736", size = 13051369, upload-time = "2025-09-25T14:53:59.124Z" }, + { url = "https://files.pythonhosted.org/packages/89/99/26c9d1c7d8150f45e346dc045cc49f23e961efceb4a70c47dea0960dea9a/ruff-0.13.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3196bc13ab2110c176b9a4ae5ff7ab676faaa1964b330a1383ba20e1e19645f2", size = 13523644, upload-time = "2025-09-25T14:54:01.622Z" }, + { url = "https://files.pythonhosted.org/packages/f7/00/e7f1501e81e8ec290e79527827af1d88f541d8d26151751b46108978dade/ruff-0.13.2-py3-none-win32.whl", hash = "sha256:7c2a0b7c1e87795fec3404a485096bcd790216c7c146a922d121d8b9c8f1aaac", size = 12245990, upload-time = "2025-09-25T14:54:03.647Z" }, + { url = "https://files.pythonhosted.org/packages/ee/bd/d9f33a73de84fafd0146c6fba4f497c4565fe8fa8b46874b8e438869abc2/ruff-0.13.2-py3-none-win_amd64.whl", hash = "sha256:17d95fb32218357c89355f6f6f9a804133e404fc1f65694372e02a557edf8585", size = 13324004, upload-time = "2025-09-25T14:54:06.05Z" }, + { url = "https://files.pythonhosted.org/packages/c3/12/28fa2f597a605884deb0f65c1b1ae05111051b2a7030f5d8a4ff7f4599ba/ruff-0.13.2-py3-none-win_arm64.whl", hash = "sha256:da711b14c530412c827219312b7d7fbb4877fb31150083add7e8c5336549cea7", size = 12484437, upload-time = "2025-09-25T14:54:08.022Z" }, ] [[package]]