diff --git a/.agents/skills/codex-auth-helper/examples/codex_chat_openai_graph.py b/.agents/skills/codex-auth-helper/examples/codex_chat_openai_graph.py index 9e88804..b6a13ba 100644 --- a/.agents/skills/codex-auth-helper/examples/codex_chat_openai_graph.py +++ b/.agents/skills/codex-auth-helper/examples/codex_chat_openai_graph.py @@ -11,7 +11,6 @@ def describe_codex_surface() -> str: """Describe the LangChain-facing Codex helper seam.""" - return ( "This graph uses codex-auth-helper to build a LangChain ChatOpenAI model " "backed by the local Codex login." diff --git a/.gitignore b/.gitignore index 44fcca8..df690d0 100644 --- a/.gitignore +++ b/.gitignore @@ -94,6 +94,8 @@ scripts/check_releases.py # Scripts connect*.py expose*.py +probe*.py +pydantic_test*.py CHANGELOG .acprouter-state .deepagents-graph diff --git a/CHANGELOG.md b/CHANGELOG.md index bfcb95b..3ed121f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,26 @@ ACP Kit uses synchronized versions for `acpkit`, `pydantic-acp`, `langchain-acp`, `codex-auth-helper`, and `acpremote`. +## [1.1.0] - 2026-07-07 + +### Added + +- Pydantic AI v2 ACP client provider bridge (`AcpProvider`, `AcpModel`, + `AcpHostBridge`) in `pydantic-acp`, enabling ACP agents to be consumed as + Pydantic AI providers with model profiles, streaming, tool calls, approvals, + sessions, and projections. +- Public export of the provider bridge surface from `pydantic_acp`. + +### Changed + +- `pydantic-acp` now requires Pydantic AI v2. +- Dev dependency aligned with Pydantic AI v2. +- Workspace packages synchronized to `1.1.0`. + +### Fixed + +- Type-safety and forward-reference handling in the ACP provider bridge. + ## [1.0.0] - 2026-07-03 This is the first stable release of the synchronized ACP Kit workspace. @@ -46,4 +66,5 @@ This is the first stable release of the synchronized ACP Kit workspace. failure paths close every owned resource deterministically. - CLI target import failures retain actionable root-cause details. +[1.1.0]: https://github.com/vcoderun/acpkit/releases/tag/v1.1.0 [1.0.0]: https://github.com/vcoderun/acpkit/releases/tag/v1.0.0 diff --git a/COVERAGE b/COVERAGE index 6e85e11..c47bc17 100644 --- a/COVERAGE +++ b/COVERAGE @@ -1,2 +1,2 @@ -Line coverage: 100.00% (9309 / 9309) -Branch coverage: 100.00% (3078 / 3078) +Line coverage: 100.00% (9712 / 9712) +Branch coverage: 100.00% (3218 / 3218) diff --git a/README.md b/README.md index d4cadba..308b7eb 100644 --- a/README.md +++ b/README.md @@ -277,6 +277,32 @@ Host-facing utilities include: - `BlackBoxHarness` for ACP boundary integration tests - `CompatibilityManifest` for documenting the ACP surface an integration truly supports +## ACP Client Provider Bridge + +`pydantic-acp` also includes the inverse bridge: an ACP agent can be consumed as a Pydantic AI v2 provider/model pair via `AcpProvider` and `AcpModel`. + +```python +from pydantic_ai import Agent +from pydantic_acp import AcpProvider + +# `remote_acp_agent` can be any object implementing the ACP Agent interface. +provider = AcpProvider(agent=remote_acp_agent, cwd="/workspace") +model = provider.model("zed-agent") +agent = Agent(model) + +result = await agent.run("Summarize the current workspace state.") +print(result.output) +``` + +This keeps ownership boundaries explicit: + +- Pydantic AI owns the outer agent run, output validation, and normal model/provider lifecycle. +- ACP owns the delegated agent session, ACP-visible updates, and any editor or host capabilities requested by that agent. +- `AcpHostBridge` records ACP `session_update` messages and can delegate filesystem, terminal, approval, and extension callbacks to a real ACP host client when one is supplied. +- Pydantic AI function tools are intentionally not executed directly by `AcpModel`; register tools on the ACP agent or expose host capabilities through ACP. + +Use this bridge when the thing you have is already an ACP agent and you want it to participate in code that expects a Pydantic AI provider/model. It is not another ACP server adapter and it does not replace `create_acp_agent(...)`. + ## What `langchain-acp` Supports `langchain-acp` keeps ACP Kit's adapter seams intact while staying graph-centric on the upstream side. diff --git a/VERSION b/VERSION index 3eefcb9..9084fa2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.0 +1.1.0 diff --git a/examples/langchain/codex_graph.py b/examples/langchain/codex_graph.py index a741f7b..f2b5581 100644 --- a/examples/langchain/codex_graph.py +++ b/examples/langchain/codex_graph.py @@ -22,9 +22,9 @@ "MODEL_NAME", "acp_agent", "build_graph", + "codex_instructions", "config", "describe_codex_surface", - "codex_instructions", "graph", "graph_from_session", "main", @@ -48,7 +48,6 @@ def codex_instructions(*, mode_id: str) -> str: """Return the Codex Responses instructions used by this example graph.""" - base = ( "You are a precise workspace assistant. " "Use the available tools when they help, keep answers concise, " @@ -63,14 +62,13 @@ def codex_instructions(*, mode_id: str) -> str: def describe_codex_surface() -> str: """Summarize the Codex-backed LangChain example surface.""" - return "\n".join( ( "Codex graph features:", "- LangChain ChatOpenAI wired through codex-auth-helper", "- OpenAI Responses API transport through local Codex auth state", "- ready for `langchain-acp` exposure through `run_acp(graph=...)`", - ) + ), ) diff --git a/examples/langchain/deepagents_graph.py b/examples/langchain/deepagents_graph.py index c643606..c47ac3e 100644 --- a/examples/langchain/deepagents_graph.py +++ b/examples/langchain/deepagents_graph.py @@ -32,8 +32,8 @@ "MODEL_NAME", "WORKSPACE_ROOT", "acp_agent", - "config", "codex_instructions", + "config", "graph", "graph_from_session", "list_workspace_files", @@ -74,7 +74,6 @@ def codex_instructions(*, mode_id: str) -> str: """Return the Codex Responses instructions used by the DeepAgents example.""" - base = ( "You are a workspace agent that can inspect and update files in the current demo workspace. " "Use tools for concrete file work, keep changes scoped, and summarize what changed." @@ -126,7 +125,7 @@ def _resolve_workspace_path(path: str, *, root: Path | None = None) -> Path: if relative_to_parent.parts and relative_to_parent.parts[0] == workspace_root.name else relative_to_parent.parts - ) + ), ) candidate = (workspace_root / relative_to_parent).resolve() else: @@ -152,13 +151,11 @@ def _normalized_mock_path(path: str) -> str: def list_workspace_files() -> str: """List mocked workspace files exposed by the DeepAgents example.""" - return "\n".join(sorted(MOCK_WORKSPACE_FILES)) def read_file(path: str) -> str: """Read a mocked file from the DeepAgents example workspace.""" - normalized = _normalized_mock_path(path) content = MOCK_WORKSPACE_FILES.get(normalized) if content is None: @@ -168,7 +165,6 @@ def read_file(path: str) -> str: def write_file(path: str, content: str) -> str: """Pretend to write a file in the DeepAgents example workspace.""" - normalized = _normalized_mock_path(path) del content return f"Mock write accepted for {normalized}" @@ -212,7 +208,7 @@ def _write_file(path: str, content: str) -> str: def graph_from_session(session: AcpSessionContext) -> CompiledAgentGraph: if not _deepagents_available(): raise RuntimeError( - 'Install the optional DeepAgents dependency first: uv add "langchain-acp[deepagents]"' + 'Install the optional DeepAgents dependency first: uv add "langchain-acp[deepagents]"', ) workspace_root = _ensure_workspace(_session_workspace_root(session)).resolve() model_name = session.session_model_id or DEFAULT_MODEL_ID or MODEL_NAME @@ -221,7 +217,7 @@ def graph_from_session(session: AcpSessionContext) -> CompiledAgentGraph: tools: Sequence[DeepAgentTool] = [ *_bind_workspace_tools(workspace_root), - *cast(Sequence[DeepAgentTool], native_plan_tools()), + *cast("Sequence[DeepAgentTool]", native_plan_tools()), ] return create_deep_agent( model=create_codex_chat_openai( diff --git a/examples/langchain/workspace_graph.py b/examples/langchain/workspace_graph.py index 87d15fb..8fb9a9b 100644 --- a/examples/langchain/workspace_graph.py +++ b/examples/langchain/workspace_graph.py @@ -23,8 +23,8 @@ "MODEL_NAME", "WORKSPACE_ROOT", "acp_agent", - "config", "codex_instructions", + "config", "describe_workspace_surface", "graph", "graph_from_session", @@ -56,7 +56,6 @@ def codex_instructions(*, mode_id: str) -> str: """Return the Codex Responses instructions used by the workspace graph.""" - base = ( "You are a careful workspace assistant operating inside a small demo workspace. " "Prefer reading files before changing them, keep edits focused, " @@ -111,13 +110,12 @@ def _workspace_surface_summary() -> str: "- session-aware `graph_from_session(...)` for per-session graph construction", "- file read and write projection through `FileSystemProjectionMap`", "- a seeded workspace that keeps ACP rendering deterministic", - ) + ), ) def list_workspace_files() -> str: """List seeded workspace files that the demo graph can read.""" - root = _ensure_workspace() files = sorted(path.relative_to(root).as_posix() for path in root.rglob("*") if path.is_file()) return "\n".join(files) @@ -125,13 +123,11 @@ def list_workspace_files() -> str: def describe_workspace_surface() -> str: """Summarize the ACP-facing features exposed by the workspace graph example.""" - return _workspace_surface_summary() def read_workspace_note(path: str) -> str: """Read a workspace note and return its text content.""" - note_path = _resolve_workspace_path(path) if not note_path.exists(): raise ValueError(f"File not found: {path}") @@ -140,7 +136,6 @@ def read_workspace_note(path: str) -> str: def write_workspace_note(path: str, content: str) -> str: """Write a workspace note and return the saved relative path.""" - root = _ensure_workspace() return _write_workspace_note(root, path, content) diff --git a/examples/pydantic/finance_agent.py b/examples/pydantic/finance_agent.py index 0435a6c..442cea7 100644 --- a/examples/pydantic/finance_agent.py +++ b/examples/pydantic/finance_agent.py @@ -171,7 +171,6 @@ def persist_plan_state( @agent.tool_plain def describe_finance_surface() -> str: """Summarize the ACP-facing features available in this finance example.""" - return "\n".join( ( "Finance example features:", @@ -179,27 +178,25 @@ def describe_finance_surface() -> str: "- structured native plan generation in plan mode", "- approval-gated note writes with ACP file diffs", "- persisted plan snapshots under .acpkit/plans/", - ) + ), ) @agent.tool_plain(name=_WATCHLIST_TOOL) def list_watchlist() -> str: """List the seeded watchlist and workspace note files.""" - finance_root = _finance_root(Path.cwd()) return "\n\n".join( ( "Seeded symbols:\n" + "\n".join(f"- {symbol}" for symbol in sorted(_QUOTE_BOOK)), "Workspace files:\n" + _list_market_files(finance_root), - ) + ), ) @agent.tool_plain(name=_QUOTE_TOOL) def quote_symbol(symbol: str) -> str: """Return a deterministic demo quote for a watchlist symbol.""" - normalized_symbol = symbol.strip().upper() try: return _QUOTE_BOOK[normalized_symbol] @@ -210,14 +207,12 @@ def quote_symbol(symbol: str) -> str: @agent.tool_plain(name=_READ_NOTE_TOOL) def read_market_note(path: str, max_chars: int = _READ_PREVIEW_CHARS) -> str: """Read a finance workspace note relative to the current working directory.""" - return _read_market_note(_finance_root(Path.cwd()), path, max_chars=max_chars) @agent.tool_plain(name=_WRITE_NOTE_TOOL, requires_approval=True) def save_market_note(path: str, content: str) -> str: """Write a finance note inside the local workspace.""" - return _save_market_note(_finance_root(Path.cwd()), path, content) @@ -258,7 +253,7 @@ def save_market_note(path: str, content: str) -> str: FileSystemProjectionMap( default_read_tool=_READ_NOTE_TOOL, default_write_tool=_WRITE_NOTE_TOOL, - ) + ), ], ) acp_agent = create_acp_agent(agent=agent, config=config) diff --git a/examples/pydantic/mock_harness_agent.py b/examples/pydantic/mock_harness_agent.py index a167167..77f1e4b 100644 --- a/examples/pydantic/mock_harness_agent.py +++ b/examples/pydantic/mock_harness_agent.py @@ -108,7 +108,7 @@ def _harness_model(*, instructions: str = _INSTRUCTIONS) -> str | Model[Any]: except ModuleNotFoundError as exc: raise ModuleNotFoundError( "Install `codex-auth-helper`, unset `ACP_HARNESS_CODEX_MODEL`, or set " - "`ACP_HARNESS_MODEL` to a pydantic-ai model name before running the harness example." + "`ACP_HARNESS_MODEL` to a pydantic-ai model name before running the harness example.", ) from exc return create_codex_responses_model( configured_codex_model or _DEFAULT_CODEX_MODEL, @@ -130,7 +130,6 @@ def _build_config(*, include_code_mode: bool) -> AdapterConfig: def _build_agent(session: AcpSessionContext, *, include_code_mode: bool) -> Agent[None, str]: """Build a real model-backed agent wired with pydantic-ai-harness capabilities.""" - _ensure_workspace() harness_bridges = _build_harness_bridges( _WORKSPACE_ROOT, diff --git a/examples/pydantic/travel_agent.py b/examples/pydantic/travel_agent.py index 4bd86ad..49fb5ef 100644 --- a/examples/pydantic/travel_agent.py +++ b/examples/pydantic/travel_agent.py @@ -104,7 +104,8 @@ def _prompt_has_binary_media(prompt: Sequence[AgentPromptBlock]) -> bool: return True continue if isinstance(block, EmbeddedResourceContentBlock) and isinstance( - block.resource, BlobResourceContents + block.resource, + BlobResourceContents, ): return True return False @@ -204,21 +205,19 @@ async def observe_write_result( @agent.tool_plain def describe_travel_surface() -> str: """Summarize the ACP-facing surfaces available in this travel example.""" - return "\n".join( ( "Travel example features:", "- existing Hooks capability introspection rendered through HookProjectionMap", "- approval-gated file writes with ACP diffs", "- prompt-model override provider for image and audio prompts", - ) + ), ) @agent.tool_plain def list_trip_files() -> str: """List the demo travel files available in the local workspace.""" - _ensure_travel_workspace() return "\n".join(sorted(path.name for path in _TRAVEL_ROOT.iterdir() if path.is_file())) @@ -226,7 +225,6 @@ def list_trip_files() -> str: @agent.tool_plain(name=_READ_TOOL) def read_trip_file(path: str, max_chars: int = 4000) -> str: """Read a travel file and return a bounded preview.""" - if max_chars <= 0: raise ValueError("max_chars must be positive.") _ensure_travel_workspace() @@ -239,7 +237,6 @@ def read_trip_file(path: str, max_chars: int = 4000) -> str: @agent.tool_plain(name=_WRITE_TOOL, requires_approval=True) def write_trip_file(path: str, content: str) -> str: """Write a travel file inside the local demo workspace.""" - _ensure_travel_workspace() file_path = _resolve_trip_path(Path(path).name if Path(path).is_absolute() else path) file_path.write_text(content, encoding="utf-8") @@ -261,7 +258,7 @@ def write_trip_file(path: str, content: str) -> str: FileSystemProjectionMap( default_read_tool=_READ_TOOL, default_write_tool=_WRITE_TOOL, - ) + ), ], ) acp_agent = create_acp_agent(agent=agent, config=config) diff --git a/packages/adapters/langchain-acp/src/langchain_acp/__init__.py b/packages/adapters/langchain-acp/src/langchain_acp/__init__.py index bfd0639..12b406a 100644 --- a/packages/adapters/langchain-acp/src/langchain_acp/__init__.py +++ b/packages/adapters/langchain-acp/src/langchain_acp/__init__.py @@ -120,35 +120,35 @@ ) __all__ = ( - "__version__", + "DEFAULT_AGENT_NAME", + "DEFAULT_AGENT_TITLE", + "DEFAULT_AGENT_VERSION", "AcpAgent", "AcpSessionContext", "AdapterConfig", "AdapterPromptCapabilities", "AgentPromptBlock", "ApprovalBridge", + "ApprovalDecision", "ApprovalPolicy", "ApprovalPolicyStore", - "CompositeEventProjectionMap", - "ApprovalDecision", "AudioContentBlock", "BlobResourceContents", "BrowserProjectionMap", "BufferedCapabilityBridge", "CapabilityBridge", + "CommandProjectionMap", "CommunityFileManagementProjectionMap", "CompiledAgentGraph", + "CompositeEventProjectionMap", "CompositeProjectionMap", - "CommandProjectionMap", "ConfigOption", "ConfigOptionsBridge", "ConfigOptionsProvider", - "DEFAULT_AGENT_NAME", - "DEFAULT_AGENT_TITLE", - "DEFAULT_AGENT_VERSION", - "DefaultToolClassifier", - "DeepAgentsProjectionMap", "DeepAgentsCompatibilityBridge", + "DeepAgentsProjectionMap", + "DefaultPermissionToolCallBuilder", + "DefaultToolClassifier", "EmbeddedResourceContentBlock", "EventEmissionMode", "EventProjectionMap", @@ -157,14 +157,14 @@ "FileSessionStore", "FileSystemProjectionMap", "FinanceProjectionMap", - "GraphFactory", "GraphBridgeBuilder", "GraphBuildContributions", + "GraphFactory", "GraphSource", "HookEvent", "HookProjectionMap", - "HttpRequestProjectionMap", "HttpMcpServer", + "HttpRequestProjectionMap", "ImageContentBlock", "JsonValue", "LangChainAcpAgent", @@ -172,35 +172,34 @@ "MemorySessionStore", "ModeSelectionBridge", "ModeState", - "ModelSelectionState", "ModelSelectionBridge", - "NativePlanGeneration", + "ModelSelectionState", "NativeApprovalBridge", + "NativePlanGeneration", "NativePlanPersistenceProvider", + "PermissionOptionSet", + "PermissionRequestContext", + "PermissionToolCallBuilder", "PlanEntry", "PlanGenerationType", "PlanProvider", "ProjectionAwareApprovalBridge", "ProjectionAwareToolClassifier", "ProjectionMap", - "PermissionOptionSet", - "PermissionRequestContext", - "PermissionToolCallBuilder", - "DefaultPermissionToolCallBuilder", "ResourceContentBlock", "SessionMetadataApprovalPolicyStore", "SessionModelsProvider", "SessionModesProvider", "SessionStore", - "StaticGraphSource", - "StructuredEventProjectionMap", - "SseMcpServer", "SlashCommandHandler", "SlashCommandProvider", "SlashCommandRequest", "SlashCommandResult", + "SseMcpServer", + "StaticGraphSource", "StaticSlashCommand", "StaticSlashCommandProvider", + "StructuredEventProjectionMap", "TaskPlan", "TextContentBlock", "TextResourceContents", @@ -208,14 +207,15 @@ "ToolSurfaceBridge", "WebFetchProjectionMap", "WebSearchProjectionMap", + "__version__", "acp_get_plan", "acp_mark_plan_done", "acp_set_plan", "acp_update_plan_entry", "build_tool_progress_update", "build_tool_start_update", - "compose_projection_maps", "compose_event_projection_maps", + "compose_projection_maps", "create_acp_agent", "extract_tool_call_locations", "native_plan_tools", diff --git a/packages/adapters/langchain-acp/src/langchain_acp/_slash_commands.py b/packages/adapters/langchain-acp/src/langchain_acp/_slash_commands.py index 4e45eaa..3ba8dc2 100644 --- a/packages/adapters/langchain-acp/src/langchain_acp/_slash_commands.py +++ b/packages/adapters/langchain-acp/src/langchain_acp/_slash_commands.py @@ -18,7 +18,7 @@ MODEL_COMMAND_NAME, TOOLS_COMMAND_NAME, MCP_SERVERS_COMMAND_NAME, - } + }, ) @@ -30,7 +30,7 @@ def validate_mode_command_ids(mode_ids: Iterable[str]) -> None: raise ValueError("Mode slash command ids must be non-empty after normalization.") if any(character.isspace() for character in normalized_id): raise ValueError( - f"Mode slash command id {mode_id!r} cannot contain whitespace after normalization." + f"Mode slash command id {mode_id!r} cannot contain whitespace after normalization.", ) normalized_ids.append(normalized_id) duplicate_ids = sorted( @@ -42,5 +42,5 @@ def validate_mode_command_ids(mode_ids: Iterable[str]) -> None: if reserved_ids: raise ValueError( "Mode slash command ids cannot reuse reserved slash command names " - f"({', '.join(reserved_ids)})." + f"({', '.join(reserved_ids)}).", ) diff --git a/packages/adapters/langchain-acp/src/langchain_acp/_version.py b/packages/adapters/langchain-acp/src/langchain_acp/_version.py index 47a3698..19692fb 100644 --- a/packages/adapters/langchain-acp/src/langchain_acp/_version.py +++ b/packages/adapters/langchain-acp/src/langchain_acp/_version.py @@ -2,4 +2,4 @@ __all__ = ("__version__",) -__version__ = "1.0.0" +__version__ = "1.1.0" diff --git a/packages/adapters/langchain-acp/src/langchain_acp/approvals.py b/packages/adapters/langchain-acp/src/langchain_acp/approvals.py index 77be282..49d3133 100644 --- a/packages/adapters/langchain-acp/src/langchain_acp/approvals.py +++ b/packages/adapters/langchain-acp/src/langchain_acp/approvals.py @@ -76,7 +76,7 @@ class NativeApprovalBridge: option_set: PermissionOptionSet = field(default_factory=PermissionOptionSet) policy_store: ApprovalPolicyStore = field(default_factory=SessionMetadataApprovalPolicyStore) tool_call_builder: PermissionToolCallBuilder = field( - default_factory=DefaultPermissionToolCallBuilder + default_factory=DefaultPermissionToolCallBuilder, ) _supports_projection_aware_approval_bridge: bool = field( default=True, @@ -123,7 +123,7 @@ async def resolve_action_requests( allowed_decisions = review_config.get("allowed_decisions", ["approve", "reject"]) if "edit" in allowed_decisions and set(allowed_decisions) == {"edit"}: raise RequestError.invalid_request( - {"reason": "ACP permission prompts cannot collect edited tool arguments."} + {"reason": "ACP permission prompts cannot collect edited tool arguments."}, ) permission = await client.request_permission( session_id=session.session_id, @@ -137,7 +137,7 @@ async def resolve_action_requests( cwd=session.cwd, classifier=classifier, projection_map=projection_map, - ) + ), ), ) outcome = permission.outcome @@ -187,7 +187,7 @@ def _build_permission_options(self) -> list[PermissionOption]: name=self.option_set.reject_always_name, kind="reject_always", ), - ] + ], ) return options diff --git a/packages/adapters/langchain-acp/src/langchain_acp/bridge_manager.py b/packages/adapters/langchain-acp/src/langchain_acp/bridge_manager.py index 292a570..9b6f27b 100644 --- a/packages/adapters/langchain-acp/src/langchain_acp/bridge_manager.py +++ b/packages/adapters/langchain-acp/src/langchain_acp/bridge_manager.py @@ -19,7 +19,7 @@ async def _resolve_bridge_value(value: _T | Awaitable[_T]) -> _T: if isawaitable(value): - return await cast(Awaitable[_T], value) + return await cast("Awaitable[_T]", value) return value @@ -109,7 +109,7 @@ async def set_config_option( ) -> list[ConfigOption] | None: for bridge in self.bridges: options = await _resolve_bridge_value( - bridge.set_config_option(session, config_id, value) + bridge.set_config_option(session, config_id, value), ) if options is not None: return options diff --git a/packages/adapters/langchain-acp/src/langchain_acp/bridges/base.py b/packages/adapters/langchain-acp/src/langchain_acp/bridges/base.py index fc54f01..169b635 100644 --- a/packages/adapters/langchain-acp/src/langchain_acp/bridges/base.py +++ b/packages/adapters/langchain-acp/src/langchain_acp/bridges/base.py @@ -48,7 +48,8 @@ def get_session_metadata(self, session: AcpSessionContext) -> dict[str, JsonValu return None def get_interrupt_configuration( - self, session: AcpSessionContext + self, + session: AcpSessionContext, ) -> dict[str, JsonValue] | None: del session return None @@ -189,6 +190,6 @@ def _record_progress_event( kind=kind, status=status, raw_output=raw_output, - ) + ), ], ) diff --git a/packages/adapters/langchain-acp/src/langchain_acp/bridges/builtin.py b/packages/adapters/langchain-acp/src/langchain_acp/bridges/builtin.py index 8f06b38..2faaea0 100644 --- a/packages/adapters/langchain-acp/src/langchain_acp/bridges/builtin.py +++ b/packages/adapters/langchain-acp/src/langchain_acp/bridges/builtin.py @@ -187,8 +187,8 @@ def extract_plan_entries(self, payload: JsonValue) -> list[PlanEntry] | None: entries.append( PlanEntry( content=content, - status=cast(PlanEntryStatus, status), - priority=cast(PlanEntryPriority, priority), - ) + status=cast("PlanEntryStatus", status), + priority=cast("PlanEntryPriority", priority), + ), ) return entries diff --git a/packages/adapters/langchain-acp/src/langchain_acp/config.py b/packages/adapters/langchain-acp/src/langchain_acp/config.py index d5b6c3f..e532851 100644 --- a/packages/adapters/langchain-acp/src/langchain_acp/config.py +++ b/packages/adapters/langchain-acp/src/langchain_acp/config.py @@ -59,7 +59,7 @@ class AdapterConfig: plan_provider: PlanProvider | None = None projection_maps: Sequence[ProjectionMap] = field(default_factory=tuple) prompt_capabilities: AdapterPromptCapabilities = field( - default_factory=AdapterPromptCapabilities + default_factory=AdapterPromptCapabilities, ) replay_history_on_load: bool = True slash_command_provider: SlashCommandProvider | None = None diff --git a/packages/adapters/langchain-acp/src/langchain_acp/event_projection.py b/packages/adapters/langchain-acp/src/langchain_acp/event_projection.py index ecb9683..ea92df9 100644 --- a/packages/adapters/langchain-acp/src/langchain_acp/event_projection.py +++ b/packages/adapters/langchain-acp/src/langchain_acp/event_projection.py @@ -90,18 +90,18 @@ def _extract_event_payloads( projected_payloads: list[dict[str, JsonValue]] = [] for item in payload: if _is_string_keyed_json_object(item): - projected_payloads.append(cast(dict[str, JsonValue], item)) + projected_payloads.append(cast("dict[str, JsonValue]", item)) return tuple(projected_payloads) or None if not _is_string_keyed_json_object(payload): return None - payload_object = cast(dict[str, JsonValue], payload) + payload_object = cast("dict[str, JsonValue]", payload) for key in event_keys: candidate = payload_object.get(key) if isinstance(candidate, list): nested_payloads: list[dict[str, JsonValue]] = [] for item in candidate: if _is_string_keyed_json_object(item): - nested_payloads.append(cast(dict[str, JsonValue], item)) + nested_payloads.append(cast("dict[str, JsonValue]", item)) return tuple(nested_payloads) or None if _resolve_session_update_kind(payload_object) is not None: return (payload_object,) @@ -144,8 +144,8 @@ def _event_payload_to_update( normalized["content"] = [ ContentToolCallContent( type="content", - content=TextContentBlock(type="text", text=cast(str, normalized["content"])), - ).model_dump(mode="json", by_alias=True) + content=TextContentBlock(type="text", text=cast("str", normalized["content"])), + ).model_dump(mode="json", by_alias=True), ] try: return ToolCallProgress.model_validate(normalized) diff --git a/packages/adapters/langchain-acp/src/langchain_acp/graph_source.py b/packages/adapters/langchain-acp/src/langchain_acp/graph_source.py index 8f739ca..956ccf3 100644 --- a/packages/adapters/langchain-acp/src/langchain_acp/graph_source.py +++ b/packages/adapters/langchain-acp/src/langchain_acp/graph_source.py @@ -22,7 +22,8 @@ class GraphFactory(Protocol): def __call__( - self, session: AcpSessionContext + self, + session: AcpSessionContext, ) -> CompiledAgentGraph | Awaitable[CompiledAgentGraph]: ... @@ -46,5 +47,5 @@ class FactoryGraphSource: async def get_graph(self, session: AcpSessionContext) -> CompiledAgentGraph: candidate = self.factory(session) if isawaitable(candidate): - return cast(CompiledAgentGraph, await candidate) - return cast(CompiledAgentGraph, candidate) + return cast("CompiledAgentGraph", await candidate) + return cast("CompiledAgentGraph", candidate) diff --git a/packages/adapters/langchain-acp/src/langchain_acp/hook_projection.py b/packages/adapters/langchain-acp/src/langchain_acp/hook_projection.py index eeafb35..dad1249 100644 --- a/packages/adapters/langchain-acp/src/langchain_acp/hook_projection.py +++ b/packages/adapters/langchain-acp/src/langchain_acp/hook_projection.py @@ -48,7 +48,7 @@ def build_start_update( ContentToolCallContent( type="content", content=TextContentBlock(type="text", text=event.summary), - ) + ), ], ) @@ -73,6 +73,6 @@ def build_progress_update( ContentToolCallContent( type="content", content=TextContentBlock(type="text", text=detail), - ) + ), ], ) diff --git a/packages/adapters/langchain-acp/src/langchain_acp/plan.py b/packages/adapters/langchain-acp/src/langchain_acp/plan.py index f4a2371..735b798 100644 --- a/packages/adapters/langchain-acp/src/langchain_acp/plan.py +++ b/packages/adapters/langchain-acp/src/langchain_acp/plan.py @@ -74,7 +74,7 @@ def _bind_native_plan_context( session: AcpSessionContext, ) -> Iterator[None]: token: Token[_BoundPlanContext | None] = _ACTIVE_PLAN_CONTEXT.set( - _BoundPlanContext(runtime=runtime, session=session) + _BoundPlanContext(runtime=runtime, session=session), ) try: yield diff --git a/packages/adapters/langchain-acp/src/langchain_acp/projection.py b/packages/adapters/langchain-acp/src/langchain_acp/projection.py index 4a1b39c..aed360b 100644 --- a/packages/adapters/langchain-acp/src/langchain_acp/projection.py +++ b/packages/adapters/langchain-acp/src/langchain_acp/projection.py @@ -21,16 +21,16 @@ __all__ = ( "BrowserProjectionMap", + "CommandProjectionMap", "CommunityFileManagementProjectionMap", "CompositeProjectionMap", - "CommandProjectionMap", "DeepAgentsProjectionMap", "DefaultToolClassifier", "FileSystemProjectionMap", "FinanceProjectionMap", "HttpRequestProjectionMap", - "ProjectionMap", "ProjectionAwareToolClassifier", + "ProjectionMap", "ToolClassifier", "WebFetchProjectionMap", "WebSearchProjectionMap", @@ -80,7 +80,7 @@ "searx_search_results", "tavily_answer", "tavily_search_results_json", - } + }, ) _DEFAULT_WEB_FETCH_TOOL_NAMES = frozenset( { @@ -89,11 +89,11 @@ "requests_patch", "requests_post", "requests_put", - } + }, ) _DEFAULT_BROWSER_NAVIGATE_TOOL_NAMES = frozenset({"navigate_browser"}) _DEFAULT_BROWSER_READ_TOOL_NAMES = frozenset( - {"current_webpage", "extract_hyperlinks", "extract_text", "get_elements"} + {"current_webpage", "extract_hyperlinks", "extract_text", "get_elements"}, ) _DEFAULT_BROWSER_ACTION_TOOL_NAMES = frozenset({"click_element", "previous_webpage"}) _DEFAULT_COMMAND_TOOL_NAMES = frozenset({"terminal"}) @@ -103,7 +103,7 @@ _DEFAULT_FILE_MANAGEMENT_MUTATION_TOOL_NAMES = frozenset({"copy_file", "file_delete", "move_file"}) _DEFAULT_FINANCE_SEARCH_TOOL_NAMES = frozenset({"google_finance", "yahoo_finance_news"}) _DEFAULT_FINANCE_DATASET_TOOL_NAMES = frozenset( - {"balance_sheets", "cash_flow_statements", "income_statements"} + {"balance_sheets", "cash_flow_statements", "income_statements"}, ) _WEB_SEARCH_QUERY_KEYS = ("query", "q", "search_term", "search_query") _WEB_FETCH_URL_KEYS = ("url", "href", "link", "uri") @@ -298,7 +298,7 @@ def project_start( risk_note = _command_risk_note(command) if risk_note is not None: content.append( - ContentToolCallContent(type="content", content=_text_block(risk_note)) + ContentToolCallContent(type="content", content=_text_block(risk_note)), ) return ToolProjection( content=content, @@ -317,7 +317,7 @@ def project_start( path=path, old_text=old_text, new_text=new_text, - ) + ), ], locations=[ToolCallLocation(path=path)], title=_tool_title(tool_name, path=path), @@ -364,7 +364,7 @@ def project_progress( path=path, old_text="", new_text=serialized_output, - ) + ), ], locations=[ToolCallLocation(path=path)], title=_tool_title(tool_name, path=path), @@ -379,7 +379,7 @@ def project_progress( output_text = _output_text(raw_output, serialized_output) if output_text: content.append( - ContentToolCallContent(type="content", content=_text_block(output_text)) + ContentToolCallContent(type="content", content=_text_block(output_text)), ) return ToolProjection( content=content or None, @@ -478,7 +478,7 @@ def project_start( ContentToolCallContent( type="content", content=_text_block(_format_web_search_start(raw_input)), - ) + ), ], title=f"Search web for {_single_line_preview(query, limit=_MAX_COMMAND_TITLE_CHARS)}", ) @@ -502,7 +502,7 @@ def project_progress( ContentToolCallContent( type="content", content=_text_block(_format_web_search_progress(raw_output, serialized_output)), - ) + ), ], title=( f"Search web for {_single_line_preview(query, limit=_MAX_COMMAND_TITLE_CHARS)}" @@ -535,7 +535,7 @@ def project_start( ContentToolCallContent( type="content", content=_text_block(_format_web_fetch_start(raw_input)), - ) + ), ], title=f"{method} {_single_line_preview(url, limit=_MAX_COMMAND_TITLE_CHARS)}", ) @@ -560,7 +560,7 @@ def project_progress( ContentToolCallContent( type="content", content=_text_block(_format_web_fetch_progress(raw_output, serialized_output)), - ) + ), ], title=( f"{method} {_single_line_preview(url, limit=_MAX_COMMAND_TITLE_CHARS)}" @@ -598,7 +598,7 @@ def project_start( ContentToolCallContent( type="content", content=_text_block(f"URL: {url}"), - ) + ), ], title=f"Navigate {_single_line_preview(url, limit=_MAX_COMMAND_TITLE_CHARS)}", ) @@ -611,7 +611,7 @@ def project_start( ContentToolCallContent( type="content", content=_text_block(f"Selector: {selector}"), - ) + ), ], title=f"Click {_single_line_preview(selector, limit=_MAX_COMMAND_TITLE_CHARS)}", ) @@ -624,9 +624,9 @@ def project_start( content=_text_block( f"Selector: {selector}" if selector is not None - else "Inspect page elements." + else "Inspect page elements.", ), - ) + ), ], title=( f"Inspect {_single_line_preview(selector, limit=_MAX_COMMAND_TITLE_CHARS)}" @@ -659,7 +659,7 @@ def project_progress( ContentToolCallContent( type="content", content=_text_block(_browser_text_preview(raw_output, serialized_output)), - ) + ), ], title=( f"Navigate {_single_line_preview(url, limit=_MAX_COMMAND_TITLE_CHARS)}" @@ -673,9 +673,9 @@ def project_progress( ContentToolCallContent( type="content", content=_text_block( - _format_browser_link_results(raw_output, serialized_output) + _format_browser_link_results(raw_output, serialized_output), ), - ) + ), ], title="Extract hyperlinks", ) @@ -685,9 +685,9 @@ def project_progress( ContentToolCallContent( type="content", content=_text_block( - _format_browser_element_results(raw_output, serialized_output) + _format_browser_element_results(raw_output, serialized_output), ), - ) + ), ], title="Inspect page elements", ) @@ -697,7 +697,7 @@ def project_progress( ContentToolCallContent( type="content", content=_text_block(_browser_text_preview(raw_output, serialized_output)), - ) + ), ], title=_browser_progress_title(tool_name), ) @@ -716,7 +716,7 @@ def project_start( raw_input: Any = None, ) -> ToolProjection | None: projection = FileSystemProjectionMap( - execute_tool_names=self.execute_tool_names + execute_tool_names=self.execute_tool_names, ).project_start( tool_name, cwd=cwd, @@ -739,7 +739,7 @@ def project_progress( status: ToolCallStatus, ) -> ToolProjection | None: projection = FileSystemProjectionMap( - execute_tool_names=self.execute_tool_names + execute_tool_names=self.execute_tool_names, ).project_progress( tool_name, cwd=cwd, @@ -792,7 +792,7 @@ def project_start( lines.append(f"Pattern: {pattern}") return ToolProjection( content=[ - ContentToolCallContent(type="content", content=_text_block("\n".join(lines))) + ContentToolCallContent(type="content", content=_text_block("\n".join(lines))), ], locations=[ToolCallLocation(path=directory)], title=( @@ -818,7 +818,7 @@ def project_start( ContentToolCallContent( type="content", content=_text_block(f"From: {source_path}\nTo: {destination_path}"), - ) + ), ], locations=[ ToolCallLocation(path=source_path), @@ -869,9 +869,9 @@ def project_progress( ContentToolCallContent( type="content", content=_text_block( - _truncate_text(serialized_output, limit=_MAX_CONTENT_PREVIEW_CHARS) + _truncate_text(serialized_output, limit=_MAX_CONTENT_PREVIEW_CHARS), ), - ) + ), ], locations=[ToolCallLocation(path=directory)], title=( @@ -887,9 +887,9 @@ def project_progress( ContentToolCallContent( type="content", content=_text_block( - _truncate_text(serialized_output, limit=_MAX_CONTENT_PREVIEW_CHARS) + _truncate_text(serialized_output, limit=_MAX_CONTENT_PREVIEW_CHARS), ), - ) + ), ], locations=[ToolCallLocation(path=directory)], title=f"List `{directory}`", @@ -901,9 +901,9 @@ def project_progress( ContentToolCallContent( type="content", content=_text_block( - _truncate_text(serialized_output, limit=_MAX_CONTENT_PREVIEW_CHARS) + _truncate_text(serialized_output, limit=_MAX_CONTENT_PREVIEW_CHARS), ), - ) + ), ], locations=_file_management_locations(raw_input), ) @@ -930,9 +930,9 @@ def project_start( ContentToolCallContent( type="content", content=_text_block( - f"Query: {query}" if query is not None else "Lookup financial data." + f"Query: {query}" if query is not None else "Lookup financial data.", ), - ) + ), ], title=(f"Search finance for {query}" if query is not None else "Search finance"), ) @@ -965,9 +965,9 @@ def project_progress( _truncate_text( _output_text(raw_output, serialized_output), limit=_MAX_CONTENT_PREVIEW_CHARS, - ) + ), ), - ) + ), ], ) if tool_name in self.dataset_tool_names: @@ -980,9 +980,9 @@ def project_progress( _truncate_text( _output_text(raw_output, serialized_output), limit=_MAX_CONTENT_PREVIEW_CHARS, - ) + ), ), - ) + ), ], ) return None @@ -996,7 +996,7 @@ class DeepAgentsProjectionMap: write_tool_names=frozenset({"edit_file", "write_file"}), search_tool_names=frozenset({"glob", "grep", "ls"}), execute_tool_names=frozenset({"execute"}), - ) + ), ) def project_start( diff --git a/packages/adapters/langchain-acp/src/langchain_acp/runtime/_native_plan_runtime.py b/packages/adapters/langchain-acp/src/langchain_acp/runtime/_native_plan_runtime.py index f914dc8..4eced98 100644 --- a/packages/adapters/langchain-acp/src/langchain_acp/runtime/_native_plan_runtime.py +++ b/packages/adapters/langchain-acp/src/langchain_acp/runtime/_native_plan_runtime.py @@ -44,7 +44,7 @@ def supports_native_plan_writes(self, session: AcpSessionContext) -> bool: def requires_structured_plan_output(self, session: AcpSessionContext) -> bool: return self.supports_native_plan_state(session) and self.uses_structured_plan_generation( - session + session, ) def supports_plan_generation_selection(self) -> bool: @@ -56,7 +56,7 @@ def current_plan_generation_type(self, session: AcpSessionContext) -> PlanGenera isinstance(configured_value, str) and configured_value in _PLAN_GENERATION_CONFIG_OPTIONS ): - return cast(PlanGenerationType, configured_value) + return cast("PlanGenerationType", configured_value) return self._owner._config.default_plan_generation_type def uses_tool_plan_generation(self, session: AcpSessionContext) -> bool: @@ -87,7 +87,7 @@ async def config_options(self, session: AcpSessionContext) -> list[ConfigOption] ) for value in _PLAN_GENERATION_CONFIG_OPTIONS ], - ) + ), ] def get_native_plan_entries(self, session: AcpSessionContext) -> list[PlanEntry] | None: @@ -134,7 +134,7 @@ async def persist_native_plan_state( session=session, entries=entries, plan_markdown=plan_markdown, - ) + ), ) session.updated_at = utc_now() self._owner._store.save(session) @@ -167,7 +167,7 @@ async def update_native_plan_entry( { "index": index, "plan": f"Plan entry index must be between 1 and {len(entries)}.", - } + }, ) existing_entry = entries[index - 1] updated_payload = existing_entry.model_dump(mode="python") @@ -198,7 +198,7 @@ def format_native_plan(self, session: AcpSessionContext) -> str: session.plan_markdown.rstrip(), "Additional plan instructions:", additional_instructions, - ) + ), ) return "No plan has been recorded yet." numbered_entries = "\n".join( @@ -220,7 +220,7 @@ def format_native_plan(self, session: AcpSessionContext) -> str: "Current plan entries:", numbered_entries, *sections, - ) + ), ) def _native_plan_additional_instructions(self) -> str | None: diff --git a/packages/adapters/langchain-acp/src/langchain_acp/runtime/_prompt_conversion.py b/packages/adapters/langchain-acp/src/langchain_acp/runtime/_prompt_conversion.py index f0ef95b..98e1f5f 100644 --- a/packages/adapters/langchain-acp/src/langchain_acp/runtime/_prompt_conversion.py +++ b/packages/adapters/langchain-acp/src/langchain_acp/runtime/_prompt_conversion.py @@ -28,7 +28,7 @@ def prompt_to_langchain_content(prompt: list[AgentPromptBlock]) -> list[dict[str { "type": "image_url", "image_url": {"url": f"data:{block.mime_type};base64,{block.data}"}, - } + }, ) continue if isinstance(block, AudioContentBlock): @@ -37,7 +37,7 @@ def prompt_to_langchain_content(prompt: list[AgentPromptBlock]) -> list[dict[str "type": "audio", "base64": block.data, "mime_type": block.mime_type, - } + }, ) continue if isinstance(block, ResourceContentBlock): @@ -80,7 +80,7 @@ def _embedded_resource_content( { "type": "image_url", "image_url": {"url": f"data:{mime_type};base64,{resource.blob}"}, - } + }, ] if mime_type.startswith("audio/"): return [ @@ -88,7 +88,7 @@ def _embedded_resource_content( "type": "audio", "base64": resource.blob, "mime_type": mime_type, - } + }, ] return [{"type": "text", "text": _format_blob_resource(resource)}] return [{"type": "text", "text": f"Embedded resource: {resource.uri}"}] diff --git a/packages/adapters/langchain-acp/src/langchain_acp/runtime/adapter.py b/packages/adapters/langchain-acp/src/langchain_acp/runtime/adapter.py index a0e715c..aacd530 100644 --- a/packages/adapters/langchain-acp/src/langchain_acp/runtime/adapter.py +++ b/packages/adapters/langchain-acp/src/langchain_acp/runtime/adapter.py @@ -104,7 +104,7 @@ def __init__(self, graph_source: GraphSource, *, config: AdapterConfig) -> None: self._native_plan_runtime = _NativePlanRuntime(self) self._projection_map: ProjectionMap | None = compose_projection_maps(config.projection_maps) self._event_projection_map: EventProjectionMap | None = compose_event_projection_maps( - config.event_projection_maps + config.event_projection_maps, ) self._graph_bridge_builder = GraphBridgeBuilder.from_config(config) self._bridge_manager: BridgeManager = self._graph_bridge_builder.build_manager() @@ -220,7 +220,7 @@ async def list_sessions( updated_at=session.updated_at.isoformat(), ) for session in sessions - ] + ], ) async def set_session_mode( @@ -283,7 +283,7 @@ async def set_config_option( else: session.config_values[config_id] = value provider_options = await self._await_maybe( - self._bridge_manager.set_config_option(session, config_id, value) + self._bridge_manager.set_config_option(session, config_id, value), ) if provider_options is not None: self._sync_bridge_metadata(session) @@ -291,7 +291,7 @@ async def set_config_option( session.updated_at = utc_now() self._store.save(session) return SetSessionConfigOptionResponse( - config_options=await self._config_options(session) + config_options=await self._config_options(session), ) self._sync_bridge_metadata(session) await self._drain_bridge_updates(client=self._client, session=session) @@ -307,7 +307,7 @@ async def prompt( **kwargs: Any, ) -> PromptResponse: del kwargs - current_task = cast(asyncio.Task[Any], asyncio.current_task()) + current_task = cast("asyncio.Task[Any]", asyncio.current_task()) self._active_prompt_tasks[session_id] = current_task try: return await self._execute_prompt( @@ -348,7 +348,10 @@ async def _execute_prompt( return slash_response await self._drain_bridge_updates(client=client, session=session) await self._emit_user_prompt( - client=client, session=session, prompt=prompt, message_id=message_id + client=client, + session=session, + prompt=prompt, + message_id=message_id, ) active_tool_calls: dict[str, dict[str, Any]] = {} tool_call_accumulator: dict[int, dict[str, str | int | None]] = {} @@ -370,8 +373,8 @@ async def _execute_prompt( { "role": "user", "content": prompt_to_langchain_content(prompt), - } - ] + }, + ], } should_resume = False @@ -478,7 +481,6 @@ async def cancel(self, session_id: str, **kwargs: Any) -> None: async def authenticate(self, method_id: str, **kwargs: Any) -> None: del method_id, kwargs - return None async def ext_method(self, method: str, params: dict[str, Any]) -> dict[str, Any]: del params @@ -534,8 +536,8 @@ async def _maybe_handle_slash_prompt( raw_prompt=prompt_text, session=session, graph=graph, - ) - ) + ), + ), ) if result is None or not result.handled: return None @@ -669,7 +671,7 @@ async def _available_commands( custom_commands = None if self._config.slash_command_provider is not None: custom_commands = await self._await_maybe( - self._config.slash_command_provider.available_commands(session, graph) + self._config.slash_command_provider.available_commands(session, graph), ) return build_available_commands( mode_state=mode_state, @@ -772,12 +774,12 @@ async def _process_tool_call_chunks( if isinstance(tool_name, str): state["name"] = tool_name if isinstance(args_fragment, str): - state["args"] = f"{cast(str, state['args'])}{args_fragment}" - resolved_id = cast(str | None, state["id"]) - resolved_name = cast(str | None, state["name"]) + state["args"] = f"{cast('str', state['args'])}{args_fragment}" + resolved_id = cast("str | None", state["id"]) + resolved_name = cast("str | None", state["name"]) if resolved_id is None or resolved_name is None or resolved_id in active_tool_calls: continue - raw_input = self._try_parse_json_object(cast(str, state["args"])) + raw_input = self._try_parse_json_object(cast("str", state["args"])) if raw_input is None: continue update = build_tool_start_update( @@ -901,7 +903,7 @@ async def _handle_update_payload( ) await self._emit_projected_events(client=client, session=session, payload=payload) for update in payload.values(): - plan_entries = self._bridge_manager.extract_plan_entries(cast(JsonValue, update)) + plan_entries = self._bridge_manager.extract_plan_entries(cast("JsonValue", update)) if plan_entries is not None: await self._emit_plan_update(client=client, session=session, entries=plan_entries) return None @@ -915,11 +917,11 @@ async def _emit_projected_events( ) -> None: if self._event_projection_map is None: return - candidates: list[JsonValue] = [cast(JsonValue, payload)] + candidates: list[JsonValue] = [cast("JsonValue", payload)] seen_ids: set[int] = {id(payload)} for value in payload.values(): if isinstance(value, dict) and id(value) not in seen_ids: - candidates.append(cast(JsonValue, value)) + candidates.append(cast("JsonValue", value)) seen_ids.add(id(value)) for candidate in candidates: projected_updates = self._event_projection_map.project_event_payload(candidate) @@ -950,8 +952,8 @@ async def _resolve_interrupts( resolution = await self._approval_bridge.resolve_action_requests( client=client, session=session, - action_requests=cast(list[dict[str, Any]], action_requests), - review_configs=cast(list[dict[str, Any]], review_configs), + action_requests=cast("list[dict[str, Any]]", action_requests), + review_configs=cast("list[dict[str, Any]]", review_configs), classifier=self._tool_classifier, projection_map=self._projection_map, ) @@ -959,8 +961,8 @@ async def _resolve_interrupts( resolution = await self._approval_bridge.resolve_action_requests( client=client, session=session, - action_requests=cast(list[dict[str, Any]], action_requests), - review_configs=cast(list[dict[str, Any]], review_configs), + action_requests=cast("list[dict[str, Any]]", action_requests), + review_configs=cast("list[dict[str, Any]]", review_configs), classifier=self._tool_classifier, ) if resolution.cancelled: @@ -1075,7 +1077,7 @@ async def _config_options(self, session: AcpSessionContext) -> list[ConfigOption SessionConfigSelectOption(name=mode.name, value=mode.id) for mode in mode_state.modes ], - ) + ), ) model_state = await self._resolved_model_selection_state(session) if model_state is not None and model_state.enable_config_option: @@ -1091,7 +1093,7 @@ async def _config_options(self, session: AcpSessionContext) -> list[ConfigOption SessionConfigSelectOption(name=model.name, value=model.model_id) for model in model_state.available_models ], - ) + ), ) bridge_options = await self._await_maybe(self._bridge_manager.get_config_options(session)) if bridge_options is not None: @@ -1158,7 +1160,7 @@ def _serialize_mcp_servers( return [] return [ cast( - dict[str, JsonValue], + "dict[str, JsonValue]", server.model_dump(mode="json", by_alias=True, exclude_none=True), ) for server in mcp_servers @@ -1191,7 +1193,8 @@ def _ensure_checkpointer(self, graph: Any) -> Any: return builder.compile(checkpointer=MemorySaver(), name=getattr(graph, "name", None)) async def _resolved_model_selection_state( - self, session: AcpSessionContext + self, + session: AcpSessionContext, ) -> ModelSelectionState | None: return await self._await_maybe(self._bridge_manager.get_model_state(session)) @@ -1211,7 +1214,9 @@ async def _initial_mode_id(self, session: AcpSessionContext) -> str | None: return mode_state.current_mode_id async def _set_model( - self, session: AcpSessionContext, model_id: str + self, + session: AcpSessionContext, + model_id: str, ) -> ModelSelectionState | None: return await self._await_maybe(self._bridge_manager.set_model(session, model_id)) diff --git a/packages/adapters/langchain-acp/src/langchain_acp/runtime/server.py b/packages/adapters/langchain-acp/src/langchain_acp/runtime/server.py index 962252a..3524715 100644 --- a/packages/adapters/langchain-acp/src/langchain_acp/runtime/server.py +++ b/packages/adapters/langchain-acp/src/langchain_acp/runtime/server.py @@ -68,7 +68,7 @@ def _resolve_graph_source( provided_count = sum(provided is not None for provided in (graph, graph_factory, graph_source)) if provided_count != 1: raise ValueError( - "Exactly one of `graph`, `graph_factory`, or `graph_source` must be provided." + "Exactly one of `graph`, `graph_factory`, or `graph_source` must be provided.", ) if graph is not None: return StaticGraphSource(graph) @@ -92,10 +92,10 @@ def _resolve_config( event_projection_maps=tuple( event_projection_maps if event_projection_maps is not None - else resolved_config.event_projection_maps + else resolved_config.event_projection_maps, ), projection_maps=tuple( - projection_maps if projection_maps is not None else resolved_config.projection_maps + projection_maps if projection_maps is not None else resolved_config.projection_maps, ), ) if graph_name is None or resolved_config.agent_name != DEFAULT_AGENT_NAME: diff --git a/packages/adapters/langchain-acp/src/langchain_acp/runtime/slash_commands.py b/packages/adapters/langchain-acp/src/langchain_acp/runtime/slash_commands.py index fc929d9..2bc81cd 100644 --- a/packages/adapters/langchain-acp/src/langchain_acp/runtime/slash_commands.py +++ b/packages/adapters/langchain-acp/src/langchain_acp/runtime/slash_commands.py @@ -77,7 +77,7 @@ def build_available_commands( name=MODEL_COMMAND_NAME, description="Show the current session model, or set it with a provider:model value.", input=AvailableCommandInput(root=UnstructuredCommandInput(hint="provider:model")), - ) + ), ) commands.extend( [ @@ -89,7 +89,7 @@ def build_available_commands( name=MCP_SERVERS_COMMAND_NAME, description="List MCP servers attached to the current session.", ), - ] + ], ) if custom_commands: validate_custom_commands(custom_commands, mode_state=mode_state) @@ -108,7 +108,7 @@ def validate_custom_commands( if command.name != normalized_name: raise ValueError( f"Slash command name {command.name!r} must already be normalized as " - "a lowercase slash command id." + "a lowercase slash command id.", ) if not _COMMAND_NAME_PATTERN.fullmatch(normalized_name): raise ValueError(f"Slash command name {command.name!r} must match ^[a-z][a-z0-9-]*$.") @@ -119,13 +119,13 @@ def validate_custom_commands( if duplicate_names: raise ValueError( "Custom slash command names must be unique after normalization. " - f"Duplicate ids: {', '.join(duplicate_names)}." + f"Duplicate ids: {', '.join(duplicate_names)}.", ) reserved_names = sorted(set(normalized_names) & RESERVED_SLASH_COMMAND_NAMES) if reserved_names: raise ValueError( "Custom slash command names cannot reuse reserved slash command names " - f"({', '.join(reserved_names)})." + f"({', '.join(reserved_names)}).", ) if mode_state is None: return @@ -134,7 +134,7 @@ def validate_custom_commands( if conflicting_mode_ids: raise ValueError( "Custom slash command names cannot reuse active mode ids " - f"({', '.join(conflicting_mode_ids)})." + f"({', '.join(conflicting_mode_ids)}).", ) @@ -184,7 +184,7 @@ def render_mcp_server_listing(server_infos: list[McpServerInfo]) -> str: for server_info in server_infos: lines.append( f"- {server_info.name} ({server_info.transport}, {server_info.source}): " - f"{server_info.target}" + f"{server_info.target}", ) return "\n".join(lines) @@ -212,7 +212,7 @@ def list_graph_tools(graph: Any) -> list[ToolInfo]: ToolInfo( name=name, description=description if isinstance(description, str) else None, - ) + ), ) return tool_infos diff --git a/packages/adapters/langchain-acp/src/langchain_acp/session/state.py b/packages/adapters/langchain-acp/src/langchain_acp/session/state.py index 377db72..c597aaf 100644 --- a/packages/adapters/langchain-acp/src/langchain_acp/session/state.py +++ b/packages/adapters/langchain-acp/src/langchain_acp/session/state.py @@ -66,7 +66,7 @@ class StoredSessionUpdate: @classmethod def from_update(cls, update: SessionTranscriptUpdate) -> StoredSessionUpdate: payload = _coerce_json_object( - update.model_dump(mode="json", by_alias=True, exclude_none=True) + update.model_dump(mode="json", by_alias=True, exclude_none=True), ) session_update = payload.get("sessionUpdate") if not _is_transcript_kind(session_update): diff --git a/packages/adapters/langchain-acp/src/langchain_acp/session/store.py b/packages/adapters/langchain-acp/src/langchain_acp/session/store.py index f88db97..5575bba 100644 --- a/packages/adapters/langchain-acp/src/langchain_acp/session/store.py +++ b/packages/adapters/langchain-acp/src/langchain_acp/session/store.py @@ -24,7 +24,7 @@ _MAX_SESSION_ID_LENGTH = 128 _SESSION_ID_SAFE_CHARS = frozenset( - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-" + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-", ) _STORE_LOCKS: dict[str, threading.RLock] = {} _STORE_LOCKS_GUARD = threading.Lock() @@ -34,7 +34,11 @@ class SessionStore(Protocol): def delete(self, session_id: str) -> None: ... def fork( - self, session_id: str, *, new_session_id: str, cwd: Path + self, + session_id: str, + *, + new_session_id: str, + cwd: Path, ) -> AcpSessionContext | None: ... def get(self, session_id: str) -> AcpSessionContext | None: ... diff --git a/packages/adapters/pydantic-acp/README.md b/packages/adapters/pydantic-acp/README.md index 575742a..a19e9ed 100644 --- a/packages/adapters/pydantic-acp/README.md +++ b/packages/adapters/pydantic-acp/README.md @@ -18,6 +18,7 @@ The core contract is simple: 2. expose it through ACP 3. only publish ACP-visible state the runtime can actually honor +The package also includes the inverse bridge: an ACP agent can be consumed as a Pydantic AI v2 provider/model pair via `AcpProvider` and `AcpModel`. The final v1 stability boundary is defined by the [ACP Kit versioning policy](https://vcoderun.github.io/acpkit/versioning/). @@ -29,8 +30,9 @@ The final v1 stability boundary is defined by the - `AcpSessionContext` - `StaticAgentSource` - `FactoryAgentSource` -- `MemorySessionStore` -- `FileSessionStore` +- `AcpProvider` +- `AcpModel` +- `AcpHostBridge` ## What It Covers @@ -45,9 +47,12 @@ The final v1 stability boundary is defined by the - projection maps for filesystem, hooks, web tools, and builtin tool families - capability bridges for upstream Pydantic AI capabilities - client-backed filesystem and terminal helpers +- ACP client/provider bridging for consuming ACP agents from the Pydantic AI ecosystem ## Quick Start +Expose a Pydantic AI agent through ACP: + ```python from pydantic_ai import Agent from pydantic_acp import run_acp @@ -73,6 +78,31 @@ acp_agent = create_acp_agent( run_agent(acp_agent) ``` +## ACP Client Provider Bridge + +`AcpProvider` is the client-side mirror of the ACP server adapter. It wraps an ACP agent as a Pydantic AI v2 `Provider`; `AcpModel` is the model object Pydantic AI agents run against. + +```python +from pydantic_ai import Agent +from pydantic_acp import AcpProvider + +# `remote_acp_agent` can be any object implementing the ACP Agent interface. +provider = AcpProvider(agent=remote_acp_agent, cwd="/workspace") +model = provider.model("zed-agent") +agent = Agent(model) + +result = await agent.run("Summarize the current workspace state.") +print(result.output) +``` + +This keeps ownership boundaries explicit: + +- Pydantic AI owns the outer agent run, output validation, and normal model/provider lifecycle. +- ACP owns the delegated agent session, ACP-visible updates, and any editor or host capabilities requested by that agent. +- `AcpHostBridge` records ACP `session_update` messages and can delegate filesystem, terminal, approval, and extension callbacks to a real ACP host client when one is supplied. +- Pydantic AI function tools are intentionally not executed directly by `AcpModel`; register tools on the ACP agent or expose host capabilities through ACP. + +Use this bridge when the thing you have is already an ACP agent and you want it to participate in code that expects a Pydantic AI provider/model. It is not another ACP server adapter and it does not replace `create_acp_agent(...)`. If you are using Codex-backed Pydantic models through `codex-auth-helper`, pass explicit instructions when building the model. That is the preferred seam for Codex-specific system behavior: @@ -357,6 +387,8 @@ Focused docs recipes: `pydantic-acp` supports `pydantic-ai-slim>=2.0.0,<=2.4.0`. Pydantic AI V1 is no longer supported. +The ACP client provider bridge depends on the Pydantic AI v2 `Provider` and `Model` contracts. Upgrades across major Pydantic AI versions should be deliberate because the adapter exposes both server-side ACP translation and client-side ACP provider integration. + Every supported minor is exercised by the repository's runtime and type-check compatibility matrix. The adapter keeps upstream compatibility behind ACP Kit's bridge and runtime seams instead of scattering version checks through callers. diff --git a/packages/adapters/pydantic-acp/pyproject.toml b/packages/adapters/pydantic-acp/pyproject.toml index a3dcbe4..7387ab6 100644 --- a/packages/adapters/pydantic-acp/pyproject.toml +++ b/packages/adapters/pydantic-acp/pyproject.toml @@ -15,7 +15,7 @@ classifiers = [ "Programming Language :: Python :: 3.13", ] dependencies = [ - # fixed for compliance with current API + # fixed for compliance with current ACP API "agent-client-protocol==0.9.0", "anyio>=4.0.0", "pydantic-ai-slim>=2.0.0,<=2.4.0", diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/__init__.py b/packages/adapters/pydantic-acp/src/pydantic_acp/__init__.py index 0193573..d04180b 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/__init__.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/__init__.py @@ -52,6 +52,14 @@ WebSearchBridge, ) from .builders import AgentBridgeBuilder, AgentBridgeContributions +from .client import ( + ACP_MODEL_PROFILE, + AcpHostBridge, + AcpModel, + AcpPromptRenderer, + AcpProvider, + AcpUpdateRecord, +) from .config import AdapterConfig from .hook_projection import HookEvent, HookProjectionMap from .host import ( @@ -138,48 +146,48 @@ ) __all__ = ( - "AcpSessionContext", + "ACP_MODEL_PROFILE", + "DEFAULT_TEXT_TRUNCATION_MARKER", "AcpAgent", - "AgentFactory", - "AgentPromptBlock", - "AgentSource", - "ApprovalBridge", - "ApprovalStateProvider", + "AcpHostBridge", + "AcpModel", + "AcpPromptRenderer", + "AcpProvider", + "AcpSessionContext", + "AcpUpdateRecord", "AdapterConfig", "AdapterModel", + "AdapterPromptCapabilities", "AgentBridgeBuilder", "AgentBridgeContributions", + "AgentFactory", + "AgentPromptBlock", + "AgentSource", "AnthropicCompactionBridge", + "ApprovalBridge", + "ApprovalPolicy", + "ApprovalPolicyStore", + "ApprovalStateProvider", "AudioContentBlock", - "BufferedCapabilityBridge", "BlackBoxHarness", "BlobResourceContents", + "BufferedCapabilityBridge", "BuiltinToolProjectionMap", "CapabilityBridge", "ClientFilesystemBackend", "ClientHostContext", "ClientTerminalBackend", + "CompositeProjectionMap", "ConfigOption", "ConfigOptionsProvider", - "CompositeProjectionMap", - "compose_projection_maps", - "caution_for_command", - "caution_for_path", - "DEFAULT_TEXT_TRUNCATION_MARKER", "DefaultPermissionToolCallBuilder", "EmbeddedResourceContentBlock", "EventEmissionMode", "ExternalHookEventBridge", + "FactoryAgentSource", "FileSessionStore", "FileSystemProjectionMap", - "FactoryAgentSource", "FilesystemBackend", - "HostAccessDisposition", - "HostAccessPolicy", - "HostCommandEvaluation", - "HostPathEvaluation", - "HostRisk", - "HistoryProcessorCallable", "HarnessCodeModeBridge", "HarnessCodeModeProjectionMap", "HarnessFileSystemBridge", @@ -187,84 +195,90 @@ "HarnessShellBridge", "HarnessShellProjectionMap", "HistoryProcessorBridge", + "HistoryProcessorCallable", "HistoryProcessorContextual", "HistoryProcessorPlain", "HistoryProcessorWithContextAsync", "HistoryProcessorWithContextSync", + "HookBridge", "HookEvent", "HookProjectionMap", - "HookBridge", + "HostAccessDisposition", + "HostAccessPolicy", + "HostCommandEvaluation", + "HostPathEvaluation", + "HostRisk", "HttpMcpServer", - "ImageGenerationBridge", "ImageContentBlock", + "ImageGenerationBridge", "IncludeToolReturnSchemasBridge", "JsonValue", - "list_agent_hooks", - "MemorySessionStore", - "McpCapabilityBridge", "McpBridge", + "McpCapabilityBridge", "McpServerDefinition", "McpServerStdio", "McpToolDefinition", + "MemorySessionStore", "ModeState", "ModelSelectionState", "NativeApprovalBridge", "NativePlanPersistenceProvider", "OpenAICompactionBridge", - "AdapterPromptCapabilities", + "PermissionOptionSet", + "PermissionRequestContext", + "PermissionToolCallBuilder", "PlanEntry", "PlanGenerationType", "PlanProvider", "PrefixToolsBridge", - "ApprovalPolicy", - "ApprovalPolicyStore", - "ProjectionMap", - "ProjectionAwareApprovalBridge", - "ProjectionAwareToolClassifier", - "PromptModelOverrideProvider", - "PermissionOptionSet", - "PermissionRequestContext", - "PermissionToolCallBuilder", - "ResourceContentBlock", - "format_code_block", - "format_diff_preview", - "format_terminal_status", "PrepareOutputToolsBridge", "PrepareOutputToolsMode", "PrepareToolsBridge", "PrepareToolsMode", - "RegisteredHookInfo", + "ProjectionAwareApprovalBridge", + "ProjectionAwareToolClassifier", + "ProjectionMap", + "PromptModelOverrideProvider", "RecordingACPClient", + "RegisteredHookInfo", + "ResourceContentBlock", "RuntimeAgent", - "SetToolMetadataBridge", - "ThinkingBridge", - "ThreadExecutorBridge", - "ToolsetBridge", - "WebFetchBridge", - "WebSearchBridge", - "WebToolProjectionMap", - "SessionStore", "SessionMetadataApprovalPolicyStore", "SessionModelsProvider", "SessionModesProvider", + "SessionStore", + "SetToolMetadataBridge", "SlashCommandHandler", "SlashCommandProvider", "SlashCommandRequest", "SlashCommandResult", + "SseMcpServer", "StaticAgentSource", "StaticSlashCommand", "StaticSlashCommandProvider", - "SseMcpServer", - "single_line_summary", "TerminalBackend", "TextContentBlock", "TextResourceContents", - "truncate_lines", - "truncate_text", + "ThinkingBridge", + "ThreadExecutorBridge", + "ToolsetBridge", "UpdateRecord", + "WebFetchBridge", + "WebSearchBridge", + "WebToolProjectionMap", "__version__", "agent_message_texts", + "caution_for_command", + "caution_for_path", + "compose_projection_maps", "create_acp_agent", + "format_code_block", + "format_diff_preview", + "format_terminal_status", + "list_agent_hooks", "run_acp", + "single_line_summary", "supports_projection_aware_approval_bridge", + "truncate_lines", + "truncate_text", ) diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/_projection_text.py b/packages/adapters/pydantic-acp/src/pydantic_acp/_projection_text.py index 979d3ca..d1c86ee 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/_projection_text.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/_projection_text.py @@ -87,7 +87,7 @@ def format_diff_preview( new_text.strip().splitlines(), lineterm="", n=context_lines, - ) + ), ) if not include_diff_headers: diff_lines = [ diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/_slash_commands.py b/packages/adapters/pydantic-acp/src/pydantic_acp/_slash_commands.py index 9be9657..06cbc57 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/_slash_commands.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/_slash_commands.py @@ -3,8 +3,8 @@ from collections.abc import Iterable __all__ = ( - "MCP_SERVERS_COMMAND_NAME", "HOOKS_COMMAND_NAME", + "MCP_SERVERS_COMMAND_NAME", "MODEL_COMMAND_NAME", "RESERVED_SLASH_COMMAND_NAMES", "THINKING_COMMAND_NAME", @@ -24,7 +24,7 @@ TOOLS_COMMAND_NAME, HOOKS_COMMAND_NAME, MCP_SERVERS_COMMAND_NAME, - } + }, ) @@ -43,12 +43,12 @@ def validate_mode_command_ids(mode_ids: Iterable[str]) -> None: if duplicate_ids: duplicate_text = ", ".join(duplicate_ids) raise ValueError( - f"Mode ids must be unique after normalization. Duplicate ids: {duplicate_text}." + f"Mode ids must be unique after normalization. Duplicate ids: {duplicate_text}.", ) conflicting_ids = sorted(set(normalized_ids) & RESERVED_SLASH_COMMAND_NAMES) if conflicting_ids: conflict_text = ", ".join(conflicting_ids) raise ValueError( "Mode ids cannot reuse reserved slash command names " - f"({conflict_text}). Choose a more specific id outside the reserved keywords." + f"({conflict_text}). Choose a more specific id outside the reserved keywords.", ) diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/_version.py b/packages/adapters/pydantic-acp/src/pydantic_acp/_version.py index 47a3698..19692fb 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/_version.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/_version.py @@ -2,4 +2,4 @@ __all__ = ("__version__",) -__version__ = "1.0.0" +__version__ = "1.1.0" diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/agent_source.py b/packages/adapters/pydantic-acp/src/pydantic_acp/agent_source.py index 283aaa7..d30727e 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/agent_source.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/agent_source.py @@ -19,7 +19,8 @@ class AgentFactory(Protocol[AgentFactoryDepsT, AgentFactoryOutputDataT]): def __call__( - self, session: AcpSessionContext + self, + session: AcpSessionContext, ) -> ( PydanticAgent[AgentFactoryDepsT, AgentFactoryOutputDataT] | Awaitable[PydanticAgent[AgentFactoryDepsT, AgentFactoryOutputDataT]] @@ -28,7 +29,8 @@ def __call__( class AgentSource(Protocol[AgentDepsT, OutputDataT]): async def get_agent( - self, session: AcpSessionContext + self, + session: AcpSessionContext, ) -> PydanticAgent[AgentDepsT, OutputDataT]: ... async def get_deps( diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/approvals.py b/packages/adapters/pydantic-acp/src/pydantic_acp/approvals.py index eb3a1d3..7b28e75 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/approvals.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/approvals.py @@ -88,7 +88,7 @@ def supports_projection_aware_approval_bridge( class NativeApprovalBridge: enable_persistent_choices: bool = False tool_call_builder: PermissionToolCallBuilder = field( - default_factory=DefaultPermissionToolCallBuilder + default_factory=DefaultPermissionToolCallBuilder, ) policy_store: ApprovalPolicyStore = field(default_factory=SessionMetadataApprovalPolicyStore) option_set: PermissionOptionSet = field(default_factory=PermissionOptionSet) @@ -109,7 +109,7 @@ async def resolve_deferred_approvals( remembered_policy = self._get_remembered_policy(session, approval_policy_key) if remembered_policy is not None: deferred_results.approvals[tool_call.tool_call_id] = self._policy_to_result( - remembered_policy + remembered_policy, ) continue @@ -124,7 +124,7 @@ async def resolve_deferred_approvals( cwd=session.cwd, classifier=classifier, projection_map=projection_map, - ) + ), ), ) outcome = permission_response.outcome diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/awaitables.py b/packages/adapters/pydantic-acp/src/pydantic_acp/awaitables.py index e05c8b7..d523ea9 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/awaitables.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/awaitables.py @@ -21,6 +21,6 @@ def is_resolved(value: ValueT | Awaitable[ValueT]) -> TypeIs[ValueT]: async def resolve_value(value: ValueT | Awaitable[ValueT]) -> ValueT: if is_awaitable(value): - return await cast(Awaitable[ValueT], value) + return await cast("Awaitable[ValueT]", value) assert is_resolved(value) return value diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/__init__.py b/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/__init__.py index fdb495d..22f7c5d 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/__init__.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/__init__.py @@ -38,16 +38,16 @@ from .thinking import ThinkingBridge __all__ = ( + "AnthropicCompactionBridge", "BufferedCapabilityBridge", "CapabilityBridge", - "AnthropicCompactionBridge", "EventEmissionMode", "ExternalHookEventBridge", "HarnessCodeModeBridge", "HarnessFileSystemBridge", "HarnessShellBridge", - "HistoryProcessorCallable", "HistoryProcessorBridge", + "HistoryProcessorCallable", "HistoryProcessorContextual", "HistoryProcessorPlain", "HistoryProcessorWithContextAsync", @@ -55,8 +55,8 @@ "HookBridge", "ImageGenerationBridge", "IncludeToolReturnSchemasBridge", - "McpCapabilityBridge", "McpBridge", + "McpCapabilityBridge", "McpServerDefinition", "McpToolDefinition", "OpenAICompactionBridge", diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/_hook_capability.py b/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/_hook_capability.py index aa1e202..47741c0 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/_hook_capability.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/_hook_capability.py @@ -64,7 +64,7 @@ def enabled_hook_events(bridge: HookBridge) -> list[str]: "wrap_tool_execute", "after_tool_execute", "on_tool_execute_error", - ] + ], ) if bridge._output_validation_enabled: enabled.extend( @@ -73,7 +73,7 @@ def enabled_hook_events(bridge: HookBridge) -> list[str]: "wrap_output_validate", "after_output_validate", "on_output_validate_error", - ] + ], ) if bridge._output_processing_enabled: enabled.extend( @@ -82,7 +82,7 @@ def enabled_hook_events(bridge: HookBridge) -> list[str]: "wrap_output_process", "after_output_process", "on_output_process_error", - ] + ], ) if bridge._deferred_tool_calls_enabled: enabled.append("handle_deferred_tool_calls") diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/base.py b/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/base.py index 8e6732b..105bb38 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/base.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/base.py @@ -195,7 +195,7 @@ def _record_started_event( kind=kind, status="in_progress", raw_input=raw_input, - ) + ), ], ) return event_id @@ -220,7 +220,7 @@ def _record_progress_event( kind=kind, status=status, raw_output=raw_output, - ) + ), ], ) diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/capability_support.py b/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/capability_support.py index 091e273..71e8856 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/capability_support.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/capability_support.py @@ -65,18 +65,18 @@ "exa_search", "tavily_search", "web_search", - } + }, ) _DEFAULT_WEB_FETCH_TOOL_NAMES: Final[frozenset[str]] = frozenset({"web_fetch"}) _DEFAULT_IMAGE_GENERATION_TOOL_NAMES: Final[frozenset[str]] = frozenset( - {"generate_image", "image_generation"} + {"generate_image", "image_generation"}, ) _DEFAULT_MCP_TOOL_NAME_PREFIXES: Final[frozenset[str]] = frozenset({"mcp_server:"}) _DEFAULT_HARNESS_FILESYSTEM_TOOL_NAMES: Final[frozenset[str]] = frozenset( - {"create_directory", "edit_file", "list_directory", "read_file", "search_files", "write_file"} + {"create_directory", "edit_file", "list_directory", "read_file", "search_files", "write_file"}, ) _DEFAULT_HARNESS_SHELL_TOOL_NAMES: Final[frozenset[str]] = frozenset( - {"check_command", "run_command", "start_command", "stop_command"} + {"check_command", "run_command", "start_command", "stop_command"}, ) _DEFAULT_HARNESS_CODE_MODE_TOOL_NAMES: Final[frozenset[str]] = frozenset({"run_code"}) @@ -85,7 +85,7 @@ def _missing_harness_dependency(extra: str | None = None) -> ImportError: suffix = f"[{extra}]" if extra else "" return ImportError( "pydantic-ai-harness is required for this bridge. " - f"Install `pydantic-ai-harness{suffix}` alongside `pydantic-acp`." + f"Install `pydantic-ai-harness{suffix}` alongside `pydantic-acp`.", ) @@ -241,7 +241,7 @@ def build_capability(self, session: AcpSessionContext) -> AbstractCapability[Age } if self.protected_patterns is not None: kwargs["protected_patterns"] = list(self.protected_patterns) - return cast(AbstractCapability[AgentDepsT], FileSystem(**kwargs)) + return cast("AbstractCapability[AgentDepsT]", FileSystem(**kwargs)) def build_agent_capabilities( self, @@ -320,7 +320,7 @@ def build_capability(self, session: AcpSessionContext) -> AbstractCapability[Age } if self.denied_commands is not None: kwargs["denied_commands"] = list(self.denied_commands) - return cast(AbstractCapability[AgentDepsT], Shell(**kwargs)) + return cast("AbstractCapability[AgentDepsT]", Shell(**kwargs)) def build_agent_capabilities( self, @@ -377,9 +377,9 @@ def build_capability(self, session: AcpSessionContext) -> AbstractCapability[Age except ImportError as exc: raise _missing_harness_dependency("code-mode") from exc return cast( - AbstractCapability[AgentDepsT], + "AbstractCapability[AgentDepsT]", CodeMode( - tools=cast(Any, self.tools), + tools=cast("Any", self.tools), max_retries=self.max_retries, os_access=self.os_access, mount=self.mount, @@ -468,7 +468,7 @@ def get_session_metadata( "aspect_ratio": _json_string(self.aspect_ratio), "background": _json_string(self.background), "fallback_model": _json_string( - self.fallback_model if isinstance(self.fallback_model, str) else None + self.fallback_model if isinstance(self.fallback_model, str) else None, ), "input_fidelity": _json_string(self.input_fidelity), "moderation": _json_string(self.moderation), @@ -480,7 +480,9 @@ def get_session_metadata( } def get_tool_kind( - self, tool_name: str, raw_input: JsonValue | None = None + self, + tool_name: str, + raw_input: JsonValue | None = None, ) -> Literal["execute"] | None: del raw_input return "execute" if tool_name in self.tool_names else None @@ -538,7 +540,9 @@ def get_session_metadata( } def get_tool_kind( - self, tool_name: str, raw_input: JsonValue | None = None + self, + tool_name: str, + raw_input: JsonValue | None = None, ) -> Literal["execute"] | None: del raw_input return ( @@ -610,7 +614,9 @@ def get_session_metadata( } def get_tool_kind( - self, tool_name: str, raw_input: JsonValue | None = None + self, + tool_name: str, + raw_input: JsonValue | None = None, ) -> Literal["execute"] | None: del raw_input return "execute" if tool_name.startswith(f"{self.prefix}_") else None @@ -833,7 +839,9 @@ def get_session_metadata( } def get_tool_kind( - self, tool_name: str, raw_input: JsonValue | None = None + self, + tool_name: str, + raw_input: JsonValue | None = None, ) -> Literal["search"] | None: del raw_input return "search" if tool_name in self.tool_names else None @@ -888,7 +896,9 @@ def get_session_metadata( } def get_tool_kind( - self, tool_name: str, raw_input: JsonValue | None = None + self, + tool_name: str, + raw_input: JsonValue | None = None, ) -> Literal["fetch"] | None: del raw_input return "fetch" if tool_name in self.tool_names else None diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/history_processor.py b/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/history_processor.py index 92f3b84..ad59b92 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/history_processor.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/history_processor.py @@ -17,10 +17,12 @@ HistoryProcessorNoContextSync: TypeAlias = Callable[[ModelMessages], ModelMessages] HistoryProcessorNoContextAsync: TypeAlias = Callable[[ModelMessages], Awaitable[ModelMessages]] HistoryProcessorWithContextSync: TypeAlias = Callable[ - [RunContext[AgentDepsT], ModelMessages], ModelMessages + [RunContext[AgentDepsT], ModelMessages], + ModelMessages, ] HistoryProcessorWithContextAsync: TypeAlias = Callable[ - [RunContext[AgentDepsT], ModelMessages], Awaitable[ModelMessages] + [RunContext[AgentDepsT], ModelMessages], + Awaitable[ModelMessages], ] HistoryProcessorPlain: TypeAlias = HistoryProcessorNoContextSync | HistoryProcessorNoContextAsync HistoryProcessorContextual: TypeAlias = ( @@ -29,8 +31,8 @@ HistoryProcessorCallable: TypeAlias = HistoryProcessorPlain | HistoryProcessorContextual[AgentDepsT] __all__ = ( - "HistoryProcessorCallable", "HistoryProcessorBridge", + "HistoryProcessorCallable", "HistoryProcessorContextual", "HistoryProcessorPlain", "HistoryProcessorWithContextAsync", diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/prepare_tools.py b/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/prepare_tools.py index ff43584..819401d 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/prepare_tools.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/prepare_tools.py @@ -174,7 +174,7 @@ def get_config_options( ) for value in _PLAN_GENERATION_CONFIG_OPTIONS ], - ) + ), ] def set_mode( @@ -249,7 +249,7 @@ def current_plan_generation_type(self, session: AcpSessionContext) -> PlanGenera isinstance(configured_value, str) and configured_value in _PLAN_GENERATION_CONFIG_OPTIONS ): - return cast(PlanGenerationType, configured_value) + return cast("PlanGenerationType", configured_value) return self.default_plan_generation_type def uses_tool_plan_generation(self, session: AcpSessionContext) -> bool: diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/thinking.py b/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/thinking.py index aff0f49..29e2bc2 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/thinking.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/thinking.py @@ -65,7 +65,7 @@ def get_config_options( ) for value in _THINKING_OPTIONS ], - ) + ), ] def get_model_settings( @@ -79,7 +79,7 @@ def get_model_settings( return None if current_value == _DISABLED_THINKING_VALUE: return Thinking(False).get_model_settings() - effort = cast(ThinkingEffort, current_value) + effort = cast("ThinkingEffort", current_value) return Thinking(effort=effort).get_model_settings() def get_session_metadata( diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/client.py b/packages/adapters/pydantic-acp/src/pydantic_acp/client.py new file mode 100644 index 0000000..e7accc1 --- /dev/null +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/client.py @@ -0,0 +1,973 @@ +from __future__ import annotations as _annotations + +import asyncio +import inspect +from collections.abc import AsyncGenerator, Awaitable, Callable, Sequence +from contextlib import asynccontextmanager +from datetime import datetime +from pathlib import Path +from typing import Any, Literal, TypeAlias, cast, overload +from uuid import uuid4 + +from acp import PROTOCOL_VERSION +from acp.exceptions import RequestError +from acp.helpers import text_block +from acp.interfaces import Agent as AcpAgent +from acp.interfaces import Client as AcpClient +from acp.schema import ( + AgentMessageChunk, + ClientCapabilities, + CreateTerminalResponse, + EnvVariable, + Implementation, + KillTerminalResponse, + PermissionOption, + ReadTextFileResponse, + ReleaseTerminalResponse, + RequestPermissionResponse, + TerminalOutputResponse, + ToolCallUpdate, + UsageUpdate, + WaitForTerminalExitResponse, + WriteTextFileResponse, +) +from pydantic_ai.exceptions import UserError +from pydantic_ai.messages import ( + AudioUrl, + BinaryContent, + DocumentUrl, + FinishReason, + ImageUrl, + ModelMessage, + ModelRequest, + ModelResponse, + ModelResponseStreamEvent, + RetryPromptPart, + SystemPromptPart, + TextContent, + TextPart, + ToolReturnPart, + UploadedFile, + UserContent, + UserPromptPart, + VideoUrl, +) +from pydantic_ai.models import Model, ModelRequestParameters, StreamedResponse +from pydantic_ai.native_tools import AbstractNativeTool +from pydantic_ai.profiles import ModelProfile, ModelProfileSpec +from pydantic_ai.providers import Provider +from pydantic_ai.settings import ModelSettings +from pydantic_ai.usage import RequestUsage + +from ._version import __version__ +from .types import AgentPromptBlock + +HistoryMode: TypeAlias = Literal["latest_user", "full"] + +AcpPromptRenderer: TypeAlias = Callable[ + [Sequence[ModelMessage], ModelRequestParameters], + Sequence[AgentPromptBlock] | Awaitable[Sequence[AgentPromptBlock]], +] + +ACP_MODEL_PROFILE: ModelProfile = ModelProfile( + supports_tools=False, + supports_json_schema_output=False, + supports_json_object_output=False, + supports_image_output=False, + supported_native_tools=frozenset[type[AbstractNativeTool]](), +) + +__all__ = ( + "ACP_MODEL_PROFILE", + "AcpHostBridge", + "AcpModel", + "AcpPromptRenderer", + "AcpProvider", + "AcpUpdateRecord", +) + + +# --------------------------------------------------------------------------- +# AcpUpdateRecord +# --------------------------------------------------------------------------- + + +class AcpUpdateRecord: + """A host-side ACP update observed while an ACP-backed model request runs.""" + + __slots__ = ("session_id", "source", "update") + + def __init__(self, *, session_id: str, update: Any, source: str | None = None) -> None: + self.session_id = session_id + self.update = update + self.source = source + + +# --------------------------------------------------------------------------- +# AcpHostBridge +# --------------------------------------------------------------------------- + + +class AcpHostBridge: + """Minimal ACP host/client implementation used by :class:`AcpProvider`. + + ACP agents send their visible output to a connected ACP client via + ``session_update``. Pydantic AI models, however, return a ``ModelResponse``. + This bridge is the seam between the two contracts: it records ACP updates so + ``AcpModel`` can fold agent message chunks back into Pydantic AI response + parts, while optionally delegating real host operations to an upstream ACP + client supplied by the caller. + + The bridge intentionally does not emulate a filesystem, terminal, approval + UI, or extension namespace. When an ACP agent asks for such host operations + and no delegate was supplied, the request fails explicitly instead of + inventing host behavior that is not present. + """ + + def __init__(self, *, delegate: AcpClient | None = None) -> None: + self.delegate = delegate + self.updates: list[AcpUpdateRecord] = [] + + def snapshot_index(self) -> int: + """Return an index that can later be used to read only new updates.""" + return len(self.updates) + + def records_since( + self, + index: int, + *, + session_id: str | None = None, + ) -> list[AcpUpdateRecord]: + """Return recorded updates after ``index``, optionally scoped to a session.""" + records = self.updates[index:] + if session_id is None: + return list(records) + return [record for record in records if record.session_id == session_id] + + def agent_message_text_since(self, index: int, *, session_id: str) -> str: + """Concatenate ACP agent message chunks recorded after ``index``.""" + text_parts: list[str] = [] + for record in self.records_since(index, session_id=session_id): + update = record.update + if not _is_agent_message_chunk(update): + continue + content = getattr(update, "content", None) + text = getattr(content, "text", None) + if isinstance(text, str): + text_parts.append(text) + return "".join(text_parts) + + def usage_update_since(self, index: int, *, session_id: str) -> RequestUsage: + """Collect the latest ACP usage update observed after ``index``.""" + usage = RequestUsage() + for record in self.records_since(index, session_id=session_id): + update = record.update + if not isinstance(update, UsageUpdate): + continue + usage = _usage_from_acp(getattr(update, "usage", None)) + return usage + + async def session_update( + self, + session_id: str, + update: Any, + **kwargs: Any, + ) -> None: + """Record an ACP update and optionally forward it to a real host client.""" + self.updates.append( + AcpUpdateRecord( + session_id=session_id, + update=update, + source=kwargs.get("source"), + ), + ) + if self.delegate is not None and hasattr(self.delegate, "session_update"): + await self._call_delegate( + "session_update", + session_id=session_id, + update=update, + **kwargs, + ) + + async def request_permission( + self, + options: list[PermissionOption], + session_id: str, + tool_call: ToolCallUpdate, + **kwargs: Any, + ) -> RequestPermissionResponse: + return await self._call_delegate( + "request_permission", + options=options, + session_id=session_id, + tool_call=tool_call, + **kwargs, + ) + + async def write_text_file( + self, + content: str, + path: str, + session_id: str, + **kwargs: Any, + ) -> WriteTextFileResponse | None: + return await self._call_delegate( + "write_text_file", + content=content, + path=path, + session_id=session_id, + **kwargs, + ) + + async def read_text_file( + self, + path: str, + session_id: str, + limit: int | None = None, + line: int | None = None, + **kwargs: Any, + ) -> ReadTextFileResponse: + return await self._call_delegate( + "read_text_file", + path=path, + session_id=session_id, + limit=limit, + line=line, + **kwargs, + ) + + async def create_terminal( + self, + command: str, + session_id: str, + args: list[str] | None = None, + cwd: str | None = None, + env: list[EnvVariable] | None = None, + output_byte_limit: int | None = None, + **kwargs: Any, + ) -> CreateTerminalResponse: + return await self._call_delegate( + "create_terminal", + command=command, + session_id=session_id, + args=args, + cwd=cwd, + env=env, + output_byte_limit=output_byte_limit, + **kwargs, + ) + + async def terminal_output( + self, + session_id: str, + terminal_id: str, + **kwargs: Any, + ) -> TerminalOutputResponse: + return await self._call_delegate( + "terminal_output", + session_id=session_id, + terminal_id=terminal_id, + **kwargs, + ) + + async def release_terminal( + self, + session_id: str, + terminal_id: str, + **kwargs: Any, + ) -> ReleaseTerminalResponse | None: + return await self._call_delegate( + "release_terminal", + session_id=session_id, + terminal_id=terminal_id, + **kwargs, + ) + + async def wait_for_terminal_exit( + self, + session_id: str, + terminal_id: str, + **kwargs: Any, + ) -> WaitForTerminalExitResponse: + return await self._call_delegate( + "wait_for_terminal_exit", + session_id=session_id, + terminal_id=terminal_id, + **kwargs, + ) + + async def kill_terminal( + self, + session_id: str, + terminal_id: str, + **kwargs: Any, + ) -> KillTerminalResponse | None: + return await self._call_delegate( + "kill_terminal", + session_id=session_id, + terminal_id=terminal_id, + **kwargs, + ) + + async def ext_method(self, method: str, params: dict[str, Any]) -> dict[str, Any]: + return await self._call_delegate("ext_method", method=method, params=params) + + async def ext_notification(self, method: str, params: dict[str, Any]) -> None: + if self.delegate is None or not hasattr(self.delegate, "ext_notification"): + return + await self._call_delegate("ext_notification", method=method, params=params) + + def on_connect(self, conn: AcpAgent) -> None: + """Forward reverse connections to a delegate host client when it supports them.""" + if self.delegate is not None and hasattr(self.delegate, "on_connect"): + self.delegate.on_connect(conn) + + async def _call_delegate(self, method_name: str, **kwargs: Any) -> Any: + delegate = self.delegate + method = getattr(delegate, method_name, None) if delegate is not None else None + if method is None: + raise RuntimeError( + f"ACP agent requested host method {method_name!r}, but no host client delegate " + "was supplied to AcpProvider.", + ) + result = method(**kwargs) + if inspect.isawaitable(result): + return await result + return result + + +# --------------------------------------------------------------------------- +# Internal result type +# --------------------------------------------------------------------------- + + +class _AcpPromptResult: + __slots__ = ("session_id", "stop_reason", "text", "usage") + + def __init__( + self, + *, + text: str, + usage: RequestUsage, + stop_reason: str | None, + session_id: str, + ) -> None: + self.text = text + self.usage = usage + self.stop_reason = stop_reason + self.session_id = session_id + + +# --------------------------------------------------------------------------- +# AcpProvider +# --------------------------------------------------------------------------- + + +class AcpProvider(Provider[AcpAgent]): + """Pydantic AI provider that treats an ACP agent as the model backend. + + This is the inverse of the normal ``pydantic-acp`` server adapter. The + server adapter exposes a ``pydantic_ai.Agent`` through ACP. ``AcpProvider`` + consumes an existing ACP agent and makes it available to Pydantic AI as a + provider/model pair, so application code can write ordinary Pydantic AI + agents while delegating the underlying model turn to ACP. + + The provider owns ACP protocol/session setup, model selection handoff via + ``set_session_model`` when the remote agent supports it, host/client update + capture, and prompt rendering. It deliberately remains a provider rather + than an alternate agent framework: Pydantic AI still owns the outer agent + run, result validation, usage accumulation, and history shape. + """ + + _history_mode: HistoryMode + + # -- overloads matching the OpenAIProvider pattern ---------------------- + + @overload + def __init__(self, *, acp_client: AcpAgent) -> None: ... + + @overload + def __init__( + self, + acp_client: None = None, + *, + agent: AcpAgent, + host_client: AcpClient | None = None, + cwd: str | Path = ".", + name: str = "acp", + base_url: str = "acp://local", + protocol_version: int = PROTOCOL_VERSION, + client_capabilities: ClientCapabilities | None = None, + client_info: Implementation | None = None, + mcp_servers: Sequence[Any] | None = None, + prompt_renderer: AcpPromptRenderer | None = None, + history_mode: HistoryMode = "latest_user", + ) -> None: ... + + def __init__( + self, + acp_client: AcpAgent | None = None, + *, + agent: AcpAgent | None = None, + host_client: AcpClient | None = None, + cwd: str | Path = ".", + name: str = "acp", + base_url: str = "acp://local", + protocol_version: int = PROTOCOL_VERSION, + client_capabilities: ClientCapabilities | None = None, + client_info: Implementation | None = None, + mcp_servers: Sequence[Any] | None = None, + prompt_renderer: AcpPromptRenderer | None = None, + history_mode: HistoryMode = "latest_user", + ) -> None: + """Create a new ACP provider. + + Args: + acp_client: An existing :class:`AcpAgent` client to use directly. + If provided, all other arguments must be ``None`` / defaults. + agent: The in-process ACP agent to wrap. Required when + ``acp_client`` is ``None``. + host_client: Optional upstream :class:`AcpClient` to delegate real + host operations to (file I/O, terminals, permissions, etc.). + cwd: Working directory passed to the ACP session on creation. + name: Provider name reported via :attr:`name`. Defaults to + ``"acp"``. + base_url: Base URL reported via :attr:`base_url`. Defaults to + ``"acp://local"``. + protocol_version: ACP protocol version used during + ``initialize``. Defaults to :data:`acp.PROTOCOL_VERSION`. + client_capabilities: ACP client capabilities sent during + ``initialize``. Defaults to an empty + :class:`~acp.schema.ClientCapabilities`. + client_info: ACP implementation info sent during ``initialize``. + Defaults to a ``pydantic-acp-client`` stub. + mcp_servers: Optional list of MCP servers forwarded to + ``new_session``. + prompt_renderer: Custom callable that converts Pydantic AI + messages into ACP prompt blocks. When ``None`` the built-in + renderer is used. + history_mode: Controls how previous messages are rendered into + the ACP prompt. ``"latest_user"`` (default) sends only the + latest user turn; ``"full"`` sends the entire conversation. + + """ + if acp_client is not None: + assert agent is None, "Cannot provide both `acp_client` and `agent`" + assert host_client is None, "Cannot provide both `acp_client` and `host_client`" + self._client = acp_client + else: + assert agent is not None, "Must provide either `acp_client` or `agent`" + self._client = agent + + self._host = AcpHostBridge(delegate=host_client) + self._name = name + self._base_url = base_url + self._cwd = str(cwd) + self._protocol_version = protocol_version + self._client_capabilities = client_capabilities + self._client_info = client_info or Implementation( + name="pydantic-acp-client", + version=__version__, + ) + self._mcp_servers = list(mcp_servers or []) + self._prompt_renderer = prompt_renderer + self._history_mode = history_mode + self._initialized = False + self._session_id: str | None = None + self._current_model_name: str | None = None + self._session_lock: asyncio.Lock | None = None + self._session_lock_loop: asyncio.AbstractEventLoop | None = None + + if hasattr(self._client, "on_connect"): + self._client.on_connect(self._host) + + # -- Provider abstract interface ---------------------------------------- + + @property + def name(self) -> str: + return self._name + + @property + def base_url(self) -> str: + return self._base_url + + @property + def client(self) -> AcpAgent: + return self._client + + @staticmethod + def model_profile(model_name: str) -> ModelProfile | None: + del model_name + return ACP_MODEL_PROFILE + + # -- Additional public API ---------------------------------------------- + + @property + def session_id(self) -> str | None: + return self._session_id + + @property + def host(self) -> AcpHostBridge: + """The ACP host bridge connected to the wrapped ACP agent.""" + return self._host + + @property + def updates(self) -> list[AcpUpdateRecord]: + """All ACP updates recorded by the host bridge so far.""" + return list(self._host.updates) + + def model( + self, + model_name: str = "agent", + *, + settings: ModelSettings | None = None, + profile: ModelProfileSpec | None = None, + history_mode: HistoryMode | None = None, + ) -> AcpModel: + """Build an :class:`AcpModel` bound to this provider.""" + if history_mode is not None: + self._history_mode = history_mode + return AcpModel( + model_name=model_name, + provider=self, + settings=settings, + profile=profile, + ) + + async def render_prompt_blocks( + self, + messages: Sequence[ModelMessage], + model_request_parameters: ModelRequestParameters, + ) -> list[AgentPromptBlock]: + """Render Pydantic AI model messages into ACP prompt blocks.""" + if self._prompt_renderer is None: + return _default_render_prompt_blocks( + messages, + model_request_parameters, + history_mode=self._history_mode, + ) + rendered = self._prompt_renderer(messages, model_request_parameters) + if inspect.isawaitable(rendered): + rendered = await rendered + return list(cast(Sequence[AgentPromptBlock], rendered)) + + async def request_prompt( + self, + *, + model_name: str, + prompt: Sequence[AgentPromptBlock], + ) -> _AcpPromptResult: + """Send one prompt turn to the ACP agent and collect its visible text.""" + session_id = await self._ensure_session(model_name=model_name) + start_index = self._host.snapshot_index() + prompt_response = await self._client.prompt( + prompt=list(prompt), + session_id=session_id, + message_id=uuid4().hex, + ) + text = self._host.agent_message_text_since(start_index, session_id=session_id) + if not text: + text = _extract_text(prompt_response) + + usage = _usage_from_acp(getattr(prompt_response, "usage", None)) + if not usage.has_values(): + usage = self._host.usage_update_since(start_index, session_id=session_id) + stop_reason = getattr(prompt_response, "stop_reason", None) or getattr( + prompt_response, + "stopReason", + None, + ) + return _AcpPromptResult( + text=text, + usage=usage, + stop_reason=stop_reason, + session_id=session_id, + ) + + async def _ensure_session(self, *, model_name: str) -> str: + async with self._get_session_lock(): + if not self._initialized: + await self._client.initialize( + protocol_version=self._protocol_version, + client_capabilities=self._client_capabilities or ClientCapabilities(), + client_info=self._client_info, + ) + self._initialized = True + + if self._session_id is None: + session = await self._client.new_session( + cwd=self._cwd, + mcp_servers=list(self._mcp_servers), + ) + self._session_id = session.session_id + + if self._current_model_name == model_name: + return self._session_id + + set_session_model = getattr(self._client, "set_session_model", None) + if set_session_model is not None: + try: + result = set_session_model( + model_id=model_name, + session_id=self._session_id, + ) + if inspect.isawaitable(result): + await result + self._current_model_name = model_name + except RequestError as exc: + if exc.code != -32601: + raise + if not ( + (exc.data or {}).get("method") == "session/set_model" + or "session/set_model" in str(exc) + ): + raise + # Method not found - assume model was set during session creation + self._current_model_name = model_name + else: + # Method doesn't exist - assume model was set during session creation + self._current_model_name = model_name + + return self._session_id + + def _get_session_lock(self) -> asyncio.Lock: + loop = asyncio.get_running_loop() + if self._session_lock is None or self._session_lock_loop is not loop: + self._session_lock = asyncio.Lock() + self._session_lock_loop = loop + return self._session_lock + + +# --------------------------------------------------------------------------- +# AcpModel +# --------------------------------------------------------------------------- + + +class AcpModel(Model[AcpAgent]): + """Pydantic AI ``Model`` backed by an ACP agent provider.""" + + _provider: Provider[AcpAgent] + + def __init__( + self, + model_name: str, + *, + provider: AcpProvider, + settings: ModelSettings | None = None, + profile: ModelProfileSpec | None = None, + ) -> None: + self._model_name = model_name + self._provider = provider + super().__init__(settings=settings, profile=profile or ACP_MODEL_PROFILE) + + @property + def model_name(self) -> str: + return self._model_name + + @property + def system(self) -> str: + return self._provider.name + + @property + def base_url(self) -> str: + return self._provider.base_url + + @classmethod + def supported_native_tools(cls) -> frozenset[type[AbstractNativeTool]]: + return frozenset() + + async def request( + self, + messages: list[ModelMessage], + model_settings: ModelSettings | None, + model_request_parameters: ModelRequestParameters, + ) -> ModelResponse: + model_settings, model_request_parameters = self.prepare_request( + model_settings, + model_request_parameters, + ) + del model_settings + self._ensure_supported_request(model_request_parameters) + provider = cast(AcpProvider, self._provider) + prompt = await provider.render_prompt_blocks(messages, model_request_parameters) + acp_result = await provider.request_prompt( + model_name=self.model_name, + prompt=prompt, + ) + parts = [TextPart(acp_result.text, provider_name=self.system)] if acp_result.text else [] + return ModelResponse( + parts=parts, + model_name=self.model_name, + provider_name=self.system, + provider_url=self.base_url, + usage=acp_result.usage, + finish_reason=_finish_reason_from_acp(acp_result.stop_reason), + provider_details={"acp_session_id": acp_result.session_id}, + ) + + @asynccontextmanager + async def request_stream( + self, + messages: list[ModelMessage], + model_settings: ModelSettings | None, + model_request_parameters: ModelRequestParameters, + run_context: Any | None = None, + ) -> AsyncGenerator[StreamedResponse, None]: + response = await self.request(messages, model_settings, model_request_parameters) + yield _AcpBufferedStreamedResponse( + model_request_parameters=model_request_parameters, + response=response, + ) + + def _ensure_supported_request(self, params: ModelRequestParameters) -> None: + if params.function_tools: + tool_names = ", ".join(tool.name for tool in params.function_tools) + raise UserError( + "AcpModel delegates a model turn to an ACP agent and cannot execute " + f"Pydantic AI function tools directly: {tool_names}. Register tools on " + "the ACP agent or provide them through an ACP host bridge instead.", + ) + if params.native_tools: + raise UserError( + "AcpModel does not expose Pydantic AI native tools directly; use the " + "ACP agent/provider side for native capabilities.", + ) + if params.output_tools or not params.allow_text_output: + raise UserError( + "AcpModel is a text-response provider bridge. Structured/tool-only " + "output must be implemented by the ACP agent or validated after the run.", + ) + + +# --------------------------------------------------------------------------- +# _AcpBufferedStreamedResponse +# --------------------------------------------------------------------------- + + +class _AcpBufferedStreamedResponse(StreamedResponse): + __slots__ = ("_response", "_usage", "finish_reason", "provider_details", "provider_response_id") + + def __init__( + self, + *, + model_request_parameters: ModelRequestParameters, + response: ModelResponse, + ) -> None: + super().__init__(model_request_parameters=model_request_parameters) + self._response = response + self._usage = response.usage + self.provider_response_id = response.provider_response_id + self.provider_details = response.provider_details + self.finish_reason = response.finish_reason + + async def _get_event_iterator(self) -> AsyncGenerator[ModelResponseStreamEvent, None]: + for part in self._response.parts: + if not isinstance(part, TextPart): + continue + for event in self._parts_manager.handle_text_delta( + vendor_part_id=part.id or "content", + content=part.content, + ): + yield event + + async def close_stream(self) -> None: + return None + + @property + def model_name(self) -> str: + return self._response.model_name or "acp" + + @property + def provider_name(self) -> str | None: + return self._response.provider_name + + @property + def provider_url(self) -> str | None: + return self._response.provider_url + + @property + def timestamp(self) -> datetime: + return self._response.timestamp + + +# --------------------------------------------------------------------------- +# Helpers +# --------------------------------------------------------------------------- + + +def _default_render_prompt_blocks( + messages: Sequence[ModelMessage], + model_request_parameters: ModelRequestParameters, + *, + history_mode: HistoryMode = "latest_user", +) -> list[AgentPromptBlock]: + del model_request_parameters + if history_mode == "latest_user": + latest = _latest_model_request(messages) + if latest is not None: + text = _render_message(latest, include_role=False) + if text.strip(): + return [text_block(text)] + if not messages: + return [] + full_text = "\n\n".join( + _render_message(message, include_role=True) for message in messages + ).strip() + return [text_block(full_text)] if full_text else [] + + +def _latest_model_request(messages: Sequence[ModelMessage]) -> ModelMessage | None: + for message in reversed(messages): + if isinstance(message, ModelRequest): + return message + return messages[-1] if messages else None + + +def _render_message(message: ModelMessage, *, include_role: bool) -> str: + if isinstance(message, ModelRequest): + text = _render_request_as_text(message) + else: + text = message.text or "" + if not include_role or not text: + return text + role = "user" if isinstance(message, ModelRequest) else "assistant" + return f"<{role}>\n{text}\n{role}>" + + +def _render_request_as_text(request: ModelRequest) -> str: + rendered: list[str] = [] + if request.instructions: + rendered.append(_section("Instructions", request.instructions)) + for part in request.parts: + if isinstance(part, UserPromptPart): + rendered.append(_render_user_prompt(part)) + elif isinstance(part, SystemPromptPart): + rendered.append(_section("System", part.content)) + elif isinstance(part, ToolReturnPart): + rendered.append(_render_tool_return(part)) + elif isinstance(part, RetryPromptPart): + rendered.append(part.model_response()) + return "\n\n".join(item for item in rendered if item).strip() + + +def _render_user_prompt(part: UserPromptPart) -> str: + return _render_user_content(part.content) + + +def _render_user_content(content: str | Sequence[UserContent]) -> str: + if isinstance(content, str): + return content + rendered: list[str] = [] + for item in content: + rendered.append(_render_user_content_item(item)) + return "\n\n".join(item for item in rendered if item) + + +def _render_user_content_item(item: UserContent) -> str: + if isinstance(item, str): + return item + if isinstance(item, TextContent): + return item.content + if isinstance(item, BinaryContent): + return f"[binary:{item.media_type}:{len(item.data)} bytes]" + if isinstance(item, ImageUrl | AudioUrl | DocumentUrl | VideoUrl): + return f"[{item.kind}:{item.url}]" + if isinstance(item, UploadedFile): + return f"[uploaded-file:{item.provider_name}:{item.file_id}]" + kind = getattr(item, "kind", type(item).__name__) + return f"[{kind}]" + + +def _render_tool_return(part: ToolReturnPart) -> str: + label = part.tool_name or part.tool_call_id + content = part.model_response_str() + return _section(f"Tool result: {label}", content) + + +def _section(title: str, content: str) -> str: + content = content.strip() + if not content: + return "" + return f"{title}:\n{content}" + + +def _is_agent_message_chunk(update: Any) -> bool: + return ( + isinstance(update, AgentMessageChunk) + or getattr(update, "session_update", None) == "agent_message_chunk" + ) + + +def _usage_from_acp(value: Any) -> RequestUsage: + if value is None: + return RequestUsage() + details: dict[str, int] = {} + thought_tokens = _int_attr(value, "thought_tokens") + if thought_tokens: + details["reasoning_tokens"] = thought_tokens + return RequestUsage( + input_tokens=_int_attr(value, "input_tokens"), + cache_write_tokens=_int_attr(value, "cached_write_tokens"), + cache_read_tokens=_int_attr(value, "cached_read_tokens"), + output_tokens=_int_attr(value, "output_tokens"), + details=details, + ) + + +def _int_attr(value: Any, name: str) -> int: + raw_value = getattr(value, name, 0) or 0 + return int(raw_value) + + +def _finish_reason_from_acp(stop_reason: str | None) -> FinishReason: + if stop_reason in (None, "end_turn", "stop"): + return "stop" + if stop_reason in ("max_tokens", "length"): + return "length" + if stop_reason == "cancelled": + return "error" + return "stop" + + +_TEXT_FIELD_NAMES = ("text", "delta", "message", "output_text", "content", "response", "data") + + +def _extract_text(value: Any) -> str: + """Recursively collect text from an ACP response or session-update payload.""" + return "".join( + candidate for candidate in _walk_text_candidates(value) if isinstance(candidate, str) + ) + + +def _walk_text_candidates(value: Any) -> list[Any]: + if value is None: + return [] + if isinstance(value, str): + return [value] + if isinstance(value, AgentMessageChunk): + content = getattr(value, "content", None) + text = getattr(content, "text", None) + return [text] if isinstance(text, str) else [] + if isinstance(value, Sequence) and not isinstance(value, (bytes, bytearray)): + items: list[Any] = [] + for item in value: + items.extend(_walk_text_candidates(item)) + return items + candidates: list[Any] = [] + content = _response_field(value, "content") + if content is not None and content is not value: + candidates.extend(_walk_text_candidates(content)) + for name in _TEXT_FIELD_NAMES: + attr = _response_field(value, name) + if isinstance(attr, str): + candidates.append(attr) + return candidates + + +def _response_field(response: Any, *names: str) -> Any: + for name in names: + if isinstance(response, dict) and name in response: + return response[name] + if hasattr(response, name): + return getattr(response, name) + return None diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/config.py b/packages/adapters/pydantic-acp/src/pydantic_acp/config.py index 4008b26..f65209e 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/config.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/config.py @@ -56,7 +56,7 @@ class AdapterConfig: native_plan_persistence_provider: NativePlanPersistenceProvider | None = None plan_provider: PlanProvider | None = None prompt_capabilities: AdapterPromptCapabilities = field( - default_factory=AdapterPromptCapabilities + default_factory=AdapterPromptCapabilities, ) prompt_model_override_provider: PromptModelOverrideProvider | None = None replay_history_on_load: bool = True diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/host/__init__.py b/packages/adapters/pydantic-acp/src/pydantic_acp/host/__init__.py index d51bdad..60c54e3 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/host/__init__.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/host/__init__.py @@ -12,14 +12,14 @@ from .terminal import ClientTerminalBackend, TerminalBackend __all__ = ( + "ClientFilesystemBackend", + "ClientHostContext", + "ClientTerminalBackend", + "FilesystemBackend", "HostAccessDisposition", "HostAccessPolicy", "HostCommandEvaluation", "HostPathEvaluation", "HostRisk", - "ClientFilesystemBackend", - "ClientHostContext", - "ClientTerminalBackend", - "FilesystemBackend", "TerminalBackend", ) diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/host/policy.py b/packages/adapters/pydantic-acp/src/pydantic_acp/host/policy.py index 22e1eb7..ea63447 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/host/policy.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/host/policy.py @@ -198,7 +198,8 @@ def evaluate_path( disposition: HostAccessDisposition = "allow" outside_cwd = not path_is_within_root(resolved_path, normalized_session_cwd) outside_workspace = normalized_workspace_root is not None and not path_is_within_root( - resolved_path, normalized_workspace_root + resolved_path, + normalized_workspace_root, ) if is_absolute_input: @@ -208,7 +209,7 @@ def evaluate_path( code="absolute_path", message=f"Path is absolute: {resolved_path}", path=resolved_path, - ) + ), ) if outside_cwd: disposition = _stronger_disposition(disposition, self.path_outside_cwd) @@ -217,7 +218,7 @@ def evaluate_path( code="outside_cwd", message=f"Path is outside the active session cwd: {resolved_path}", path=resolved_path, - ) + ), ) if outside_workspace: disposition = _stronger_disposition(disposition, self.path_outside_workspace) @@ -226,7 +227,7 @@ def evaluate_path( code="outside_workspace", message=f"Path escapes the workspace root: {resolved_path}", path=resolved_path, - ) + ), ) return HostPathEvaluation( @@ -279,7 +280,8 @@ def evaluate_command( disposition: HostAccessDisposition = "allow" outside_cwd = not path_is_within_root(resolved_cwd, normalized_session_cwd) outside_workspace = normalized_workspace_root is not None and not path_is_within_root( - resolved_cwd, normalized_workspace_root + resolved_cwd, + normalized_workspace_root, ) referenced_external_paths = tuple( path @@ -300,7 +302,7 @@ def evaluate_command( code="command_cwd_outside_cwd", message=f"Command cwd is outside the active session cwd: {resolved_cwd}", path=resolved_cwd, - ) + ), ) if outside_workspace: disposition = _stronger_disposition(disposition, self.command_cwd_outside_workspace) @@ -309,7 +311,7 @@ def evaluate_command( code="command_cwd_outside_workspace", message=f"Command cwd escapes the workspace root: {resolved_cwd}", path=resolved_cwd, - ) + ), ) if referenced_external_paths: disposition = _stronger_disposition(disposition, self.command_external_paths) @@ -320,7 +322,7 @@ def evaluate_command( "Command references paths outside the active session cwd: " f"{_join_paths(referenced_external_paths)}" ), - ) + ), ) if referenced_outside_workspace: disposition = _stronger_disposition(disposition, self.command_paths_outside_workspace) @@ -331,7 +333,7 @@ def evaluate_command( "Command references paths outside the workspace root: " f"{_join_paths(referenced_outside_workspace)}" ), - ) + ), ) return HostCommandEvaluation( diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/projection.py b/packages/adapters/pydantic-acp/src/pydantic_acp/projection.py index 2e65009..82456f0 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/projection.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/projection.py @@ -39,13 +39,13 @@ "HarnessCodeModeProjectionMap", "HarnessFileSystemProjectionMap", "HarnessShellProjectionMap", - "ProjectionMap", "ProjectionAwareToolClassifier", + "ProjectionMap", "ToolClassifier", "WebToolProjectionMap", + "build_compaction_updates", "build_tool_progress_update", "build_tool_start_update", - "build_compaction_updates", "build_tool_updates", "compose_projection_maps", "extract_tool_call_locations", @@ -69,7 +69,7 @@ _MAX_FILE_READ_PREVIEW_CHARS = 12000 _MAX_WEB_PREVIEW_CHARS = 2000 _DEFAULT_SEARCH_TOOL_NAMES = frozenset( - {"duckduckgo_search", "exa_search", "tavily_search", "web_search"} + {"duckduckgo_search", "exa_search", "tavily_search", "web_search"}, ) _DEFAULT_FETCH_TOOL_NAMES = frozenset({"web_fetch"}) _DEFAULT_IMAGE_GENERATION_TOOL_NAMES = frozenset({"generate_image", "image_generation"}) @@ -79,7 +79,7 @@ _HARNESS_EDIT_TOOL_NAMES = frozenset({"edit_file"}) _HARNESS_SEARCH_TOOL_NAMES = frozenset({"list_directory", "search_files"}) _HARNESS_SHELL_TOOL_NAMES = frozenset( - {"run_command", "start_command", "check_command", "stop_command"} + {"run_command", "start_command", "check_command", "stop_command"}, ) _HARNESS_CODE_MODE_TOOL_NAMES = frozenset({"run_code"}) @@ -224,7 +224,7 @@ def project_start( ContentToolCallContent( type="content", content=_text_block(_format_command_preview(command)), - ) + ), ], title=_format_command_title(command), ) @@ -243,7 +243,7 @@ def project_start( path=path, old_text=self._old_text_from_input(raw_input, path=path, cwd=cwd), new_text=new_text, - ) + ), ], locations=[ToolCallLocation(path=path)], ) @@ -295,7 +295,7 @@ def project_progress( ContentToolCallContent( type="content", content=_text_block(rendered_output), - ) + ), ], locations=self._search_locations_from_input(raw_input), status=status, @@ -323,7 +323,7 @@ def project_progress( path=path, old_text="", new_text=new_text, - ) + ), ], locations=[ToolCallLocation(path=path)], ) @@ -388,7 +388,8 @@ def _search_pattern_from_input(self, raw_input: dict[str, Any]) -> str | None: return None def _search_locations_from_input( - self, raw_input: dict[str, Any] + self, + raw_input: dict[str, Any], ) -> list[ToolCallLocation] | None: path = self._search_path_from_input(raw_input) return [ToolCallLocation(path=path)] if path is not None else None @@ -483,7 +484,7 @@ def project_start( ContentToolCallContent( type="content", content=_text_block(_format_web_search_start(raw_input)), - ) + ), ], title=f"Search web for {_single_line_preview(query, limit=_MAX_COMMAND_TITLE_CHARS)}", ) @@ -497,7 +498,7 @@ def project_start( ContentToolCallContent( type="content", content=_text_block(_format_web_fetch_start(raw_input)), - ) + ), ], title=f"Fetch {_single_line_preview(url, limit=_MAX_COMMAND_TITLE_CHARS)}", ) @@ -521,10 +522,10 @@ def project_progress( ContentToolCallContent( type="content", content=_text_block( - _format_web_search_progress(raw_output, serialized_output) + _format_web_search_progress(raw_output, serialized_output), ), - ) - ] + ), + ], ) if tool_name not in self.fetch_tool_names: return None @@ -533,8 +534,8 @@ def project_progress( ContentToolCallContent( type="content", content=_text_block(_format_web_fetch_progress(raw_output, serialized_output)), - ) - ] + ), + ], ) @@ -567,7 +568,7 @@ def project_start( ContentToolCallContent( type="content", content=_text_block(_format_image_generation_start(raw_input)), - ) + ), ], title=( f"Generate image for {_single_line_preview(prompt, limit=_MAX_COMMAND_TITLE_CHARS)}" @@ -582,7 +583,7 @@ def project_start( ContentToolCallContent( type="content", content=_text_block(_format_mcp_start(tool_name, raw_input)), - ) + ), ], title=_format_mcp_title(tool_name, raw_input), ) @@ -615,10 +616,10 @@ def project_progress( ContentToolCallContent( type="content", content=_text_block( - _format_image_generation_progress(raw_output, serialized_output) + _format_image_generation_progress(raw_output, serialized_output), ), - ) - ] + ), + ], ) if not any(tool_name.startswith(prefix) for prefix in self.mcp_tool_name_prefixes): return None @@ -627,8 +628,8 @@ def project_progress( ContentToolCallContent( type="content", content=_text_block(_format_mcp_progress(raw_output, serialized_output)), - ) - ] + ), + ], ) @@ -701,7 +702,7 @@ def _project_read_start(self, raw_input: Any) -> ToolProjection | None: ContentToolCallContent( type="content", content=_text_block(f"Read file: `{path}`"), - ) + ), ], locations=[ToolCallLocation(path=path)], title=f"Read {_single_line_preview(path, limit=_MAX_COMMAND_TITLE_CHARS)}", @@ -726,7 +727,7 @@ def _project_read_progress( ContentToolCallContent( type="content", content=_text_block(_format_harness_read_progress(path, output_text)), - ) + ), ], locations=[ToolCallLocation(path=path)], status=status, @@ -772,7 +773,7 @@ def project_start( ContentToolCallContent( type="content", content=_text_block(f"Command ID: {command_id}"), - ) + ), ], title=f"{action} command {command_id}", ) @@ -819,7 +820,7 @@ def project_start( ContentToolCallContent( type="content", content=_text_block(format_code_block(code, language="python")), - ) + ), ], title=f"Run code: {_single_line_preview(code, limit=_MAX_COMMAND_TITLE_CHARS)}", ) @@ -842,8 +843,8 @@ def project_progress( ContentToolCallContent( type="content", content=_text_block(_stringify_value(raw_output, serialized_output)), - ) - ] + ), + ], ) @@ -1012,7 +1013,7 @@ def _render_tree_node(node: _PathTreeNode, *, prefix: str) -> list[str]: _render_tree_node( node.directories[name], prefix=f"{prefix}{child_prefix}", - ) + ), ) else: rendered.append(f"{prefix}{connector}{name}") @@ -1175,7 +1176,7 @@ def _bash_progress_content( "", "Stdout:", format_code_block(stdout, language="text", limit=_MAX_COMMAND_PREVIEW_CHARS), - ) + ), ) stderr = raw_output.get("stderr") if isinstance(stderr, str) and stderr: @@ -1184,7 +1185,7 @@ def _bash_progress_content( "", "Stderr:", format_code_block(stderr, language="text", limit=_MAX_COMMAND_PREVIEW_CHARS), - ) + ), ) return [ContentToolCallContent(type="content", content=_text_block("\n".join(sections)))] @@ -1310,7 +1311,7 @@ def _format_web_fetch_progress(raw_output: Any, serialized_output: str) -> str: "", "Preview:", format_code_block(content, language="text", limit=_MAX_WEB_PREVIEW_CHARS), - ) + ), ) if not lines: return truncate_text(serialized_output, limit=_MAX_WEB_PREVIEW_CHARS) @@ -1387,7 +1388,7 @@ def _format_mcp_start(tool_name: str, raw_input: dict[str, Any]) -> str: language="json", limit=_MAX_WEB_PREVIEW_CHARS, ), - ) + ), ) return "\n".join(lines) @@ -1422,7 +1423,7 @@ def _format_mcp_progress(raw_output: Any, serialized_output: str) -> str: language="json", limit=_MAX_WEB_PREVIEW_CHARS, ), - ) + ), ) if not lines: return truncate_text(serialized_output, limit=_MAX_WEB_PREVIEW_CHARS) @@ -1658,7 +1659,7 @@ def _build_progress_updates_for_message( known_start=known_call_starts.get(part.tool_call_id), projection_map=projection_map, serializer=serializer, - ) + ), ) return updates @@ -1674,7 +1675,7 @@ def _build_progress_updates_for_message( known_start=known_call_starts.get(part.tool_call_id), projection_map=projection_map, serializer=serializer, - ) + ), ) elif ( isinstance(part, RetryPromptPart) @@ -1689,7 +1690,7 @@ def _build_progress_updates_for_message( known_start=known_call_starts.get(part.tool_call_id), projection_map=projection_map, serializer=serializer, - ) + ), ) return updates @@ -1714,7 +1715,7 @@ def build_tool_updates( known_call_starts=known_call_starts, projection_map=projection_map, serializer=serializer, - ) + ), ) return updates @@ -1764,7 +1765,7 @@ def build_compaction_updates( kind=known_start.kind, status="completed", raw_output=_format_compaction_progress(part, provider_name=provider_name), - ) + ), ) return updates diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_adapter_mixins.py b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_adapter_mixins.py index f7839d1..921b70a 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_adapter_mixins.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_adapter_mixins.py @@ -235,7 +235,7 @@ async def _resolve_prompt_model_override( agent, prompt, model_override, - ) + ), ) if override is None: return model_override @@ -481,14 +481,20 @@ async def resume_session( return await self._session_runtime.resume_session(cwd, session_id, mcp_servers) async def set_session_mode( - self, mode_id: str, session_id: str, **kwargs: Any + self, + mode_id: str, + session_id: str, + **kwargs: Any, ) -> SetSessionModeResponse | None: """Set the current ACP session mode through the active mode provider.""" del kwargs return await self._session_runtime.set_session_mode(mode_id, session_id) async def set_session_model( - self, model_id: str, session_id: str, **kwargs: Any + self, + model_id: str, + session_id: str, + **kwargs: Any, ) -> SetSessionModelResponse | None: """Set the current ACP session model selection.""" del kwargs diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_adapter_prompt.py b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_adapter_prompt.py index a6715b0..974fa23 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_adapter_prompt.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_adapter_prompt.py @@ -174,8 +174,8 @@ async def _handle_custom_slash_command( raw_prompt=raw_prompt, session=session, agent=agent, - ) - ) + ), + ), ) if result is None or not result.handled: return None @@ -254,7 +254,7 @@ async def _handle_cancelled_prompt( "", "Run details:", cancellation_details, - ) + ), ) await self._owner._record_update( session, @@ -288,7 +288,7 @@ def _handle_prompt_error( session.message_history_json, prompt_text=prompt_text, traceback_text="".join( - traceback.format_exception(type(error), error, error.__traceback__) + traceback.format_exception(type(error), error, error.__traceback__), ), ) session.updated_at = utc_now() @@ -337,7 +337,7 @@ async def _finalize_prompt_outcome( if prompt_outcome.stop_reason == "cancelled" else None ), - ) + ), ) session.updated_at = utc_now() self._owner._config.session_store.save(session) diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_agent_state.py b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_agent_state.py index 7eb4b44..268df75 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_agent_state.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_agent_state.py @@ -155,5 +155,5 @@ def assign_model( agent: Any, model: ModelOverride, ) -> None: - mutable_agent = cast(_AgentRuntimeCarrier, agent) + mutable_agent = cast("_AgentRuntimeCarrier", agent) mutable_agent.model = model diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_compat.py b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_compat.py index 4df6c1d..5b6d23a 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_compat.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_compat.py @@ -87,7 +87,7 @@ def replace_hook_entry( ) -> object | None: if is_dataclass(entry): try: - return replace(cast(Any, entry), func=func, timeout=timeout) + return replace(cast("Any", entry), func=func, timeout=timeout) except TypeError: return None try: @@ -95,7 +95,7 @@ def replace_hook_entry( except Exception: return None try: - wrapped_entry_any = cast(Any, wrapped_entry) + wrapped_entry_any = cast("Any", wrapped_entry) wrapped_entry_any.func = func wrapped_entry_any.timeout = timeout except Exception: diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_native_plan_runtime.py b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_native_plan_runtime.py index 1bad9c8..eba13a2 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_native_plan_runtime.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_native_plan_runtime.py @@ -99,7 +99,7 @@ async def persist_external_plan_state( agent, entries, plan_markdown, - ) + ), ) async def emit_native_plan_update(self, session: AcpSessionContext) -> None: @@ -177,7 +177,7 @@ def replace_native_plan_entry( { "index": index, "plan": f"Plan entry index must be between 1 and {len(entries)}.", - } + }, ) existing_entry = entries[index - 1] updated_payload = existing_entry.model_dump(mode="python") @@ -208,7 +208,7 @@ def format_native_plan(self, session: AcpSessionContext) -> str: session.plan_markdown.rstrip(), "Additional plan instructions:", additional_instructions, - ) + ), ) return "No plan has been recorded yet." numbered_entries = "\n".join( @@ -231,7 +231,7 @@ def format_native_plan(self, session: AcpSessionContext) -> str: "Current plan entries:", numbered_entries, *sections, - ) + ), ) def _native_plan_additional_instructions(self) -> str | None: diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_prompt_runtime.py b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_prompt_runtime.py index b5968e9..035a266 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_prompt_runtime.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_prompt_runtime.py @@ -30,7 +30,7 @@ OutputDataT = TypeVar("OutputDataT", covariant=True) RunOutputType: TypeAlias = OutputSpec[Any] -__all__ = ("TaskPlan", "NativePlanGeneration", "_PromptRuntime") +__all__ = ("NativePlanGeneration", "TaskPlan", "_PromptRuntime") class TaskPlan(BaseModel): diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_session_lifecycle.py b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_session_lifecycle.py index 4c32f85..2ba1d86 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_session_lifecycle.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_session_lifecycle.py @@ -39,7 +39,7 @@ async def new_session( cwd=self._runtime._normalize_cwd(cwd), created_at=utc_now(), updated_at=utc_now(), - ) + ), ) self._runtime._update_session_mcp_servers(session, mcp_servers) owner._config.session_store.save(session) diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_session_model_runtime.py b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_session_model_runtime.py index 65a60e9..1776e7a 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_session_model_runtime.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_session_model_runtime.py @@ -70,12 +70,14 @@ async def handle_slash_command( if command_name == "thinking": if argument is None: return render_thinking_message( - self._runtime._current_thinking_value(session, agent) + self._runtime._current_thinking_value(session, agent), ) normalized_argument = argument.strip().lower() if ( await self._runtime.set_config_option( - "thinking", session.session_id, normalized_argument + "thinking", + session.session_id, + normalized_argument, ) is None ): diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_session_runtime.py b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_session_runtime.py index 7937f31..86ad113 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_session_runtime.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_session_runtime.py @@ -82,7 +82,7 @@ async def list_sessions( updated_at=session.updated_at.isoformat(), ) for session in sessions - ] + ], ) async def fork_session( @@ -591,7 +591,7 @@ def add_model(model_id: str, *, override: ModelOverride | None = None) -> None: model_id=normalized_model_id, name=normalized_model_id, override=normalized_model_id if override is None else override, - ) + ), ) add_model(current_model_id, override=current_model_value) diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_session_surface_runtime.py b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_session_surface_runtime.py index 7089a07..56d460f 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_session_surface_runtime.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_session_surface_runtime.py @@ -340,7 +340,8 @@ async def synchronize_session_metadata( agent: PydanticAgent[AgentDepsT, OutputDataT], ) -> None: metadata_sections = self._runtime._owner._bridge_manager.get_metadata_sections( - session, agent + session, + agent, ) approval_state = await self.get_approval_state(session, agent) if approval_state is not None: @@ -409,7 +410,7 @@ def resolve_model_id_from_value(self, model_value: ModelOverride | None) -> str if model_option.override is model_value: return model_option.model_id if model_identity is not None and model_identity == self._runtime._model_identity( - model_option.override + model_option.override, ): return model_option.model_id if model_identity is not None: @@ -475,7 +476,7 @@ def add_model(model_id: str, *, override: ModelOverride | None = None) -> None: model_id=normalized_model_id, name=normalized_model_id, override=normalized_model_id if override is None else override, - ) + ), ) add_model(current_model_id, override=current_model_value) diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/adapter.py b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/adapter.py index cc0832f..98482d5 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/adapter.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/adapter.py @@ -44,7 +44,7 @@ AgentDepsT = TypeVar("AgentDepsT", contravariant=True) OutputDataT = TypeVar("OutputDataT", covariant=True) -__all__ = ("TaskPlan", "NativePlanGeneration", "PydanticAcpAgent") +__all__ = ("NativePlanGeneration", "PydanticAcpAgent", "TaskPlan") class PydanticAcpAgent( @@ -131,7 +131,6 @@ async def initialize( async def authenticate(self, method_id: str, **kwargs: Any) -> None: """Accept ACP auth handshakes when the host does not require extra auth.""" del method_id, kwargs - return None async def fork_session( self, diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/hook_introspection.py b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/hook_introspection.py index f2f2af6..b644a9d 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/hook_introspection.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/hook_introspection.py @@ -167,7 +167,7 @@ def list_agent_hooks(agent: PydanticAgent[Any, Any]) -> list[RegisteredHookInfo] event_id=event_id, hook_name=getattr(func, "__name__", "") or event_id, tool_filters=_tool_filters(entry), - ) + ), ) return sorted( hook_infos, diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/prompts.py b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/prompts.py index 07fd6dd..93583b0 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/prompts.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/prompts.py @@ -52,11 +52,11 @@ "PromptBlock", "PromptInput", "PromptRunOutcome", - "build_user_updates", "build_cancelled_history", + "build_user_updates", "contains_deferred_tool_requests", - "dump_message_history", "derive_title", + "dump_message_history", "load_message_history", "prompt_to_input", "prompt_to_text", @@ -143,10 +143,10 @@ def sanitize_message_history( _render_unprocessed_tool_call_text( unresolved_tool_calls, error_text=error_text, - ) - ) - ] - ) + ), + ), + ], + ), ) return sanitized_messages @@ -208,11 +208,11 @@ def build_error_history( "", "Traceback:", traceback_text.rstrip(), - ) - ) - ) - ] - ) + ), + ), + ), + ], + ), ) return dump_message_history(messages) @@ -308,12 +308,12 @@ def _embedded_resource_to_user_content( resource = block.resource if isinstance(resource, TextResourceContents): return _format_text_resource_context(resource.uri, resource.text) - blob_resource = cast(BlobResourceContents, resource) + blob_resource = cast("BlobResourceContents", resource) return BinaryContent.narrow_type( BinaryContent( data=base64.b64decode(blob_resource.blob), media_type=blob_resource.mime_type or "application/octet-stream", - ) + ), ) @@ -333,7 +333,7 @@ def _format_text_resource_context(uri: str, text: str) -> str: f'', text, "", - ) + ), ) @@ -343,7 +343,7 @@ def _resource_name_from_uri(uri: str) -> str | None: name = path.split("/")[-1] return name or path if uri.startswith("zed://"): - name = uri.split("/")[-1] + name = uri.rsplit("/", maxsplit=1)[-1] return name or uri return None @@ -372,7 +372,7 @@ def _render_cancelled_run_text(details_text: str) -> str: "", "Run details:", details_text.rstrip(), - ) + ), ) diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/server.py b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/server.py index 23a575e..217c5bd 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/server.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/server.py @@ -70,7 +70,7 @@ def _resolve_agent_source( provided_count = sum(provided is not None for provided in (agent, agent_factory, agent_source)) if provided_count != 1: raise ValueError( - "Exactly one of `agent`, `agent_factory`, or `agent_source` must be provided." + "Exactly one of `agent`, `agent_factory`, or `agent_source` must be provided.", ) if agent is not None: return StaticAgentSource(agent) diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/slash_commands.py b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/slash_commands.py index d786f64..2b203e7 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/slash_commands.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/slash_commands.py @@ -96,9 +96,9 @@ def build_available_commands( name=MODEL_COMMAND_NAME, description="Show the current session model, or set it with a provider:model value.", input=AvailableCommandInput( - root=UnstructuredCommandInput(hint="provider:model or codex:model") + root=UnstructuredCommandInput(hint="provider:model or codex:model"), ), - ) + ), ) if _has_config_option(config_options, THINKING_COMMAND_NAME): commands.append( @@ -106,9 +106,9 @@ def build_available_commands( name=THINKING_COMMAND_NAME, description="Show or set the current thinking effort.", input=AvailableCommandInput( - root=UnstructuredCommandInput(hint="default|off|minimal|low|medium|high|xhigh") + root=UnstructuredCommandInput(hint="default|off|minimal|low|medium|high|xhigh"), ), - ) + ), ) commands.extend( [ @@ -124,7 +124,7 @@ def build_available_commands( name=MCP_SERVERS_COMMAND_NAME, description="List MCP servers extracted from the active agent and session metadata.", ), - ] + ], ) if custom_commands: validate_custom_commands(custom_commands, mode_state=mode_state) @@ -143,7 +143,7 @@ def validate_custom_commands( if command.name != normalized_name: raise ValueError( f"Slash command name {command.name!r} must already be normalized as " - "a lowercase slash command id." + "a lowercase slash command id.", ) if not _COMMAND_NAME_PATTERN.fullmatch(normalized_name): raise ValueError(f"Slash command name {command.name!r} must match ^[a-z][a-z0-9-]*$.") @@ -154,13 +154,13 @@ def validate_custom_commands( if duplicate_names: raise ValueError( "Custom slash command names must be unique after normalization. " - f"Duplicate ids: {', '.join(duplicate_names)}." + f"Duplicate ids: {', '.join(duplicate_names)}.", ) reserved_names = sorted(set(normalized_names) & RESERVED_SLASH_COMMAND_NAMES) if reserved_names: raise ValueError( "Custom slash command names cannot reuse reserved slash command names " - f"({', '.join(reserved_names)})." + f"({', '.join(reserved_names)}).", ) if mode_state is None: return @@ -169,7 +169,7 @@ def validate_custom_commands( if conflicting_mode_ids: raise ValueError( "Custom slash command names cannot reuse active mode ids " - f"({', '.join(conflicting_mode_ids)})." + f"({', '.join(conflicting_mode_ids)}).", ) @@ -243,7 +243,7 @@ def list_agent_tools(agent: PydanticAgent[Any, Any]) -> list[ToolInfo]: name=name, description=description, requires_approval=tool.requires_approval, - ) + ), ) return tool_infos @@ -359,7 +359,7 @@ def render_mcp_server_listing(server_infos: list[McpServerInfo]) -> str: for server_info in server_infos: lines.append( f"- {server_info.name} ({server_info.transport}, {server_info.source}): " - f"{server_info.target}" + f"{server_info.target}", ) return "\n".join(lines) diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/session/state.py b/packages/adapters/pydantic-acp/src/pydantic_acp/session/state.py index 9536e1d..1505c2a 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/session/state.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/session/state.py @@ -58,7 +58,7 @@ class StoredSessionUpdate: @classmethod def from_update(cls, update: SessionTranscriptUpdate) -> StoredSessionUpdate: payload = _coerce_json_object( - update.model_dump(mode="json", by_alias=True, exclude_none=True) + update.model_dump(mode="json", by_alias=True, exclude_none=True), ) session_update = payload.get("sessionUpdate") if not _is_transcript_kind(session_update): diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/session/store.py b/packages/adapters/pydantic-acp/src/pydantic_acp/session/store.py index d760369..c0ea677 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/session/store.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/session/store.py @@ -24,7 +24,7 @@ _MAX_SESSION_ID_LENGTH = 128 _SESSION_ID_SAFE_CHARS = frozenset( - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-" + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-", ) _STORE_LOCKS: dict[str, threading.RLock] = {} _STORE_LOCKS_GUARD = threading.Lock() @@ -34,7 +34,11 @@ class SessionStore(Protocol): def delete(self, session_id: str) -> None: ... def fork( - self, session_id: str, *, new_session_id: str, cwd: Path + self, + session_id: str, + *, + new_session_id: str, + cwd: Path, ) -> AcpSessionContext | None: ... def get(self, session_id: str) -> AcpSessionContext | None: ... diff --git a/packages/adapters/pydantic-acp/src/pydantic_acp/testing/fakes.py b/packages/adapters/pydantic-acp/src/pydantic_acp/testing/fakes.py index 4a868d9..1127e69 100644 --- a/packages/adapters/pydantic-acp/src/pydantic_acp/testing/fakes.py +++ b/packages/adapters/pydantic-acp/src/pydantic_acp/testing/fakes.py @@ -57,7 +57,7 @@ class RecordingACPClient: updates: list[UpdateRecord] = field(default_factory=list) permission_option_ids: list[tuple[str, list[str], ToolCallUpdate]] = field(default_factory=list) permission_option_names: list[tuple[str, list[str], ToolCallUpdate]] = field( - default_factory=list + default_factory=list, ) permission_responses: list[RequestPermissionResponse] = field(default_factory=list) read_calls: list[tuple[str, str, int | None, int | None]] = field(default_factory=list) @@ -78,26 +78,26 @@ class RecordingACPClient: kill_calls: list[tuple[str, str]] = field(default_factory=list) write_response: WriteTextFileResponse | None = field(default_factory=WriteTextFileResponse) release_response: ReleaseTerminalResponse | None = field( - default_factory=ReleaseTerminalResponse + default_factory=ReleaseTerminalResponse, ) kill_response: KillTerminalResponse | None = field(default_factory=KillTerminalResponse) wait_response: WaitForTerminalExitResponse = field( - default_factory=lambda: WaitForTerminalExitResponse(exit_code=0) + default_factory=lambda: WaitForTerminalExitResponse(exit_code=0), ) terminal_output_response: TerminalOutputResponse = field( - default_factory=lambda: TerminalOutputResponse(output="terminal-output", truncated=False) + default_factory=lambda: TerminalOutputResponse(output="terminal-output", truncated=False), ) def queue_permission_selected(self, option_id: str) -> None: self.permission_responses.append( RequestPermissionResponse( outcome=AllowedOutcome(outcome="selected", option_id=option_id), - ) + ), ) def queue_permission_cancelled(self) -> None: self.permission_responses.append( - RequestPermissionResponse(outcome=DeniedOutcome(outcome="cancelled")) + RequestPermissionResponse(outcome=DeniedOutcome(outcome="cancelled")), ) async def request_permission( @@ -109,10 +109,10 @@ async def request_permission( ) -> RequestPermissionResponse: del kwargs self.permission_option_ids.append( - (session_id, [option.option_id for option in options], tool_call) + (session_id, [option.option_id for option in options], tool_call), ) self.permission_option_names.append( - (session_id, [option.name for option in options], tool_call) + (session_id, [option.name for option in options], tool_call), ) if not self.permission_responses: raise AssertionError("unexpected permission request") diff --git a/packages/helpers/codex-auth-helper/src/codex_auth_helper/__init__.py b/packages/helpers/codex-auth-helper/src/codex_auth_helper/__init__.py index e6292c1..0ad31b8 100644 --- a/packages/helpers/codex-auth-helper/src/codex_auth_helper/__init__.py +++ b/packages/helpers/codex-auth-helper/src/codex_auth_helper/__init__.py @@ -10,9 +10,9 @@ "CodexAsyncOpenAI", "CodexAuthConfig", "CodexAuthState", - "CodexResponsesModel", - "CodexOpenAI", "CodexAuthStore", + "CodexOpenAI", + "CodexResponsesModel", "CodexTokenManager", "__version__", "create_codex_async_openai", diff --git a/packages/helpers/codex-auth-helper/src/codex_auth_helper/_version.py b/packages/helpers/codex-auth-helper/src/codex_auth_helper/_version.py index 47a3698..19692fb 100644 --- a/packages/helpers/codex-auth-helper/src/codex_auth_helper/_version.py +++ b/packages/helpers/codex-auth-helper/src/codex_auth_helper/_version.py @@ -2,4 +2,4 @@ __all__ = ("__version__",) -__version__ = "1.0.0" +__version__ = "1.1.0" diff --git a/packages/helpers/codex-auth-helper/src/codex_auth_helper/auth/manager.py b/packages/helpers/codex-auth-helper/src/codex_auth_helper/auth/manager.py index 1974103..dc31630 100644 --- a/packages/helpers/codex-auth-helper/src/codex_auth_helper/auth/manager.py +++ b/packages/helpers/codex-auth-helper/src/codex_auth_helper/auth/manager.py @@ -100,8 +100,8 @@ async def _refresh_locked(self) -> CodexAuthState: "client_id": self.config.client_id, "grant_type": "refresh_token", "refresh_token": self._state.refresh_token, - } - ) + }, + ), ), headers={"Content-Type": "application/x-www-form-urlencoded"}, ) @@ -120,7 +120,7 @@ async def _refresh_locked(self) -> CodexAuthState: "refresh_token": _string_value(payload, "refresh_token") or self._state.refresh_token, }, - } + }, ) self.store.write_state(refreshed_state) return refreshed_state @@ -140,8 +140,8 @@ def _refresh_locked_sync(self) -> CodexAuthState: "client_id": self.config.client_id, "grant_type": "refresh_token", "refresh_token": self._state.refresh_token, - } - ) + }, + ), ), headers={"Content-Type": "application/x-www-form-urlencoded"}, ) @@ -160,7 +160,7 @@ def _refresh_locked_sync(self) -> CodexAuthState: "refresh_token": _string_value(payload, "refresh_token") or self._state.refresh_token, }, - } + }, ) self.store.write_state(refreshed_state) return refreshed_state diff --git a/packages/helpers/codex-auth-helper/src/codex_auth_helper/auth/state.py b/packages/helpers/codex-auth-helper/src/codex_auth_helper/auth/state.py index 905eef7..d2273b7 100644 --- a/packages/helpers/codex-auth-helper/src/codex_auth_helper/auth/state.py +++ b/packages/helpers/codex-auth-helper/src/codex_auth_helper/auth/state.py @@ -87,7 +87,10 @@ def _extract_account_id_from_claims(claims: Mapping[str, JsonValue]) -> str | No def _extract_account_id( - *, access_token: str, account_id: str | None, id_token: str | None + *, + access_token: str, + account_id: str | None, + id_token: str | None, ) -> str | None: if account_id is not None: return account_id diff --git a/packages/helpers/codex-auth-helper/src/codex_auth_helper/auth/store.py b/packages/helpers/codex-auth-helper/src/codex_auth_helper/auth/store.py index 37c5fa6..f6838ba 100644 --- a/packages/helpers/codex-auth-helper/src/codex_auth_helper/auth/store.py +++ b/packages/helpers/codex-auth-helper/src/codex_auth_helper/auth/store.py @@ -27,7 +27,7 @@ def read_state(self) -> CodexAuthState: raw = json.loads(text) except JSONDecodeError as exc: raise ValueError( - f"Codex auth file at `{self.path}` does not contain valid JSON." + f"Codex auth file at `{self.path}` does not contain valid JSON.", ) from exc if not isinstance(raw, dict): diff --git a/packages/helpers/codex-auth-helper/src/codex_auth_helper/client.py b/packages/helpers/codex-auth-helper/src/codex_auth_helper/client.py index f303ba3..69a1ae3 100644 --- a/packages/helpers/codex-auth-helper/src/codex_auth_helper/client.py +++ b/packages/helpers/codex-auth-helper/src/codex_auth_helper/client.py @@ -17,7 +17,8 @@ def _resolve_default_headers( - token_manager: CodexTokenManager, headers: dict[str, str | Omit] + token_manager: CodexTokenManager, + headers: dict[str, str | Omit], ) -> None: account_id = token_manager.current_account_id if account_id is not None: diff --git a/packages/helpers/codex-auth-helper/src/codex_auth_helper/factory.py b/packages/helpers/codex-auth-helper/src/codex_auth_helper/factory.py index 60e596a..3592679 100644 --- a/packages/helpers/codex-auth-helper/src/codex_auth_helper/factory.py +++ b/packages/helpers/codex-auth-helper/src/codex_auth_helper/factory.py @@ -27,7 +27,7 @@ def create_codex_responses_model( if instructions is None: raise ValueError( "`instructions` is required for Codex-backed Pydantic models. " - "Pass an explicit system instruction string." + "Pass an explicit system instruction string.", ) client = create_codex_async_openai(config=config, http_client=http_client) model_settings: OpenAIResponsesModelSettings = {"openai_store": False} @@ -61,14 +61,13 @@ def create_codex_chat_openai( The returned model is pinned to the OpenAI Responses API and reuses the same Codex auth flow as the Pydantic helper path. """ - try: from langchain_openai import ChatOpenAI except ModuleNotFoundError as exc: raise ModuleNotFoundError( "Install the optional LangChain dependency first: " 'uv add "codex-auth-helper[langchain]" or ' - 'pip install "codex-auth-helper[langchain]".' + 'pip install "codex-auth-helper[langchain]".', ) from exc async_root_client = create_codex_async_openai(config=config, http_client=http_client) @@ -77,17 +76,17 @@ def create_codex_chat_openai( if instructions is None: raise ValueError( "`instructions` is required for Codex-backed LangChain models. " - "Pass an explicit system instruction string." + "Pass an explicit system instruction string.", ) if "store" in chat_model_kwargs: raise ValueError( "Do not pass `model_kwargs['store']`; Codex-backed ChatOpenAI always forces " - "`store=False`." + "`store=False`.", ) if "instructions" in chat_model_kwargs: raise ValueError( "Pass `instructions` either through the dedicated parameter or " - "`model_kwargs['instructions']`, not both." + "`model_kwargs['instructions']`, not both.", ) chat_model_kwargs["instructions"] = instructions chat_openai_kwargs: dict[str, Any] = { diff --git a/packages/transports/acpremote/src/acpremote/__init__.py b/packages/transports/acpremote/src/acpremote/__init__.py index 4f27080..12613ed 100644 --- a/packages/transports/acpremote/src/acpremote/__init__.py +++ b/packages/transports/acpremote/src/acpremote/__init__.py @@ -23,25 +23,25 @@ from .stream import WebSocketStreamBridge, open_websocket_stream_bridge __all__ = ( - "__version__", - "CommandOptions", "DEFAULT_HEALTH_PATH", + "CommandOptions", "RemoteClientConnection", "RemoteProxyAgent", "ServerMetadata", "ServerOptions", "ServerPaths", - "TransportOptions", "TransportMetadata", + "TransportOptions", "WebSocketStreamBridge", + "__version__", "build_server_metadata", "build_server_paths", - "connect_remote_agent", "connect_acp", + "connect_remote_agent", "normalize_mount_path", "open_websocket_stream_bridge", - "run_remote_command_connection", "run_remote_agent_connection", + "run_remote_command_connection", "serve_acp", "serve_command", "serve_remote_agent", diff --git a/packages/transports/acpremote/src/acpremote/_version.py b/packages/transports/acpremote/src/acpremote/_version.py index 47a3698..19692fb 100644 --- a/packages/transports/acpremote/src/acpremote/_version.py +++ b/packages/transports/acpremote/src/acpremote/_version.py @@ -2,4 +2,4 @@ __all__ = ("__version__",) -__version__ = "1.0.0" +__version__ = "1.1.0" diff --git a/packages/transports/acpremote/src/acpremote/cli.py b/packages/transports/acpremote/src/acpremote/cli.py index a988bf0..8171ef2 100644 --- a/packages/transports/acpremote/src/acpremote/cli.py +++ b/packages/transports/acpremote/src/acpremote/cli.py @@ -258,7 +258,7 @@ def _load_native_agent_target(target: str, *, import_roots: Sequence[str]) -> Ag return loaded_target raise AcpRemoteCliError( "Target must resolve to a native `acp.interfaces.Agent`. " - "Use `acpkit serve` for Pydantic or LangChain targets." + "Use `acpkit serve` for Pydantic or LangChain targets.", ) @@ -274,7 +274,7 @@ def _parse_target_ref(target: str) -> _TargetRef: module_name, separator, attribute_path = target.partition(":") if not module_name: raise AcpRemoteCliError( - "Target must include a module name, for example `my_app` or `my_app:agent`." + "Target must include a module name, for example `my_app` or `my_app:agent`.", ) if separator and not attribute_path: raise AcpRemoteCliError("Target attribute cannot be empty.") @@ -298,7 +298,7 @@ def _import_target_module( return importlib.import_module(reference.module_name) except ImportError as exc: raise AcpRemoteCliError( - f"Could not import module `{reference.module_name}` from target `{target}`." + f"Could not import module `{reference.module_name}` from target `{target}`.", ) from exc @@ -310,7 +310,7 @@ def _resolve_latest_native_agent(module: ModuleType, target: str) -> Agent: if latest_target is None: raise AcpRemoteCliError( f"Target `{target}` did not resolve to a native ACP agent and the module defines no " - "native ACP agent instance." + "native ACP agent instance.", ) return latest_target @@ -322,7 +322,7 @@ def _resolve_attribute(module: ModuleType, attribute_path: str, *, target: str) value = getattr(value, attribute_name) except AttributeError as exc: raise AcpRemoteCliError( - f"Target `{target}` is missing attribute `{attribute_name}`." + f"Target `{target}` is missing attribute `{attribute_name}`.", ) from exc return value diff --git a/packages/transports/acpremote/src/acpremote/client.py b/packages/transports/acpremote/src/acpremote/client.py index 494c15b..aa049f8 100644 --- a/packages/transports/acpremote/src/acpremote/client.py +++ b/packages/transports/acpremote/src/acpremote/client.py @@ -115,10 +115,10 @@ def _merge_headers( if base is None: return extra if isinstance(base, Mapping): - base_mapping = cast(Mapping[str, str], base) + base_mapping = cast("Mapping[str, str]", base) merged_items: list[tuple[str, str]] = [*base_mapping.items(), *extra.items()] return merged_items - base_pairs = cast(Sequence[tuple[str, str]], base) + base_pairs = cast("Sequence[tuple[str, str]]", base) merged_pairs: list[tuple[str, str]] = [*base_pairs, *extra.items()] return merged_pairs diff --git a/packages/transports/acpremote/src/acpremote/proxy_agent.py b/packages/transports/acpremote/src/acpremote/proxy_agent.py index 5ee40fa..0472467 100644 --- a/packages/transports/acpremote/src/acpremote/proxy_agent.py +++ b/packages/transports/acpremote/src/acpremote/proxy_agent.py @@ -85,8 +85,8 @@ def update_meta(self, session_id: str) -> dict[str, Any] | None: "elapsed_ms": elapsed_ms, "first_update_ms": state.first_update_ms, "update_count": state.update_count, - } - } + }, + }, } def finish_prompt(self, session_id: str) -> _PromptLatencySnapshot | None: @@ -378,7 +378,7 @@ async def _remote_connection(self) -> RemoteClientConnection: remote_client: Client = client if self.options.emit_latency_meta: remote_client = cast( - Client, + "Client", _LatencyClient( delegate=client, tracker=self._latency_tracker, @@ -435,8 +435,8 @@ async def _emit_latency_projection( "total_ms": snapshot.total_ms, "first_update_ms": snapshot.first_update_ms, "update_count": snapshot.update_count, - } - } + }, + }, }, ), source="acpremote-latency", @@ -451,7 +451,7 @@ def connect_acp( options: TransportOptions | None = None, ) -> Agent: return cast( - Agent, + "Agent", RemoteProxyAgent( url=url, bearer_token=bearer_token, diff --git a/packages/transports/acpremote/src/acpremote/server.py b/packages/transports/acpremote/src/acpremote/server.py index 8d11586..16b9655 100644 --- a/packages/transports/acpremote/src/acpremote/server.py +++ b/packages/transports/acpremote/src/acpremote/server.py @@ -55,7 +55,7 @@ async def serve_remote_agent( if options is not None and server_options is not None: raise ValueError("pass either options or server_options, not both") resolved_server_options = server_options or ServerOptions( - transport=options or TransportOptions() + transport=options or TransportOptions(), ) resolved_transport = resolved_server_options.transport metadata = build_server_metadata(resolved_server_options) diff --git a/pyproject.toml b/pyproject.toml index e8219c2..c7017e9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,16 +17,17 @@ classifiers = [ keywords = ["acp", "agents", "protocol", "pydantic-ai"] dependencies = [ "click>=8.1.8", + "pydantic-ai>=2.4.0", "typing-extensions>=4.12.0", ] [project.optional-dependencies] -codex = ["codex-auth-helper>=1.0.0,<2.0.0"] -deepagents = ["langchain-acp[deepagents]>=1.0.0,<2.0.0"] -langchain = ["langchain-acp>=1.0.0,<2.0.0"] +codex = ["codex-auth-helper>=1.1.0,<2.0.0"] +deepagents = ["langchain-acp[deepagents]>=1.1.0,<2.0.0"] +langchain = ["langchain-acp>=1.1.0,<2.0.0"] launch = ["uv>=0.8.3"] -pydantic = ["pydantic-acp>=1.0.0,<2.0.0"] -remote = ["acpremote>=1.0.0,<2.0.0"] +pydantic = ["pydantic-acp>=1.1.0,<2.0.0"] +remote = ["acpremote>=1.1.0,<2.0.0"] dev = [ "acpremote", @@ -81,10 +82,10 @@ members = [ ] [tool.uv.sources] -acpremote = { workspace = true } codex-auth-helper = { workspace = true } langchain-acp = { workspace = true } pydantic-acp = { workspace = true } +acpremote = { workspace = true } [tool.hatch.build.targets.wheel] packages = ["src/acpkit"] diff --git a/scripts/generate_llms_docs.py b/scripts/generate_llms_docs.py index 2b339d8..022539d 100644 --- a/scripts/generate_llms_docs.py +++ b/scripts/generate_llms_docs.py @@ -332,7 +332,7 @@ def _build_llms_index() -> str: f"- [{page.title}]({page.url})", f" Source: `{page.path}`", f" Summary: {page.summary}", - ) + ), ) lines.append("") return "\n".join(lines).rstrip() + "\n" @@ -365,7 +365,7 @@ def _build_llms_full() -> str: f"Source: `{page.path}`", "", _load_doc_source(page), - ) + ), ) return "\n".join(lines).rstrip() + "\n" diff --git a/scripts/release.py b/scripts/release.py index f61eecc..2ae1963 100644 --- a/scripts/release.py +++ b/scripts/release.py @@ -22,7 +22,7 @@ _VERSION_PATTERN: Final[re.Pattern[str]] = re.compile(r'__version__\s*=\s*"(?P[^"]+)"') _SUPPORTED_VERSION_PATTERN: Final[re.Pattern[str]] = re.compile( r"^(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)" - r"(?:(?:a|b|rc)\d+)?$" + r"(?:(?:a|b|rc)\d+)?$", ) _RELEASE_DATE_PATTERN: Final[re.Pattern[str]] = re.compile(r"^\d{4}-\d{2}-\d{2}$") @@ -61,7 +61,7 @@ class Project: ), Project( name="acpkit", - directory=Path("."), + directory=Path(), version_file=Path("src/acpkit/_version.py"), ), ) @@ -83,7 +83,7 @@ def _workspace_version(root: Path) -> str: version = unique_versions.pop() if _SUPPORTED_VERSION_PATTERN.fullmatch(version) is None: raise ReleaseValidationError( - f"Unsupported release version {version!r}; expected X.Y.Z or X.Y.ZrcN." + f"Unsupported release version {version!r}; expected X.Y.Z or X.Y.ZrcN.", ) return version @@ -106,7 +106,7 @@ def _check_changelog(root: Path, version: str) -> None: heading = re.compile(rf"^## \[{re.escape(version)}\](?:\s|$)", re.MULTILINE) if heading.search(changelog_path.read_text(encoding="utf-8")) is None: raise ReleaseValidationError( - f"CHANGELOG.md does not contain a [{version}] release heading." + f"CHANGELOG.md does not contain a [{version}] release heading.", ) @@ -126,7 +126,7 @@ def _check_root_extras(root: Path, version: str) -> None: for extra, requirement in expected.items(): if requirement not in optional.get(extra, []): raise ReleaseValidationError( - f"Root extra {extra!r} must require the synchronized package as {requirement!r}." + f"Root extra {extra!r} must require the synchronized package as {requirement!r}.", ) @@ -148,7 +148,7 @@ def _check_release_tag(tag: str, version: str) -> None: raise ReleaseValidationError( f"Release tag {tag!r} does not match workspace version {version!r}; " - f"expected {version_tag!r} or {version_tag + '_YYYY-MM-DD'!r}." + f"expected {version_tag!r} or {version_tag + '_YYYY-MM-DD'!r}.", ) @@ -240,7 +240,7 @@ def _validate_root_requirements(metadata: Message, version: str) -> None: ] if not matching: raise ReleaseValidationError( - f"acpkit wheel does not declare its {package_name} integration dependency." + f"acpkit wheel does not declare its {package_name} integration dependency.", ) if _is_prerelease(version): valid_requirement = any(f"=={version}" in requirement for requirement in matching) @@ -251,7 +251,7 @@ def _validate_root_requirements(metadata: Message, version: str) -> None: ) if not valid_requirement: raise ReleaseValidationError( - f"acpkit wheel does not constrain {package_name} to the synchronized release." + f"acpkit wheel does not constrain {package_name} to the synchronized release.", ) @@ -266,7 +266,7 @@ def _validate_artifacts(*, output_dir: Path, version: str) -> None: ] if unexpected: raise ReleaseValidationError( - f"Unexpected files in release directory: {', '.join(unexpected)}." + f"Unexpected files in release directory: {', '.join(unexpected)}.", ) artifacts = [ path for path in files if path.name.endswith(".whl") or path.name.endswith(".tar.gz") @@ -274,7 +274,7 @@ def _validate_artifacts(*, output_dir: Path, version: str) -> None: expected_count = len(_PROJECTS) * 2 if len(artifacts) != expected_count: raise ReleaseValidationError( - f"Expected {expected_count} release artifacts, found {len(artifacts)}." + f"Expected {expected_count} release artifacts, found {len(artifacts)}.", ) observed: dict[str, set[str]] = {} root_wheel_metadata: Message | None = None @@ -287,7 +287,7 @@ def _validate_artifacts(*, output_dir: Path, version: str) -> None: raise ReleaseValidationError(f"Unexpected package name {name!r} in {artifact.name}.") if artifact_version != version: raise ReleaseValidationError( - f"{artifact.name} reports version {artifact_version!r}, expected {version!r}." + f"{artifact.name} reports version {artifact_version!r}, expected {version!r}.", ) observed.setdefault(name, set()).add(artifact_kind) if name == "acpkit" and artifact_kind == "wheel": @@ -296,7 +296,7 @@ def _validate_artifacts(*, output_dir: Path, version: str) -> None: for project in _PROJECTS: if observed.get(project.name) != expected_kinds: raise ReleaseValidationError( - f"{project.name} must provide exactly one wheel and one source distribution." + f"{project.name} must provide exactly one wheel and one source distribution.", ) if root_wheel_metadata is None: raise ReleaseValidationError("The acpkit wheel metadata was not found.") @@ -351,7 +351,7 @@ def smoke_test_artifacts(*, root: Path, dist_dir: Path) -> None: def _parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser( - description="Validate and build synchronized ACP Kit releases." + description="Validate and build synchronized ACP Kit releases.", ) subparsers = parser.add_subparsers(dest="command", required=True) @@ -365,12 +365,14 @@ def _parser() -> argparse.ArgumentParser: build_parser.add_argument("--output-dir", type=Path, default=Path("dist")) smoke_parser = subparsers.add_parser( - "smoke", help="Install built artifacts in a clean environment." + "smoke", + help="Install built artifacts in a clean environment.", ) smoke_parser.add_argument("--dist-dir", type=Path, default=Path("dist")) prepare_parser = subparsers.add_parser( - "prepare", help="Validate, build, and smoke test a tagged release." + "prepare", + help="Validate, build, and smoke test a tagged release.", ) prepare_parser.add_argument( "--tag", diff --git a/scripts/run_if_major_change.py b/scripts/run_if_major_change.py index f7c2970..4c65cc6 100644 --- a/scripts/run_if_major_change.py +++ b/scripts/run_if_major_change.py @@ -23,7 +23,7 @@ "Makefile", ".pre-commit-config.yaml", "uv.lock", - } + }, ) @@ -36,7 +36,7 @@ class ChangeSelection: def _parse_args() -> tuple[HookStage, list[str]]: parser = argparse.ArgumentParser( - description="Run an expensive command only when the staged change set is major." + description="Run an expensive command only when the staged change set is major.", ) parser.add_argument( "--stage", @@ -99,7 +99,7 @@ def _print_skip_message(selection: ChangeSelection, command: list[str]) -> None: return print( f"Skipping {' '.join(command)}: no major staged changes " - f"among {len(selection.changed_files)} staged file(s)." + f"among {len(selection.changed_files)} staged file(s).", ) diff --git a/scripts/save_coverage_summary.py b/scripts/save_coverage_summary.py index 2eda058..202f807 100644 --- a/scripts/save_coverage_summary.py +++ b/scripts/save_coverage_summary.py @@ -82,11 +82,11 @@ def _validate_thresholds(summary: CoverageSummary) -> None: failures: list[str] = [] if summary.line_coverage < MIN_LINE_COVERAGE: failures.append( - f"line coverage {summary.line_coverage:.2f}% is below required {MIN_LINE_COVERAGE:.2f}%" + f"line coverage {summary.line_coverage:.2f}% is below required {MIN_LINE_COVERAGE:.2f}%", ) if summary.branch_coverage < MIN_BRANCH_COVERAGE: failures.append( - f"branch coverage {summary.branch_coverage:.2f}% is below required {MIN_BRANCH_COVERAGE:.2f}%" + f"branch coverage {summary.branch_coverage:.2f}% is below required {MIN_BRANCH_COVERAGE:.2f}%", ) if failures: raise SystemExit("Coverage thresholds failed:\n- " + "\n- ".join(failures)) @@ -97,7 +97,7 @@ def _parse_args() -> argparse.Namespace: description=( "Validate ACP Kit adapter-package coverage thresholds and optionally write the " "COVERAGE summary." - ) + ), ) parser.add_argument( "--input", diff --git a/src/acpkit/__init__.py b/src/acpkit/__init__.py index 905bdef..9537715 100644 --- a/src/acpkit/__init__.py +++ b/src/acpkit/__init__.py @@ -22,7 +22,6 @@ __all__ = ( "AcpKitError", "CompatibilityManifest", - "connect_acp", "MissingAdapterError", "SurfaceOwner", "SurfaceStatus", @@ -31,6 +30,7 @@ "TargetResolutionError", "UnsupportedAgentError", "__version__", + "connect_acp", "launch_command", "launch_target", "load_target", diff --git a/src/acpkit/_compatibility_schema.py b/src/acpkit/_compatibility_schema.py index 4d29881..4d1107d 100644 --- a/src/acpkit/_compatibility_schema.py +++ b/src/acpkit/_compatibility_schema.py @@ -63,7 +63,7 @@ def to_markdown(self) -> str: f"{_render_cell(support.status)} | " f"{_render_cell(support.owner)} | " f"{_render_cell(support.mapping)} | " - f"{_render_cell(support.rationale)} |" + f"{_render_cell(support.rationale)} |", ) return "\n".join(lines) @@ -73,19 +73,19 @@ def _validate_surface_name(self, surface_name: str) -> None: raise ValueError("Compatibility manifest surface names must not be empty.") if normalized != surface_name: raise ValueError( - f"Compatibility manifest surface `{surface_name}` must not have surrounding whitespace." + f"Compatibility manifest surface `{surface_name}` must not have surrounding whitespace.", ) def _validate_support(self, surface_name: str, support: SurfaceSupport) -> None: if support.status in {"implemented", "partial"} and support.owner is None: raise ValueError( f"Compatibility manifest surface `{surface_name}` must declare an owner " - "when status is implemented or partial." + "when status is implemented or partial.", ) if support.status == "implemented" and _is_blank(support.mapping): raise ValueError( f"Compatibility manifest surface `{surface_name}` must declare a mapping " - "when status is implemented." + "when status is implemented.", ) if support.status in { "partial", @@ -94,12 +94,12 @@ def _validate_support(self, surface_name: str, support: SurfaceSupport) -> None: } and _is_blank(support.rationale): raise ValueError( f"Compatibility manifest surface `{surface_name}` must declare a rationale " - f"when status is {support.status}." + f"when status is {support.status}.", ) if support.owner == "mixed" and _is_blank(support.rationale): raise ValueError( f"Compatibility manifest surface `{surface_name}` must explain how mixed " - "ownership works." + "ownership works.", ) diff --git a/src/acpkit/_version.py b/src/acpkit/_version.py index 47a3698..19692fb 100644 --- a/src/acpkit/_version.py +++ b/src/acpkit/_version.py @@ -2,4 +2,4 @@ __all__ = ("__version__",) -__version__ = "1.0.0" +__version__ = "1.1.0" diff --git a/src/acpkit/runtime.py b/src/acpkit/runtime.py index 8879e42..7e962ad 100644 --- a/src/acpkit/runtime.py +++ b/src/acpkit/runtime.py @@ -29,8 +29,8 @@ "TargetResolutionError", "UnsupportedAgentError", "launch_command", - "load_target", "launch_target", + "load_target", "run_remote_addr", "run_target", "serve_target", @@ -62,7 +62,7 @@ class MissingAdapterError(AcpKitError): def for_adapter(cls, adapter: AdapterDefinition) -> MissingAdapterError: return cls( f"The resolved target requires the `{adapter.extra_name}` adapter. " - f"Install it with: `{adapter.install_command()}`." + f"Install it with: `{adapter.install_command()}`.", ) @classmethod @@ -86,11 +86,11 @@ def parse_target_ref(target: str) -> TargetRef: module_name, separator, attribute_path = target.partition(":") if not module_name: raise TargetResolutionError( - "Target must include a module name, for example `my_app` or `my_app:agent`." + "Target must include a module name, for example `my_app` or `my_app:agent`.", ) if separator != "" and not attribute_path: raise TargetResolutionError( - "Target attribute cannot be empty. Use `my_app` or `my_app:agent`." + "Target attribute cannot be empty. Use `my_app` or `my_app:agent`.", ) return TargetRef( module_name=module_name, @@ -165,7 +165,7 @@ def launch_command(command: str) -> int: except FileNotFoundError as exc: raise AcpKitError( "`uvx` is required to launch Toad ACP sessions. " - 'Install it with: `uv pip install "acpkit[launch]"`.' + 'Install it with: `uv pip install "acpkit[launch]"`.', ) from exc return completed.returncode @@ -254,7 +254,7 @@ def _import_target_module( import_error = str(exc).strip() detail = f" Import error: {import_error}" if import_error else "" raise TargetResolutionError( - f"Could not import module `{reference.module_name}` from target `{target}`.{detail}" + f"Could not import module `{reference.module_name}` from target `{target}`.{detail}", ) from exc @@ -266,7 +266,7 @@ def _resolve_latest_supported_target(module: ModuleType, target: str) -> Any: if latest_target is None: raise UnsupportedAgentError( f"Target `{target}` did not resolve to a supported agent and the module defines no " - "known agent instance." + "known agent instance.", ) return latest_target @@ -295,7 +295,7 @@ def _resolve_target_from_module(module: ModuleType, reference: TargetRef, target value = getattr(value, attribute_name) except AttributeError as exc: raise TargetResolutionError( - f"Target `{target}` is missing attribute `{attribute_name}`." + f"Target `{target}` is missing attribute `{attribute_name}`.", ) from exc return value diff --git a/tests/acpremote/test_cli.py b/tests/acpremote/test_cli.py index c55151a..2897116 100644 --- a/tests/acpremote/test_cli.py +++ b/tests/acpremote/test_cli.py @@ -62,7 +62,7 @@ def _write_native_agent_module(tmp_path: Path) -> None: "", "ignored = object()", "agent = NativeAgent()", - ) + ), ) + "\n", encoding="utf-8", @@ -112,14 +112,14 @@ async def fake_serve_stdio_command( "python", "agent.py", "--flag", - ] + ], ) assert exit_code == 0 assert server.serve_forever_calls == 1 assert server.close_calls == 1 assert server.wait_closed_calls == 1 - command_options = cast(CommandOptions, calls[0]["command_options"]) + command_options = cast("CommandOptions", calls[0]["command_options"]) assert command_options.command == ("python", "agent.py", "--flag") assert command_options.cwd == str(tmp_path) assert command_options.env == {"A": "1", "EMPTY": ""} @@ -162,7 +162,7 @@ async def fake_serve_acp(agent: Any, **kwargs: Any) -> _FakeServer: "/acp", "--bearer-token", "direct-token", - ] + ], ) assert exit_code == 0 @@ -258,7 +258,7 @@ def test_acpremote_cli_banner_handles_servers_without_tcp_port( capsys: pytest.CaptureFixture[str], ) -> None: server_without_sockets = _FakeServer(sockets=[]) - server_with_non_tcp_socket = _FakeServer(sockets=[cast(Any, _FakeNonTcpSocket())]) + server_with_non_tcp_socket = _FakeServer(sockets=[cast("Any", _FakeNonTcpSocket())]) cli_module._print_server_banner(server_without_sockets, host="127.0.0.1", mount_path="/acp") diff --git a/tests/acpremote/test_command_server.py b/tests/acpremote/test_command_server.py index 0f53311..884677d 100644 --- a/tests/acpremote/test_command_server.py +++ b/tests/acpremote/test_command_server.py @@ -35,7 +35,7 @@ async def request_permission( async def session_update(self, session_id: str, update: Any, **kwargs: Any) -> None: self.updates.append( - SessionNotification(session_id=session_id, update=update, field_meta=kwargs or None) + SessionNotification(session_id=session_id, update=update, field_meta=kwargs or None), ) async def ext_method(self, method: str, params: dict[str, Any]) -> dict[str, Any]: @@ -54,7 +54,7 @@ async def test_command_server_recording_client_stub_methods() -> None: client = _RecordingClient() with pytest.raises(AssertionError, match="permission flow"): - await client.request_permission([], "session-1", cast(Any, object())) + await client.request_permission([], "session-1", cast("Any", object())) with pytest.raises(AssertionError, match="extension methods"): await client.ext_method("demo.echo", {"value": 1}) @@ -137,7 +137,7 @@ def _write_stdio_acp_script(tmp_path: Path, *, emit_stderr: bool = False) -> Pat " await run_agent(EchoAgent())", "", "asyncio.run(main())", - ) + ), ).strip() + "\n", encoding="utf-8", @@ -179,7 +179,7 @@ async def test_serve_command_relays_stdio_acp_process(tmp_path: Path) -> None: assert server.sockets is not None port = next(iter(server.sockets)).getsockname()[1] remote = await connect_remote_agent( - cast(Client, client), + cast("Client", client), f"ws://127.0.0.1:{port}/command/ws", ) try: @@ -220,7 +220,7 @@ async def test_serve_command_metadata_exposes_remote_cwd(tmp_path: Path) -> None assert server.sockets is not None port = next(iter(server.sockets)).getsockname()[1] remote = await connect_remote_agent( - cast(Client, client), + cast("Client", client), f"ws://127.0.0.1:{port}/command/ws", ) try: @@ -251,7 +251,7 @@ async def test_serve_stdio_command_supports_discarded_stderr(tmp_path: Path) -> assert server.sockets is not None port = next(iter(server.sockets)).getsockname()[1] remote = await connect_remote_agent( - cast(Client, client), + cast("Client", client), f"ws://127.0.0.1:{port}/discard/ws", ) try: diff --git a/tests/acpremote/test_helpers.py b/tests/acpremote/test_helpers.py index 98039cf..04b3743 100644 --- a/tests/acpremote/test_helpers.py +++ b/tests/acpremote/test_helpers.py @@ -79,7 +79,7 @@ async def request_permission( "session_id": session_id, "tool_call": tool_call, "kwargs": kwargs, - } + }, ) return "ok" @@ -99,7 +99,7 @@ class _FakeRemoteMethods: async def initialize(self, protocol_version: int, **kwargs: Any) -> InitializeResponse: self.calls.append( - ("initialize", {"protocol_version": protocol_version, **kwargs}) + ("initialize", {"protocol_version": protocol_version, **kwargs}), ) # pragma: no cover return InitializeResponse(protocol_version=protocol_version) # pragma: no cover @@ -109,23 +109,23 @@ async def new_session(self, **kwargs: Any) -> NewSessionResponse: async def load_session(self, **kwargs: Any) -> LoadSessionResponse | None: self.calls.append(("load_session", kwargs)) - return cast(LoadSessionResponse, {"ok": True}) + return cast("LoadSessionResponse", {"ok": True}) async def list_sessions(self, **kwargs: Any) -> ListSessionsResponse: self.calls.append(("list_sessions", kwargs)) - return cast(ListSessionsResponse, {"sessions": []}) + return cast("ListSessionsResponse", {"sessions": []}) async def set_session_mode(self, **kwargs: Any) -> SetSessionModeResponse | None: self.calls.append(("set_session_mode", kwargs)) - return cast(SetSessionModeResponse, {"mode": kwargs["mode_id"]}) + return cast("SetSessionModeResponse", {"mode": kwargs["mode_id"]}) async def set_session_model(self, **kwargs: Any) -> SetSessionModelResponse | None: self.calls.append(("set_session_model", kwargs)) - return cast(SetSessionModelResponse, {"model": kwargs["model_id"]}) + return cast("SetSessionModelResponse", {"model": kwargs["model_id"]}) async def set_config_option(self, **kwargs: Any) -> SetSessionConfigOptionResponse | None: self.calls.append(("set_config_option", kwargs)) - return cast(SetSessionConfigOptionResponse, {"config": kwargs["config_id"]}) + return cast("SetSessionConfigOptionResponse", {"config": kwargs["config_id"]}) async def authenticate(self, **kwargs: Any) -> AuthenticateResponse | None: self.calls.append(("authenticate", kwargs)) @@ -137,11 +137,11 @@ async def prompt(self, **kwargs: Any) -> PromptResponse: async def fork_session(self, **kwargs: Any) -> ForkSessionResponse: self.calls.append(("fork_session", kwargs)) - return cast(ForkSessionResponse, {"session_id": kwargs["session_id"]}) + return cast("ForkSessionResponse", {"session_id": kwargs["session_id"]}) async def resume_session(self, **kwargs: Any) -> ResumeSessionResponse: self.calls.append(("resume_session", kwargs)) - return cast(ResumeSessionResponse, {"session_id": kwargs["session_id"]}) + return cast("ResumeSessionResponse", {"session_id": kwargs["session_id"]}) async def close_session(self, **kwargs: Any) -> CloseSessionResponse | None: self.calls.append(("close_session", kwargs)) @@ -271,7 +271,7 @@ async def test_helper_fakes_cover_unreached_stub_paths() -> None: assert await methods.list_sessions(cursor="c-1") == {"sessions": []} assert await methods.set_session_mode(session_id="s-1", mode_id="ask") == {"mode": "ask"} assert await methods.set_session_model(session_id="s-1", model_id="model-a") == { - "model": "model-a" + "model": "model-a", } assert await methods.set_config_option(session_id="s-1", config_id="flag") == {"config": "flag"} assert isinstance(await methods.authenticate(method_id="demo"), AuthenticateResponse) @@ -339,8 +339,8 @@ async def test_client_helper_paths_cover_metadata_edge_cases( b'"auth_required":1,"supported_auth_modes":"bearer","max_size":"12","max_queue":"4",' b'"compression":5,"health_path":"/healthz","metadata_path":"/acp",' b'"websocket_path":"/acp/ws","supported_agent_families":"none","remote_cwd":123}' - ) - ) + ), + ), ) broken_request = _FakeHttpConnection( response=_FakeHttpResponse(), @@ -354,7 +354,7 @@ async def test_client_helper_paths_cover_metadata_edge_cases( missing_keys, good_payload, broken_request, - ] + ], ) monkeypatch.setattr( @@ -419,9 +419,9 @@ async def close(self) -> None: closed.append("streams") remote = RemoteClientConnection( - connection=cast(Any, _FakeConnection()), - websocket=cast(Any, object()), - streams=cast(Any, _FakeStreams()), + connection=cast("Any", _FakeConnection()), + websocket=cast("Any", object()), + streams=cast("Any", _FakeStreams()), ) await remote.close() assert closed == ["connection", "streams"] @@ -462,9 +462,9 @@ async def close(self) -> None: closed.append("streams") remote = RemoteClientConnection( - connection=cast(Any, _FailingConnection()), - websocket=cast(Any, object()), - streams=cast(Any, _FakeStreams()), + connection=cast("Any", _FailingConnection()), + websocket=cast("Any", object()), + streams=cast("Any", _FakeStreams()), ) with pytest.raises(RuntimeError, match="connection close failed"): @@ -500,7 +500,7 @@ async def fail_open_streams(*args: Any, **kwargs: Any) -> None: with pytest.raises(RuntimeError, match="stream setup failed"): await client_module.connect_remote_agent( - cast(Any, object()), + cast("Any", object()), "ws://example.com/acp/ws", ) @@ -539,7 +539,7 @@ def fail_connect_to_agent(*args: Any, **kwargs: Any) -> None: with pytest.raises(RuntimeError, match="ACP setup failed"): await client_module.connect_remote_agent( - cast(Any, object()), + cast("Any", object()), "ws://example.com/acp/ws", ) @@ -588,7 +588,7 @@ async def fail_metadata(*args: Any, **kwargs: Any) -> None: with pytest.raises(RuntimeError, match="metadata failed"): await client_module.connect_remote_agent( - cast(Any, object()), + cast("Any", object()), "ws://example.com/acp/ws", ) @@ -605,29 +605,29 @@ async def test_command_helper_paths_cover_process_relay_edges( fake_stdin = _FakeStdin() with pytest.raises(TypeError, match="binary WebSocket frames"): await command_module._relay_websocket_to_stdin( - cast(Any, _FakeCommandWebSocket(messages=[b"binary"])), - cast(Any, fake_stdin), + cast("Any", _FakeCommandWebSocket(messages=[b"binary"])), + cast("Any", fake_stdin), ) assert fake_stdin.closed is True stdout_websocket = _FakeCommandWebSocket(messages=[]) await command_module._relay_stdout_to_websocket( - cast(Any, _FakeStdout(lines=[b"first\n", b"second", b""])), - cast(Any, stdout_websocket), + cast("Any", _FakeStdout(lines=[b"first\n", b"second", b""])), + cast("Any", stdout_websocket), ) assert stdout_websocket.sent == ["first", "second"] already_closed = _FakeStdin() already_closed.close() - await command_module._close_stdin(cast(Any, already_closed)) + await command_module._close_stdin(cast("Any", already_closed)) assert already_closed.closed is True broken_pipe = _FakeStdin(wait_closed_error=BrokenPipeError()) - await command_module._close_stdin(cast(Any, broken_pipe)) + await command_module._close_stdin(cast("Any", broken_pipe)) assert broken_pipe.closed is True connection_reset = _FakeStdin(wait_closed_error=ConnectionResetError()) - await command_module._close_stdin(cast(Any, connection_reset)) + await command_module._close_stdin(cast("Any", connection_reset)) assert connection_reset.closed is True @@ -664,7 +664,7 @@ async def _raises(exc: BaseException) -> None: raise exc for exc in ( - cast(BaseException, ConnectionClosedOK(None, None)), + cast("BaseException", ConnectionClosedOK(None, None)), BrokenPipeError(), ConnectionResetError(), ProcessLookupError(), @@ -672,7 +672,7 @@ async def _raises(exc: BaseException) -> None: task = asyncio.create_task(_raises(exc)) with contextlib.suppress(type(exc)): await task - command_module._raise_if_needed(cast(asyncio.Task[object], task)) + command_module._raise_if_needed(cast("asyncio.Task[object]", task)) cancelled = asyncio.create_task(asyncio.sleep(1)) await asyncio.sleep(0) @@ -680,7 +680,7 @@ async def _raises(exc: BaseException) -> None: with contextlib.suppress(asyncio.CancelledError): await cancelled with pytest.raises(asyncio.CancelledError): - command_module._raise_if_needed(cast(asyncio.Task[object], cancelled)) + command_module._raise_if_needed(cast("asyncio.Task[object]", cancelled)) @pytest.mark.asyncio @@ -703,7 +703,6 @@ async def fake_close_stdin(stdin: Any) -> None: async def done_immediately(*args: Any, **kwargs: Any) -> None: del args, kwargs - return None async def done_later(*args: Any, **kwargs: Any) -> None: del args, kwargs @@ -719,7 +718,7 @@ async def create_fast_process(**kwargs: Any) -> _FakeCommandProcess: monkeypatch.setattr(command_module, "_relay_websocket_to_stdin", done_later) monkeypatch.setattr(command_module, "_relay_stdout_to_websocket", done_later) await command_module.run_remote_command_connection( - cast(Any, object()), + cast("Any", object()), command_options=command_module.CommandOptions(command=("echo", "hi")), ) assert close_calls @@ -736,7 +735,7 @@ async def create_delayed_process(**kwargs: Any) -> _FakeCommandProcess: monkeypatch.setattr(command_module, "_relay_websocket_to_stdin", done_immediately) monkeypatch.setattr(command_module, "_relay_stdout_to_websocket", done_later) await command_module.run_remote_command_connection( - cast(Any, object()), + cast("Any", object()), command_options=command_module.CommandOptions(command=("echo", "hi")), ) assert delayed_exit.terminate_calls >= 1 @@ -762,7 +761,7 @@ async def create_hanging_process(**kwargs: Any) -> _FakeCommandProcess: monkeypatch.setattr(command_module, "_relay_stdout_to_websocket", slow_relay) with pytest.raises(ValueError, match="boom"): await command_module.run_remote_command_connection( - cast(Any, object()), + cast("Any", object()), command_options=command_module.CommandOptions( command=("echo", "hi"), terminate_timeout=0.001, @@ -778,7 +777,7 @@ async def create_hanging_process(**kwargs: Any) -> _FakeCommandProcess: async def test_command_process_terminate_timeout_kills() -> None: process = _FakeCommandProcess(wait_delay=0.02) - await command_module._terminate_process(cast(Any, process), timeout=0.001) + await command_module._terminate_process(cast("Any", process), timeout=0.001) assert process.terminate_calls == 1 assert process.kill_calls == 1 @@ -789,7 +788,7 @@ async def test_command_process_terminate_timeout_kills() -> None: async def test_command_process_terminate_returns_when_already_exited() -> None: process = _FakeCommandProcess(returncode=0) - await command_module._terminate_process(cast(Any, process), timeout=0.001) + await command_module._terminate_process(cast("Any", process), timeout=0.001) assert process.terminate_calls == 0 assert process.kill_calls == 0 @@ -809,7 +808,7 @@ async def wait(self) -> int: process = _ExitingOnCancelledProcess() - await command_module._terminate_process(cast(Any, process), timeout=0.001) + await command_module._terminate_process(cast("Any", process), timeout=0.001) assert process.terminate_calls == 1 assert process.kill_calls == 0 @@ -820,7 +819,7 @@ async def wait(self) -> int: async def test_command_process_terminate_kills_when_cancelled() -> None: process = _FakeCommandProcess(wait_delay=0.01) task = asyncio.create_task( - command_module._terminate_process(cast(Any, process), timeout=1), + command_module._terminate_process(cast("Any", process), timeout=1), ) await asyncio.sleep(0) @@ -846,7 +845,7 @@ async def wait(self) -> int: process = _ExitedOnCancelledProcess() task = asyncio.create_task( - command_module._terminate_process(cast(Any, process), timeout=1), + command_module._terminate_process(cast("Any", process), timeout=1), ) await asyncio.sleep(0) @@ -865,7 +864,6 @@ async def test_command_connection_covers_all_done_path( ) -> None: async def all_done(*args: Any, **kwargs: Any) -> None: del args, kwargs - return None process = _FakeCommandProcess(wait_delay=0.0) @@ -878,7 +876,7 @@ async def create_process(**kwargs: Any) -> _FakeCommandProcess: monkeypatch.setattr(command_module, "_relay_stdout_to_websocket", all_done) await command_module.run_remote_command_connection( - cast(Any, _FakeCommandWebSocket(messages=[])), + cast("Any", _FakeCommandWebSocket(messages=[])), command_options=command_module.CommandOptions(command=("echo", "hi")), ) @@ -903,7 +901,7 @@ async def test_proxy_agent_helper_paths_cover_delegate_and_metadata_edges( client = _FakeClient() latency_client = proxy_agent_module._LatencyClient( - delegate=cast(Any, client), + delegate=cast("Any", client), tracker=tracker, emit_latency_meta=False, ) @@ -918,7 +916,7 @@ async def test_proxy_agent_helper_paths_cover_delegate_and_metadata_edges( assert proxy_agent_module._merge_field_meta({"source": "x"}, None) == {"source": "x"} assert proxy_agent_module._merge_field_meta({}, {"acpremote": {"value": 1}}) == { - "field_meta": {"acpremote": {"value": 1}} + "field_meta": {"acpremote": {"value": 1}}, } assert proxy_agent_module._merge_field_meta( {"field_meta": "not-a-dict"}, @@ -986,17 +984,17 @@ class _ClosableRemote: async def close(self) -> None: closers.append("closed") # pragma: no cover - proxy._client = cast(Any, object()) - proxy._remote = cast(RemoteClientConnection, _ClosableRemote()) + proxy._client = cast("Any", object()) + proxy._remote = cast("RemoteClientConnection", _ClosableRemote()) monkeypatch.setattr(asyncio, "get_running_loop", lambda: (_ for _ in ()).throw(RuntimeError())) - proxy.on_connect(cast(Any, object())) + proxy.on_connect(cast("Any", object())) assert proxy._remote is None await proxy.close() assert closers == ["closed"] - proxy._client = cast(Any, object()) - proxy._remote = cast(RemoteClientConnection, _ClosableRemote()) - proxy.on_connect(cast(Any, object())) + proxy._client = cast("Any", object()) + proxy._remote = cast("RemoteClientConnection", _ClosableRemote()) + proxy.on_connect(cast("Any", object())) assert proxy._remote is None await proxy.close() assert closers == ["closed", "closed"] @@ -1012,7 +1010,7 @@ async def _close_remote() -> None: return None # pragma: no cover remote = cast( - RemoteClientConnection, + "RemoteClientConnection", SimpleNamespace( connection=methods, metadata=ServerMetadata( @@ -1037,7 +1035,7 @@ async def _close_remote() -> None: url="ws://example.invalid/acp/ws", options=TransportOptions(), ) - proxy._client = cast(Any, object()) + proxy._client = cast("Any", object()) proxy._remote = remote proxy._remote_cwd = "/srv/remote" @@ -1083,14 +1081,14 @@ async def __aexit__(self, exc_type: Any, exc: Any, tb: Any) -> bool: del exc_type, exc, tb return False - proxy._connect_lock = cast(Any, _PreloadedLock(proxy)) + proxy._connect_lock = cast("Any", _PreloadedLock(proxy)) assert await proxy._remote_connection() is remote prompt_proxy = proxy_agent_module.RemoteProxyAgent(url="ws://example.invalid/acp/ws") - prompt_proxy._client = cast(Any, object()) + prompt_proxy._client = cast("Any", object()) prompt_proxy._remote = remote prompt_proxy._latency_tracker = cast( - Any, + "Any", SimpleNamespace( start_prompt=lambda session_id: None, finish_prompt=lambda session_id: None, @@ -1116,7 +1114,7 @@ async def test_stream_helper_paths_cover_protocol_and_sender_edge_cases() -> Non loop = asyncio.get_running_loop() protocol = stream_module._WriterProtocol(loop=loop) await protocol._drain_helper() - waiter = protocol._get_close_waiter(cast(asyncio.StreamWriter, object())) + waiter = protocol._get_close_waiter(cast("asyncio.StreamWriter", object())) protocol.connection_lost(None) await waiter @@ -1126,7 +1124,7 @@ async def test_stream_helper_paths_cover_protocol_and_sender_edge_cases() -> Non websocket = _FakeStreamWebSocket() transport = stream_module._WebSocketTransport( - websocket=cast(Any, websocket), + websocket=cast("Any", websocket), loop=loop, protocol=protocol, ) @@ -1139,7 +1137,7 @@ async def test_stream_helper_paths_cover_protocol_and_sender_edge_cases() -> Non second_future: asyncio.Future[None] = loop.create_future() transport._pending.put_nowait(stream_module._PendingWrite(payload="first", future=first_future)) transport._pending.put_nowait( - stream_module._PendingWrite(payload="second", future=second_future) + stream_module._PendingWrite(payload="second", future=second_future), ) transport._pending.put_nowait(None) await transport._sender_loop() @@ -1149,7 +1147,7 @@ async def test_stream_helper_paths_cover_protocol_and_sender_edge_cases() -> Non error_websocket = _FakeStreamWebSocket(send_error=ConnectionResetError("boom")) error_protocol = stream_module._WriterProtocol(loop=loop) error_transport = stream_module._WebSocketTransport( - websocket=cast(Any, error_websocket), + websocket=cast("Any", error_websocket), loop=loop, protocol=error_protocol, ) @@ -1160,10 +1158,10 @@ async def test_stream_helper_paths_cover_protocol_and_sender_edge_cases() -> Non failed_future: asyncio.Future[None] = loop.create_future() pending_future: asyncio.Future[None] = loop.create_future() error_transport._pending.put_nowait( - stream_module._PendingWrite(payload="fail", future=failed_future) + stream_module._PendingWrite(payload="fail", future=failed_future), ) error_transport._pending.put_nowait( - stream_module._PendingWrite(payload="pending", future=pending_future) + stream_module._PendingWrite(payload="pending", future=pending_future), ) error_transport._pending.put_nowait(None) await error_transport._sender_loop() @@ -1174,7 +1172,7 @@ async def test_stream_helper_paths_cover_protocol_and_sender_edge_cases() -> Non cancelled_websocket = _FakeStreamWebSocket(send_error=asyncio.CancelledError()) cancelled_protocol = stream_module._WriterProtocol(loop=loop) cancelled_transport = stream_module._WebSocketTransport( - websocket=cast(Any, cancelled_websocket), + websocket=cast("Any", cancelled_websocket), loop=loop, protocol=cancelled_protocol, ) @@ -1183,7 +1181,7 @@ async def test_stream_helper_paths_cover_protocol_and_sender_edge_cases() -> Non await cancelled_transport._sender_task cancelled_future: asyncio.Future[None] = loop.create_future() cancelled_transport._pending.put_nowait( - stream_module._PendingWrite(payload="cancel", future=cancelled_future) + stream_module._PendingWrite(payload="cancel", future=cancelled_future), ) with pytest.raises(asyncio.CancelledError): await cancelled_transport._sender_loop() diff --git a/tests/acpremote/test_phase1.py b/tests/acpremote/test_phase1.py index e61147c..a89e814 100644 --- a/tests/acpremote/test_phase1.py +++ b/tests/acpremote/test_phase1.py @@ -80,7 +80,7 @@ async def request_permission( async def session_update(self, session_id: str, update: Any, **kwargs: Any) -> None: self.updates.append( - SessionNotification(session_id=session_id, update=update, field_meta=kwargs or None) + SessionNotification(session_id=session_id, update=update, field_meta=kwargs or None), ) async def write_text_file( @@ -154,7 +154,7 @@ async def test_phase1_recording_client_stub_methods_cover_error_paths() -> None: client = _RecordingClient() with pytest.raises(AssertionError, match="permission flow"): - await client.request_permission([], "session-1", cast(Any, object())) + await client.request_permission([], "session-1", cast("Any", object())) with pytest.raises(AssertionError, match="filesystem flow"): await client.write_text_file("content", "/tmp/demo", "session-1") with pytest.raises(AssertionError, match="filesystem flow"): @@ -176,7 +176,7 @@ async def test_phase1_recording_client_stub_methods_cover_error_paths() -> None: with pytest.raises(RequestError): await client.ext_method("demo.missing", {}) await client.ext_notification("demo.note", {"value": 1}) - assert client.on_connect(cast(Agent, object())) is None + assert client.on_connect(cast("Agent", object())) is None @dataclass(slots=True) @@ -235,11 +235,11 @@ async def prompt( @pytest.mark.asyncio async def test_phase1_round_trip_supports_initialize_prompt_and_session_update() -> None: agent = _EchoAgent() - server = await serve_remote_agent(cast(Agent, agent)) + server = await serve_remote_agent(cast("Agent", agent)) assert server.sockets is not None port = next(iter(server.sockets)).getsockname()[1] client = _RecordingClient() - remote = await connect_remote_agent(cast(Client, client), f"ws://127.0.0.1:{port}/acp/ws") + remote = await connect_remote_agent(cast("Client", client), f"ws://127.0.0.1:{port}/acp/ws") try: response = await remote.connection.initialize(protocol_version=1) assert response.protocol_version == 1 @@ -270,7 +270,7 @@ def test_phase1_helpers_cover_header_merge_and_transport_defaults() -> None: assert bearer_headers(" ") is None assert bearer_headers("token") == {"Authorization": "Bearer token"} assert _merge_headers(None, {"Authorization": "Bearer token"}) == { - "Authorization": "Bearer token" + "Authorization": "Bearer token", } assert _merge_headers({"X-Test": "1"}, {"Authorization": "Bearer token"}) == [ ("X-Test", "1"), @@ -294,7 +294,7 @@ def test_phase1_helpers_cover_header_merge_and_transport_defaults() -> None: async def test_phase1_stream_bridge_handles_partial_lines_and_binary_frame_failures() -> None: websocket = _FakeWebSocket() await websocket.incoming.put("from remote") - bridge = await open_websocket_stream_bridge(cast(Any, websocket)) + bridge = await open_websocket_stream_bridge(cast("Any", websocket)) bridge.writer.write(b"partial") await bridge.writer.drain() @@ -316,7 +316,7 @@ async def test_phase1_stream_bridge_handles_partial_lines_and_binary_frame_failu @pytest.mark.asyncio async def test_phase1_stream_bridge_supports_large_lines_with_configured_reader_limit() -> None: websocket = _FakeWebSocket() - bridge = await open_websocket_stream_bridge(cast(Any, websocket), reader_limit=1_048_576) + bridge = await open_websocket_stream_bridge(cast("Any", websocket), reader_limit=1_048_576) large_message = "x" * 70_000 try: await websocket.incoming.put(large_message) @@ -332,7 +332,7 @@ async def test_phase1_stream_bridge_supports_large_lines_with_configured_reader_ @pytest.mark.asyncio async def test_phase1_stream_bridge_handles_sender_failures_and_transport_edges() -> None: websocket = _FakeWebSocket(send_error=RuntimeError("send failed")) - bridge = await open_websocket_stream_bridge(cast(Any, websocket)) + bridge = await open_websocket_stream_bridge(cast("Any", websocket)) assert bridge.writer.transport.can_write_eof() is False assert bridge.writer.transport.get_extra_info("missing", "fallback") == "fallback" diff --git a/tests/acpremote/test_phase2.py b/tests/acpremote/test_phase2.py index d7c44f3..db70ce8 100644 --- a/tests/acpremote/test_phase2.py +++ b/tests/acpremote/test_phase2.py @@ -51,7 +51,7 @@ async def request_permission( async def session_update(self, session_id: str, update: Any, **kwargs: Any) -> None: self.updates.append( - SessionNotification(session_id=session_id, update=update, field_meta=kwargs or None) + SessionNotification(session_id=session_id, update=update, field_meta=kwargs or None), ) async def ext_method(self, method: str, params: dict[str, Any]) -> dict[str, Any]: @@ -70,7 +70,7 @@ async def test_phase2_recording_client_stub_methods() -> None: client = _RecordingClient() with pytest.raises(AssertionError, match="permission flow"): - await client.request_permission([], "session-1", cast(Any, object())) + await client.request_permission([], "session-1", cast("Any", object())) with pytest.raises(AssertionError, match="extension methods"): await client.ext_method("demo.echo", {"value": 1}) @@ -81,7 +81,7 @@ async def test_phase2_recording_client_stub_methods() -> None: source="phase2", ) assert client.updates[0].field_meta == {"source": "phase2"} - assert client.on_connect(cast(Agent, object())) is None + assert client.on_connect(cast("Agent", object())) is None @dataclass(slots=True) @@ -162,7 +162,7 @@ def test_phase2_server_path_and_metadata_helpers() -> None: bearer_token="secret", supported_agent_families=("pydantic-acp", "langchain-acp"), remote_cwd="/srv/app", - ) + ), ) assert metadata.auth_required is True assert metadata.supported_auth_modes == ("bearer",) @@ -176,7 +176,7 @@ def test_phase2_server_path_and_metadata_helpers() -> None: @pytest.mark.asyncio async def test_phase2_http_metadata_and_health_routes_are_served() -> None: server = await serve_acp( - cast(Agent, _EchoAgent()), + cast("Agent", _EchoAgent()), mount_path="/transport/", supported_agent_families=("generic-acp",), ) @@ -215,7 +215,7 @@ async def test_phase2_http_metadata_and_health_routes_are_served() -> None: @pytest.mark.asyncio async def test_phase2_websocket_path_and_bearer_auth_are_enforced() -> None: server = await serve_acp( - cast(Agent, _EchoAgent()), + cast("Agent", _EchoAgent()), mount_path="/secure", bearer_token="secret-token", supported_agent_families=("generic-acp",), @@ -238,7 +238,7 @@ async def test_phase2_websocket_path_and_bearer_auth_are_enforced() -> None: client = _RecordingClient() remote = await connect_remote_agent( - cast(Client, client), + cast("Client", client), f"ws://127.0.0.1:{port}/secure/ws", bearer_token="secret-token", ) @@ -265,7 +265,7 @@ async def test_phase2_websocket_path_and_bearer_auth_are_enforced() -> None: async def test_phase2_rejects_mixed_server_and_transport_options() -> None: with pytest.raises(ValueError, match="pass either options or server_options, not both"): await serve_remote_agent( - cast(Agent, _EchoAgent()), + cast("Agent", _EchoAgent()), options=ServerOptions().transport, server_options=ServerOptions(), ) diff --git a/tests/acpremote/test_phase3.py b/tests/acpremote/test_phase3.py index 71a1319..4b4806b 100644 --- a/tests/acpremote/test_phase3.py +++ b/tests/acpremote/test_phase3.py @@ -45,7 +45,7 @@ async def request_permission( async def session_update(self, session_id: str, update: Any, **kwargs: Any) -> None: self.updates.append( - SessionNotification(session_id=session_id, update=update, field_meta=kwargs or None) + SessionNotification(session_id=session_id, update=update, field_meta=kwargs or None), ) async def ext_method(self, method: str, params: dict[str, Any]) -> dict[str, Any]: @@ -64,7 +64,7 @@ async def test_phase3_recording_client_stub_methods() -> None: client = _RecordingClient() with pytest.raises(AssertionError, match="permission flow"): - await client.request_permission([], "session-1", cast(Any, object())) + await client.request_permission([], "session-1", cast("Any", object())) with pytest.raises(AssertionError, match="extension methods"): await client.ext_method("demo.echo", {"value": 1}) @@ -75,7 +75,7 @@ async def test_phase3_recording_client_stub_methods() -> None: source="phase3", ) assert client.updates[0].field_meta == {"source": "phase3"} - assert client.on_connect(cast(Agent, object())) is None + assert client.on_connect(cast("Agent", object())) is None @dataclass(slots=True) @@ -118,7 +118,7 @@ async def list_sessions( ) -> ListSessionsResponse: del cursor, cwd, kwargs return ListSessionsResponse( - sessions=[SessionInfo(cwd="/tmp", session_id="phase3-session", title="Remote session")] + sessions=[SessionInfo(cwd="/tmp", session_id="phase3-session", title="Remote session")], ) async def authenticate(self, method_id: str, **kwargs: Any) -> AuthenticateResponse | None: @@ -187,12 +187,12 @@ async def _handle(reader: asyncio.StreamReader, writer: asyncio.StreamWriter) -> @pytest.mark.asyncio async def test_phase3_connect_acp_returns_local_agent_proxy_with_remote_passthrough() -> None: target = _ProxyTargetAgent() - server = await serve_acp(cast(Agent, target), mount_path="/proxy", remote_cwd="/srv/remote") + server = await serve_acp(cast("Agent", target), mount_path="/proxy", remote_cwd="/srv/remote") assert server.sockets is not None port = next(iter(server.sockets)).getsockname()[1] - proxy = cast(RemoteProxyAgent, connect_acp(f"ws://127.0.0.1:{port}/proxy/ws")) + proxy = cast("RemoteProxyAgent", connect_acp(f"ws://127.0.0.1:{port}/proxy/ws")) client = _RecordingClient() - proxy.on_connect(cast(Client, client)) + proxy.on_connect(cast("Client", client)) try: initialized = await proxy.initialize(protocol_version=1) assert initialized.protocol_version == 1 @@ -273,14 +273,14 @@ async def _fake_connect_remote_agent( ) -> RemoteClientConnection: del url, options, headers, bearer_token calls.append(client) - return cast(RemoteClientConnection, _StubRemote()) + return cast("RemoteClientConnection", _StubRemote()) monkeypatch.setattr( "acpremote.proxy_agent.connect_remote_agent", _fake_connect_remote_agent, ) - client = cast(Client, _RecordingClient()) + client = cast("Client", _RecordingClient()) proxy.on_connect(client) first = await proxy.initialize(protocol_version=1) @@ -296,24 +296,24 @@ async def test_phase3_proxy_defaults_to_remote_host_ownership_but_can_opt_into_p None ): remote_target = _ProxyTargetAgent() - remote_server = await serve_acp(cast(Agent, remote_target), mount_path="/remote") + remote_server = await serve_acp(cast("Agent", remote_target), mount_path="/remote") assert remote_server.sockets is not None remote_port = next(iter(remote_server.sockets)).getsockname()[1] - remote_proxy = cast(RemoteProxyAgent, connect_acp(f"ws://127.0.0.1:{remote_port}/remote/ws")) - remote_proxy.on_connect(cast(Client, _RecordingClient())) + remote_proxy = cast("RemoteProxyAgent", connect_acp(f"ws://127.0.0.1:{remote_port}/remote/ws")) + remote_proxy.on_connect(cast("Client", _RecordingClient())) passthrough_target = _ProxyTargetAgent() - passthrough_server = await serve_acp(cast(Agent, passthrough_target), mount_path="/pass") + passthrough_server = await serve_acp(cast("Agent", passthrough_target), mount_path="/pass") assert passthrough_server.sockets is not None passthrough_port = next(iter(passthrough_server.sockets)).getsockname()[1] passthrough_proxy = cast( - RemoteProxyAgent, + "RemoteProxyAgent", connect_acp( f"ws://127.0.0.1:{passthrough_port}/pass/ws", options=TransportOptions(host_ownership="client_passthrough"), ), ) - passthrough_proxy.on_connect(cast(Client, _RecordingClient())) + passthrough_proxy.on_connect(cast("Client", _RecordingClient())) capabilities = ClientCapabilities( fs=FileSystemCapabilities(read_text_file=True, write_text_file=True), @@ -349,7 +349,7 @@ async def test_phase3_proxy_defaults_to_remote_host_ownership_but_can_opt_into_p @pytest.mark.asyncio async def test_phase3_proxy_supports_local_acp_stream_clients_transparently() -> None: target = _ProxyTargetAgent() - remote_server = await serve_acp(cast(Agent, target), mount_path="/proxy") + remote_server = await serve_acp(cast("Agent", target), mount_path="/proxy") assert remote_server.sockets is not None remote_port = next(iter(remote_server.sockets)).getsockname()[1] @@ -358,9 +358,9 @@ async def test_phase3_proxy_supports_local_acp_stream_clients_transparently() -> (client_reader, client_writer), (proxy_reader, proxy_writer) = await _open_stream_pair() proxy_task = asyncio.create_task( - run_agent(proxy, input_stream=proxy_writer, output_stream=proxy_reader) + run_agent(proxy, input_stream=proxy_writer, output_stream=proxy_reader), ) - local_connection = connect_to_agent(cast(Client, local_client), client_writer, client_reader) + local_connection = connect_to_agent(cast("Client", local_client), client_writer, client_reader) try: initialized = await local_connection.initialize(protocol_version=1) assert initialized.protocol_version == 1 @@ -379,7 +379,7 @@ async def test_phase3_proxy_supports_local_acp_stream_clients_transparently() -> proxy_writer.close() await client_writer.wait_closed() await proxy_writer.wait_closed() - await cast(RemoteProxyAgent, proxy).close() + await cast("RemoteProxyAgent", proxy).close() await proxy_task remote_server.close() await remote_server.wait_closed() @@ -393,7 +393,7 @@ async def test_phase3_proxy_supports_local_acp_stream_clients_transparently() -> @pytest.mark.asyncio async def test_phase3_proxy_can_emit_transport_latency_meta_and_projection() -> None: target = _ProxyTargetAgent() - remote_server = await serve_acp(cast(Agent, target), mount_path="/latency") + remote_server = await serve_acp(cast("Agent", target), mount_path="/latency") assert remote_server.sockets is not None remote_port = next(iter(remote_server.sockets)).getsockname()[1] @@ -405,7 +405,7 @@ async def test_phase3_proxy_can_emit_transport_latency_meta_and_projection() -> ), ) local_client = _RecordingClient() - proxy.on_connect(cast(Client, local_client)) + proxy.on_connect(cast("Client", local_client)) try: await proxy.initialize(protocol_version=1) session = await proxy.new_session(cwd="/tmp") @@ -415,7 +415,7 @@ async def test_phase3_proxy_can_emit_transport_latency_meta_and_projection() -> ) assert response.stop_reason == "end_turn" finally: - await cast(RemoteProxyAgent, proxy).close() + await cast("RemoteProxyAgent", proxy).close() remote_server.close() await remote_server.wait_closed() diff --git a/tests/codex_auth_helper/support.py b/tests/codex_auth_helper/support.py index 7f95583..60ef875 100644 --- a/tests/codex_auth_helper/support.py +++ b/tests/codex_auth_helper/support.py @@ -43,7 +43,7 @@ def write_auth_file( "exp": int(expires_at.timestamp()), "https://api.openai.com/auth": auth_claims, "sub": "user_123", - } + }, ), "account_id": account_id, "id_token": _jwt( @@ -52,7 +52,7 @@ def write_auth_file( "exp": int(expires_at.timestamp()), "https://api.openai.com/auth": auth_claims, "sub": "user_123", - } + }, ), "refresh_token": refresh_token, }, diff --git a/tests/codex_auth_helper/test_auth.py b/tests/codex_auth_helper/test_auth.py index f95e8e7..bfcef5c 100644 --- a/tests/codex_auth_helper/test_auth.py +++ b/tests/codex_auth_helper/test_auth.py @@ -37,7 +37,7 @@ def test_auth_state_helpers_cover_required_optional_and_mapping_paths() -> None: assert _optional_str({"token": "value"}, "token") == "value" assert _optional_str({"token": ""}, "token") is None assert _as_string_mapping(None) is None - assert _as_string_mapping(cast(Any, {"ok": 1, 2: "ignored"})) == {"ok": 1} + assert _as_string_mapping(cast("Any", {"ok": 1, 2: "ignored"})) == {"ok": 1} def test_auth_state_parses_timestamps_claims_and_account_fallbacks() -> None: @@ -52,13 +52,13 @@ def test_auth_state_parses_timestamps_claims_and_account_fallbacks() -> None: { "exp": int((now + timedelta(hours=1)).timestamp()), "organizations": [{"id": "org_123"}], - } + }, ) id_token = write_auth_file.__globals__["_jwt"]( { "exp": int((now + timedelta(hours=2)).timestamp()), "https://api.openai.com/auth": {"chatgpt_account_id": "acct_nested"}, - } + }, ) assert _parse_jwt_claims("not-a-jwt") is None @@ -115,7 +115,8 @@ def test_auth_state_helper_edge_paths_cover_missing_nested_claims() -> None: invalid_exp_token = write_auth_file.__globals__["_jwt"]({"exp": "not-an-int"}) fallback_exp_token = write_auth_file.__globals__["_jwt"]({"exp": 1}) assert _extract_expiry( - access_token=fallback_exp_token, id_token=invalid_exp_token + access_token=fallback_exp_token, + id_token=invalid_exp_token, ) == datetime.fromtimestamp( 1, tz=UTC, @@ -128,7 +129,7 @@ def test_auth_state_json_round_trip_and_invalid_payloads() -> None: { "exp": int((now + timedelta(hours=1)).timestamp()), "chatgpt_account_id": "acct_direct", - } + }, ) state = CodexAuthState.from_json_dict( { @@ -139,13 +140,13 @@ def test_auth_state_json_round_trip_and_invalid_payloads() -> None: "access_token": access_token, "refresh_token": "refresh-token", }, - } + }, ) assert state.account_id == "acct_direct" assert state.openai_api_key == "sk-demo" - payload = cast(dict[str, Any], state.to_json_dict()) - tokens = cast(dict[str, Any], payload["tokens"]) + payload = cast("dict[str, Any]", state.to_json_dict()) + tokens = cast("dict[str, Any]", payload["tokens"]) assert tokens["account_id"] == "acct_direct" with pytest.raises(ValueError, match="Expected `tokens`"): @@ -458,7 +459,7 @@ def post(self, url: str, *, content: str, headers: dict[str, str]) -> httpx.Resp "client_id=app_EMoamEEZ73f0CkXaXp7hrann&" "grant_type=refresh_token&refresh_token=refresh_before", {"Content-Type": "application/x-www-form-urlencoded"}, - ) + ), ] persisted_state = CodexAuthStore(auth_path).read_state() assert persisted_state.access_token == "sync_refreshed_access" diff --git a/tests/codex_auth_helper/test_factory.py b/tests/codex_auth_helper/test_factory.py index 286b07a..3ff0f53 100644 --- a/tests/codex_auth_helper/test_factory.py +++ b/tests/codex_auth_helper/test_factory.py @@ -85,13 +85,14 @@ def test_create_codex_responses_model_rejects_missing_instructions_runtime( create_codex_responses_model( "gpt-5", config=_config(auth_path), - instructions=cast(Any, None), + instructions=cast("Any", None), ) @pytest.mark.asyncio async def test_codex_responses_model_forces_streaming_on_request( - tmp_path: Path, monkeypatch: pytest.MonkeyPatch + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, ) -> None: auth_path = tmp_path / "auth.json" write_auth_file(auth_path, account_id="acct_demo") @@ -376,7 +377,7 @@ def test_create_codex_chat_openai_rejects_missing_instructions_runtime( create_codex_chat_openai( "gpt-5", config=_config(auth_path), - instructions=cast(Any, None), + instructions=cast("Any", None), ) diff --git a/tests/langchain/support.py b/tests/langchain/support.py index d3541da..2309bb5 100644 --- a/tests/langchain/support.py +++ b/tests/langchain/support.py @@ -85,7 +85,7 @@ def _stream( if self.stream_delimiter is None: content_chunks = [content] else: - content_chunks = cast(list[str], re.split(self.stream_delimiter, content)) + content_chunks = cast("list[str]", re.split(self.stream_delimiter, content)) content_chunks = [chunk for chunk in content_chunks if chunk] for index, token in enumerate(content_chunks): is_last = index == len(content_chunks) - 1 @@ -95,7 +95,7 @@ def _stream( id=message.id, tool_calls=tool_calls if is_last else [], chunk_position="last" if is_last else None, - ) + ), ) if run_manager is not None: run_manager.on_llm_new_token(token, chunk=chunk) @@ -109,7 +109,7 @@ def _stream( id=message.id, tool_calls=tool_calls, chunk_position="last", - ) + ), ) if run_manager is not None: run_manager.on_llm_new_token("", chunk=chunk) @@ -137,26 +137,26 @@ class RecordingACPClient: permission_responses: list[RequestPermissionResponse] = field(default_factory=list) write_response: WriteTextFileResponse | None = field(default_factory=WriteTextFileResponse) release_response: ReleaseTerminalResponse | None = field( - default_factory=ReleaseTerminalResponse + default_factory=ReleaseTerminalResponse, ) kill_response: KillTerminalResponse | None = field(default_factory=KillTerminalResponse) wait_response: WaitForTerminalExitResponse = field( - default_factory=lambda: WaitForTerminalExitResponse(exit_code=0) + default_factory=lambda: WaitForTerminalExitResponse(exit_code=0), ) terminal_output_response: TerminalOutputResponse = field( - default_factory=lambda: TerminalOutputResponse(output="terminal-output", truncated=False) + default_factory=lambda: TerminalOutputResponse(output="terminal-output", truncated=False), ) def queue_permission_selected(self, option_id: str) -> None: self.permission_responses.append( RequestPermissionResponse( - outcome=AllowedOutcome(outcome="selected", option_id=option_id) - ) + outcome=AllowedOutcome(outcome="selected", option_id=option_id), + ), ) def queue_permission_cancelled(self) -> None: self.permission_responses.append( - RequestPermissionResponse(outcome=DeniedOutcome(outcome="cancelled")) + RequestPermissionResponse(outcome=DeniedOutcome(outcome="cancelled")), ) async def request_permission( @@ -168,7 +168,7 @@ async def request_permission( ) -> RequestPermissionResponse: del kwargs self.permission_requests.append( - (session_id, [option.option_id for option in options], tool_call) + (session_id, [option.option_id for option in options], tool_call), ) if not self.permission_responses: raise AssertionError("unexpected permission request") diff --git a/tests/langchain/test_examples.py b/tests/langchain/test_examples.py index 19a7c2a..e51fd6b 100644 --- a/tests/langchain/test_examples.py +++ b/tests/langchain/test_examples.py @@ -457,7 +457,7 @@ def fake_create_deep_agent(**kwargs: Any) -> object: monkeypatch.setitem( sys.modules, "deepagents", - cast(Any, SimpleNamespace(create_deep_agent=fake_create_deep_agent)), + cast("Any", SimpleNamespace(create_deep_agent=fake_create_deep_agent)), ) session = AcpSessionContext( @@ -471,7 +471,7 @@ def fake_create_deep_agent(**kwargs: Any) -> object: assert graph is not None assert captured["interrupt_on"] == {"write_file": True} assert captured["name"] == "deepagents-ask-.deepagents-graph" - tool_names = {tool.__name__ for tool in cast(list[Any], captured["tools"])} + tool_names = {tool.__name__ for tool in cast("list[Any]", captured["tools"])} assert { "list_workspace_files", "read_file", @@ -499,7 +499,7 @@ def fake_create_deep_agent(**kwargs: Any) -> object: monkeypatch.setitem( sys.modules, "deepagents", - cast(Any, SimpleNamespace(create_deep_agent=fake_create_deep_agent)), + cast("Any", SimpleNamespace(create_deep_agent=fake_create_deep_agent)), ) session = AcpSessionContext( @@ -512,7 +512,7 @@ def fake_create_deep_agent(**kwargs: Any) -> object: ) assert deepagents_graph.graph_from_session(session) is fake_graph - tool_names = {tool.__name__ for tool in cast(list[Any], captured["tools"])} + tool_names = {tool.__name__ for tool in cast("list[Any]", captured["tools"])} assert { "list_workspace_files", "read_file", diff --git a/tests/langchain/test_low_level_helpers.py b/tests/langchain/test_low_level_helpers.py index 2745ed3..22df130 100644 --- a/tests/langchain/test_low_level_helpers.py +++ b/tests/langchain/test_low_level_helpers.py @@ -362,13 +362,13 @@ class _Phase5StateBridge(BufferedCapabilityBridge): default_factory=lambda: [ ModelInfo(model_id="bridge-model", name="Bridge Model"), ModelInfo(model_id="pro", name="Pro"), - ] + ], ) modes: list[SessionMode] = field( default_factory=lambda: [ SessionMode(id="ask", name="Ask"), SessionMode(id="plan", name="Plan"), - ] + ], ) def get_model_state(self, session: AcpSessionContext) -> ModelSelectionState: @@ -406,7 +406,7 @@ def get_config_options(self, session: AcpSessionContext) -> list[ConfigOption]: name="Bridge Flag", type="boolean", current_value=bool(session.config_values.get("bridge_flag", False)), - ) + ), ] def set_config_option( @@ -454,7 +454,7 @@ def _make_session(*, session_id: str = "session-1", cwd: Path | None = None) -> def _make_adapter(*, config: AdapterConfig | None = None) -> LangChainAcpAgent: return LangChainAcpAgent( - StaticGraphSource(graph=cast(Any, object())), + StaticGraphSource(graph=cast("Any", object())), config=config or AdapterConfig(), ) @@ -485,7 +485,7 @@ def test_native_approval_bridge_handles_success_cancel_and_invalid_paths() -> No session = _make_session() decision = asyncio.run( bridge.resolve_action_requests( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, action_requests=[ {"name": "read_file", "args": {"path": "notes.txt"}}, @@ -502,7 +502,7 @@ def test_native_approval_bridge_handles_success_cancel_and_invalid_paths() -> No }, ], classifier=classifier, - ) + ), ) assert decision == ApprovalDecision(decisions=[{"type": "approve"}, {"type": "reject"}]) @@ -515,24 +515,24 @@ def test_native_approval_bridge_handles_success_cancel_and_invalid_paths() -> No client.queue_permission_cancelled() cancelled = asyncio.run( bridge.resolve_action_requests( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, action_requests=[{"name": "execute_shell", "args": {"command": "pwd"}}], review_configs=[{"action_name": "execute_shell", "allowed_decisions": ["approve"]}], classifier=classifier, - ) + ), ) assert cancelled.cancelled is True with pytest.raises(RequestError): asyncio.run( bridge.resolve_action_requests( - client=cast(AcpClient, RecordingACPClient()), + client=cast("AcpClient", RecordingACPClient()), session=session, - action_requests=[cast(dict[str, Any], "bad")], + action_requests=[cast("dict[str, Any]", "bad")], review_configs=[], classifier=classifier, - ) + ), ) @@ -550,23 +550,23 @@ def test_native_approval_bridge_supports_persistent_choices_and_projection_build first_decision = asyncio.run( bridge.resolve_action_requests( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, action_requests=[{"name": "read_file", "args": {"path": "notes.txt"}}], review_configs=[{"action_name": "read_file", "allowed_decisions": ["approve"]}], classifier=classifier, projection_map=FileSystemProjectionMap(read_tool_names=frozenset({"read_file"})), - ) + ), ) second_decision = asyncio.run( bridge.resolve_action_requests( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, action_requests=[{"name": "read_file", "args": {"path": "notes.txt"}}], review_configs=[{"action_name": "read_file", "allowed_decisions": ["approve"]}], classifier=classifier, projection_map=FileSystemProjectionMap(read_tool_names=frozenset({"read_file"})), - ) + ), ) assert first_decision.decisions == [{"type": "approve"}] @@ -584,12 +584,12 @@ def test_native_approval_bridge_supports_persistent_choices_and_projection_build with pytest.raises(RequestError): asyncio.run( bridge.resolve_action_requests( - client=cast(AcpClient, RecordingACPClient()), + client=cast("AcpClient", RecordingACPClient()), session=session, action_requests=[{"name": "write_file", "args": {"path": "a.txt"}}], review_configs=[{"action_name": "write_file", "allowed_decisions": ["edit"]}], classifier=classifier, - ) + ), ) client = RecordingACPClient() @@ -598,34 +598,34 @@ def test_native_approval_bridge_supports_persistent_choices_and_projection_build with pytest.raises(RequestError): asyncio.run( unexpected_bridge.resolve_action_requests( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=_make_session(), action_requests=[{"name": "read_file", "args": {"path": "notes.txt"}}], review_configs=[], classifier=classifier, - ) + ), ) with pytest.raises(RequestError): asyncio.run( bridge.resolve_action_requests( - client=cast(AcpClient, RecordingACPClient()), + client=cast("AcpClient", RecordingACPClient()), session=session, action_requests=[{"name": "read_file", "args": "bad"}], review_configs=[], classifier=classifier, - ) + ), ) with pytest.raises(RequestError): asyncio.run( bridge.resolve_action_requests( - client=cast(AcpClient, RecordingACPClient()), + client=cast("AcpClient", RecordingACPClient()), session=session, action_requests=[{"name": 1, "args": {"path": "notes.txt"}}], review_configs=[], classifier=classifier, - ) + ), ) @@ -639,7 +639,7 @@ def test_approval_store_and_support_shims_cover_empty_and_reject_paths() -> None session.metadata[store.metadata_key] = {"bad": "maybe"} assert store.get_policy(session, "bad") is None - store.set_policy(session, "dangerous", cast(ApprovalPolicy, "reject")) + store.set_policy(session, "dangerous", cast("ApprovalPolicy", "reject")) assert store.export_state(session) == {"bad": "maybe", "dangerous": "reject"} bridge = NativeApprovalBridge(enable_persistent_choices=True) @@ -648,12 +648,12 @@ def test_approval_store_and_support_shims_cover_empty_and_reject_paths() -> None classifier = DefaultToolClassifier() decision = asyncio.run( bridge.resolve_action_requests( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=_make_session(session_id="reject-always"), action_requests=[{"id": "action-1", "name": "terminal", "args": {"command": "pwd"}}], review_configs=[], classifier=classifier, - ) + ), ) assert decision.decisions == [{"type": "reject"}] assert client.permission_requests[0][2].tool_call_id == "action-1" @@ -662,12 +662,12 @@ def test_approval_store_and_support_shims_cover_empty_and_reject_paths() -> None bridge.policy_store.set_policy(rejecting_session, "terminal", "reject") remembered = asyncio.run( bridge.resolve_action_requests( - client=cast(AcpClient, RecordingACPClient()), + client=cast("AcpClient", RecordingACPClient()), session=rejecting_session, action_requests=[{"name": "terminal", "args": {"command": "pwd"}}], review_configs=[], classifier=classifier, - ) + ), ) assert remembered.decisions == [{"type": "reject"}] @@ -680,7 +680,7 @@ def test_approval_store_and_support_shims_cover_empty_and_reject_paths() -> None assert supports_projection_aware_approval_bridge(None) is False assert supports_projection_aware_approval_bridge(NativeApprovalBridge()) is True - assert supports_projection_aware_approval_bridge(cast(Any, object())) is False + assert supports_projection_aware_approval_bridge(cast("Any", object())) is False def test_slash_command_helpers_cover_validation_and_rendering_edges() -> None: @@ -715,7 +715,8 @@ def test_slash_command_helpers_cover_validation_and_rendering_edges() -> None: with pytest.raises(ValueError, match="already be normalized"): validate_custom_commands( - [AvailableCommand(name=" Ping ", description="x")], mode_state=None + [AvailableCommand(name=" Ping ", description="x")], + mode_state=None, ) with pytest.raises(ValueError, match=r"\^\[a-z\]\[a-z0-9-\]\*\$"): validate_custom_commands([AvailableCommand(name="9ping", description="x")], mode_state=None) @@ -731,7 +732,8 @@ def test_slash_command_helpers_cover_validation_and_rendering_edges() -> None: validate_custom_commands([AvailableCommand(name="tools", description="x")], mode_state=None) with pytest.raises(ValueError, match="active mode ids"): validate_custom_commands( - [AvailableCommand(name="ask", description="x")], mode_state=mode_state + [AvailableCommand(name="ask", description="x")], + mode_state=mode_state, ) validate_custom_commands([AvailableCommand(name="ping", description="x")], mode_state=None) @@ -753,7 +755,7 @@ def test_slash_command_helpers_cover_validation_and_rendering_edges() -> None: assert render_mcp_server_listing([]) == "No MCP servers are currently attached." assert ( render_mcp_server_listing( - [McpServerInfo(name="repo", transport="http", target="https://repo", source="session")] + [McpServerInfo(name="repo", transport="http", target="https://repo", source="session")], ) == "MCP servers:\n- repo (http, session): https://repo" ) @@ -768,12 +770,12 @@ def test_slash_command_helpers_cover_graph_tool_and_mcp_server_edge_paths() -> N _tools_by_name={ "read": SimpleNamespace(description="Read file"), 1: object(), - } - ) + }, + ), ), "other": SimpleNamespace(data=object()), - } - ) + }, + ), ) assert list_graph_tools(graph) == [ToolInfo(name="read", description="Read file")] assert list_graph_tools(SimpleNamespace(get_graph=lambda: SimpleNamespace(nodes=None))) == [] @@ -794,8 +796,8 @@ def test_slash_command_helpers_cover_graph_tool_and_mcp_server_edge_paths() -> N {"name": "bridge", "transport": "sse", "description": "docs"}, {"name": "bad-bridge", "transport": 1}, "bad", - cast(Any, {1: "bad"}), - ] + cast("Any", {1: "bad"}), + ], } infos = extract_session_mcp_servers(session) assert [(info.name, info.transport, info.source) for info in infos] == [ @@ -816,8 +818,8 @@ def test_static_slash_command_provider_handles_match_and_miss() -> None: StaticSlashCommand( command=AvailableCommand(name="ping", description="Return pong."), handler=lambda request: SlashCommandResult(text=request.name), - ) - ] + ), + ], ) request = SlashCommandRequest( name="ping", @@ -852,7 +854,7 @@ def test_hook_projection_and_external_hook_bridge_cover_hidden_and_start_only_pa hidden_bridge.record_event(hidden_session, hidden_event) assert hidden_bridge.drain_updates(hidden_session) is None - projection_map = cast(Any, ExternalHookEventBridge()).projection_map + projection_map = cast("Any", ExternalHookEventBridge()).projection_map assert projection_map.build_start_update(tool_call_id="x", event=hidden_event) is None assert projection_map.build_progress_update(tool_call_id="x", event=hidden_event) is None @@ -871,11 +873,10 @@ def build_start_update(self, *, tool_call_id: str, event: HookEvent) -> ToolCall def build_progress_update(self, *, tool_call_id: str, event: HookEvent) -> None: del tool_call_id, event - return None bridge = ExternalHookEventBridge( emission_mode="start_only", - projection_map=cast(Any, _StartOnlyProjectionMap()), + projection_map=cast("Any", _StartOnlyProjectionMap()), ) session = _make_session(session_id="external-hooks") bridge.record_event( @@ -900,7 +901,7 @@ def build_progress_update(self, *, tool_call_id: str, event: HookEvent) -> None: assert len(no_status_updates) == 1 fallback_bridge = ExternalHookEventBridge( - projection_map=cast(Any, _StartOnlyProjectionMap()), + projection_map=cast("Any", _StartOnlyProjectionMap()), ) fallback_bridge.record_event( session, @@ -933,7 +934,9 @@ def __init__(self, result: SlashCommandResult | None) -> None: self.result = result def available_commands( - self, session: AcpSessionContext, graph: Any + self, + session: AcpSessionContext, + graph: Any, ) -> list[AvailableCommand]: del session, graph return [AvailableCommand(name="ping", description="pong")] @@ -943,17 +946,17 @@ def handle_command(self, request: SlashCommandRequest) -> SlashCommandResult | N return self.result adapter = LangChainAcpAgent( - cast(Any, _NullGraphSource()), + cast("Any", _NullGraphSource()), config=AdapterConfig(), ) client = _EmptyClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) session = _make_session() null_graph_source = _NullGraphSource() assert asyncio.run(null_graph_source.get_graph(session)) is null_graph_source.graph custom_provider = _CustomProvider(None) assert [command.name for command in custom_provider.available_commands(session, object())] == [ - "ping" + "ping", ] assert ( asyncio.run( @@ -962,7 +965,7 @@ def handle_command(self, request: SlashCommandRequest) -> SlashCommandResult | N graph=object(), prompt=[], acknowledged_message_id=None, - ) + ), ) is None ) @@ -971,9 +974,9 @@ def handle_command(self, request: SlashCommandRequest) -> SlashCommandResult | N adapter._maybe_handle_slash_prompt( session=session, graph=object(), - prompt=[cast(Any, object())], + prompt=[cast("Any", object())], acknowledged_message_id=None, - ) + ), ) is None ) @@ -984,16 +987,16 @@ def handle_command(self, request: SlashCommandRequest) -> SlashCommandResult | N graph=object(), prompt=[TextContentBlock(type="text", text="/unknown")], acknowledged_message_id=None, - ) + ), ) is None ) provider_adapter = LangChainAcpAgent( - cast(Any, _NullGraphSource()), - config=AdapterConfig(slash_command_provider=cast(Any, custom_provider)), + cast("Any", _NullGraphSource()), + config=AdapterConfig(slash_command_provider=cast("Any", custom_provider)), ) - provider_adapter.on_connect(cast(AcpClient, client)) + provider_adapter.on_connect(cast("AcpClient", client)) assert ( asyncio.run( provider_adapter._maybe_handle_slash_prompt( @@ -1001,20 +1004,21 @@ def handle_command(self, request: SlashCommandRequest) -> SlashCommandResult | N graph=object(), prompt=[TextContentBlock(type="text", text="/ping")], acknowledged_message_id="msg-1", - ) + ), ) is None ) handled_false_adapter = LangChainAcpAgent( - cast(Any, _NullGraphSource()), + cast("Any", _NullGraphSource()), config=AdapterConfig( slash_command_provider=cast( - Any, _CustomProvider(SlashCommandResult(handled=False, text="ignored")) - ) + "Any", + _CustomProvider(SlashCommandResult(handled=False, text="ignored")), + ), ), ) - handled_false_adapter.on_connect(cast(AcpClient, client)) + handled_false_adapter.on_connect(cast("AcpClient", client)) assert ( asyncio.run( handled_false_adapter._maybe_handle_slash_prompt( @@ -1022,7 +1026,7 @@ def handle_command(self, request: SlashCommandRequest) -> SlashCommandResult | N graph=object(), prompt=[TextContentBlock(type="text", text="/ping")], acknowledged_message_id="msg-2", - ) + ), ) is None ) @@ -1033,22 +1037,22 @@ def handle_command(self, request: SlashCommandRequest) -> SlashCommandResult | N AgentMessageChunk( session_update="agent_message_chunk", content=TextContentBlock(type="text", text="update-only"), - ) + ), ], refresh_session_surface=False, ) no_text_adapter = LangChainAcpAgent( - cast(Any, _NullGraphSource()), - config=AdapterConfig(slash_command_provider=cast(Any, _CustomProvider(no_text_result))), + cast("Any", _NullGraphSource()), + config=AdapterConfig(slash_command_provider=cast("Any", _CustomProvider(no_text_result))), ) - no_text_adapter.on_connect(cast(AcpClient, client)) + no_text_adapter.on_connect(cast("AcpClient", client)) response = asyncio.run( no_text_adapter._maybe_handle_slash_prompt( session=session, graph=object(), prompt=[TextContentBlock(type="text", text="/ping")], acknowledged_message_id="msg-3", - ) + ), ) assert response is not None assert response.stop_reason == "end_turn" @@ -1073,10 +1077,10 @@ def set_mode(self, session: AcpSessionContext, mode_id: str) -> ModeState | None assert unavailable_mode_state.current_mode_id is None mode_adapter = LangChainAcpAgent( - cast(Any, _NullGraphSource()), + cast("Any", _NullGraphSource()), config=AdapterConfig(capability_bridges=[_ModeBridge()]), ) - mode_adapter.on_connect(cast(AcpClient, client)) + mode_adapter.on_connect(cast("AcpClient", client)) assert ( asyncio.run( mode_adapter._handle_builtin_slash_command( @@ -1084,7 +1088,7 @@ def set_mode(self, session: AcpSessionContext, mode_id: str) -> ModeState | None graph=object(), command_name="review", argument=None, - ) + ), ) == "Mode is unavailable or invalid" ) @@ -1103,10 +1107,10 @@ def set_mode(self, session: AcpSessionContext, mode_id: str) -> ModeState | None assert none_mode_state.current_mode_id is None none_mode_adapter = LangChainAcpAgent( - cast(Any, _NullGraphSource()), + cast("Any", _NullGraphSource()), config=AdapterConfig(capability_bridges=[_NoneModeBridge()]), ) - none_mode_adapter.on_connect(cast(AcpClient, client)) + none_mode_adapter.on_connect(cast("AcpClient", client)) async def _return_none_mode( _session: AcpSessionContext, @@ -1118,7 +1122,7 @@ async def _return_none_mode( enable_config_option=False, ) - cast(Any, none_mode_adapter)._set_mode = _return_none_mode + cast("Any", none_mode_adapter)._set_mode = _return_none_mode assert ( asyncio.run( none_mode_adapter._handle_builtin_slash_command( @@ -1126,7 +1130,7 @@ async def _return_none_mode( graph=object(), command_name="review", argument=None, - ) + ), ) == "Mode is unavailable or invalid" ) @@ -1144,10 +1148,10 @@ def get_model_state(self, session: AcpSessionContext) -> ModelSelectionState: assert model_state.current_model_id is None model_adapter = LangChainAcpAgent( - cast(Any, _NullGraphSource()), + cast("Any", _NullGraphSource()), config=AdapterConfig(capability_bridges=[_ModelBridge()]), ) - model_adapter.on_connect(cast(AcpClient, client)) + model_adapter.on_connect(cast("AcpClient", client)) assert ( asyncio.run( model_adapter._handle_builtin_slash_command( @@ -1155,7 +1159,7 @@ def get_model_state(self, session: AcpSessionContext) -> ModelSelectionState: graph=object(), command_name="model", argument=None, - ) + ), ) == "Current model: unavailable" ) @@ -1166,7 +1170,7 @@ def get_model_state(self, session: AcpSessionContext) -> ModelSelectionState: graph=object(), command_name="model", argument="bad-model", - ) + ), ) == "Model is unavailable or invalid" ) @@ -1188,7 +1192,7 @@ def test_phase5_builtin_bridges_cover_direct_paths(tmp_path: Path) -> None: available_models=( ModelInfo(model_id="base", name="Base"), ModelInfo(model_id="pro", name="Pro"), - ) + ), ) assert model_bridge.get_model_state(session) is not None assert model_bridge.set_model(session, "missing") is None @@ -1199,7 +1203,7 @@ def test_phase5_builtin_bridges_cover_direct_paths(tmp_path: Path) -> None: available_modes=( SessionMode(id="ask", name="Ask"), SessionMode(id="plan", name="Plan"), - ) + ), ) assert mode_bridge.get_mode_state(session) is not None assert mode_bridge.set_mode(session, "missing") is None @@ -1213,8 +1217,8 @@ def test_phase5_builtin_bridges_cover_direct_paths(tmp_path: Path) -> None: name="Safe Tools", type="boolean", current_value=True, - ) - ] + ), + ], ) config_bridge = ConfigOptionsBridge(provider=config_provider) assert asyncio.run(_await_value(config_bridge.get_config_options(session))) is not None @@ -1229,7 +1233,7 @@ def test_phase5_builtin_bridges_cover_direct_paths(tmp_path: Path) -> None: assert deepagents_metadata["cwd"] == str(tmp_path) assert deepagents_metadata["plan_generation_type"] == "tools" assert deepagents_bridge.extract_plan_entries( - {"todos": [{"content": "Inspect repo", "status": "pending", "priority": "high"}]} + {"todos": [{"content": "Inspect repo", "status": "pending", "priority": "high"}]}, ) == [PlanEntry(content="Inspect repo", status="pending", priority="high")] assert deepagents_bridge.extract_plan_entries( { @@ -1237,8 +1241,8 @@ def test_phase5_builtin_bridges_cover_direct_paths(tmp_path: Path) -> None: "bad", {"content": 1}, {"content": "Bad status", "status": "???", "priority": "???"}, - ] - } + ], + }, ) == [PlanEntry(content="Bad status", status="pending", priority="medium")] @dataclass(slots=True, kw_only=True) @@ -1250,7 +1254,7 @@ def record(self, session: AcpSessionContext) -> None: AgentMessageChunk( session_update="agent_message_chunk", content=TextContentBlock(type="text", text="buffered"), - ) + ), ], ) self._record_completed_event(session, title="buffered-complete", kind="other") @@ -1285,8 +1289,8 @@ def test_phase5_graph_bridge_builder_and_manager_cover_custom_and_builtin_paths( name="Safe Tools", type="boolean", current_value=True, - ) - ] + ), + ], ) @dataclass(slots=True, kw_only=True) @@ -1318,15 +1322,15 @@ def get_interrupt_configuration(self, session: AcpSessionContext) -> dict[str, A capability_bridges=[ _ContributionBridge(), cast( - CapabilityBridge, + "CapabilityBridge", ToolSurfaceBridge( - tool_kinds={"shell_exec": cast(ToolKind, "execute")}, + tool_kinds={"shell_exec": cast("ToolKind", "execute")}, approval_policy_keys={"shell_exec": "shell-policy"}, ), ), ], config_options_provider=config_provider, - ) + ), ) manager = builder.build_manager() @@ -1339,9 +1343,9 @@ def get_interrupt_configuration(self, session: AcpSessionContext) -> dict[str, A assert asyncio.run(manager.set_config_option(session, "safe_tools", False)) is not None metadata_sections = manager.get_metadata_sections(session) assert metadata_sections["deepagents"] is not None - assert cast(dict[str, Any], metadata_sections["deepagents"])["cwd"] == str(tmp_path) + assert cast("dict[str, Any]", metadata_sections["deepagents"])["cwd"] == str(tmp_path) contributions = builder.build_graph_contributions(session) - deepagents_metadata = cast(dict[str, Any], contributions.metadata["deepagents"]) + deepagents_metadata = cast("dict[str, Any]", contributions.metadata["deepagents"]) assert deepagents_metadata["cwd"] == str(tmp_path) assert deepagents_metadata["plan_generation_type"] == "tools" assert contributions.middleware == ("middleware",) @@ -1365,21 +1369,21 @@ def graph_factory(session: AcpSessionContext) -> Any: (), "messages", (AIMessageChunk(content="Bridge graph ready."), {}), - ) - ] - ] + ), + ], + ], ) bridge = _Phase5StateBridge() adapter = cast( - LangChainAcpAgent, + "LangChainAcpAgent", create_acp_agent( graph_factory=graph_factory, config=AdapterConfig(capability_bridges=[bridge]), ), ) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) created = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) assert created.models is not None @@ -1390,20 +1394,20 @@ def graph_factory(session: AcpSessionContext) -> Any: assert [option.id for option in created.config_options] == ["bridge_flag"] session = adapter._require_session(created.session_id) - custom_metadata = cast(dict[str, Any], session.metadata["custom"]) - deepagents_metadata = cast(dict[str, Any], session.metadata["deepagents"]) + custom_metadata = cast("dict[str, Any]", session.metadata["custom"]) + deepagents_metadata = cast("dict[str, Any]", session.metadata["deepagents"]) assert custom_metadata["model"] == "bridge-model" assert deepagents_metadata["cwd"] == str(tmp_path) assert asyncio.run(adapter.set_session_model("pro", session_id=created.session_id)) is not None assert asyncio.run(adapter.set_session_mode("plan", session_id=created.session_id)) is not None config_response = asyncio.run( - adapter.set_config_option("bridge_flag", session_id=created.session_id, value=True) + adapter.set_config_option("bridge_flag", session_id=created.session_id, value=True), ) assert config_response is not None updated_session = adapter._require_session(created.session_id) - updated_custom_metadata = cast(dict[str, Any], updated_session.metadata["custom"]) + updated_custom_metadata = cast("dict[str, Any]", updated_session.metadata["custom"]) assert updated_custom_metadata["model"] == "pro" assert updated_custom_metadata["mode"] == "plan" metadata_sections = ( @@ -1411,8 +1415,8 @@ def graph_factory(session: AcpSessionContext) -> Any: .build_manager() .get_metadata_sections(updated_session) ) - assert cast(dict[str, Any], metadata_sections["custom"])["model"] == "pro" - assert cast(dict[str, Any], metadata_sections["deepagents"])["cwd"] == str(tmp_path) + assert cast("dict[str, Any]", metadata_sections["custom"])["model"] == "pro" + assert cast("dict[str, Any]", metadata_sections["deepagents"])["cwd"] == str(tmp_path) buffered_updates = [ update for _, update in client.updates @@ -1424,7 +1428,7 @@ def graph_factory(session: AcpSessionContext) -> Any: adapter.prompt( prompt=[TextContentBlock(type="text", text="hello")], session_id=created.session_id, - ) + ), ) assert prompt_response.stop_reason == "end_turn" assert captured_metadata[-1]["custom"]["model"] == "pro" @@ -1461,7 +1465,7 @@ async def get_mode_state(self, session: AcpSessionContext) -> ModeState: ) async_manager = GraphBridgeBuilder.from_config( - AdapterConfig(capability_bridges=[_AsyncStateBridge()]) + AdapterConfig(capability_bridges=[_AsyncStateBridge()]), ).build_manager() assert asyncio.run(async_manager.get_model_state(session)) is not None assert asyncio.run(async_manager.get_mode_state(session)) is not None @@ -1472,11 +1476,11 @@ class _NoneMetadataBridge(CapabilityBridge): metadata_key: str | None = "none" metadata_manager = GraphBridgeBuilder.from_config( - AdapterConfig(capability_bridges=[_NoneMetadataBridge(), _Phase5StateBridge()]) + AdapterConfig(capability_bridges=[_NoneMetadataBridge(), _Phase5StateBridge()]), ).build_manager() metadata_sections = metadata_manager.get_metadata_sections(session) assert "none" not in metadata_sections - assert cast(dict[str, Any], metadata_sections["custom"])["model"] == "async-model" + assert cast("dict[str, Any]", metadata_sections["custom"])["model"] == "async-model" @dataclass(slots=True, kw_only=True) class _NoCurrentSelectionBridge(CapabilityBridge): @@ -1499,7 +1503,7 @@ def get_mode_state(self, session: AcpSessionContext) -> ModeState: available_models=[ModelInfo(model_id="base", name="Base")], available_modes=[SessionMode(id="ask", name="Ask")], capability_bridges=[_NoCurrentSelectionBridge()], - ) + ), ) assert adapter._model_exists("base") is True assert adapter._model_exists("missing") is False @@ -1541,8 +1545,8 @@ def test_projection_helpers_cover_classification_composition_and_locations() -> write_tool_names=frozenset({"write_file"}), execute_tool_names=frozenset({"execute_shell"}), ), - ) - ) + ), + ), ], ) assert nested_classifier.classify("write_file") == "edit" @@ -1646,7 +1650,9 @@ def test_projection_helpers_cover_classification_composition_and_locations() -> hide_dot_directories=False, ) assert _render_path_tree( - ".hidden/file.py\n", root_label=".", hide_dot_directories=False + ".hidden/file.py\n", + root_label=".", + hide_dot_directories=False, ).startswith("Tree: .") assert _render_path_tree("/", root_label=".", hide_dot_directories=False).startswith("Tree: .") flat_search_progress = search_projection_with_default.project_progress( @@ -1757,15 +1763,15 @@ def test_projection_helpers_cover_classification_composition_and_locations() -> start_projection=ToolProjection( title="Tool A", locations=[ToolCallLocation(path="a.txt")], - ) + ), ), _StaticProjectionMap( start_projection=ToolProjection( - content=[cast(Any, merged_progress.content[0])], + content=[cast("Any", merged_progress.content[0])], status="completed", - ) + ), ), - ) + ), ).project_start("other_tool", raw_input={}) assert merged is not None assert merged.title == "Tool A" @@ -1774,7 +1780,7 @@ def test_projection_helpers_cover_classification_composition_and_locations() -> maps=( _StaticProjectionMap(progress_projection=ToolProjection(title="Progress A")), _StaticProjectionMap(progress_projection=ToolProjection(status="failed")), - ) + ), ).project_progress("tool", serialized_output="done") assert merged_progress_projection is not None assert merged_progress_projection.title == "Progress A" @@ -1786,7 +1792,7 @@ def test_projection_helpers_cover_classification_composition_and_locations() -> composite_map = compose_projection_maps((projection_map, projection_map)) assert isinstance(composite_map, CompositeProjectionMap) assert extract_tool_call_locations({"path": "draft.txt"}) == [ - ToolCallLocation(path="draft.txt") + ToolCallLocation(path="draft.txt"), ] assert extract_tool_call_locations({"nope": "value"}) == [] assert extract_tool_call_locations("bad") == [] @@ -2237,7 +2243,8 @@ def test_projection_maps_cover_negative_and_default_paths() -> None: assert copy_start.title == "Copy `a.txt` -> `b.txt`" assert file_projection_map.project_start("copy_file", raw_input={"source_path": "a"}) is None delete_start = file_projection_map.project_start( - "file_delete", raw_input={"file_path": "a.txt"} + "file_delete", + raw_input={"file_path": "a.txt"}, ) assert delete_start is not None assert delete_start.title == "Delete `a.txt`" @@ -2474,7 +2481,7 @@ def test_default_output_serializer_handles_supported_shapes() -> None: "model": _ModelPayload(name="demo", enabled=True), "dataclass": _DataclassPayload(name="demo", size=2), "tuple": (1, 2), - } + }, ) assert compatible == { "bytes": "hi", @@ -2508,8 +2515,8 @@ def test_structured_event_projection_map_normalizes_explicit_event_payloads() -> "content": "Projected text", "messageId": "m-1", }, - ] - } + ], + }, ) assert projected is not None @@ -2517,7 +2524,7 @@ def test_structured_event_projection_map_normalizes_explicit_event_payloads() -> assert isinstance(projected[1], ToolCallProgress) assert isinstance(projected[2], AgentMessageChunk) assert projected[1].content is not None - assert cast(Any, projected[1].content[0]).type == "content" + assert cast("Any", projected[1].content[0]).type == "content" assert projected[2].content.text == "Projected text" assert projection_map.project_event_payload({"events": ["bad"]}) is None @@ -2534,9 +2541,9 @@ def test_structured_event_projection_map_normalizes_explicit_event_payloads() -> "title": "echo hi", "kind": "execute", "status": "in_progress", - } - ] - } + }, + ], + }, ) assert double_projected is not None assert len(double_projected) == 2 @@ -2559,7 +2566,7 @@ def test_structured_event_projection_map_covers_direct_list_and_invalid_variants "content": "Inspect repo", "status": "pending", "priority": "high", - } + }, ], }, { @@ -2567,7 +2574,7 @@ def test_structured_event_projection_map_covers_direct_list_and_invalid_variants "content": "hello", "messageId": "u-1", }, - ] + ], ) assert direct_list is not None @@ -2591,8 +2598,8 @@ def test_structured_event_projection_map_covers_direct_list_and_invalid_variants "type": "agent_message_chunk", "content": {"type": "text", "text": 1}, }, - ] - } + ], + }, ) is None ) @@ -2617,7 +2624,7 @@ def test_prompt_conversion_covers_audio_blob_and_defensive_embedded_resource_pat mime_type="text/markdown", size=42, ), - ] + ], ) assert audio_content[0] == { "type": "audio", @@ -2629,9 +2636,9 @@ def test_prompt_conversion_covers_audio_blob_and_defensive_embedded_resource_pat unknown_resource = _embedded_resource_content( cast( - EmbeddedResourceContentBlock, + "EmbeddedResourceContentBlock", SimpleNamespace(resource=SimpleNamespace(uri="file:///opaque")), - ) + ), ) assert unknown_resource == [{"type": "text", "text": "Embedded resource: file:///opaque"}] @@ -2645,7 +2652,7 @@ def test_prompt_conversion_covers_audio_blob_and_defensive_embedded_resource_pat type="resource", resource=BlobResourceContents(uri="file:///blob.bin", blob="AA=="), ), - ] + ], ) assert "MIME:" not in no_mime_content[0]["text"] assert "MIME:" not in no_mime_content[1]["text"] @@ -2689,7 +2696,7 @@ def project_event_payload( ( StructuredEventProjectionMap(), _NullEventMap(), - ) + ), ) assert composite is not None assert ( @@ -2752,10 +2759,12 @@ def test_stored_session_update_round_trips_all_supported_update_kinds() -> None: ] for update in updates: - stored = StoredSessionUpdate.from_update(cast(Any, update)) + stored = StoredSessionUpdate.from_update(cast("Any", update)) restored = stored.to_update() assert restored.model_dump( - mode="json", by_alias=True, exclude_none=True + mode="json", + by_alias=True, + exclude_none=True, ) == update.model_dump( mode="json", by_alias=True, @@ -2763,7 +2772,7 @@ def test_stored_session_update_round_trips_all_supported_update_kinds() -> None: ) with pytest.raises(TypeError): - StoredSessionUpdate.from_update(cast(Any, TextContentBlock(type="text", text="bad"))) + StoredSessionUpdate.from_update(cast("Any", TextContentBlock(type="text", text="bad"))) now = utc_now() assert now.tzinfo is not None @@ -2777,7 +2786,7 @@ def test_stored_session_update_round_trips_all_supported_update_kinds() -> None: with pytest.raises(TypeError): _coerce_json_value(object()) invalid_update = StoredSessionUpdate(kind="plan", payload={}) - cast(Any, invalid_update).kind = "bad-kind" + cast("Any", invalid_update).kind = "bad-kind" with pytest.raises(AssertionError): invalid_update.to_update() @@ -2793,7 +2802,7 @@ def test_memory_and_file_session_stores_cover_lifecycle(tmp_path: Path) -> None: "content": "Inspect repo", "status": "pending", "priority": "high", - } + }, ] session.transcript.append( StoredSessionUpdate.from_update( @@ -2801,8 +2810,8 @@ def test_memory_and_file_session_stores_cover_lifecycle(tmp_path: Path) -> None: session_update="user_message_chunk", content=TextContentBlock(type="text", text="hello"), message_id="u1", - ) - ) + ), + ), ) store.save(session) @@ -2856,7 +2865,9 @@ def test_memory_and_file_session_stores_cover_lifecycle(tmp_path: Path) -> None: session.updated_at = utc_now() file_store.save(session) session_copy = file_store.fork( - session.session_id, new_session_id="fork-file", cwd=tmp_path / "fork" + session.session_id, + new_session_id="fork-file", + cwd=tmp_path / "fork", ) assert session_copy is not None assert session_copy.cwd == tmp_path / "fork" @@ -2917,10 +2928,10 @@ def test_native_plan_runtime_and_tools_cover_phase4_paths(tmp_path: Path) -> Non native_plan_additional_instructions="Stay concise.", native_plan_persistence_provider=persistence_provider, plan_mode_id="plan", - ) + ), ) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) created = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) assert created.config_options is not None assert [option.id for option in created.config_options] == [ @@ -2948,10 +2959,10 @@ def test_native_plan_runtime_and_tools_cover_phase4_paths(tmp_path: Path) -> Non content="Inspect repo", status="pending", priority="high", - ) + ), ], "# Native plan", - ) + ), ) == "Recorded 1 plan entries." ) @@ -2969,10 +2980,10 @@ def test_native_plan_runtime_and_tools_cover_phase4_paths(tmp_path: Path) -> Non "content": "Inspect repo", "status": "completed", "priority": "high", - } + }, ] plan_updates = [ - cast(AgentPlanUpdate, update) + cast("AgentPlanUpdate", update) for _, update in client.updates if isinstance(update, AgentPlanUpdate) ] @@ -2989,7 +3000,7 @@ def test_native_plan_runtime_structured_mode_and_unbound_tools() -> None: default_mode_id="plan", default_plan_generation_type="structured", plan_mode_id="plan", - ) + ), ) session = _make_session() session.session_mode_id = "plan" @@ -3015,9 +3026,9 @@ def test_task_plan_validation_and_payload_parsing() -> None: "content": "Inspect repo", "status": "pending", "priority": "high", - } + }, ], - } + }, ) assert parsed.plan_entries[0].content == "Inspect repo" @@ -3047,8 +3058,8 @@ def test_phase4_native_plan_runtime_negative_and_formatting_paths( default_plan_generation_type="structured", native_plan_additional_instructions=" ", plan_mode_id="plan", - plan_provider=cast(Any, object()), - ) + plan_provider=cast("Any", object()), + ), ) markdown_runtime = _NativePlanRuntime(markdown_only_adapter) markdown_session = _make_session(cwd=tmp_path) @@ -3068,7 +3079,7 @@ def test_phase4_native_plan_runtime_negative_and_formatting_paths( default_plan_generation_type="structured", native_plan_additional_instructions="Keep milestones coarse.", plan_mode_id="plan", - ) + ), ) markdown_guidance_runtime = _NativePlanRuntime(markdown_guidance_adapter) markdown_guidance_session = _make_session(cwd=tmp_path) @@ -3084,7 +3095,7 @@ def test_phase4_native_plan_runtime_negative_and_formatting_paths( default_mode_id="plan", default_plan_generation_type="tools", plan_mode_id="plan", - ) + ), ) entries_runtime = _NativePlanRuntime(entries_adapter) entries_session = _make_session(cwd=tmp_path) @@ -3094,7 +3105,7 @@ def test_phase4_native_plan_runtime_negative_and_formatting_paths( "content": "Inspect repo", "status": "pending", "priority": "medium", - } + }, ] updated = asyncio.run( entries_runtime.update_native_plan_entry( @@ -3102,7 +3113,7 @@ def test_phase4_native_plan_runtime_negative_and_formatting_paths( index=1, content="Inspect repository", priority="low", - ) + ), ) assert updated.content == "Inspect repository" assert updated.priority == "low" @@ -3112,11 +3123,11 @@ def test_phase4_native_plan_runtime_negative_and_formatting_paths( entries_runtime_adapter_session = _make_session(cwd=tmp_path, session_id="persist-current") entries_runtime_adapter_session.session_mode_id = "plan" entries_runtime_adapter_session.plan_entries = [ - {"content": "Persist me", "status": "pending", "priority": "high"} + {"content": "Persist me", "status": "pending", "priority": "high"}, ] asyncio.run(entries_runtime.persist_current_native_plan_state(entries_runtime_adapter_session)) assert entries_runtime_adapter_session.plan_entries == [ - {"content": "Persist me", "status": "pending", "priority": "high"} + {"content": "Persist me", "status": "pending", "priority": "high"}, ] @@ -3127,32 +3138,31 @@ def test_phase4_adapter_helper_branches_cover_native_plan_edges(tmp_path: Path) default_mode_id="plan", default_plan_generation_type="tools", plan_mode_id="plan", - ) + ), ) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) session = _make_session(cwd=tmp_path) session.session_mode_id = "plan" asyncio.run( adapter._emit_plan_update( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, entries=[PlanEntry(content="Inspect repo", status="pending", priority="high")], - ) + ), ) assert session.plan_entries == [ { "content": "Inspect repo", "status": "pending", "priority": "high", - } + }, ] class _NoneConfigProvider: async def get_config_options(self, session: AcpSessionContext) -> None: del session - return None async def set_config_option( self, @@ -3161,10 +3171,9 @@ async def set_config_option( value: str | bool, ) -> None: del session, config_id, value - return None options_adapter = _make_adapter( - config=AdapterConfig(config_options_provider=_NoneConfigProvider()) + config=AdapterConfig(config_options_provider=_NoneConfigProvider()), ) assert asyncio.run(options_adapter._config_options(_make_session())) == [] assert ( @@ -3193,7 +3202,7 @@ async def set_mode(self, session: AcpSessionContext, mode_id: str) -> ModeState: config=AdapterConfig( models_provider=_NullModelsProvider(), modes_provider=_NullModesProvider(), - ) + ), ) provider_session = _make_session(cwd=tmp_path) assert ( @@ -3216,7 +3225,7 @@ class _StructuredPlanModel(BaseModel): ) assert adapter._task_plan_from_value(structured_plan) == structured_plan model_backed = adapter._task_plan_from_value( - {"structured_response": _StructuredPlanModel(**structured_plan.model_dump(mode="python"))} + {"structured_response": _StructuredPlanModel(**structured_plan.model_dump(mode="python"))}, ) assert model_backed == structured_plan assert adapter._task_plan_from_value({"structured_response": {"bad": "payload"}}) is None @@ -3225,7 +3234,7 @@ class _StructuredPlanModel(BaseModel): def test_runtime_server_and_root_surface_helpers( monkeypatch: pytest.MonkeyPatch, ) -> None: - graph = cast(Any, object()) + graph = cast("Any", object()) source = StaticGraphSource(graph=graph) assert _resolve_graph_source(graph=graph, graph_factory=None, graph_source=None) is not None assert _resolve_graph_source(graph=None, graph_factory=None, graph_source=source) is source @@ -3245,13 +3254,13 @@ async def factory(session: AcpSessionContext) -> Any: model_state=ModelSelectionState( available_models=[ModelInfo(model_id="base", name="Base")], current_model_id="base", - ) + ), ) modes_provider = _AsyncModesProvider( mode_state=ModeState( modes=[SessionMode(id="ask", name="Ask")], current_mode_id="ask", - ) + ), ) config_provider = _ConfigProvider( options=[ @@ -3260,8 +3269,8 @@ async def factory(session: AcpSessionContext) -> Any: name="Safety", type="boolean", current_value=True, - ) - ] + ), + ], ) config = AdapterConfig( config_options_provider=config_provider, @@ -3310,7 +3319,7 @@ def test_langchain_adapter_lifecycle_replay_and_helper_paths(tmp_path: Path) -> ) adapter = _make_adapter(config=config) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) initialize = asyncio.run(adapter.initialize(protocol_version=1)) assert initialize.agent_info is not None @@ -3330,23 +3339,23 @@ def test_langchain_adapter_lifecycle_replay_and_helper_paths(tmp_path: Path) -> asyncio.run( adapter._emit_update( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=adapter._require_session(session_id), update=AgentMessageChunk( session_update="agent_message_chunk", content=TextContentBlock(type="text", text="replay me"), message_id="m1", ), - ) + ), ) replay_count = len(client.updates) transcript_count = len(adapter._require_session(session_id).transcript) asyncio.run( adapter._emit_update( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=adapter._require_session(session_id), update=SimpleNamespace(session_update="ignored"), - ) + ), ) assert len(adapter._require_session(session_id).transcript) == transcript_count @@ -3360,7 +3369,7 @@ def test_langchain_adapter_lifecycle_replay_and_helper_paths(tmp_path: Path) -> cwd=str(tmp_path / "loaded"), session_id=session_id, mcp_servers=[mcp_servers[0]], - ) + ), ) assert load_response is not None assert len(client.updates) > replay_count @@ -3371,7 +3380,7 @@ def test_langchain_adapter_lifecycle_replay_and_helper_paths(tmp_path: Path) -> list_response = asyncio.run(adapter.list_sessions(cwd=str(tmp_path / "loaded"))) assert [item.session_id for item in list_response.sessions] == [session_id] assert [item.session_id for item in asyncio.run(adapter.list_sessions()).sessions] == [ - session_id + session_id, ] assert asyncio.run(adapter.set_session_model("gpt-5", session_id=session_id)) is not None @@ -3386,7 +3395,7 @@ def test_langchain_adapter_lifecycle_replay_and_helper_paths(tmp_path: Path) -> cwd=str(tmp_path / "resumed"), session_id=session_id, mcp_servers=[mcp_servers[1]], - ) + ), ) assert resume_response.models is not None resumed_session = adapter._require_session(session_id) @@ -3398,7 +3407,7 @@ def test_langchain_adapter_lifecycle_replay_and_helper_paths(tmp_path: Path) -> cwd=str(tmp_path / "forked"), session_id=session_id, mcp_servers=[mcp_servers[2]], - ) + ), ) forked_session = adapter._require_session(fork_response.session_id) assert forked_session.cwd == tmp_path / "forked" @@ -3441,7 +3450,7 @@ def test_langchain_session_lifecycle_preserves_mcp_servers_when_omitted(tmp_path cwd=str(tmp_path), session_id=created.session_id, mcp_servers=None, - ) + ), ) resumed = adapter._require_session(created.session_id) assert resumed.mcp_servers[0]["name"] == "stdio" @@ -3451,7 +3460,7 @@ def test_langchain_session_lifecycle_preserves_mcp_servers_when_omitted(tmp_path cwd=str(tmp_path), session_id=created.session_id, mcp_servers=None, - ) + ), ) assert adapter._require_session(forked.session_id).mcp_servers[0]["name"] == "stdio" @@ -3459,44 +3468,46 @@ def test_langchain_session_lifecycle_preserves_mcp_servers_when_omitted(tmp_path def test_langchain_adapter_prompt_and_interrupt_helpers(tmp_path: Path) -> None: adapter = _make_adapter() client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) session = _make_session(cwd=tmp_path) asyncio.run( adapter._emit_user_prompt( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, prompt=[TextContentBlock(type="text", text="Summarize the repo")], message_id="u1", - ) + ), ) assert session.title == "Summarize the repo" titled_session = _make_session(cwd=tmp_path, session_id="session-2") titled_session.title = "Existing title" asyncio.run( adapter._emit_user_prompt( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=titled_session, prompt=[TextContentBlock(type="text", text=" ")], message_id="u2", - ) + ), ) assert titled_session.title == "Existing title" untitled_session = _make_session(cwd=tmp_path, session_id="session-3") asyncio.run( adapter._emit_user_prompt( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=untitled_session, prompt=[ResourceContentBlock(type="resource_link", name="doc", uri="file:///doc")], message_id="u3", - ) + ), ) assert untitled_session.title is None generic_block = EmbeddedResourceContentBlock( type="resource", resource=BlobResourceContents( - uri="file:///blob", mime_type="application/octet-stream", blob="AA==" + uri="file:///blob", + mime_type="application/octet-stream", + blob="AA==", ), ) content = prompt_to_langchain_content( @@ -3527,7 +3538,7 @@ def test_langchain_adapter_prompt_and_interrupt_helpers(tmp_path: Path) -> None: ), ), generic_block, - ] + ], ) assert content[0] == {"type": "text", "text": "hello"} assert content[1]["type"] == "image_url" @@ -3541,7 +3552,7 @@ def test_langchain_adapter_prompt_and_interrupt_helpers(tmp_path: Path) -> None: assert ( "user-message" in prompt_to_langchain_content( - cast(list[Any], [_UnknownPromptBlock(payload="user-message")]) + cast("list[Any]", [_UnknownPromptBlock(payload="user-message")]), )[0]["text"] ) assert message_text(["a", {"type": "text", "text": "b"}]) == "ab" @@ -3578,25 +3589,25 @@ def test_langchain_adapter_prompt_and_interrupt_helpers(tmp_path: Path) -> None: "name": "read_file", "args": '{"path":"notes.txt"}', "index": 0, - } + }, ], ) asyncio.run( adapter._process_tool_call_chunks( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, message_chunk=tool_chunk, active_tool_calls=active_tool_calls, tool_call_accumulator=tool_call_accumulator, - ) + ), ) assert "call-1" in active_tool_calls asyncio.run( adapter._process_tool_call_chunks( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, message_chunk=cast( - AIMessageChunk, + "AIMessageChunk", SimpleNamespace( tool_call_chunks=[ "bad", @@ -3607,34 +3618,34 @@ def test_langchain_adapter_prompt_and_interrupt_helpers(tmp_path: Path) -> None: "index": 0, }, {"name": "late_name", "args": '{"path":"other.txt"}'}, - ] + ], ), ), active_tool_calls=active_tool_calls, tool_call_accumulator=tool_call_accumulator, - ) + ), ) asyncio.run( adapter._process_tool_call_chunks( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, message_chunk=cast( - AIMessageChunk, + "AIMessageChunk", SimpleNamespace( tool_call_chunks=[ {"id": "call-2", "name": object(), "args": 1, "index": 1}, - ] + ], ), ), active_tool_calls=active_tool_calls, tool_call_accumulator=tool_call_accumulator, - ) + ), ) assert "call-2" not in active_tool_calls asyncio.run( adapter._handle_tool_message( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, message_chunk=ToolMessage( content="done", @@ -3642,53 +3653,53 @@ def test_langchain_adapter_prompt_and_interrupt_helpers(tmp_path: Path) -> None: status="success", ), active_tool_calls=active_tool_calls, - ) + ), ) assert "call-1" not in active_tool_calls asyncio.run( adapter._handle_tool_message( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, - message_chunk=cast(Any, SimpleNamespace(content="ignored", tool_call_id=None)), + message_chunk=cast("Any", SimpleNamespace(content="ignored", tool_call_id=None)), active_tool_calls=active_tool_calls, - ) + ), ) asyncio.run( adapter._process_message_chunk( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, message_chunk="agent text", active_tool_calls={}, tool_call_accumulator={}, - ) + ), ) asyncio.run( adapter._process_message_chunk( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, message_chunk="", active_tool_calls={}, tool_call_accumulator={}, - ) + ), ) asyncio.run( adapter._process_message_chunk( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, message_chunk=AIMessageChunk(content=[{"type": "text", "text": "chunk text"}]), active_tool_calls={}, tool_call_accumulator={}, - ) + ), ) asyncio.run( adapter._process_message_chunk( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, message_chunk=SimpleNamespace(content=[{"type": "other"}]), active_tool_calls={}, tool_call_accumulator={}, - ) + ), ) @dataclass @@ -3697,24 +3708,24 @@ class _ContentWrapper: asyncio.run( adapter._process_message_chunk( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, message_chunk=_ContentWrapper(content=[{"type": "text", "text": "wrapped"}]), active_tool_calls={}, tool_call_accumulator={}, - ) + ), ) assert any(isinstance(update, AgentMessageChunk) for _, update in client.updates) projection_adapter = _make_adapter( - config=AdapterConfig(event_projection_maps=[StructuredEventProjectionMap()]) + config=AdapterConfig(event_projection_maps=[StructuredEventProjectionMap()]), ) projection_client = RecordingACPClient() - projection_adapter.on_connect(cast(AcpClient, projection_client)) + projection_adapter.on_connect(cast("AcpClient", projection_client)) projection_session = _make_session(cwd=tmp_path, session_id="projection") asyncio.run( projection_adapter._emit_projected_events( - client=cast(AcpClient, projection_client), + client=cast("AcpClient", projection_client), session=projection_session, payload={ "node": { @@ -3725,12 +3736,12 @@ class _ContentWrapper: "title": "nested", "kind": "other", "status": "in_progress", - } - ] + }, + ], }, "noop": {"ignored": True}, }, - ) + ), ) nested_updates = [ update for _, update in projection_client.updates if isinstance(update, ToolCallStart) @@ -3740,85 +3751,87 @@ class _ContentWrapper: assert ( asyncio.run( adapter._handle_update_payload( - client=cast(AcpClient, client), session=session, payload="bad" - ) + client=cast("AcpClient", client), + session=session, + payload="bad", + ), ) is None ) with pytest.raises(RequestError): asyncio.run( adapter._handle_update_payload( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, payload={"__interrupt__": "bad"}, - ) + ), ) with pytest.raises(RequestError): asyncio.run( adapter._resolve_interrupts( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, interrupts=[{"bad": "shape"}], - ) + ), ) no_approval_adapter = _make_adapter(config=AdapterConfig(approval_bridge=None)) - no_approval_adapter.on_connect(cast(AcpClient, client)) + no_approval_adapter.on_connect(cast("AcpClient", client)) with pytest.raises(RequestError): asyncio.run( no_approval_adapter._resolve_interrupts( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, interrupts=[{"action_requests": [], "review_configs": []}], - ) + ), ) with pytest.raises(RequestError): asyncio.run( adapter._resolve_interrupts( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, interrupts=[object()], - ) + ), ) cancelling_client = RecordingACPClient() cancelling_client.queue_permission_cancelled() approval_adapter = _make_adapter() - approval_adapter.on_connect(cast(AcpClient, cancelling_client)) + approval_adapter.on_connect(cast("AcpClient", cancelling_client)) with pytest.raises(RequestError): asyncio.run( approval_adapter._resolve_interrupts( - client=cast(AcpClient, cancelling_client), + client=cast("AcpClient", cancelling_client), session=session, interrupts=[ { "action_requests": [{"name": "read_file", "args": {"path": "notes.txt"}}], "review_configs": [{"action_name": "read_file"}], - } + }, ], - ) + ), ) assert ( asyncio.run( adapter._handle_update_payload( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, payload={"node": {"todos": "bad"}}, - ) + ), ) is None ) asyncio.run( adapter._emit_plan_update( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, entries=[ PlanEntry(content="Inspect repo", status="completed", priority="high"), PlanEntry(content="Bad status", status="pending", priority="medium"), ], - ) + ), ) assert session.plan_entries == [ {"content": "Inspect repo", "status": "completed", "priority": "high"}, @@ -3826,10 +3839,10 @@ class _ContentWrapper: ] asyncio.run( adapter._emit_agent_text( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, text="", - ) + ), ) assert adapter._derive_title([TextContentBlock(type="text", text=" hello ")]) == "hello" assert ( @@ -3837,20 +3850,20 @@ class _ContentWrapper: [ TextContentBlock(type="text", text=" "), TextContentBlock(type="text", text="next title"), - ] + ], ) == "next title" ) assert ( adapter._derive_title( - [ResourceContentBlock(type="resource_link", name="doc", uri="file:///doc")] + [ResourceContentBlock(type="resource_link", name="doc", uri="file:///doc")], ) is None ) assert adapter._serialize_mcp_servers(None) == [] replay_disabled_adapter = _make_adapter(config=AdapterConfig(replay_history_on_load=False)) - replay_disabled_adapter.on_connect(cast(AcpClient, client)) + replay_disabled_adapter.on_connect(cast("AcpClient", client)) replay_session = _make_session(cwd=tmp_path, session_id="replay-disabled") replay_session.transcript.append( StoredSessionUpdate.from_update( @@ -3858,8 +3871,8 @@ class _ContentWrapper: session_update="agent_message_chunk", content=TextContentBlock(type="text", text="ignore replay"), message_id="m-disabled", - ) - ) + ), + ), ) replay_count = len(client.updates) asyncio.run(replay_disabled_adapter._replay_transcript(replay_session)) @@ -3871,7 +3884,7 @@ class _ContentWrapper: default_model_id="explicit-model", available_modes=[SessionMode(id="ask", name="Ask")], default_mode_id="explicit-mode", - ) + ), ) assert explicit_default_adapter._default_model_id() == "explicit-model" assert explicit_default_adapter._default_mode_id() == "explicit-mode" @@ -3882,7 +3895,7 @@ class _ContentWrapper: try: no_current_session = _make_session(cwd=tmp_path, session_id="no-current") resolved_model_state = asyncio.run( - explicit_default_adapter._model_state(no_current_session) + explicit_default_adapter._model_state(no_current_session), ) resolved_mode_state = asyncio.run(explicit_default_adapter._mode_state(no_current_session)) assert resolved_model_state is not None @@ -3902,7 +3915,7 @@ def test_streamed_tool_start_waits_for_complete_json_arguments(tmp_path: Path) - adapter = _make_adapter( config=AdapterConfig( projection_maps=[CommunityFileManagementProjectionMap()], - ) + ), ) client = RecordingACPClient() session = _make_session(cwd=tmp_path) @@ -3911,10 +3924,10 @@ def test_streamed_tool_start_waits_for_complete_json_arguments(tmp_path: Path) - asyncio.run( adapter._process_tool_call_chunks( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, message_chunk=cast( - AIMessageChunk, + "AIMessageChunk", SimpleNamespace( tool_call_chunks=[ { @@ -3922,13 +3935,13 @@ def test_streamed_tool_start_waits_for_complete_json_arguments(tmp_path: Path) - "name": "read_file", "args": '{"file_path":', "index": 0, - } - ] + }, + ], ), ), active_tool_calls=active_tool_calls, tool_call_accumulator=tool_call_accumulator, - ) + ), ) assert active_tool_calls == {} @@ -3936,10 +3949,10 @@ def test_streamed_tool_start_waits_for_complete_json_arguments(tmp_path: Path) - asyncio.run( adapter._process_tool_call_chunks( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, message_chunk=cast( - AIMessageChunk, + "AIMessageChunk", SimpleNamespace( tool_call_chunks=[ { @@ -3947,13 +3960,13 @@ def test_streamed_tool_start_waits_for_complete_json_arguments(tmp_path: Path) - "name": None, "args": '"proof.txt"}', "index": 0, - } - ] + }, + ], ), ), active_tool_calls=active_tool_calls, tool_call_accumulator=tool_call_accumulator, - ) + ), ) assert active_tool_calls["call-streamed"]["raw_input"] == {"file_path": "proof.txt"} @@ -3964,10 +3977,10 @@ def test_streamed_tool_start_waits_for_complete_json_arguments(tmp_path: Path) - asyncio.run( adapter._process_tool_call_chunks( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, message_chunk=cast( - AIMessageChunk, + "AIMessageChunk", SimpleNamespace( tool_call_chunks=[ { @@ -3975,13 +3988,13 @@ def test_streamed_tool_start_waits_for_complete_json_arguments(tmp_path: Path) - "name": "read_file", "args": '{"file_path":"next.txt"}', "index": 0, - } - ] + }, + ], ), ), active_tool_calls=active_tool_calls, tool_call_accumulator=tool_call_accumulator, - ) + ), ) assert active_tool_calls["call-next-round"]["raw_input"] == {"file_path": "next.txt"} @@ -3996,11 +4009,11 @@ def test_streamed_tool_start_accepts_empty_arguments(tmp_path: Path) -> None: active_tool_calls: dict[str, dict[str, Any]] = {} tool_call_accumulator: dict[int, dict[str, str | int | None]] = { - 99: {"args": "{}", "id": "other-call", "name": "other"} + 99: {"args": "{}", "id": "other-call", "name": "other"}, } asyncio.run( adapter._process_tool_call_chunks( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, message_chunk=AIMessageChunk( content="", @@ -4010,16 +4023,16 @@ def test_streamed_tool_start_accepts_empty_arguments(tmp_path: Path) -> None: "name": "ping", "args": "", "index": 0, - } + }, ], ), active_tool_calls=active_tool_calls, tool_call_accumulator=tool_call_accumulator, - ) + ), ) asyncio.run( adapter._handle_tool_message( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, message_chunk=ToolMessage( content="pong", @@ -4028,7 +4041,7 @@ def test_streamed_tool_start_accepts_empty_arguments(tmp_path: Path) -> None: ), active_tool_calls=active_tool_calls, tool_call_accumulator=tool_call_accumulator, - ) + ), ) start = next(update for _, update in client.updates if isinstance(update, ToolCallStart)) @@ -4047,7 +4060,7 @@ def test_tool_result_without_start_uses_a_string_tool_name(tmp_path: Path) -> No asyncio.run( adapter._handle_tool_message( - client=cast(AcpClient, client), + client=cast("AcpClient", client), session=session, message_chunk=ToolMessage( content="done", @@ -4055,7 +4068,7 @@ def test_tool_result_without_start_uses_a_string_tool_name(tmp_path: Path) -> No name=None, ), active_tool_calls={}, - ) + ), ) start = next(update for _, update in client.updates if isinstance(update, ToolCallStart)) @@ -4072,7 +4085,7 @@ def test_phase3_provider_state_helpers_cover_sync_async_and_reserved_config_path available_models=[ModelInfo(model_id="base", name="Base")], current_model_id="base", config_option_name="Graph Model", - ) + ), ) modes_provider = _AsyncModesProvider( mode_state=ModeState( @@ -4082,7 +4095,7 @@ def test_phase3_provider_state_helpers_cover_sync_async_and_reserved_config_path ], current_mode_id="ask", config_option_name="Graph Mode", - ) + ), ) config_provider = _ConfigProvider( options=[ @@ -4091,18 +4104,18 @@ def test_phase3_provider_state_helpers_cover_sync_async_and_reserved_config_path name="Safe Tools", type="boolean", current_value=True, - ) - ] + ), + ], ) adapter = _make_adapter( config=AdapterConfig( config_options_provider=config_provider, models_provider=models_provider, modes_provider=modes_provider, - ) + ), ) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) created = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) assert created.models is not None @@ -4133,7 +4146,7 @@ def test_phase3_provider_state_helpers_cover_sync_async_and_reserved_config_path assert session.config_values["provider-mode"] == "plan" response = asyncio.run( - adapter.set_config_option("safe_tools", session_id=created.session_id, value=False) + adapter.set_config_option("safe_tools", session_id=created.session_id, value=False), ) assert response is not None assert config_provider.set_calls == [("safe_tools", False)] @@ -4141,11 +4154,11 @@ def test_phase3_provider_state_helpers_cover_sync_async_and_reserved_config_path assert session.config_values["safe_tools"] is False model_response = asyncio.run( - adapter.set_config_option("model", session_id=created.session_id, value="ultra") + adapter.set_config_option("model", session_id=created.session_id, value="ultra"), ) assert model_response is not None mode_response = asyncio.run( - adapter.set_config_option("mode", session_id=created.session_id, value="ask") + adapter.set_config_option("mode", session_id=created.session_id, value="ask"), ) assert mode_response is not None session = adapter._require_session(created.session_id) @@ -4157,7 +4170,7 @@ def test_phase3_provider_state_helpers_cover_sync_async_and_reserved_config_path available_modes=[SessionMode(id="plan", name="Plan")], default_mode_id="plan", plan_mode_id="plan", - ) + ), ) plan_created = asyncio.run(plan_adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) plan_response = asyncio.run( @@ -4165,7 +4178,7 @@ def test_phase3_provider_state_helpers_cover_sync_async_and_reserved_config_path "plan_generation_type", session_id=plan_created.session_id, value="tools", - ) + ), ) assert plan_response is not None plan_session = plan_adapter._require_session(plan_created.session_id) @@ -4176,7 +4189,7 @@ def test_phase3_provider_state_helpers_cover_sync_async_and_reserved_config_path "plan_generation_type", session_id=plan_created.session_id, value="bad", - ) + ), ) disabled_options_adapter = _make_adapter( @@ -4186,16 +4199,16 @@ def test_phase3_provider_state_helpers_cover_sync_async_and_reserved_config_path available_models=[ModelInfo(model_id="hidden", name="Hidden")], current_model_id="hidden", enable_config_option=False, - ) + ), ), modes_provider=_AsyncModesProvider( mode_state=ModeState( modes=[SessionMode(id="hidden-mode", name="Hidden Mode")], current_mode_id="hidden-mode", enable_config_option=False, - ) + ), ), - ) + ), ) hidden_session = _make_session(cwd=tmp_path, session_id="hidden") assert asyncio.run(disabled_options_adapter._config_options(hidden_session)) == [] @@ -4204,7 +4217,7 @@ def test_phase3_provider_state_helpers_cover_sync_async_and_reserved_config_path config=AdapterConfig( models_provider=_SyncModelsProvider(model_state=None), modes_provider=_AsyncModesProvider(mode_state=None), - ) + ), ) rejected_session = _make_session(cwd=tmp_path, session_id="rejected") rejected_adapter._store.save(rejected_session) @@ -4233,11 +4246,10 @@ async def set_config_option( ) -> None: self.calls.append((config_id, value)) session.config_values["provider-echo"] = value - return None non_mutating_provider = _NonMutatingConfigProvider() fallback_adapter = _make_adapter( - config=AdapterConfig(config_options_provider=cast(Any, non_mutating_provider)) + config=AdapterConfig(config_options_provider=cast("Any", non_mutating_provider)), ) fallback_created = asyncio.run(fallback_adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) fallback_session_before = fallback_adapter._require_session(fallback_created.session_id) @@ -4247,7 +4259,7 @@ async def set_config_option( "demo-flag", session_id=fallback_created.session_id, value=True, - ) + ), ) assert fallback_response is not None fallback_session_after = fallback_adapter._require_session(fallback_created.session_id) @@ -4273,12 +4285,12 @@ def test_langchain_adapter_prompt_resume_and_stream_edge_paths(tmp_path: Path) - { "name": "delete_file", "args": {"path": "draft.txt"}, - } + }, ], "review_configs": [{"action_name": "delete_file"}], - } - ) - ] + }, + ), + ], }, ), ], @@ -4287,26 +4299,26 @@ def test_langchain_adapter_prompt_resume_and_stream_edge_paths(tmp_path: Path) - (), "messages", (AIMessageChunk(content=[{"type": "text", "text": "resumed"}]), {}), - ) + ), ], - ] + ], ) adapter = cast( - LangChainAcpAgent, + "LangChainAcpAgent", create_acp_agent( - graph=cast(Any, graph), - config=AdapterConfig(approval_bridge=cast(Any, approval_bridge)), + graph=cast("Any", graph), + config=AdapterConfig(approval_bridge=cast("Any", approval_bridge)), ), ) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) response = asyncio.run( adapter.prompt( prompt=[TextContentBlock(type="text", text="resume me")], session_id=session.session_id, - ) + ), ) assert response.stop_reason == "end_turn" @@ -4334,11 +4346,11 @@ async def astream( yield ((), "messages", (AIMessageChunk(content="ignored"), {})) adapter = cast( - LangChainAcpAgent, - create_acp_agent(graph=cast(Any, _CancellingGraph()), config=AdapterConfig()), + "LangChainAcpAgent", + create_acp_agent(graph=cast("Any", _CancellingGraph()), config=AdapterConfig()), ) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) session_holder["session_id"] = session.session_id @@ -4346,7 +4358,7 @@ async def astream( adapter.prompt( prompt=[TextContentBlock(type="text", text="cancel during stream")], session_id=session.session_id, - ) + ), ) assert response.stop_reason == "cancelled" @@ -4372,18 +4384,18 @@ async def astream( yield # pragma: no cover adapter = cast( - LangChainAcpAgent, - create_acp_agent(graph=cast(Any, _BlockingGraph()), config=AdapterConfig()), + "LangChainAcpAgent", + create_acp_agent(graph=cast("Any", _BlockingGraph()), config=AdapterConfig()), ) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) session = await adapter.new_session(cwd=str(tmp_path), mcp_servers=[]) prompt_task = asyncio.create_task( adapter.prompt( prompt=[TextContentBlock(type="text", text="wait forever")], session_id=session.session_id, message_id="blocking-message", - ) + ), ) await started.wait() @@ -4416,16 +4428,16 @@ async def astream( yield # pragma: no cover adapter = cast( - LangChainAcpAgent, - create_acp_agent(graph=cast(Any, _BlockingGraph()), config=AdapterConfig()), + "LangChainAcpAgent", + create_acp_agent(graph=cast("Any", _BlockingGraph()), config=AdapterConfig()), ) - adapter.on_connect(cast(AcpClient, RecordingACPClient())) + adapter.on_connect(cast("AcpClient", RecordingACPClient())) session = await adapter.new_session(cwd=str(tmp_path), mcp_servers=[]) prompt_task = asyncio.create_task( adapter.prompt( prompt=[TextContentBlock(type="text", text="wait")], session_id=session.session_id, - ) + ), ) await started.wait() @@ -4452,7 +4464,7 @@ def read_file(path: str) -> str: ) adapter = create_acp_agent(graph=graph, config=AdapterConfig()) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) asyncio.run(adapter.cancel(session_id=session.session_id)) @@ -4460,7 +4472,7 @@ def read_file(path: str) -> str: adapter.prompt( prompt=[TextContentBlock(type="text", text="cancel now")], session_id=session.session_id, - ) + ), ) assert response.stop_reason == "cancelled" diff --git a/tests/langchain/test_runtime.py b/tests/langchain/test_runtime.py index 2898bb4..82e1bae 100644 --- a/tests/langchain/test_runtime.py +++ b/tests/langchain/test_runtime.py @@ -81,12 +81,12 @@ def read_file(path: str) -> str: "args": {"path": "notes.txt"}, "id": "tool-1", "type": "tool_call", - } + }, ], ), AIMessage(content="Done reading."), - ] - ) + ], + ), ) graph = create_agent(model=fake_model, tools=[read_file], name="reader") adapter = create_acp_agent( @@ -94,15 +94,15 @@ def read_file(path: str) -> str: config=AdapterConfig( projection_maps=[ FileSystemProjectionMap(read_tool_names=frozenset({"read_file"})), - ] + ], ), ) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) response = asyncio.run( - adapter.prompt(prompt=[text_block("read notes.txt")], session_id=session.session_id) + adapter.prompt(prompt=[text_block("read notes.txt")], session_id=session.session_id), ) assert response.stop_reason == "end_turn" @@ -133,7 +133,7 @@ def test_langchain_acp_initialize_uses_configured_prompt_capabilities() -> None: audio=False, image=False, embedded_context=True, - ) + ), ), ) @@ -176,27 +176,27 @@ def read_file(path: str) -> str: StaticSlashCommand( command=AvailableCommand(name="ping", description="Return pong."), handler=lambda _request: SlashCommandResult(text="pong"), - ) - ] + ), + ], ), ), ) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) - stored_session = cast(Any, adapter)._store.get(session.session_id) + stored_session = cast("Any", adapter)._store.get(session.session_id) assert stored_session is not None stored_session.mcp_servers = [ - {"name": "repo-http", "transport": "http", "url": "https://repo.example/mcp"} + {"name": "repo-http", "transport": "http", "url": "https://repo.example/mcp"}, ] - cast(Any, adapter)._store.save(stored_session) + cast("Any", adapter)._store.save(stored_session) client.updates.clear() asyncio.run(adapter.prompt(prompt=[text_block("/tools")], session_id=session.session_id)) asyncio.run(adapter.prompt(prompt=[text_block("/review")], session_id=session.session_id)) asyncio.run( - adapter.prompt(prompt=[text_block("/model openai:gpt-5")], session_id=session.session_id) + adapter.prompt(prompt=[text_block("/model openai:gpt-5")], session_id=session.session_id), ) asyncio.run(adapter.prompt(prompt=[text_block("/mcp-servers")], session_id=session.session_id)) asyncio.run(adapter.prompt(prompt=[text_block("/ping")], session_id=session.session_id)) @@ -232,7 +232,7 @@ def duckduckgo_results_json(query: str) -> list[dict[str, str]]: "title": "ACP Kit", "url": "https://example.com/acpkit", "snippet": "Truthful ACP adapters.", - } + }, ] fake_model = GenericFakeChatModel( @@ -246,12 +246,12 @@ def duckduckgo_results_json(query: str) -> list[dict[str, str]]: "args": {"query": "acpkit"}, "id": "tool-search", "type": "tool_call", - } + }, ], ), AIMessage(content="Search finished."), - ] - ) + ], + ), ) graph = create_agent(model=fake_model, tools=[duckduckgo_results_json], name="web-search") adapter = create_acp_agent( @@ -259,11 +259,11 @@ def duckduckgo_results_json(query: str) -> list[dict[str, str]]: config=AdapterConfig(projection_maps=[WebSearchProjectionMap()]), ) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) response = asyncio.run( - adapter.prompt(prompt=[text_block("search acpkit")], session_id=session.session_id) + adapter.prompt(prompt=[text_block("search acpkit")], session_id=session.session_id), ) assert response.stop_reason == "end_turn" @@ -300,12 +300,12 @@ def requests_get(url: str) -> str: "args": {"url": "https://example.com/docs"}, "id": "tool-fetch", "type": "tool_call", - } + }, ], ), AIMessage(content="Fetch finished."), - ] - ) + ], + ), ) graph = create_agent(model=fake_model, tools=[requests_get], name="web-fetch") adapter = create_acp_agent( @@ -313,11 +313,11 @@ def requests_get(url: str) -> str: config=AdapterConfig(projection_maps=[HttpRequestProjectionMap()]), ) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) response = asyncio.run( - adapter.prompt(prompt=[text_block("fetch the docs")], session_id=session.session_id) + adapter.prompt(prompt=[text_block("fetch the docs")], session_id=session.session_id), ) assert response.stop_reason == "end_turn" @@ -363,7 +363,7 @@ def terminal(commands: list[str]) -> str: "args": {"url": "https://example.com/docs"}, "id": "tool-nav", "type": "tool_call", - } + }, ], ), AIMessage( @@ -374,7 +374,7 @@ def terminal(commands: list[str]) -> str: "args": {}, "id": "tool-links", "type": "tool_call", - } + }, ], ), AIMessage( @@ -385,12 +385,12 @@ def terminal(commands: list[str]) -> str: "args": {"commands": ["pwd", "ls"]}, "id": "tool-terminal", "type": "tool_call", - } + }, ], ), AIMessage(content="Browser and shell finished."), - ] - ) + ], + ), ) graph = create_agent( model=fake_model, @@ -404,11 +404,11 @@ def terminal(commands: list[str]) -> str: ), ) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) response = asyncio.run( - adapter.prompt(prompt=[text_block("browse and inspect")], session_id=session.session_id) + adapter.prompt(prompt=[text_block("browse and inspect")], session_id=session.session_id), ) assert response.stop_reason == "end_turn" @@ -455,12 +455,12 @@ def move_file(source_path: str, destination_path: str) -> str: }, "id": "tool-move", "type": "tool_call", - } + }, ], ), AIMessage(content="Move finished."), - ] - ) + ], + ), ) graph = create_agent(model=fake_model, tools=[move_file], name="file-manager") adapter = create_acp_agent( @@ -468,11 +468,11 @@ def move_file(source_path: str, destination_path: str) -> str: config=AdapterConfig(projection_maps=[CommunityFileManagementProjectionMap()]), ) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) response = asyncio.run( - adapter.prompt(prompt=[text_block("archive draft")], session_id=session.session_id) + adapter.prompt(prompt=[text_block("archive draft")], session_id=session.session_id), ) assert response.stop_reason == "end_turn" @@ -507,12 +507,12 @@ def google_finance(query: str) -> str: "args": {"query": "NVDA"}, "id": "tool-finance", "type": "tool_call", - } + }, ], ), AIMessage(content="Finance finished."), - ] - ) + ], + ), ) graph = create_agent(model=fake_model, tools=[google_finance], name="finance") adapter = create_acp_agent( @@ -520,11 +520,11 @@ def google_finance(query: str) -> str: config=AdapterConfig(projection_maps=[FinanceProjectionMap()]), ) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) response = asyncio.run( - adapter.prompt(prompt=[text_block("check nvda")], session_id=session.session_id) + adapter.prompt(prompt=[text_block("check nvda")], session_id=session.session_id), ) assert response.stop_reason == "end_turn" @@ -556,27 +556,27 @@ def delete_file(path: str) -> str: "args": {"path": "draft.txt"}, "id": "tool-2", "type": "tool_call", - } + }, ], ), AIMessage(content="Approved."), - ] - ) + ], + ), ) middleware = [ HumanInTheLoopMiddleware( - interrupt_on={"delete_file": {"allowed_decisions": ["approve", "reject"]}} - ) + interrupt_on={"delete_file": {"allowed_decisions": ["approve", "reject"]}}, + ), ] graph = create_agent(model=fake_model, tools=[delete_file], middleware=middleware) adapter = create_acp_agent(graph=graph, config=AdapterConfig()) client = RecordingACPClient() client.queue_permission_selected("allow_once") - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) response = asyncio.run( - adapter.prompt(prompt=[text_block("delete draft.txt")], session_id=session.session_id) + adapter.prompt(prompt=[text_block("delete draft.txt")], session_id=session.session_id), ) assert response.stop_reason == "end_turn" @@ -601,7 +601,7 @@ def planner(state: _PlanState) -> dict[str, Any]: "status": "in_progress", "priority": "medium", }, - ] + ], } builder = StateGraph(_PlanState) @@ -611,16 +611,16 @@ def planner(state: _PlanState) -> dict[str, Any]: graph = builder.compile() adapter = create_acp_agent(graph=graph, config=AdapterConfig()) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) response = asyncio.run( - adapter.prompt(prompt=[text_block("plan this")], session_id=session.session_id) + adapter.prompt(prompt=[text_block("plan this")], session_id=session.session_id), ) assert response.stop_reason == "end_turn" plan_update = next( - cast(AgentPlanUpdate, update) + cast("AgentPlanUpdate", update) for _, update in client.updates if isinstance(update, AgentPlanUpdate) ) @@ -655,9 +655,9 @@ def extract_plan_entries(self, payload: Any) -> list[PlanEntry] | None: entries.append( PlanEntry( content=content, - status=cast(PlanEntryStatus, task.get("status", "pending")), - priority=cast(PlanEntryPriority, task.get("priority", "medium")), - ) + status=cast("PlanEntryStatus", task.get("status", "pending")), + priority=cast("PlanEntryPriority", task.get("priority", "medium")), + ), ) return entries @@ -675,7 +675,7 @@ def planner(state: _CustomPlanState) -> dict[str, Any]: "status": "in_progress", "priority": "medium", }, - ] + ], } builder = StateGraph(_CustomPlanState) @@ -688,16 +688,16 @@ def planner(state: _CustomPlanState) -> dict[str, Any]: config=AdapterConfig(capability_bridges=[_TasksBridge()]), ) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) response = asyncio.run( - adapter.prompt(prompt=[text_block("plan this")], session_id=session.session_id) + adapter.prompt(prompt=[text_block("plan this")], session_id=session.session_id), ) assert response.stop_reason == "end_turn" plan_update = next( - cast(AgentPlanUpdate, update) + cast("AgentPlanUpdate", update) for _, update in client.updates if isinstance(update, AgentPlanUpdate) ) @@ -712,7 +712,6 @@ def test_langchain_acp_phase6_projects_deepagents_execute_updates_at_runtime( ) -> None: def execute(command: str) -> dict[str, str]: """Execute a shell command in the workspace.""" - return { "terminal_id": "terminal-1", "stdout": f"ran:{command}", @@ -729,12 +728,12 @@ def execute(command: str) -> dict[str, str]: "args": {"command": "echo hi && sudo rm /tmp/demo"}, "id": "tool-exec", "type": "tool_call", - } + }, ], ), AIMessage(content="Command finished."), - ] - ) + ], + ), ) graph = create_agent(model=fake_model, tools=[execute], name="deepagents-execute") adapter = create_acp_agent( @@ -742,11 +741,11 @@ def execute(command: str) -> dict[str, str]: config=AdapterConfig(projection_maps=[DeepAgentsProjectionMap()]), ) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) response = asyncio.run( - adapter.prompt(prompt=[text_block("run the command")], session_id=session.session_id) + adapter.prompt(prompt=[text_block("run the command")], session_id=session.session_id), ) assert response.stop_reason == "end_turn" @@ -784,14 +783,14 @@ def test_langchain_acp_runs_real_deepagents_graph(tmp_path: Path) -> None: ), ) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) response = asyncio.run( adapter.prompt( prompt=[text_block("Confirm the integration.")], session_id=session.session_id, - ) + ), ) assert response.stop_reason == "end_turn" @@ -842,13 +841,13 @@ def read_file(path: str) -> str: def graph_factory(session) -> Any: captured_session_ids.append(session.session_id) fake_model = GenericFakeChatModel( - messages=iter([AIMessage(content="Factory graph ready.")]) + messages=iter([AIMessage(content="Factory graph ready.")]), ) return create_agent(model=fake_model, tools=[read_file]) adapter = create_acp_agent(graph_factory=graph_factory, config=AdapterConfig()) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) asyncio.run(adapter.prompt(prompt=[text_block("hello")], session_id=session.session_id)) @@ -912,7 +911,7 @@ def graph_factory(session) -> Any: mode_id = session.session_mode_id or "ask" captured_builds.append((model_id, mode_id)) fake_model = GenericFakeChatModel( - messages=iter([AIMessage(content=f"{model_id}:{mode_id}")]) + messages=iter([AIMessage(content=f"{model_id}:{mode_id}")]), ) return create_agent(model=fake_model, tools=[], name=f"{model_id}-{mode_id}") @@ -924,7 +923,7 @@ def graph_factory(session) -> Any: ), ) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) assert session.models is not None @@ -939,7 +938,7 @@ def graph_factory(session) -> Any: asyncio.run(adapter.set_session_model("gpt-5", session_id=session.session_id)) asyncio.run(adapter.set_session_mode("plan", session_id=session.session_id)) second = asyncio.run( - adapter.prompt(prompt=[text_block("again")], session_id=session.session_id) + adapter.prompt(prompt=[text_block("again")], session_id=session.session_id), ) assert second.stop_reason == "end_turn" assert agent_message_texts(client)[-1] == "gpt-5:plan" @@ -1006,16 +1005,16 @@ def test_langchain_acp_phase4_structured_plan_output_persists_task_plan( "priority": "medium", }, ], - } - } + }, + }, }, - ) - ] + ), + ], ) adapter = cast( - Any, + "Any", create_acp_agent( - graph=cast(Any, graph), + graph=cast("Any", graph), config=AdapterConfig( available_modes=[SessionMode(id="plan", name="Plan")], default_mode_id="plan", @@ -1024,11 +1023,11 @@ def test_langchain_acp_phase4_structured_plan_output_persists_task_plan( ), ) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) response = asyncio.run( - adapter.prompt(prompt=[text_block("plan the work")], session_id=session.session_id) + adapter.prompt(prompt=[text_block("plan the work")], session_id=session.session_id), ) assert response.stop_reason == "end_turn" @@ -1039,7 +1038,7 @@ def test_langchain_acp_phase4_structured_plan_output_persists_task_plan( "Write summary", ] plan_update = next( - cast(AgentPlanUpdate, update) + cast("AgentPlanUpdate", update) for _, update in client.updates if isinstance(update, AgentPlanUpdate) ) @@ -1066,13 +1065,13 @@ def test_langchain_acp_phase4_tool_based_plan_generation_updates_plan_state( "content": "Book flights", "status": "pending", "priority": "high", - } + }, ], "plan_md": "# Travel booking", }, "id": "tool-1", "type": "tool_call", - } + }, ], ), AIMessage( @@ -1083,20 +1082,20 @@ def test_langchain_acp_phase4_tool_based_plan_generation_updates_plan_state( "args": {"index": 1}, "id": "tool-2", "type": "tool_call", - } + }, ], ), AIMessage(content="Trip plan saved."), - ] - ) + ], + ), ) graph = create_agent( model=fake_model, - tools=cast(list[Callable[..., Any]], list(native_plan_tools())), + tools=cast("list[Callable[..., Any]]", list(native_plan_tools())), name="planner", ) adapter = cast( - Any, + "Any", create_acp_agent( graph=graph, config=AdapterConfig( @@ -1108,11 +1107,11 @@ def test_langchain_acp_phase4_tool_based_plan_generation_updates_plan_state( ), ) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) response = asyncio.run( - adapter.prompt(prompt=[text_block("save a plan")], session_id=session.session_id) + adapter.prompt(prompt=[text_block("save a plan")], session_id=session.session_id), ) assert response.stop_reason == "end_turn" @@ -1123,16 +1122,16 @@ def test_langchain_acp_phase4_tool_based_plan_generation_updates_plan_state( "content": "Book flights", "status": "completed", "priority": "high", - } + }, ] plan_updates = [ - cast(AgentPlanUpdate, update) + cast("AgentPlanUpdate", update) for _, update in client.updates if isinstance(update, AgentPlanUpdate) ] assert len(plan_updates) == 2 assert plan_updates[-1].entries == [ - PlanEntry(content="Book flights", status="completed", priority="high") + PlanEntry(content="Book flights", status="completed", priority="high"), ] assert agent_message_texts(client)[-1] == "Trip plan saved." @@ -1160,21 +1159,21 @@ def test_langchain_acp_phase6_projects_structured_runtime_events( "status": "completed", "content": "shell complete", }, - ] + ], }, - ) - ] + ), + ], ) adapter = create_acp_agent( - graph=cast(Any, graph), + graph=cast("Any", graph), config=AdapterConfig(event_projection_maps=[StructuredEventProjectionMap()]), ) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) response = asyncio.run( - adapter.prompt(prompt=[text_block("run diagnostics")], session_id=session.session_id) + adapter.prompt(prompt=[text_block("run diagnostics")], session_id=session.session_id), ) assert response.stop_reason == "end_turn" @@ -1184,20 +1183,20 @@ def test_langchain_acp_phase6_projects_structured_runtime_events( if isinstance(update, ToolCallStart | ToolCallProgress) ] assert len(projected_updates) == 2 - assert cast(ToolCallStart, projected_updates[0]).title == "run shell" - progress = cast(ToolCallProgress, projected_updates[1]) + assert cast("ToolCallStart", projected_updates[0]).title == "run shell" + progress = cast("ToolCallProgress", projected_updates[1]) assert progress.status == "completed" assert progress.content is not None - assert cast(Any, progress.content[0]).content.text == "shell complete" + assert cast("Any", progress.content[0]).content.text == "shell complete" def test_langchain_acp_phase6_preserves_multimodal_and_resource_prompt_blocks( tmp_path: Path, ) -> None: graph = _RecordingGraph() - adapter = create_acp_agent(graph=cast(Any, graph), config=AdapterConfig()) + adapter = create_acp_agent(graph=cast("Any", graph), config=AdapterConfig()) client = RecordingACPClient() - adapter.on_connect(cast(AcpClient, client)) + adapter.on_connect(cast("AcpClient", client)) session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) response = asyncio.run( @@ -1229,7 +1228,7 @@ def test_langchain_acp_phase6_preserves_multimodal_and_resource_prompt_blocks( ), ], session_id=session.session_id, - ) + ), ) assert response.stop_reason == "end_turn" diff --git a/tests/langchain/test_support.py b/tests/langchain/test_support.py index 263ae69..1e07222 100644 --- a/tests/langchain/test_support.py +++ b/tests/langchain/test_support.py @@ -25,7 +25,7 @@ def test_generic_fake_chat_model_support_stream_paths() -> None: messages=iter([AIMessage(content="alpha,beta", id="stream-1")]), stream_delimiter=",", ) - chunks = list(model._stream([], run_manager=cast(Any, manager))) + chunks = list(model._stream([], run_manager=cast("Any", manager))) assert [chunk.message.content for chunk in chunks] == ["alpha", "beta"] assert manager.tokens == ["alpha", "beta"] @@ -37,11 +37,11 @@ def test_generic_fake_chat_model_support_stream_paths() -> None: content="", id="tool-1", tool_calls=[{"name": "demo", "args": {}, "id": "call-1", "type": "tool_call"}], - ) - ] - ) + ), + ], + ), ) - tool_chunks = list(tool_model._stream([], run_manager=cast(Any, tool_manager))) + tool_chunks = list(tool_model._stream([], run_manager=cast("Any", tool_manager))) assert len(tool_chunks) == 1 assert tool_manager.tokens == [""] @@ -50,16 +50,16 @@ def test_generic_fake_chat_model_support_stream_paths() -> None: invalid_message_model = GenericFakeChatModel(messages=iter(["ignored"])) invalid_message_model._generate = cast( # type: ignore[method-assign] - Any, + "Any", lambda *args, **kwargs: SimpleNamespace( - generations=[SimpleNamespace(message=cast(Any, object()))] + generations=[SimpleNamespace(message=cast("Any", object()))], ), ) with pytest.raises(ValueError, match="Expected `AIMessage`"): list(invalid_message_model._stream([])) invalid_content_model = GenericFakeChatModel( - messages=iter([AIMessage(content=cast(Any, ["bad-content"]), id="invalid-1")]) + messages=iter([AIMessage(content=cast("Any", ["bad-content"]), id="invalid-1")]), ) with pytest.raises(ValueError, match="Expected string content"): list(invalid_content_model._stream([])) @@ -69,7 +69,7 @@ def test_generic_fake_chat_model_support_stream_paths() -> None: async def test_langchain_recording_acp_client_support_helpers() -> None: client = RecordingACPClient() option = PermissionOption(option_id="allow_once", name="Allow once", kind="allow_once") - tool_call = cast(Any, object()) + tool_call = cast("Any", object()) with pytest.raises(AssertionError, match="unexpected permission request"): await client.request_permission([option], "session-1", tool_call) @@ -116,4 +116,4 @@ async def test_langchain_recording_acp_client_support_helpers() -> None: with pytest.raises(AssertionError, match="unexpected extension notification"): await client.ext_notification("demo.note", {"value": 2}) - assert client.on_connect(cast(Any, object())) is None + assert client.on_connect(cast("Any", object())) is None diff --git a/tests/pydantic/support.py b/tests/pydantic/support.py index cda330c..7cee9c4 100644 --- a/tests/pydantic/support.py +++ b/tests/pydantic/support.py @@ -113,6 +113,7 @@ from pydantic_ai.tools import RunContext, ToolDefinition __all__ = ( + "UTC", "AcpSessionContext", "AdapterConfig", "AdapterModel", @@ -124,22 +125,22 @@ "AgentPlanUpdate", "AgentSource", "AllowedOutcome", + "AnthropicCompactionBridge", "ApprovalPolicy", "ApprovalPolicyStore", "ApprovalRequired", "AsyncDemoConfigOptionsProvider", "AsyncDemoModesProvider", "AsyncDemoPlanProvider", - "AnthropicCompactionBridge", "AvailableCommandsUpdate", "BuiltinToolProjectionMap", "ClientFilesystemBackend", "ClientHostContext", "ClientTerminalBackend", "CompositeProjectionMap", - "ContentToolCallContent", "ConfigOption", "ConfigOptionUpdate", + "ContentToolCallContent", "CreateTerminalResponse", "CurrentModeUpdate", "DefaultPermissionToolCallBuilder", @@ -152,43 +153,43 @@ "EnvVariable", "ExternalHookEventBridge", "FactoryAgentSource", - "FileSessionStore", "FileEditToolCallContent", + "FileSessionStore", + "FileSystemProjectionMap", "FilesystemBackend", "FilesystemRecordingClient", - "FileSystemProjectionMap", "FreeformModelsProvider", "HistoryProcessorBridge", "HookBridge", "HookEvent", "HookProjectionMap", + "HostRecordingClient", "ImageGenerationBridge", "IncludeToolReturnSchemasBridge", - "HostRecordingClient", "JsonValue", "KillTerminalResponse", "McpBridge", + "McpCapabilityBridge", "McpServerDefinition", "McpToolDefinition", "MemorySessionStore", "ModeState", "ModelMessage", "ModelSelectionState", - "McpCapabilityBridge", "NativeApprovalBridge", "OpenAICompactionBridge", "Path", - "PermissionOptionSet", "PermissionOption", + "PermissionOptionSet", "PermissionRequestContext", "PermissionToolCallBuilder", "PlanEntry", "PrefixToolsBridge", - "ProjectionAwareToolClassifier", "PrepareOutputToolsBridge", "PrepareOutputToolsMode", "PrepareToolsBridge", "PrepareToolsMode", + "ProjectionAwareToolClassifier", "ReadTextFileResponse", "RecordingClient", "ReleaseTerminalResponse", @@ -209,25 +210,24 @@ "StaticAgentSource", "StaticSlashCommand", "StaticSlashCommandProvider", - "TerminalToolCallContent", "TerminalBackend", "TerminalOutputResponse", "TerminalRecordingClient", + "TerminalToolCallContent", "TestModel", - "ThreadExecutorBridge", "ThinkingBridge", - "ToolsetBridge", + "ThreadExecutorBridge", "ToolCallProgress", "ToolCallStart", "ToolCallUpdate", - "WebFetchBridge", - "WebSearchBridge", - "WebToolProjectionMap", "ToolDefinition", - "UTC", + "ToolsetBridge", "UsageUpdate", "UserMessageChunk", "WaitForTerminalExitResponse", + "WebFetchBridge", + "WebSearchBridge", + "WebToolProjectionMap", "WriteTextFileResponse", "agent_message_texts", "create_acp_agent", @@ -247,12 +247,12 @@ def queue_permission_selected(self, option_id: str) -> None: self.permission_responses.append( RequestPermissionResponse( outcome=AllowedOutcome(outcome="selected", option_id=option_id), - ) + ), ) def queue_permission_cancelled(self) -> None: self.permission_responses.append( - RequestPermissionResponse(outcome=DeniedOutcome(outcome="cancelled")) + RequestPermissionResponse(outcome=DeniedOutcome(outcome="cancelled")), ) async def request_permission( @@ -264,10 +264,10 @@ async def request_permission( ) -> RequestPermissionResponse: del kwargs self.permission_option_ids.append( - (session_id, [option.option_id for option in options], tool_call) + (session_id, [option.option_id for option in options], tool_call), ) self.permission_option_names.append( - (session_id, [option.name for option in options], tool_call) + (session_id, [option.name for option in options], tool_call), ) if not self.permission_responses: raise AssertionError("unexpected permission request") @@ -295,7 +295,11 @@ async def session_update( self.updates.append((session_id, update)) async def write_text_file( - self, content: str, path: str, session_id: str, **kwargs: Any + self, + content: str, + path: str, + session_id: str, + **kwargs: Any, ) -> WriteTextFileResponse | None: del content, path, session_id, kwargs raise AssertionError("filesystem flow is not part of this test") @@ -325,25 +329,37 @@ async def create_terminal( raise AssertionError("terminal flow is not part of this test") async def terminal_output( - self, session_id: str, terminal_id: str, **kwargs: Any + self, + session_id: str, + terminal_id: str, + **kwargs: Any, ) -> TerminalOutputResponse: del session_id, terminal_id, kwargs raise AssertionError("terminal flow is not part of this test") async def release_terminal( - self, session_id: str, terminal_id: str, **kwargs: Any + self, + session_id: str, + terminal_id: str, + **kwargs: Any, ) -> ReleaseTerminalResponse | None: del session_id, terminal_id, kwargs raise AssertionError("terminal flow is not part of this test") async def wait_for_terminal_exit( - self, session_id: str, terminal_id: str, **kwargs: Any + self, + session_id: str, + terminal_id: str, + **kwargs: Any, ) -> WaitForTerminalExitResponse: del session_id, terminal_id, kwargs raise AssertionError("terminal flow is not part of this test") async def kill_terminal( - self, session_id: str, terminal_id: str, **kwargs: Any + self, + session_id: str, + terminal_id: str, + **kwargs: Any, ) -> KillTerminalResponse | None: del session_id, terminal_id, kwargs raise AssertionError("terminal flow is not part of this test") @@ -354,7 +370,7 @@ async def ext_method(self, method: str, params: dict[str, Any]) -> dict[str, Any async def ext_notification(self, method: str, params: dict[str, Any]) -> None: raise AssertionError(f"unexpected extension notification: {method!r} {params!r}") - def on_connect(self, conn: AcpAgent) -> None: + def on_connect(self, conn: AcpAgent) -> None: # type: ignore[misc] del conn @@ -391,7 +407,11 @@ def __init__(self) -> None: self.write_response: WriteTextFileResponse | None = WriteTextFileResponse() async def write_text_file( - self, content: str, path: str, session_id: str, **kwargs: Any + self, + content: str, + path: str, + session_id: str, + **kwargs: Any, ) -> WriteTextFileResponse | None: del kwargs self.write_calls.append((session_id, path, content)) @@ -446,28 +466,40 @@ async def create_terminal( return CreateTerminalResponse(terminal_id="terminal-1") async def terminal_output( - self, session_id: str, terminal_id: str, **kwargs: Any + self, + session_id: str, + terminal_id: str, + **kwargs: Any, ) -> TerminalOutputResponse: del kwargs self.output_calls.append((session_id, terminal_id)) return TerminalOutputResponse(output="terminal-output", truncated=False) async def release_terminal( - self, session_id: str, terminal_id: str, **kwargs: Any + self, + session_id: str, + terminal_id: str, + **kwargs: Any, ) -> ReleaseTerminalResponse | None: del kwargs self.release_calls.append((session_id, terminal_id)) return self.release_response async def wait_for_terminal_exit( - self, session_id: str, terminal_id: str, **kwargs: Any + self, + session_id: str, + terminal_id: str, + **kwargs: Any, ) -> WaitForTerminalExitResponse: del kwargs self.wait_calls.append((session_id, terminal_id)) return self.wait_response async def kill_terminal( - self, session_id: str, terminal_id: str, **kwargs: Any + self, + session_id: str, + terminal_id: str, + **kwargs: Any, ) -> KillTerminalResponse | None: del kwargs self.kill_calls.append((session_id, terminal_id)) @@ -582,7 +614,7 @@ def get_config_options( description="Enable streamed responses.", type="boolean", current_value=stream_enabled, - ) + ), ] def set_config_option( @@ -631,7 +663,7 @@ async def get_model_state( model_id="custom-model-a", name="Custom Model A", override="custom-model-a", - ) + ), ], current_model_id=current_model_id, allow_any_model_id=True, @@ -667,7 +699,7 @@ def get_config_options( SessionConfigSelectOption(value="provider-model-a", name="Provider Model A"), SessionConfigSelectOption(value="provider-model-b", name="Provider Model B"), ], - ) + ), ] def set_config_option( diff --git a/tests/pydantic/test_acp_client_provider.py b/tests/pydantic/test_acp_client_provider.py new file mode 100644 index 0000000..0cab1fd --- /dev/null +++ b/tests/pydantic/test_acp_client_provider.py @@ -0,0 +1,1174 @@ +from __future__ import annotations as _annotations + +import tomllib +from pathlib import Path +from typing import Any, Literal, cast + +import pydantic_acp +import pytest +from acp import PROTOCOL_VERSION +from acp.exceptions import RequestError +from acp.helpers import text_block +from acp.interfaces import Agent as AcpAgent +from acp.interfaces import Client as AcpClient +from acp.schema import ( + AgentCapabilities, + AgentMessageChunk, + AllowedOutcome, + ClientCapabilities, + Implementation, + InitializeResponse, + NewSessionResponse, + PermissionOption, + PromptResponse, + ToolCallUpdate, + Usage, + UsageUpdate, +) +from pydantic_acp import AcpHostBridge, AcpModel, AcpProvider, create_acp_agent +from pydantic_acp import client as client_module +from pydantic_ai import Agent +from pydantic_ai.exceptions import UserError +from pydantic_ai.messages import ( + BinaryContent, + ImageUrl, + InstructionPart, + ModelRequest, + ModelResponse, + RetryPromptPart, + SystemPromptPart, + TextContent, + TextPart, + ToolCallPart, + ToolReturnPart, + UploadedFile, + UserPromptPart, +) +from pydantic_ai.models import ModelRequestParameters +from pydantic_ai.models.test import TestModel +from pydantic_ai.native_tools import WebSearchTool +from pydantic_ai.providers import Provider +from pydantic_ai.tools import ToolDefinition + +from .support import HostRecordingClient, RecordingClient + + +class EchoACPAgent: # type: ignore[misc] + def __init__( + self, + *, + stop_reason: Literal[ + "end_turn", "max_tokens", "max_turn_requests", "refusal", "cancelled" + ] = "end_turn", + usage: Usage | None = None, + ) -> None: + self.client: Any | None = None + self.initialized_protocols: list[int] = [] + self.session_cwds: list[str] = [] + self.session_models: list[tuple[str, str]] = [] + self.prompts: list[tuple[str, str]] = [] + self.stop_reason: Literal[ + "end_turn", "max_tokens", "max_turn_requests", "refusal", "cancelled" + ] = stop_reason + self.usage = usage + self.client_capabilities: ClientCapabilities | None = None + self.client_info: Implementation | None = None + self.mcp_servers_seen: list[list[Any] | None] = [] + + def on_connect(self, conn: Any) -> None: + self.client = conn + + async def initialize( + self, + protocol_version: int, + client_capabilities: ClientCapabilities | None = None, + client_info: Implementation | None = None, + **kwargs: Any, + ) -> InitializeResponse: + del kwargs + self.initialized_protocols.append(protocol_version) + self.client_capabilities = client_capabilities + self.client_info = client_info + return InitializeResponse( + protocol_version=protocol_version, + agent_info=Implementation(name="echo-acp-agent", version="test"), + agent_capabilities=AgentCapabilities(), + ) + + async def new_session( + self, + cwd: str, + mcp_servers: list[Any] | None = None, + **kwargs: Any, + ) -> NewSessionResponse: + del kwargs + self.session_cwds.append(cwd) + self.mcp_servers_seen.append(mcp_servers) + return NewSessionResponse(session_id=f"session-{len(self.session_cwds)}") + + async def set_session_model( + self, + model_id: str, + session_id: str, + **kwargs: Any, + ) -> None: + del kwargs + self.session_models.append((session_id, model_id)) + + async def prompt( + self, + prompt: list[Any], + session_id: str, + message_id: str | None = None, + **kwargs: Any, + ) -> PromptResponse: + del message_id, kwargs + if self.client is None: + raise AssertionError("ACP agent was not connected to a host client") + rendered_prompt = "".join(str(getattr(block, "text", "")) for block in prompt) + self.prompts.append((session_id, rendered_prompt)) + await self.client.session_update( + session_id=session_id, + update=AgentMessageChunk( + session_update="agent_message_chunk", + content=text_block(f"acp echo: {rendered_prompt}"), + ), + source="echo-acp-agent", + ) + return PromptResponse(stop_reason=self.stop_reason, usage=self.usage) + + +def _build_provider_and_model( + agent: Any, + *, + model_name: str = "zed-agent", + cwd: str = "/workspace", + prompt_renderer: Any = None, +) -> tuple[AcpProvider, AcpModel]: + """Construct an ``AcpProvider``/``AcpModel`` pair with this file's shared test defaults.""" + provider = AcpProvider(agent=agent, cwd=cwd, prompt_renderer=prompt_renderer) + model = AcpModel(model_name=model_name, provider=provider) + return provider, model + + +class SetModelErrorACPAgent(EchoACPAgent): + def __init__(self, error: RequestError) -> None: + super().__init__() + self.error = error + + async def set_session_model( + self, + model_id: str, + session_id: str, + **kwargs: Any, + ) -> None: + del model_id, session_id, kwargs + raise self.error + + +def test_acp_client_provider_is_plain_pydantic_ai_provider() -> None: + acp_agent = EchoACPAgent() + provider, model = _build_provider_and_model(acp_agent) + + assert isinstance(provider, Provider) + assert provider.client is acp_agent + assert provider.name == "acp" + assert provider.base_url == "acp://local" + assert model.provider is provider + assert model.system == "acp" + assert model.model_name == "zed-agent" + assert model.base_url == "acp://local" + + +async def test_pydantic_ai_agent_can_use_acp_as_just_a_provider() -> None: + acp_agent = EchoACPAgent() + _provider, model = _build_provider_and_model(acp_agent) + agent = Agent(model) + + result = await agent.run("Summarize the ACP bridge") + + assert "Summarize the ACP bridge" in result.output + assert acp_agent.initialized_protocols == [PROTOCOL_VERSION] + assert acp_agent.session_cwds == ["/workspace"] + assert acp_agent.session_models == [("session-1", "zed-agent")] + assert len(acp_agent.prompts) == 1 + assert "Summarize the ACP bridge" in acp_agent.prompts[0][1] + + +def test_pydantic_acp_requires_pydantic_ai_v2() -> None: + package_pyproject = Path("packages/adapters/pydantic-acp/pyproject.toml") + data: dict[str, Any] = tomllib.loads(package_pyproject.read_text()) + dependencies: list[str] = data["project"]["dependencies"] + pydantic_ai_dependency: str = next( + dependency for dependency in dependencies if dependency.startswith("pydantic-ai-slim") + ) + + assert ">=2.0.0" in pydantic_ai_dependency + assert "==1." not in pydantic_ai_dependency + + +# --- AcpProvider / AcpModel behavior (changed code) --------------------------------- + + +def test_acp_provider_accepts_acp_client_directly_and_exposes_accessors() -> None: + acp_agent = EchoACPAgent() + + provider = AcpProvider(acp_client=cast(AcpAgent, acp_agent)) + model = provider.model(history_mode="full") + + assert provider.client is acp_agent + assert provider.host.delegate is None + assert provider.name == "acp" + assert provider.base_url == "acp://local" + assert provider.session_id is None + assert provider.updates == [] + assert model.provider is provider + + +def test_acp_provider_rejects_ambiguous_client_construction() -> None: + acp_agent = EchoACPAgent() + + with pytest.raises(AssertionError, match="both `acp_client` and `agent`"): + cast(Any, AcpProvider)( + acp_client=acp_agent, + agent=EchoACPAgent(), + cwd="/workspace", + ) + + with pytest.raises(AssertionError, match="both `acp_client` and `host_client`"): + cast(Any, AcpProvider)( + acp_client=acp_agent, + host_client=HostRecordingClient(), + cwd="/workspace", + ) + + +async def test_acp_provider_reuses_session_and_model_across_multiple_requests() -> None: + acp_agent = EchoACPAgent() + _provider, model = _build_provider_and_model(acp_agent) + agent = Agent(model) + + await agent.run("first turn") + await agent.run("second turn") + + assert acp_agent.initialized_protocols == [PROTOCOL_VERSION] + assert acp_agent.session_cwds == ["/workspace"] + assert acp_agent.session_models == [("session-1", "zed-agent")] + assert len(acp_agent.prompts) == 2 + + +def test_acp_provider_model_factory_uses_default_model_name() -> None: + acp_agent = EchoACPAgent() + provider = AcpProvider(agent=cast(AcpAgent, acp_agent), cwd="/workspace") + + model = provider.model() + + assert model.model_name == "agent" + assert model.provider is provider + + +async def test_acp_provider_accepts_sync_set_session_model_hooks() -> None: + acp_agent = EchoACPAgent() + set_model_calls: list[tuple[str, str]] = [] + + def set_session_model(model_id: str, session_id: str, **kwargs: Any) -> None: + del kwargs + set_model_calls.append((session_id, model_id)) + + cast(Any, acp_agent).set_session_model = set_session_model + _provider, model = _build_provider_and_model(acp_agent) + + await Agent(model).run("sync model hook") + + assert set_model_calls == [("session-1", "zed-agent")] + + +async def test_acp_provider_ensure_session_returns_existing_session_for_same_model() -> None: + acp_agent = EchoACPAgent() + provider = AcpProvider(agent=cast(AcpAgent, acp_agent), cwd="/workspace") + + first_session_id = await provider._ensure_session(model_name="zed-agent") + second_session_id = await provider._ensure_session(model_name="zed-agent") + + assert first_session_id == "session-1" + assert second_session_id == "session-1" + assert acp_agent.session_models == [("session-1", "zed-agent")] + + +@pytest.mark.parametrize( + "error", + [ + RequestError(-32601, "Method not found", {"method": "session/set_model"}), + RequestError(-32601, "session/set_model is unavailable"), + ], +) +async def test_acp_provider_treats_missing_set_model_as_supported_fallback( + error: RequestError, +) -> None: + acp_agent = SetModelErrorACPAgent(error) + _provider, model = _build_provider_and_model(acp_agent) + + response = await model.request( + [ModelRequest(parts=[UserPromptPart("hello")])], + None, + ModelRequestParameters(), + ) + + assert response.provider_details == {"acp_session_id": "session-1"} + assert acp_agent.prompts == [("session-1", "hello")] + + +@pytest.mark.parametrize( + "error", + [ + RequestError(-32000, "backend failed"), + RequestError(-32601, "different missing method", {"method": "session/load"}), + ], +) +async def test_acp_provider_reraises_unexpected_set_model_errors( + error: RequestError, +) -> None: + acp_agent = SetModelErrorACPAgent(error) + _provider, model = _build_provider_and_model(acp_agent) + + with pytest.raises(RequestError): + await model.request( + [ModelRequest(parts=[UserPromptPart("hello")])], + None, + ModelRequestParameters(), + ) + + +async def test_acp_provider_custom_prompt_renderer_is_used_instead_of_default() -> None: + acp_agent = EchoACPAgent() + seen_message_counts: list[int] = [] + + def render(messages: Any, params: Any) -> list[Any]: + del params + seen_message_counts.append(len(messages)) + return [text_block("rendered by custom renderer")] + + _provider, model = _build_provider_and_model(acp_agent, prompt_renderer=render) + agent = Agent(model) + + result = await agent.run("ignored by custom renderer") + + assert seen_message_counts == [1] + assert acp_agent.prompts == [("session-1", "rendered by custom renderer")] + assert "acp echo: rendered by custom renderer" in result.output + + +async def test_acp_provider_custom_prompt_renderer_supports_async_callables() -> None: + acp_agent = EchoACPAgent() + + async def render(messages: Any, params: Any) -> list[Any]: + del messages, params + return [text_block("rendered async")] + + _provider, model = _build_provider_and_model(acp_agent, prompt_renderer=render) + agent = Agent(model) + + await agent.run("ignored") + + assert acp_agent.prompts == [("session-1", "rendered async")] + + +async def test_acp_provider_prefers_prompt_response_usage_over_host_updates() -> None: + acp_agent = EchoACPAgent( + usage=Usage( + input_tokens=11, + output_tokens=7, + cached_read_tokens=2, + cached_write_tokens=1, + thought_tokens=3, + total_tokens=24, + ), + ) + _provider, model = _build_provider_and_model(acp_agent) + agent = Agent(model) + + result = await agent.run("count my tokens") + + usage = result.usage + assert usage.input_tokens == 11 + assert usage.output_tokens == 7 + assert usage.cache_read_tokens == 2 + assert usage.cache_write_tokens == 1 + assert usage.details.get("reasoning_tokens") == 3 + + +@pytest.mark.parametrize( + ("stop_reason", "expected_finish_reason"), + [ + ("end_turn", "stop"), + ("max_tokens", "length"), + ("cancelled", "error"), + ("refusal", "stop"), + ("max_turn_requests", "stop"), + ], +) +async def test_acp_provider_maps_acp_stop_reasons_to_finish_reasons( + stop_reason: str, + expected_finish_reason: str, +) -> None: + acp_agent = EchoACPAgent( + stop_reason=cast( + Literal["end_turn", "max_tokens", "max_turn_requests", "refusal", "cancelled"], + stop_reason, + ) + ) + _provider, model = _build_provider_and_model(acp_agent) + + response = await model.request( + [ModelRequest(parts=[UserPromptPart("hello")])], + None, + ModelRequestParameters(), + ) + + assert response.finish_reason == expected_finish_reason + assert response.provider_details == {"acp_session_id": "session-1"} + + +async def test_acp_model_rejects_function_tools() -> None: + acp_agent = EchoACPAgent() + _provider, model = _build_provider_and_model(acp_agent) + + with pytest.raises(UserError, match="function tools"): + await model.request( + [ModelRequest(parts=[UserPromptPart("hello")])], + None, + ModelRequestParameters(function_tools=[ToolDefinition(name="do_thing")]), + ) + assert acp_agent.prompts == [] + + +async def test_acp_model_rejects_native_tools() -> None: + # AcpModel advertises no supported native tools, so pydantic-ai's own + # `Model.prepare_request` rejects the native tool before AcpModel's own + # `_ensure_supported_request` guard is ever reached. + acp_agent = EchoACPAgent() + _provider, model = _build_provider_and_model(acp_agent) + + with pytest.raises(UserError, match="(?i)native tool"): + await model.request( + [ModelRequest(parts=[UserPromptPart("hello")])], + None, + ModelRequestParameters(native_tools=[WebSearchTool()]), + ) + assert acp_agent.prompts == [] + + +def test_acp_model_own_guard_rejects_native_tools() -> None: + acp_agent = EchoACPAgent() + _provider, model = _build_provider_and_model(acp_agent) + + with pytest.raises(UserError, match="native tools directly"): + model._ensure_supported_request(ModelRequestParameters(native_tools=[WebSearchTool()])) + + +async def test_acp_model_rejects_disallowed_text_output() -> None: + acp_agent = EchoACPAgent() + _provider, model = _build_provider_and_model(acp_agent) + + with pytest.raises(UserError, match="text-response provider bridge"): + await model.request( + [ModelRequest(parts=[UserPromptPart("hello")])], + None, + ModelRequestParameters(allow_text_output=False), + ) + assert acp_agent.prompts == [] + + +async def test_acp_model_request_stream_yields_the_buffered_response_text() -> None: + acp_agent = EchoACPAgent() + _provider, model = _build_provider_and_model(acp_agent) + + async with model.request_stream( + [ModelRequest(parts=[UserPromptPart("stream this")])], + None, + ModelRequestParameters(), + ) as streamed_response: + async for _ in streamed_response: + pass + final_response = streamed_response.get() + + assert len(final_response.parts) == 1 + assert isinstance(final_response.parts[0], TextPart) + assert final_response.parts[0].content == "acp echo: stream this" + assert streamed_response.finish_reason == "stop" + + +async def test_acp_buffered_stream_skips_non_text_response_parts() -> None: + response = ModelResponse( + parts=[ToolCallPart(tool_name="lookup", args={})], + model_name="agent", + ) + stream = client_module._AcpBufferedStreamedResponse( + model_request_parameters=ModelRequestParameters(), + response=response, + ) + + events = [event async for event in stream] + await stream.close_stream() + + assert events == [] + assert stream.model_name == "agent" + + +async def test_acp_provider_switches_session_model_when_model_name_changes() -> None: + acp_agent = EchoACPAgent() + provider = AcpProvider(agent=cast(AcpAgent, acp_agent), cwd="/workspace") + first_model = AcpModel(model_name="model-a", provider=provider) + second_model = AcpModel(model_name="model-b", provider=provider) + + await Agent(first_model).run("first turn") + await Agent(second_model).run("second turn") + + # The ACP session is created once and reused; only the model selection changes. + assert acp_agent.session_cwds == ["/workspace"] + assert acp_agent.session_models == [("session-1", "model-a"), ("session-1", "model-b")] + + +async def test_acp_provider_forwards_client_capabilities_info_and_mcp_servers() -> None: + acp_agent = EchoACPAgent() + capabilities = ClientCapabilities() + client_info = Implementation(name="custom-client", version="9.9.9") + mcp_servers = [{"name": "demo"}] + + provider = AcpProvider( + agent=cast(AcpAgent, acp_agent), + cwd="/workspace", + client_capabilities=capabilities, + client_info=client_info, + mcp_servers=mcp_servers, + ) + model = AcpModel(model_name="zed-agent", provider=provider) + + await Agent(model).run("hello") + + assert acp_agent.client_capabilities is capabilities + assert acp_agent.client_info is client_info + assert acp_agent.mcp_servers_seen == [mcp_servers] + + +def test_acp_provider_model_profile_returns_the_shared_acp_profile() -> None: + provider = AcpProvider(agent=cast(AcpAgent, EchoACPAgent()), cwd="/workspace") + assert provider.model_profile("anything") is client_module.ACP_MODEL_PROFILE + + +def test_acp_model_supported_native_tools_is_empty() -> None: + assert AcpModel.supported_native_tools() == frozenset() + + +class NoHandshakeACPAgent: # type: ignore[misc] + """An ACP agent that never receives a reverse connection via ``on_connect``. + + This models an ACP agent implementation that does not implement the + optional ``on_connect`` hook. ``AcpProvider`` must still be constructible + and usable; the agent simply never observes host updates, so the resulting + model response carries no text. + """ + + async def initialize( + self, + protocol_version: int, + client_capabilities: ClientCapabilities | None = None, + client_info: Implementation | None = None, + **kwargs: Any, + ) -> InitializeResponse: + del client_capabilities, client_info, kwargs + return InitializeResponse( + protocol_version=protocol_version, + agent_info=Implementation(name="no-handshake-agent", version="test"), + agent_capabilities=AgentCapabilities(), + ) + + async def new_session( + self, + cwd: str, + mcp_servers: list[Any] | None = None, + **kwargs: Any, + ) -> NewSessionResponse: + del cwd, mcp_servers, kwargs + return NewSessionResponse(session_id="session-1") + + async def prompt( + self, + prompt: list[Any], + session_id: str, + message_id: str | None = None, + **kwargs: Any, + ) -> PromptResponse: + del prompt, session_id, message_id, kwargs + return PromptResponse(stop_reason="end_turn") # type: ignore[arg-type] + + +async def test_acp_provider_does_not_require_the_agent_to_support_on_connect() -> None: + acp_agent = NoHandshakeACPAgent() + provider = AcpProvider(agent=acp_agent, cwd="/workspace") # type: ignore + model = AcpModel(model_name="agent", provider=provider) + + response = await model.request( + [ModelRequest(parts=[UserPromptPart("hello")])], + None, + ModelRequestParameters(), + ) + + assert response.parts == [] + assert response.finish_reason == "stop" + assert response.provider_details == {"acp_session_id": "session-1"} + + +async def test_echo_acp_agent_requires_a_connected_host_client() -> None: + acp_agent = EchoACPAgent() + + with pytest.raises(AssertionError, match="connected to a host client"): + await acp_agent.prompt(prompt=[text_block("hello")], session_id="session-1") + + +# --- AcpHostBridge behavior (changed code) ------------------------------------------- + + +async def test_host_bridge_records_updates_without_a_delegate() -> None: + bridge = AcpHostBridge() + + await bridge.session_update( + session_id="session-1", + update=AgentMessageChunk(session_update="agent_message_chunk", content=text_block("hi")), + ) + + assert len(bridge.updates) == 1 + assert bridge.updates[0].session_id == "session-1" + assert bridge.updates[0].source is None + assert bridge.agent_message_text_since(0, session_id="session-1") == "hi" + + +async def test_host_bridge_ignores_agent_message_chunks_without_text_content() -> None: + class FakeChunk: + session_update = "agent_message_chunk" + content = object() + + bridge = AcpHostBridge() + + await bridge.session_update( + session_id="session-1", + update=FakeChunk(), + ) + + assert bridge.agent_message_text_since(0, session_id="session-1") == "" + + +async def test_host_bridge_forwards_session_update_to_delegate_when_present() -> None: + delegate = RecordingClient() + bridge = AcpHostBridge(delegate=delegate) + update = AgentMessageChunk(session_update="agent_message_chunk", content=text_block("hi")) + + await bridge.session_update(session_id="session-1", update=update) + + assert bridge.updates[0].update is update + assert delegate.updates == [("session-1", update)] + + +@pytest.mark.parametrize( + "call", + [ + lambda bridge: bridge.request_permission( + options=[PermissionOption(kind="allow_once", name="Allow", option_id="allow")], + session_id="session-1", + tool_call=ToolCallUpdate(tool_call_id="call-1"), + ), + lambda bridge: bridge.write_text_file( + content="data", path="/tmp/f", session_id="session-1" + ), + lambda bridge: bridge.read_text_file(path="/tmp/f", session_id="session-1"), + lambda bridge: bridge.create_terminal(command="ls", session_id="session-1"), + lambda bridge: bridge.ext_method(method="custom/thing", params={}), + ], +) +async def test_host_bridge_raises_without_a_delegate_for_host_methods(call: Any) -> None: + bridge = AcpHostBridge() + + with pytest.raises(RuntimeError, match="no host client delegate"): + await call(bridge) + + +async def test_host_bridge_ext_notification_is_a_noop_without_a_delegate() -> None: + bridge = AcpHostBridge() + + await bridge.ext_notification(method="custom/notify", params={}) + + +async def test_host_bridge_supports_sync_delegate_methods() -> None: + class SyncExtensionClient: + def ext_method(self, method: str, params: dict[str, Any]) -> dict[str, Any]: + return {"method": method, "params": params} + + bridge = AcpHostBridge(delegate=cast(AcpClient, SyncExtensionClient())) + + result = await bridge.ext_method(method="custom/sync", params={"x": 1}) + bridge.on_connect(cast(AcpAgent, object())) + + assert result == {"method": "custom/sync", "params": {"x": 1}} + + +async def test_host_bridge_delegates_filesystem_and_terminal_calls_to_host_client() -> None: + delegate = HostRecordingClient() + bridge = AcpHostBridge(delegate=delegate) + + write_response = await bridge.write_text_file( + content="hello", path="/tmp/f", session_id="session-1" + ) + read_response = await bridge.read_text_file(path="/tmp/f", session_id="session-1") + terminal_response = await bridge.create_terminal(command="ls", session_id="session-1") + + assert write_response is delegate.write_response + assert read_response.content == "file:/tmp/f:None:None" + assert terminal_response.terminal_id == "terminal-1" + assert delegate.write_calls == [("session-1", "/tmp/f", "hello")] + assert delegate.read_calls == [("session-1", "/tmp/f", None, None)] + + +async def test_host_bridge_delegates_request_permission_to_host_client() -> None: + delegate = RecordingClient() + delegate.queue_permission_selected("allow") + bridge = AcpHostBridge(delegate=delegate) + + response = await bridge.request_permission( + options=[PermissionOption(kind="allow_once", name="Allow", option_id="allow")], + session_id="session-1", + tool_call=ToolCallUpdate(tool_call_id="call-1"), + ) + + assert isinstance(response.outcome, AllowedOutcome) + assert response.outcome.option_id == "allow" + + +async def test_host_bridge_on_connect_forwards_to_delegate_when_supported() -> None: # type: ignore[misc] + delegate = RecordingClient() + bridge = AcpHostBridge(delegate=delegate) + connected: list[Any] = [] + + def on_connect_handler(conn: Any) -> None: + connected.append(conn) + + cast(Any, delegate).on_connect = on_connect_handler + + sentinel_agent = cast(AcpAgent, object()) + bridge.on_connect(sentinel_agent) + + assert connected == [sentinel_agent] + + +async def test_host_bridge_delegates_terminal_lifecycle_calls_to_host_client() -> None: + delegate = HostRecordingClient() + bridge = AcpHostBridge(delegate=delegate) + + output = await bridge.terminal_output(session_id="session-1", terminal_id="terminal-1") + release = await bridge.release_terminal(session_id="session-1", terminal_id="terminal-1") + wait = await bridge.wait_for_terminal_exit(session_id="session-1", terminal_id="terminal-1") + kill = await bridge.kill_terminal(session_id="session-1", terminal_id="terminal-1") + + assert output.output == "terminal-output" + assert release is delegate.release_response + assert wait.exit_code == 0 + assert kill is delegate.kill_response + assert delegate.output_calls == [("session-1", "terminal-1")] + assert delegate.release_calls == [("session-1", "terminal-1")] + assert delegate.wait_calls == [("session-1", "terminal-1")] + assert delegate.kill_calls == [("session-1", "terminal-1")] + + +class ExtensionRecordingClient(RecordingClient): + """A host client double that actually answers ACP extension calls.""" + + def __init__(self) -> None: + super().__init__() + self.ext_method_calls: list[tuple[str, dict[str, Any]]] = [] + self.ext_notification_calls: list[tuple[str, dict[str, Any]]] = [] + + async def ext_method(self, method: str, params: dict[str, Any]) -> dict[str, Any]: + self.ext_method_calls.append((method, params)) + return {"ok": True} + + async def ext_notification(self, method: str, params: dict[str, Any]) -> None: + self.ext_notification_calls.append((method, params)) + + +async def test_host_bridge_delegates_extension_calls_to_host_client() -> None: + delegate = ExtensionRecordingClient() + bridge = AcpHostBridge(delegate=delegate) + + result = await bridge.ext_method(method="custom/thing", params={"x": 1}) + await bridge.ext_notification(method="custom/notify", params={"y": 2}) + + assert result == {"ok": True} + assert delegate.ext_method_calls == [("custom/thing", {"x": 1})] + assert delegate.ext_notification_calls == [("custom/notify", {"y": 2})] + + +# --- Pure helper functions (changed code) -------------------------------------------- + + +def test_usage_from_acp_extracts_token_counts_and_reasoning_tokens() -> None: + usage = client_module._usage_from_acp( + Usage( + input_tokens=10, + output_tokens=5, + cached_read_tokens=2, + cached_write_tokens=1, + thought_tokens=4, + total_tokens=18, + ), + ) + + assert usage.input_tokens == 10 + assert usage.output_tokens == 5 + assert usage.cache_read_tokens == 2 + assert usage.cache_write_tokens == 1 + assert usage.details == {"reasoning_tokens": 4} + + +def test_usage_from_acp_returns_empty_usage_for_none() -> None: + usage = client_module._usage_from_acp(None) + + assert not usage.has_values() + + +def test_default_render_prompt_blocks_covers_system_tool_and_retry_parts() -> None: + request = ModelRequest( + parts=[ + SystemPromptPart("Be terse."), + UserPromptPart("What is the status?"), + ToolReturnPart(tool_name="check_status", content="ok", tool_call_id="call-1"), + RetryPromptPart( + content="please retry", tool_name="check_status", tool_call_id="call-1" + ), + ], + ) + + blocks = client_module._default_render_prompt_blocks([request], ModelRequestParameters()) + + assert len(blocks) == 1 + rendered = blocks[0].text + assert "System:\nBe terse." in rendered + assert "What is the status?" in rendered + assert "Tool result: check_status" in rendered + assert "please retry" in rendered + + +def test_default_render_prompt_blocks_covers_instructions_and_full_history_roles() -> None: + request = ModelRequest( + parts=[UserPromptPart("What changed?")], + instructions="Answer as release notes.", + ) + response = ModelResponse(parts=[TextPart("The bridge was added.")]) + + blocks = client_module._default_render_prompt_blocks( + [request, response], + ModelRequestParameters(), + history_mode="full", + ) + + assert len(blocks) == 1 + rendered = blocks[0].text + assert "" in rendered + assert "Instructions:\nAnswer as release notes." in rendered + assert "" in rendered + assert "The bridge was added." in rendered + + +def test_default_render_prompt_blocks_covers_media_user_content() -> None: + request = ModelRequest( + parts=[ + UserPromptPart( + content=[ + "Look at this:", + TextContent("typed text"), + ImageUrl(url="https://example.com/x.png"), + BinaryContent(data=b"abc", media_type="text/plain"), + UploadedFile(file_id="file-1", provider_name="openai"), + ], + ), + ], + ) + + blocks = client_module._default_render_prompt_blocks([request], ModelRequestParameters()) + + rendered = blocks[0].text + assert "Look at this:" in rendered + assert "typed text" in rendered + assert "[image-url:https://example.com/x.png]" in rendered + assert "[binary:text/plain:3 bytes]" in rendered + assert "[uploaded-file:openai:file-1]" in rendered + + +def test_default_render_prompt_blocks_falls_back_to_message_text_without_a_request() -> None: + # No `ModelRequest` is present, so rendering must fall back to `message.text` + # instead of the request-part renderer. + response = ModelResponse(parts=[TextPart("previous turn output")]) + + blocks = client_module._default_render_prompt_blocks([response], ModelRequestParameters()) + + assert len(blocks) == 1 + assert blocks[0].text == "previous turn output" + + +def test_default_render_prompt_blocks_returns_nothing_for_empty_messages() -> None: + assert client_module._default_render_prompt_blocks([], ModelRequestParameters()) == [] + + +def test_default_render_prompt_blocks_returns_nothing_for_blank_latest_message() -> None: + response = ModelResponse(parts=[TextPart(" ")]) + + blocks = client_module._default_render_prompt_blocks([response], ModelRequestParameters()) + + assert len(blocks) == 1 + assert blocks[0].text == "\n \nassistant>" + + +def test_default_render_prompt_blocks_ignores_unrendered_request_parts() -> None: + request = ModelRequest(parts=cast(Any, [InstructionPart("internal instruction")])) + + assert client_module._default_render_prompt_blocks([request], ModelRequestParameters()) == [] + + +def test_default_render_prompt_blocks_returns_nothing_for_blank_full_history() -> None: + response = ModelResponse(parts=[]) + + assert ( + client_module._default_render_prompt_blocks( + [response], + ModelRequestParameters(), + history_mode="full", + ) + == [] + ) + + +def test_render_user_content_item_falls_back_to_runtime_kind() -> None: + class UnknownContent: + kind = "custom-content" + + assert ( + client_module._render_user_content_item(cast(Any, UnknownContent())) == "[custom-content]" + ) + + +def test_section_returns_empty_text_for_blank_content() -> None: + assert client_module._section("Empty", " \n ") == "" + + +def test_is_agent_message_chunk_supports_duck_typed_updates() -> None: + class FakeChunkLike: + session_update = "agent_message_chunk" + + assert client_module._is_agent_message_chunk(FakeChunkLike()) is True + assert client_module._is_agent_message_chunk(object()) is False + + +def test_extract_text_recursively_collects_supported_response_shapes() -> None: + class AttrResponse: + response = "attr text" + + chunk = AgentMessageChunk( + session_update="agent_message_chunk", + content=text_block("chunk text"), + ) + + extracted = client_module._extract_text( + [ + None, + "literal text", + chunk, + {"content": ["nested text", {"text": "dict text"}]}, + AttrResponse(), + ], + ) + + assert extracted == "literal textchunk textnested textdict textattr text" + + +def test_response_field_supports_dict_attr_and_missing_values() -> None: + class AttrResponse: + message = "attr message" + + assert client_module._response_field({"message": "dict message"}, "message") == "dict message" + assert client_module._response_field(AttrResponse(), "message") == "attr message" + assert client_module._response_field(object(), "message") is None + + +# --- Prior (pre-existing) server adapter behavior path -------------------------------- + + +async def test_prior_server_adapter_direction_still_works_standalone() -> None: + """Regression guard: the original ACP server adapter direction is unaffected. + + This PR adds the inverse client/provider bridge, but the original + ``create_acp_agent`` direction (exposing a ``pydantic_ai.Agent`` over ACP) + must keep working exactly as it did before this change. + """ + adapter = create_acp_agent(agent=Agent(TestModel(custom_output_text="Hello from ACP"))) + client = RecordingClient() + adapter.on_connect(client) + + await adapter.initialize(protocol_version=PROTOCOL_VERSION) + new_session_response = await adapter.new_session(cwd="/workspace", mcp_servers=[]) + prompt_response = await adapter.prompt( + prompt=[text_block("Summarize the change.")], + session_id=new_session_response.session_id, + message_id="user-message-1", + ) + + assert prompt_response.stop_reason == "end_turn" + agent_updates = [ + update for _, update in client.updates if isinstance(update, AgentMessageChunk) + ] + assert "".join(chunk.content.text for chunk in agent_updates) == "Hello from ACP" + + +async def test_prior_server_adapter_can_be_consumed_through_new_client_provider() -> None: + """The new AcpProvider/AcpModel bridge composes with the pre-existing server adapter. + + A Pydantic AI agent is exposed via the original ``create_acp_agent`` adapter + (prior, unchanged behavior) and then that very adapter is wrapped by the new + ``AcpProvider`` (this PR's change) so a *second* Pydantic AI agent can run + against it as a plain provider/model. This proves both directions interoperate. + """ + inner_model = TestModel(custom_output_text="Hello from ACP") + server_adapter = create_acp_agent(agent=Agent(inner_model)) + + _provider, model = _build_provider_and_model(server_adapter, model_name=inner_model.model_name) + outer_agent = Agent(model) + + result = await outer_agent.run("Ping the bridge") + + assert result.output == "Hello from ACP" + + +# --- Additional coverage: AcpHostBridge pagination/session scoping ------------------ + + +async def test_host_bridge_records_since_scopes_by_session_and_supports_snapshots() -> None: + bridge = AcpHostBridge() + first_update = AgentMessageChunk(session_update="agent_message_chunk", content=text_block("a")) + second_update = AgentMessageChunk(session_update="agent_message_chunk", content=text_block("b")) + + await bridge.session_update(session_id="session-1", update=first_update) + snapshot = bridge.snapshot_index() + await bridge.session_update(session_id="session-2", update=second_update) + + all_records = bridge.records_since(0) + assert [record.update for record in all_records] == [first_update, second_update] + + only_new = bridge.records_since(snapshot) + assert [record.update for record in only_new] == [second_update] + + only_session_1 = bridge.records_since(0, session_id="session-1") + assert [record.update for record in only_session_1] == [first_update] + + only_session_2_after_snapshot = bridge.records_since(snapshot, session_id="session-2") + assert [record.update for record in only_session_2_after_snapshot] == [second_update] + + +async def test_host_bridge_usage_update_since_ignores_real_acp_usage_update_without_usage_field() -> ( + None +): + # The real ACP `UsageUpdate` schema carries context-window `size`/`used` fields, not a + # `usage` attribute. `usage_update_since` only reads `getattr(update, "usage", None)`, so + # recording a genuine `UsageUpdate` must not populate any token counts. + bridge = AcpHostBridge() + start_index = bridge.snapshot_index() + + await bridge.session_update( + session_id="session-1", + update=UsageUpdate(session_update="usage_update", size=1000, used=10), + ) + + usage = bridge.usage_update_since(start_index, session_id="session-1") + + assert not usage.has_values() + + +# --- Additional coverage: AcpProvider host_client delegate wiring ------------------- + + +async def test_acp_provider_forwards_host_client_delegate_updates_end_to_end() -> None: + delegate = HostRecordingClient() + acp_agent = EchoACPAgent() + provider = AcpProvider( + agent=cast(AcpAgent, acp_agent), + cwd="/workspace", + host_client=delegate, + ) + + assert provider.host.delegate is delegate + + model = AcpModel(model_name="zed-agent", provider=provider) + result = await Agent(model).run("hello via delegate") + + assert "acp echo: hello via delegate" in result.output + forwarded_updates = [ + update for _, update in delegate.updates if isinstance(update, AgentMessageChunk) + ] + assert len(forwarded_updates) == 1 + assert forwarded_updates[0].content.text == "acp echo: hello via delegate" + + +# --- Additional coverage: pure helper edge cases ------------------------------------- + + +def test_finish_reason_from_acp_returns_stop_when_stop_reason_is_none() -> None: + assert client_module._finish_reason_from_acp(None) == "stop" + + +def test_render_tool_return_falls_back_to_tool_call_id_when_tool_name_is_empty() -> None: + part = ToolReturnPart(tool_name="", content="ok", tool_call_id="call-42") + + rendered = client_module._render_tool_return(part) + + assert rendered == "Tool result: call-42:\nok" + + +# --- Additional coverage: root workspace pyproject.toml dependency ----------------- + + +def test_root_pyproject_declares_pydantic_ai_v2_dependency() -> None: + root_pyproject = Path("pyproject.toml") + data: dict[str, Any] = tomllib.loads(root_pyproject.read_text()) + dependencies: list[str] = data["project"]["dependencies"] + + assert any(dependency.startswith("pydantic-ai>=2.4.0") for dependency in dependencies) + + +def test_pydantic_acp_pins_agent_client_protocol_version_used_by_client_module() -> None: + package_pyproject = Path("packages/adapters/pydantic-acp/pyproject.toml") + data: dict[str, Any] = tomllib.loads(package_pyproject.read_text()) + dependencies: list[str] = data["project"]["dependencies"] + + assert "agent-client-protocol==0.9.0" in dependencies + + +# --- Additional coverage: public package exports for the client bridge (__init__.py) ----- + + +def test_acp_client_provider_symbols_are_exported_from_the_top_level_package() -> None: + for name in ( + "ACP_MODEL_PROFILE", + "AcpHostBridge", + "AcpModel", + "AcpPromptRenderer", + "AcpProvider", + "AcpUpdateRecord", + ): + assert name in pydantic_acp.__all__ + assert getattr(pydantic_acp, name) is getattr(client_module, name) + + +def test_acp_model_profile_disables_tool_and_structured_output_support() -> None: + profile = pydantic_acp.ACP_MODEL_PROFILE + + assert profile["supports_tools"] is False + assert profile["supports_json_schema_output"] is False + assert profile["supports_json_object_output"] is False + assert profile["supports_image_output"] is False + assert profile["supported_native_tools"] == frozenset() diff --git a/tests/pydantic/test_adapter_helpers.py b/tests/pydantic/test_adapter_helpers.py index 13867c2..d753d8e 100644 --- a/tests/pydantic/test_adapter_helpers.py +++ b/tests/pydantic/test_adapter_helpers.py @@ -92,8 +92,8 @@ def _stored_session(adapter: Any, session_id: str) -> Any: def _fake_run_result(output: Any) -> Any: return SimpleNamespace( output=output, - new_messages=lambda: [], - all_messages=lambda: [], + new_messages=list, + all_messages=list, all_messages_json=lambda: b"[]", ) @@ -115,7 +115,7 @@ def test_session_model_selection_respects_provider_and_fallback_state( response = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) session = _stored_session(adapter, response.session_id) - cast(Any, agent).model = _INVALID_TEST_VALUE + cast("Any", agent).model = _INVALID_TEST_VALUE session.session_model_id = None model_state = asyncio.run(adapter._get_model_selection_state(session, agent)) assert model_state is None @@ -136,8 +136,8 @@ def test_session_model_selection_respects_provider_and_fallback_state( AdapterModel( model_id="model-a", name="Model A", - override=cast(Any, selected_agent.model), - ) + override=cast("Any", selected_agent.model), + ), ], ), ) @@ -145,12 +145,11 @@ def test_session_model_selection_respects_provider_and_fallback_state( assert selected_adapter._resolve_current_model_id(session, selected_agent) == "selected-model" assert selected_adapter._resolve_model_id_from_value(selected_agent.model) == "model-a" assert selected_adapter._resolve_model_id_from_value("plain-model") == "plain-model" - assert selected_adapter._resolve_model_id_from_value(cast(Any, _INVALID_TEST_VALUE)) is None + assert selected_adapter._resolve_model_id_from_value(cast("Any", _INVALID_TEST_VALUE)) is None class DemoModelsProvider: def set_model(self, session, agent, model_id): del session, agent, model_id - return None def get_model_state(self, session, agent): del session, agent @@ -170,18 +169,18 @@ def get_model_state(self, session, agent): provider_session = _stored_session(provider_adapter, provider_response.session_id) provider_session.config_values["model"] = "stale" set_response = asyncio.run( - provider_adapter.set_session_model("provider-model", provider_response.session_id) + provider_adapter.set_session_model("provider-model", provider_response.session_id), ) assert set_response is not None assert provider_session.session_model_id is None provider_state = asyncio.run( - provider_adapter._get_model_selection_state(provider_session, agent) + provider_adapter._get_model_selection_state(provider_session, agent), ) assert provider_state is not None assert provider_state.current_model_id is None missing_response = asyncio.run( - provider_adapter.set_session_model("missing", provider_response.session_id) + provider_adapter.set_session_model("missing", provider_response.session_id), ) assert missing_response is not None assert "model" not in provider_session.config_values @@ -191,7 +190,6 @@ def test_session_mode_and_config_updates_flow_through_providers(tmp_path: Path) class DemoModesProvider: def set_mode(self, session, agent, mode_id): del session, agent, mode_id - return None def get_mode_state(self, session, agent): del session, agent @@ -203,28 +201,25 @@ def get_mode_state(self, session, agent): class EmptyConfigProvider: def set_config_option(self, session, agent, config_id, value): del session, agent, config_id, value - return None def get_config_options(self, session, agent): del session, agent - return None class MatchingConfigProvider: def set_config_option(self, session, agent, config_id, value): del session, agent, config_id, value - return None def get_config_options(self, session, agent): del session, agent return cast( - Any, + "Any", [ SessionConfigOptionBoolean( id="flag", name="Flag", type="boolean", current_value=False, - ) + ), ], ) @@ -266,7 +261,7 @@ def get_config_options(self, session, agent): ) matching_response = asyncio.run(matching_adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) config_response = asyncio.run( - matching_adapter.set_config_option("flag", matching_response.session_id, True) + matching_adapter.set_config_option("flag", matching_response.session_id, True), ) assert config_response is not None @@ -291,7 +286,7 @@ def persist_plan_state(self, session, agent, entries, plan_markdown): name="Plan", prepare_func=pass_through, plan_mode=True, - ) + ), ], ) agent = Agent(TestModel(custom_output_text="plan"), output_type=str) @@ -334,14 +329,14 @@ def persist_plan_state(self, session, agent, entries, plan_markdown): assert adapter._format_native_plan(session) == "No plan has been recorded yet." session.plan_entries = [ - PlanEntry(content="Inspect", priority="medium", status="pending").model_dump(mode="json") + PlanEntry(content="Inspect", priority="medium", status="pending").model_dump(mode="json"), ] assert "Inspect" in adapter._format_native_plan(session) adapter._install_native_plan_tools(agent) tools = agent._function_toolset.tools - get_plan_tool = cast(Any, tools["acp_get_plan"]) - set_plan_tool = cast(Any, tools["acp_set_plan"]) + get_plan_tool = cast("Any", tools["acp_get_plan"]) + set_plan_tool = cast("Any", tools["acp_set_plan"]) assert get_plan_tool.function() == "No plan has been recorded yet." assert persisted_states[-1] == (["Write the plan"], "# Plan") assert get_plan_tool.prepare(None, get_plan_tool.function_schema) is not None @@ -363,7 +358,7 @@ def pass_through(ctx, tool_defs): name="Plan", prepare_func=pass_through, plan_mode=True, - ) + ), ], ) agent = Agent(TestModel(custom_output_text="plan"), output_type=str) @@ -391,7 +386,7 @@ def pass_through(ctx, tool_defs): adapter._install_native_plan_tools(agent) set_active_session(agent, session) tools = agent._function_toolset.tools - set_plan_tool = cast(Any, tools["acp_set_plan"]) + set_plan_tool = cast("Any", tools["acp_set_plan"]) assert set_plan_tool.prepare(None, set_plan_tool.function_schema) is not None @@ -423,7 +418,7 @@ def get_model_state(self, session, agent): model_id="demo-model", name="Demo Model", override=TestModel(custom_output_text="demo"), - ) + ), ], ) @@ -436,7 +431,7 @@ def set_model(self, session, agent, model_id): model_id=model_id, name="Configured Model", override=TestModel(custom_output_text="configured"), - ) + ), ], ) @@ -464,7 +459,7 @@ def get_config_options(self, session, agent) -> list[ConfigOption]: name="Flag", type="boolean", current_value=False, - ) + ), ] def set_config_option( @@ -483,7 +478,7 @@ def set_config_option( name="Flag", type="boolean", current_value=value, - ) + ), ] class PromptOverrideProvider: @@ -495,7 +490,6 @@ def get_prompt_model_override( model_override, ): del session, agent, prompt, model_override - return None agent = Agent(TestModel(custom_output_text="ok")) adapter = _adapter( @@ -518,7 +512,7 @@ def get_prompt_model_override( agent, prompt=[text_block("hi")], model_override=None, - ) + ), ) is None ) @@ -539,7 +533,7 @@ def get_prompt_model_override( cwd=str(tmp_path), session_id=response.session_id, mcp_servers=[], - ) + ), ).modes is not None ) @@ -598,7 +592,7 @@ def test_runtime_model_restore_and_error_paths_are_handled( agent=agent, config=AdapterConfig( session_store=MemorySessionStore(), - approval_bridge=cast(Any, _INVALID_TEST_VALUE), + approval_bridge=cast("Any", _INVALID_TEST_VALUE), ), ) response = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) @@ -623,7 +617,7 @@ def test_runtime_model_restore_and_error_paths_are_handled( assert session.config_values["model"] == default_model_id session.session_model_id = None - cast(Any, agent).model = _INVALID_TEST_VALUE + cast("Any", agent).model = _INVALID_TEST_VALUE assert asyncio.run(adapter._resolve_model_override(session, agent)) is None with pytest.raises(RequestError): @@ -632,12 +626,14 @@ def test_runtime_model_restore_and_error_paths_are_handled( adapter._resolve_runtime_model(agent, model_override="not a model id\n") with pytest.raises(RequestError): - asyncio.run(adapter._resolve_deferred_approvals(session=session, requests=cast(Any, None))) + asyncio.run( + adapter._resolve_deferred_approvals(session=session, requests=cast("Any", None)), + ) assert asyncio.run(adapter._record_cancelled_approval(session, None)) is None assert ( asyncio.run( - adapter._handle_slash_command("unknown", argument=None, session=session, agent=agent) + adapter._handle_slash_command("unknown", argument=None, session=session, agent=agent), ) is None ) @@ -668,7 +664,7 @@ def test_sessions_normalize_cwd_and_serialize_mcp_servers(tmp_path: Path) -> Non AdapterModel( model_id="default:test", name="Default", - override=cast(Any, agent.model), + override=cast("Any", agent.model), ), ], session_store=MemorySessionStore(), @@ -732,7 +728,7 @@ async def fake_stream_run(*args: Any, **kwargs: Any) -> tuple[Any, bool]: agent=agent, prompt=[text_block("stream please")], session=session, - ) + ), ) assert outcome.result.output == "streamed" assert outcome.streamed_output is True @@ -743,13 +739,13 @@ async def fake_run(prompt_text: str | None, **kwargs: Any) -> Any: del prompt_text, kwargs return _fake_run_result("plain") - cast(Any, agent).run = fake_run + cast("Any", agent).run = fake_run outcome = asyncio.run( adapter._run_prompt( agent=agent, prompt=[text_block("plain please")], session=session, - ) + ), ) assert outcome.result.output == "plain" assert outcome.streamed_output is False @@ -763,33 +759,33 @@ async def flaky_run(prompt_text: str | None, **kwargs: Any) -> Any: raise UserError("broken model") return _fake_run_result("recovered") - cast(Any, agent).run = flaky_run + cast("Any", agent).run = flaky_run monkeypatch.setattr(adapter, "_restore_default_model", lambda *args, **kwargs: True) outcome = asyncio.run( adapter._run_prompt( agent=agent, prompt=[text_block("recover please")], session=session, - ) + ), ) assert outcome.result.output == "recovered" no_bridge_result = _fake_run_result( - DeferredToolRequests(approvals=[ToolCallPart("approval-only", {"x": 1})]) + DeferredToolRequests(approvals=[ToolCallPart("approval-only", {"x": 1})]), ) async def no_bridge_run(prompt_text: str | None, **kwargs: Any) -> Any: del prompt_text, kwargs return no_bridge_result - cast(Any, agent).run = no_bridge_run + cast("Any", agent).run = no_bridge_run monkeypatch.setattr(adapter, "_supports_deferred_approval_bridge", lambda: False) no_bridge_outcome = asyncio.run( adapter._run_prompt( agent=agent, prompt=[text_block("approval please")], session=session, - ) + ), ) assert no_bridge_outcome.stop_reason == "end_turn" @@ -797,7 +793,7 @@ async def no_bridge_run(prompt_text: str | None, **kwargs: Any) -> Any: agent=agent, config=AdapterConfig( session_store=MemorySessionStore(), - approval_bridge=cast(Any, _INVALID_TEST_VALUE), + approval_bridge=cast("Any", _INVALID_TEST_VALUE), enable_generic_tool_projection=False, ), ) @@ -810,26 +806,26 @@ async def calls_present_run(prompt_text: str | None, **kwargs: Any) -> Any: DeferredToolRequests( calls=[ToolCallPart("needs-call", {"x": 1})], approvals=[ToolCallPart("needs-approval", {"y": 2})], - ) + ), ) - cast(Any, agent).run = calls_present_run + cast("Any", agent).run = calls_present_run bridge_outcome = asyncio.run( bridge_adapter._run_prompt( agent=agent, prompt=[text_block("calls please")], session=bridge_session, - ) + ), ) assert bridge_outcome.stop_reason == "end_turn" async def approval_loop_run(prompt_text: str | None, **kwargs: Any) -> Any: del prompt_text, kwargs return _fake_run_result( - DeferredToolRequests(approvals=[ToolCallPart("approval", {"z": 3})]) + DeferredToolRequests(approvals=[ToolCallPart("approval", {"z": 3})]), ) - cast(Any, agent).run = approval_loop_run + cast("Any", agent).run = approval_loop_run async def unresolved_approvals(**kwargs: Any) -> Any: del kwargs @@ -850,7 +846,7 @@ async def unresolved_approvals(**kwargs: Any) -> Any: agent=agent, prompt=[text_block("loop please")], session=bridge_session, - ) + ), ) async def empty_stream(prompt_text: str | None, **kwargs: Any): @@ -858,7 +854,7 @@ async def empty_stream(prompt_text: str | None, **kwargs: Any): yield FunctionToolResultEvent(RetryPromptPart("retry", tool_name=None)) yield FunctionToolResultEvent(ToolReturnPart("final_result", "done")) - cast(Any, agent).run_stream_events = empty_stream + cast("Any", agent).run_stream_events = empty_stream with pytest.raises(RequestError): asyncio.run( type(adapter)._run_prompt_with_events( @@ -867,7 +863,7 @@ async def empty_stream(prompt_text: str | None, **kwargs: Any): prompt_input="stream", run_kwargs={}, session=session, - ) + ), ) @@ -911,7 +907,7 @@ async def record_bridge_updates(_session: Any, _agent: Any) -> None: result=_fake_run_result("streamed"), model_override=None, run_output_type=None, - ) + ), ) is None ) @@ -921,7 +917,7 @@ async def retry_only_stream(prompt_text: str | None, **kwargs: Any): del prompt_text, kwargs yield FunctionToolResultEvent(RetryPromptPart("retry", tool_name=None)) - cast(Any, agent).run_stream_events = retry_only_stream + cast("Any", agent).run_stream_events = retry_only_stream with pytest.raises(RequestError): asyncio.run( type(adapter)._run_prompt_with_events( @@ -930,7 +926,7 @@ async def retry_only_stream(prompt_text: str | None, **kwargs: Any): prompt_input="stream", run_kwargs={}, session=session, - ) + ), ) @@ -976,7 +972,7 @@ async def record_bridge_updates(_session: Any, _agent: Any) -> None: result=_fake_run_result("streamed"), model_override=None, run_output_type=None, - ) + ), ) assert len(recorded_updates) == 1 @@ -1014,7 +1010,7 @@ async def blocking_run_prompt(*, agent: Any, prompt: Any, session: Any) -> Any: prompt=[text_block("Long running task")], session_id=response.session_id, message_id="cancelled-user-message", - ) + ), ) await started.wait() @@ -1052,7 +1048,7 @@ def test_prompt_emits_derived_title_without_session_metadata(tmp_path: Path) -> prompt=[text_block("Explain TCP slow start")], session_id=session.session_id, message_id="title-message", - ) + ), ) title_updates = [ @@ -1087,7 +1083,7 @@ async def failing_execute(**kwargs: Any) -> Any: agent=agent, prompt=[text_block("recover")], session=session, - ) + ), ) assert adapter._build_run_kwargs( @@ -1108,12 +1104,12 @@ async def failing_execute(**kwargs: Any) -> Any: adapter._config.approval_bridge = None assert adapter._build_run_output_type(agent, session=session) is None assert adapter._contains_text_output(NativePlanGeneration) is True - assert adapter._contains_text_output(cast(Any, _INVALID_TEST_VALUE)) is False + assert adapter._contains_text_output(cast("Any", _INVALID_TEST_VALUE)) is False assert adapter._contains_native_plan_generation([int, NativePlanGeneration]) is True assert adapter._contains_native_plan_generation([int, float]) is False tool_start_event = PartStartEvent(index=0, part=ToolCallPart("echo", {"text": "hi"})) - tool_delta_event = PartDeltaEvent(index=0, delta=cast(Any, _INVALID_TEST_VALUE)) + tool_delta_event = PartDeltaEvent(index=0, delta=cast("Any", _INVALID_TEST_VALUE)) assert adapter._text_chunk_from_event(tool_start_event) is None assert adapter._text_chunk_from_event(tool_delta_event) is None assert ( @@ -1130,7 +1126,7 @@ async def failing_execute(**kwargs: Any) -> Any: adapter._prompt_runtime._replace_native_plan_entry(session, index=1, status="completed") session.plan_entries = [ - PlanEntry(content="Pending task", priority="low", status="pending").model_dump(mode="json") + PlanEntry(content="Pending task", priority="low", status="pending").model_dump(mode="json"), ] with pytest.raises(RequestError): adapter._prompt_runtime._replace_native_plan_entry(session, index=2, status="completed") @@ -1155,10 +1151,10 @@ async def failing_execute(**kwargs: Any) -> Any: ) tool_adapter._install_native_plan_tools(tool_agent) tools = tool_agent._function_toolset.tools - get_plan_tool = cast(Any, tools["acp_get_plan"]) - set_plan_tool = cast(Any, tools["acp_set_plan"]) - update_plan_tool = cast(Any, tools["acp_update_plan_entry"]) - mark_done_tool = cast(Any, tools["acp_mark_plan_done"]) + get_plan_tool = cast("Any", tools["acp_get_plan"]) + set_plan_tool = cast("Any", tools["acp_set_plan"]) + update_plan_tool = cast("Any", tools["acp_update_plan_entry"]) + mark_done_tool = cast("Any", tools["acp_mark_plan_done"]) session.config_values["mode"] = "ask" assert get_plan_tool.prepare(None, get_plan_tool.function_schema) is None @@ -1172,7 +1168,7 @@ async def retry_and_output_stream(prompt_text: str | None, **kwargs: Any): yield FunctionToolResultEvent(RetryPromptPart("retry", tool_name="output")) yield FunctionToolResultEvent(ToolReturnPart("final_result", "done")) - cast(Any, agent).run_stream_events = retry_and_output_stream + cast("Any", agent).run_stream_events = retry_and_output_stream with pytest.raises(RequestError): asyncio.run( type(adapter)._run_prompt_with_events( @@ -1181,7 +1177,7 @@ async def retry_and_output_stream(prompt_text: str | None, **kwargs: Any): prompt_input="stream", run_kwargs={}, session=session, - ) + ), ) @@ -1203,8 +1199,8 @@ def test_native_plan_additional_instructions_append_without_replacing_core_guida session.plan_entries = [ PlanEntry(content="Inspect repo", priority="medium", status="pending").model_dump( - mode="json" - ) + mode="json", + ), ] rendered = adapter._format_native_plan(session) @@ -1233,9 +1229,9 @@ def test_native_plan_runtime_covers_empty_state_and_markdown_only_paths( description="Structured plan mode.", prepare_func=lambda ctx, tool_defs: list(tool_defs), plan_mode=True, - ) + ), ], - ) + ), ], native_plan_additional_instructions="Keep the plan reviewable.", session_store=MemorySessionStore(), @@ -1280,9 +1276,9 @@ def test_native_plan_tool_prepare_paths_cover_transient_session_loss( description="Execution mode with plan progress tools.", prepare_func=lambda ctx, tool_defs: list(tool_defs), plan_tools=True, - ) + ), ], - ) + ), ], session_store=MemorySessionStore(), ), @@ -1291,8 +1287,8 @@ def test_native_plan_tool_prepare_paths_cover_transient_session_loss( session = _stored_session(tool_adapter, response.session_id) tool_adapter._install_native_plan_tools(tool_agent) tools = tool_agent._function_toolset.tools - set_plan_tool = cast(Any, tools["acp_set_plan"]) - update_plan_tool = cast(Any, tools["acp_update_plan_entry"]) + set_plan_tool = cast("Any", tools["acp_set_plan"]) + update_plan_tool = cast("Any", tools["acp_update_plan_entry"]) calls = {"count": 0} @@ -1340,7 +1336,7 @@ def get_prompt_model_override(self, session, agent, prompt, model_override): ImageContentBlock(type="image", data="aGVsbG8=", mime_type="image/png"), ], model_override="openrouter:google/gemini-3-flash-preview", - ) + ), ) assert resolved_override == "google-gla:gemini-3-flash-preview" @@ -1354,8 +1350,8 @@ def test_workspace_prompt_model_provider_prefers_explicit_media_override_for_ima monkeypatch.setenv("MODEL_NAME", "openrouter:google/gemini-3-flash-preview") provider = TravelPromptModelProvider() - session = cast(Any, object()) - agent = cast(Any, object()) + session = cast("Any", object()) + agent = cast("Any", object()) resolved_override = provider.get_prompt_model_override( session, @@ -1481,7 +1477,7 @@ def fake_supports_native_plan_state(s: Any) -> bool: agent, model_selection_state=None, mode_state=None, - ) + ), ) == ["cfg"] assert asyncio.run(adapter._get_mode_state(session, agent)) == "mode" assert asyncio.run(adapter._get_provider_config_options(session, agent)) == ["opt"] @@ -1517,14 +1513,22 @@ def fake_supports_native_plan_progress(s: Any) -> bool: return True async def fake_persist_external_plan_state( - session: Any, *, agent: Any, entries: Any, plan_markdown: Any + session: Any, + *, + agent: Any, + entries: Any, + plan_markdown: Any, ) -> None: native_plan_calls.append( - ("persist_external", (session, agent, list(entries), plan_markdown)) + ("persist_external", (session, agent, list(entries), plan_markdown)), ) async def fake_persist_native_plan_state( - session: Any, *, agent: Any, entries: Any, plan_markdown: Any + session: Any, + *, + agent: Any, + entries: Any, + plan_markdown: Any, ) -> None: native_plan_calls.append(("persist_native", (session, agent, list(entries), plan_markdown))) @@ -1550,7 +1554,7 @@ async def fake_persist_native_plan_state( agent=agent, entries=entries, plan_markdown="# External", - ) + ), ) asyncio.run( adapter._prompt_runtime._persist_native_plan_state( @@ -1558,7 +1562,7 @@ async def fake_persist_native_plan_state( agent=agent, entries=entries, plan_markdown="# Native", - ) + ), ) assert [call[0] for call in native_plan_calls] == [ "supports_progress", @@ -1567,7 +1571,7 @@ async def fake_persist_native_plan_state( ] prompt_model_runtime = adapter._prompt_runtime._model_runtime - deferred_agent = cast(Any, SimpleNamespace(output_type=DeferredToolRequests)) + deferred_agent = cast("Any", SimpleNamespace(output_type=DeferredToolRequests)) assert ( prompt_model_runtime.build_run_output_type(deferred_agent, session=session) is DeferredToolRequests @@ -1608,11 +1612,9 @@ def fail_infer_model(value: Any) -> Any: async def unavailable_mode(mode_id: str, session_id: str) -> None: del mode_id, session_id - return None async def unavailable_config(config_id: str, session_id: str, value: Any) -> None: del config_id, session_id, value - return None adapter._session_runtime.set_session_mode = unavailable_mode adapter._session_runtime.set_config_option = unavailable_config @@ -1629,7 +1631,7 @@ async def fake_mode_state(*args: Any, **kwargs: Any) -> ModeState: argument=None, session=session, agent=agent, - ) + ), ) == "Mode `plan` is unavailable" ) @@ -1640,7 +1642,7 @@ async def fake_mode_state(*args: Any, **kwargs: Any) -> ModeState: argument="high", session=session, agent=agent, - ) + ), ) == "Thinking effort is unavailable or invalid" ) @@ -1654,7 +1656,9 @@ async def fake_mode_state(*args: Any, **kwargs: Any) -> ModeState: assert session.config_values["model"] == "test" monkeypatch.setattr( - adapter._session_runtime, "_resolve_model_id_from_value", lambda value: None + adapter._session_runtime, + "_resolve_model_id_from_value", + lambda value: None, ) assign_model(agent, "restored-model") session.session_model_id = "restored-model" @@ -1673,7 +1677,7 @@ async def fake_mode_state(*args: Any, **kwargs: Any) -> ModeState: agent, "flag", True, - ) + ), ) is False ) @@ -1698,7 +1702,7 @@ async def fake_mode_state(*args: Any, **kwargs: Any) -> ModeState: session_surface_runtime.require_model_option("missing-model") adapter._config.available_models = [ - AdapterModel(model_id="raw-model", name="Raw Model", override=cast(Any, agent.model)) + AdapterModel(model_id="raw-model", name="Raw Model", override=cast("Any", agent.model)), ] assert session_surface_runtime.require_model_option("raw-model").model_id == "raw-model" @@ -1722,13 +1726,12 @@ async def fake_mode_state(*args: Any, **kwargs: Any) -> ModeState: emit_current_mode=True, emit_plan=False, emit_session_info=False, - ) + ), ) assert client.updates == [] async def no_model_selection_state(*args: Any, **kwargs: Any) -> None: del args, kwargs - return None monkeypatch.setattr( session_surface_runtime, @@ -1759,7 +1762,7 @@ def test_adapter_prompt_handler_covers_prompt_response_and_no_current_task( config=AdapterConfig(session_store=MemorySessionStore()), ) session_response = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) - handler = cast(Any, adapter)._adapter_prompt + handler = cast("Any", adapter)._adapter_prompt adapter_prompt_module = importlib.import_module("pydantic_acp.runtime._adapter_prompt") monkeypatch.setattr(adapter_prompt_module.asyncio, "current_task", lambda: None) @@ -1774,16 +1777,16 @@ async def fake_run_prompt(**kwargs: Any) -> PromptResponse: [text_block("hello")], session_response.session_id, message_id="prompt-msg", - ) + ), ) assert response.user_message_id == "prompt-msg" - assert cast(Any, adapter)._active_prompt_tasks == {} + assert cast("Any", adapter)._active_prompt_tasks == {} cancelled = asyncio.run( handler._handle_cancelled_prompt( session=_stored_session(adapter, session_response.session_id), prompt_text="cancel me", - ) + ), ) assert cancelled.stop_reason == "cancelled" @@ -1803,7 +1806,7 @@ def test_unknown_slash_command_falls_through_to_prompt_execution( adapter.prompt( prompt=[text_block("/unknown keep going")], session_id=session.session_id, - ) + ), ) assert agent_message_texts(client) == ["continued after slash"] @@ -1815,11 +1818,9 @@ def test_adapter_public_setters_cover_none_provider_and_mode_paths( class EmptyModelsProvider: def set_model(self, session, agent, model_id): del session, agent, model_id - return None def get_model_state(self, session, agent): del session, agent - return None class ReviewModesProvider: def get_mode_state(self, session, agent): diff --git a/tests/pydantic/test_approvals.py b/tests/pydantic/test_approvals.py index 635f2c2..cdddd79 100644 --- a/tests/pydantic/test_approvals.py +++ b/tests/pydantic/test_approvals.py @@ -163,7 +163,7 @@ def dangerous(ctx: RunContext[None], path: str) -> str: assert tool_updates[1].status == "failed" assert tool_updates[1].raw_output == "Permission request cancelled." - stored_session = cast(Any, adapter)._config.session_store.get(new_session_response.session_id) + stored_session = cast("Any", adapter)._config.session_store.get(new_session_response.session_id) assert stored_session is not None message_history = load_message_history(stored_session.message_history_json) assert not any( @@ -197,8 +197,8 @@ def route_failing_tool( "dangerous", {"path": "boom.txt"}, tool_call_id="dangerous-call", - ) - ] + ), + ], ) raise AssertionError("expected the failing tool call to be requested") # pragma: no cover @@ -220,7 +220,7 @@ def dangerous(ctx: RunContext[None], path: str) -> str: adapter.on_connect(client) session_response = await adapter.new_session(cwd=str(tmp_path), mcp_servers=[]) - stored_session = cast(Any, adapter)._config.session_store.get(session_response.session_id) + stored_session = cast("Any", adapter)._config.session_store.get(session_response.session_id) assert stored_session is not None stored_session.message_history_json = dump_message_history( [ @@ -231,13 +231,13 @@ def dangerous(ctx: RunContext[None], path: str) -> str: "dangling_tool", {"path": "a"}, tool_call_id="call-1", - ) + ), ], model_name="test", ), - ] + ], ) - cast(Any, adapter)._config.session_store.save(stored_session) + cast("Any", adapter)._config.session_store.save(stored_session) with pytest.raises(RuntimeError, match="tool exploded"): await adapter.prompt( @@ -245,7 +245,7 @@ def dangerous(ctx: RunContext[None], path: str) -> str: session_id=session_response.session_id, ) - updated_session = cast(Any, adapter)._config.session_store.get(session_response.session_id) + updated_session = cast("Any", adapter)._config.session_store.get(session_response.session_id) assert updated_session is not None message_history = load_message_history(updated_session.message_history_json) assert not any( @@ -486,7 +486,8 @@ def set_policy( raise AssertionError("remembered policy should not be rewritten") def export_state( - self, session: AcpSessionContext + self, + session: AcpSessionContext, ) -> dict[str, JsonValue]: # pragma: no cover del session raise AssertionError("export_state is metadata-only, not live approval lookup") diff --git a/tests/pydantic/test_bridge_builder.py b/tests/pydantic/test_bridge_builder.py index 242eace..57e83c0 100644 --- a/tests/pydantic/test_bridge_builder.py +++ b/tests/pydantic/test_bridge_builder.py @@ -75,14 +75,14 @@ def review_tools( name="Repo MCP", transport="http", tool_prefix="mcp.", - ) + ), ], tools=[ McpToolDefinition( tool_name="mcp.search_repo", server_id="repo", kind="search", - ) + ), ], ) bridges = [hook_bridge, history_bridge, prepare_bridge, mcp_bridge] @@ -125,7 +125,7 @@ def search_repo(query: str) -> str: assert session.modes.current_mode_id == "chat" set_mode_response = asyncio.run( - adapter.set_session_mode(mode_id="review", session_id=session.session_id) + adapter.set_session_mode(mode_id="review", session_id=session.session_id), ) assert set_mode_response is not None @@ -135,7 +135,7 @@ def search_repo(query: str) -> str: adapter.prompt( prompt=[text_block("Search the repo.")], session_id=session.session_id, - ) + ), ) assert prompt_response.stop_reason == "end_turn" @@ -199,7 +199,7 @@ def search_repo(query: str) -> str: "after_output_process", "on_output_process_error", "handle_deferred_tool_calls", - ] + ], } assert metadata["history_processors"] == {"processors": ["trim_history"]} assert metadata["mcp"] == { @@ -212,7 +212,7 @@ def search_repo(query: str) -> str: "tool_prefix": "mcp.", "transport": "http", "url": None, - } + }, ], } assert metadata["prepare_tools"] == { @@ -297,7 +297,7 @@ def factory(session: AcpSessionContext) -> Agent[None, str]: adapter.prompt( prompt=[text_block("Use contextual history.")], session_id=session.session_id, - ) + ), ) assert prompt_response.stop_reason == "end_turn" diff --git a/tests/pydantic/test_bridge_capability_support.py b/tests/pydantic/test_bridge_capability_support.py index ebfd9bb..16fd760 100644 --- a/tests/pydantic/test_bridge_capability_support.py +++ b/tests/pydantic/test_bridge_capability_support.py @@ -68,9 +68,9 @@ def _install_fake_harness_modules(monkeypatch: pytest.MonkeyPatch) -> None: shell_module = ModuleType("pydantic_ai_harness.shell") code_mode_module = ModuleType("pydantic_ai_harness.code_mode") - cast(Any, filesystem_module).FileSystem = _FakeHarnessCapability - cast(Any, shell_module).Shell = _FakeHarnessCapability - cast(Any, code_mode_module).CodeMode = _FakeHarnessCapability + cast("Any", filesystem_module).FileSystem = _FakeHarnessCapability + cast("Any", shell_module).Shell = _FakeHarnessCapability + cast("Any", code_mode_module).CodeMode = _FakeHarnessCapability monkeypatch.setitem(sys.modules, "pydantic_ai_harness", harness_module) monkeypatch.setitem(sys.modules, "pydantic_ai_harness.filesystem", filesystem_module) @@ -105,7 +105,7 @@ def _write_mcp_stdio_server_script(path: Path) -> None: 'if __name__ == "__main__":', ' mcp.run("stdio")', "", - ) + ), ), encoding="utf-8", ) @@ -130,7 +130,7 @@ def _build_mcp_stdio_test_env( ( *python_path_entries, *([existing_pythonpath] if existing_pythonpath else []), - ) + ), ) mcp_env["PYTHONPATH"] = combined_pythonpath return python_executable, mcp_env @@ -166,7 +166,7 @@ def test_harness_filesystem_bridge_builds_capability_and_metadata( "protected_patterns": [".git/*", ".env"], } assert isinstance(bridge.get_projection_maps()[0], HarnessFileSystemProjectionMap) - assert bridge.get_session_metadata(session, cast(Any, object())) == { + assert bridge.get_session_metadata(session, cast("Any", object())) == { "allowed_patterns": ["src/**"], "denied_patterns": ["*.secret"], "max_find_results": 7, @@ -226,7 +226,7 @@ def test_harness_shell_bridge_builds_capability_and_metadata( "denied_commands": ["rm"], } assert isinstance(bridge.get_projection_maps()[0], HarnessShellProjectionMap) - assert bridge.get_session_metadata(session, cast(Any, object())) == { + assert bridge.get_session_metadata(session, cast("Any", object())) == { "allow_interactive": True, "allowed_commands": ["git", "pytest"], "cwd": "/workspace", @@ -285,7 +285,7 @@ def test_harness_code_mode_bridge_builds_capability_and_metadata( "dynamic_catalog": True, } assert isinstance(bridge.get_projection_maps()[0], HarnessCodeModeProjectionMap) - assert bridge.get_session_metadata(session, cast(Any, object())) == { + assert bridge.get_session_metadata(session, cast("Any", object())) == { "dynamic_catalog": True, "has_mount": True, "has_os_access": True, @@ -344,16 +344,16 @@ def test_harness_bridge_projection_maps_are_added_to_adapter_config( ), ) - config = cast(Any, adapter)._config + config = cast("Any", adapter)._config projection_map_types = {type(projection_map) for projection_map in config.projection_maps} assert HarnessFileSystemProjectionMap in projection_map_types assert HarnessShellProjectionMap in projection_map_types assert HarnessCodeModeProjectionMap in projection_map_types - classifier = cast(Any, adapter)._tool_classifier - assert cast(ToolKind, classifier.classify("read_file")) == "read" - assert cast(ToolKind, classifier.classify("run_command")) == "execute" - assert cast(ToolKind, classifier.classify("run_code")) == "execute" + classifier = cast("Any", adapter)._tool_classifier + assert cast("ToolKind", classifier.classify("read_file")) == "read" + assert cast("ToolKind", classifier.classify("run_command")) == "execute" + assert cast("ToolKind", classifier.classify("run_code")) == "execute" def test_thread_executor_bridge_runs_sync_tools_on_configured_executor( @@ -396,7 +396,7 @@ def check_thread() -> str: adapter.prompt( prompt=[text_block("Check the thread executor.")], session_id=session.session_id, - ) + ), ) assert response.stop_reason == "end_turn" @@ -454,7 +454,7 @@ def tool_b(x: str) -> str: adapter.prompt( prompt=[text_block("Inspect the available tools.")], session_id=session.session_id, - ) + ), ) assert response.stop_reason == "end_turn" @@ -507,7 +507,7 @@ def tool_b(x: str) -> str: adapter.prompt( prompt=[text_block("Inspect the available tools.")], session_id=session.session_id, - ) + ), ) assert response.stop_reason == "end_turn" @@ -604,7 +604,7 @@ def prefixed_factory(session: AcpSessionContext) -> Agent[None, str]: PrefixToolsBridge( wrapped=Toolset(toolset=prefixed_toolset), prefix="repo", - ) + ), ], ) contributions = builder.build() @@ -622,12 +622,12 @@ def prefixed_factory(session: AcpSessionContext) -> Agent[None, str]: plain_adapter.prompt( prompt=[text_block("Inspect tools.")], session_id=plain_session.session_id, - ) + ), ) assert plain_response.stop_reason == "end_turn" assert plain_model.last_model_request_parameters is not None assert [tool.name for tool in plain_model.last_model_request_parameters.function_tools] == [ - "lookup" + "lookup", ] prefixed_adapter = create_acp_agent( @@ -639,12 +639,12 @@ def prefixed_factory(session: AcpSessionContext) -> Agent[None, str]: prefixed_adapter.prompt( prompt=[text_block("Inspect prefixed tools.")], session_id=prefixed_session.session_id, - ) + ), ) assert prefixed_response.stop_reason == "end_turn" assert prefixed_model.last_model_request_parameters is not None assert [tool.name for tool in prefixed_model.last_model_request_parameters.function_tools] == [ - "repo_search" + "repo_search", ] @@ -675,7 +675,7 @@ def factory(session: AcpSessionContext) -> Agent[None, str]: adapter.prompt( prompt=[text_block("Inspect toolset instructions.")], session_id=session.session_id, - ) + ), ) assert response.stop_reason == "end_turn" @@ -717,7 +717,7 @@ def ping() -> str: adapter.prompt( prompt=[text_block("Inspect MCP instructions.")], session_id=session.session_id, - ) + ), ) assert response.stop_reason == "end_turn" and "Be a helpful assistant." in "".join( @@ -744,7 +744,7 @@ def test_mcp_stdio_test_helpers_cover_script_and_env_fallbacks(tmp_path: Path) - ) assert existing_python == str(existing_executable) assert existing_env["PYTHONPATH"] == os.pathsep.join( - ("/repo/src", "/repo/tests", "/already/set") + ("/repo/src", "/repo/tests", "/already/set"), ) missing_python, missing_env = _build_mcp_stdio_test_env( @@ -782,7 +782,7 @@ def test_capability_bridge_helper_and_metadata_edge_paths( id="repo-server", headers={"authorization": "Bearer x"}, ) - toolset_bridge = ToolsetBridge(toolset=cast(Any, SimpleNamespace(id=object()))) + toolset_bridge = ToolsetBridge(toolset=cast("Any", SimpleNamespace(id=object()))) prefix_bridge = PrefixToolsBridge(wrapped=Toolset(toolset=FunctionToolset()), prefix="repo") openai_bridge = OpenAICompactionBridge(message_count_threshold=4, instructions="compact") anthropic_bridge = AnthropicCompactionBridge( @@ -794,8 +794,8 @@ def test_capability_bridge_helper_and_metadata_edge_paths( assert _resolve_mcp_server_id("https://example.com/tools/sse", "explicit-id") == "explicit-id" assert _resolve_mcp_server_id("https://example.com/", None) == "example.com" assert _resolve_mcp_server_id("urn:acpkit", None) == "acpkit" - assert _json_user_location(cast(Any, {"city": "Istanbul", "ignored": object()})) == { - "city": "Istanbul" + assert _json_user_location(cast("Any", {"city": "Istanbul", "ignored": object()})) == { + "city": "Istanbul", } assert len(image_bridge.build_agent_capabilities(session)) == 1 @@ -966,7 +966,7 @@ def test_openai_compaction_bridge_records_visible_start_and_completion() -> None instructions="Compact aggressively.", ) capability = bridge.build_capability(session) - fake_model = cast(Any, object.__new__(_FakeOpenAIResponsesModel)) + fake_model = cast("Any", object.__new__(_FakeOpenAIResponsesModel)) request_context = ModelRequestContext( model=fake_model, messages=[ @@ -974,14 +974,14 @@ def test_openai_compaction_bridge_records_visible_start_and_completion() -> None ModelRequest(parts=[UserPromptPart(content="new")]), ], model_settings=None, - model_request_parameters=cast(Any, SimpleNamespace()), + model_request_parameters=cast("Any", SimpleNamespace()), ) updated_context = asyncio.run( capability.before_model_request( - cast(Any, SimpleNamespace()), + cast("Any", SimpleNamespace()), request_context, - ) + ), ) assert len(updated_context.messages) == 2 @@ -1007,7 +1007,7 @@ def test_openai_compaction_bridge_records_visible_start_and_completion() -> None "Status: history compacted", "Compaction payload stored for round-trip.", "Compaction id: cmp-123", - ) + ), ) @@ -1022,7 +1022,7 @@ async def compact_messages( from pydantic_ai import CompactionPart return ModelResponse( - parts=[CompactionPart(id="cmp-123", provider_name="openai", provider_details={})] + parts=[CompactionPart(id="cmp-123", provider_name="openai", provider_details={})], ) @@ -1091,16 +1091,16 @@ def test_openai_compaction_helpers_cover_trigger_threshold_and_missing_parts() - ) request_context = ModelRequestContext( - model=cast(Any, object.__new__(_FakeOpenAIResponsesModel)), + model=cast("Any", object.__new__(_FakeOpenAIResponsesModel)), messages=[ ModelRequest(parts=[UserPromptPart(content="prompt")]), ModelResponse(parts=[]), ModelResponse( - parts=[CompactionPart(id=None, provider_name="openai", provider_details={})] + parts=[CompactionPart(id=None, provider_name="openai", provider_details={})], ), ], model_settings=None, - model_request_parameters=cast(Any, SimpleNamespace()), + model_request_parameters=cast("Any", SimpleNamespace()), ) compacted_part = _extract_compaction_part(request_context.messages) @@ -1111,7 +1111,7 @@ def test_openai_compaction_helpers_cover_trigger_threshold_and_missing_parts() - "Provider: openai", "Status: history compacted", "Compaction payload stored for round-trip.", - ) + ), ) assert ( @@ -1128,9 +1128,9 @@ def test_openai_compaction_helpers_cover_trigger_threshold_and_missing_parts() - provider_name="openai", provider_details={}, ), - ] - ) - ] + ], + ), + ], ) is not None ) @@ -1146,20 +1146,20 @@ def test_openai_compaction_bridge_skips_when_not_needed_and_records_failures() - skipped_bridge = OpenAICompactionBridge(message_count_threshold=5) skipped_capability = skipped_bridge.build_capability(session) skipped_context = ModelRequestContext( - model=cast(Any, object.__new__(_FakeOpenAIResponsesModel)), + model=cast("Any", object.__new__(_FakeOpenAIResponsesModel)), messages=[ ModelRequest(parts=[UserPromptPart(content="old")]), ModelRequest(parts=[UserPromptPart(content="new")]), ], model_settings=None, - model_request_parameters=cast(Any, SimpleNamespace()), + model_request_parameters=cast("Any", SimpleNamespace()), ) unchanged_context = asyncio.run( skipped_capability.before_model_request( - cast(Any, SimpleNamespace()), + cast("Any", SimpleNamespace()), skipped_context, - ) + ), ) assert unchanged_context is skipped_context @@ -1171,21 +1171,21 @@ def test_openai_compaction_bridge_skips_when_not_needed_and_records_failures() - ) failing_capability = failing_bridge.build_capability(session) failing_context = ModelRequestContext( - model=cast(Any, object.__new__(_FailingOpenAIResponsesModel)), + model=cast("Any", object.__new__(_FailingOpenAIResponsesModel)), messages=[ ModelRequest(parts=[UserPromptPart(content="old")]), ModelRequest(parts=[UserPromptPart(content="new")]), ], model_settings=None, - model_request_parameters=cast(Any, SimpleNamespace()), + model_request_parameters=cast("Any", SimpleNamespace()), ) with pytest.raises(RuntimeError, match="boom"): asyncio.run( failing_capability.before_model_request( - cast(Any, SimpleNamespace()), + cast("Any", SimpleNamespace()), failing_context, - ) + ), ) updates = failing_bridge.drain_updates(session, Agent(TestModel())) diff --git a/tests/pydantic/test_bridge_hooks.py b/tests/pydantic/test_bridge_hooks.py index 7ba91be..ad97a53 100644 --- a/tests/pydantic/test_bridge_hooks.py +++ b/tests/pydantic/test_bridge_hooks.py @@ -60,56 +60,56 @@ async def fail_execute(args: Any) -> Any: raise RuntimeError("execute failed") with pytest.raises(RuntimeError, match="run failed"): - asyncio.run(registry["wrap_run"][0].func(cast(Any, None), handler=fail_run)) + asyncio.run(registry["wrap_run"][0].func(cast("Any", None), handler=fail_run)) with pytest.raises(RuntimeError, match="run direct"): asyncio.run( - registry["on_run_error"][0].func(cast(Any, None), error=RuntimeError("run direct")) + registry["on_run_error"][0].func(cast("Any", None), error=RuntimeError("run direct")), ) with pytest.raises(RuntimeError, match="node failed"): asyncio.run( registry["wrap_node_run"][0].func( - cast(Any, None), + cast("Any", None), node=_HOOK_CONTEXT, handler=fail_node, - ) + ), ) with pytest.raises(RuntimeError, match="model failed"): asyncio.run( registry["wrap_model_request"][0].func( - cast(Any, None), + cast("Any", None), request_context=_HOOK_CONTEXT, handler=fail_model, - ) + ), ) with pytest.raises(RuntimeError, match="validate failed"): asyncio.run( registry["wrap_tool_validate"][0].func( - cast(Any, None), + cast("Any", None), call=tool_call, tool_def=tool_def, args={"text": "hello"}, handler=fail_validate, - ) + ), ) with pytest.raises(RuntimeError, match="execute failed"): asyncio.run( registry["wrap_tool_execute"][0].func( - cast(Any, None), + cast("Any", None), call=tool_call, tool_def=tool_def, args={"text": "hello"}, handler=fail_execute, - ) + ), ) with pytest.raises(RuntimeError, match="execute direct"): asyncio.run( registry["on_tool_execute_error"][0].func( - cast(Any, None), + cast("Any", None), call=tool_call, tool_def=tool_def, args={"text": "hello"}, error=RuntimeError("execute direct"), - ) + ), ) updates = bridge.drain_updates(session, Agent(TestModel(custom_output_text="unused"))) @@ -145,7 +145,7 @@ def test_hook_bridge_success_paths_and_disabled_metadata() -> None: response = ModelResponse(parts=[]) async def ok_run() -> Any: - return cast(Any, "run-result") + return cast("Any", "run-result") async def ok_node(node: Any) -> Any: return node @@ -168,126 +168,128 @@ async def fail_output(output: Any) -> Any: raise RuntimeError("output failed") async def event_stream(): - yield cast(Any, SimpleNamespace(event_kind="demo_event")) + yield cast("Any", SimpleNamespace(event_kind="demo_event")) - request_context = cast(Any, SimpleNamespace(messages=[1, 2])) - assert asyncio.run(registry["before_run"][0].func(cast(Any, None))) is None + request_context = cast("Any", SimpleNamespace(messages=[1, 2])) + assert asyncio.run(registry["before_run"][0].func(cast("Any", None))) is None assert ( - asyncio.run(registry["wrap_run"][0].func(cast(Any, None), handler=ok_run)) == "run-result" + asyncio.run(registry["wrap_run"][0].func(cast("Any", None), handler=ok_run)) == "run-result" ) assert ( - asyncio.run(registry["after_run"][0].func(cast(Any, None), result=cast(Any, "done"))) + asyncio.run(registry["after_run"][0].func(cast("Any", None), result=cast("Any", "done"))) == "done" ) assert ( - asyncio.run(registry["before_node_run"][0].func(cast(Any, None), node=tool_call)) + asyncio.run(registry["before_node_run"][0].func(cast("Any", None), node=tool_call)) is tool_call ) assert ( asyncio.run( registry["after_node_run"][0].func( - cast(Any, None), + cast("Any", None), node=tool_call, - result=cast(Any, "node-result"), - ) + result=cast("Any", "node-result"), + ), ) == "node-result" ) assert ( asyncio.run( registry["wrap_node_run"][0].func( - cast(Any, None), + cast("Any", None), node=tool_call, handler=ok_node, - ) + ), ) is tool_call ) assert ( - asyncio.run(registry["_on_event"][0].func(cast(Any, None), cast(Any, tool_call))) + asyncio.run(registry["_on_event"][0].func(cast("Any", None), cast("Any", tool_call))) is tool_call ) wrapped_stream = registry["wrap_run_event_stream"][0].func( - cast(Any, None), + cast("Any", None), stream=event_stream(), ) assert asyncio.run(wrapped_stream.__anext__()).event_kind == "demo_event" assert ( - asyncio.run(registry["before_model_request"][0].func(cast(Any, None), request_context)) + asyncio.run(registry["before_model_request"][0].func(cast("Any", None), request_context)) is request_context ) assert ( asyncio.run( registry["wrap_model_request"][0].func( - cast(Any, None), + cast("Any", None), request_context=request_context, handler=ok_model, - ) + ), ) is response ) assert ( asyncio.run( registry["after_model_request"][0].func( - cast(Any, None), + cast("Any", None), request_context=request_context, response=response, - ) + ), ) is response ) - assert asyncio.run(registry["prepare_tools"][0].func(cast(Any, None), [tool_def])) == [tool_def] + assert asyncio.run(registry["prepare_tools"][0].func(cast("Any", None), [tool_def])) == [ + tool_def, + ] assert asyncio.run( registry["before_tool_validate"][0].func( - cast(Any, None), + cast("Any", None), call=tool_call, tool_def=tool_def, args={"text": "hello"}, - ) + ), ) == {"text": "hello"} assert asyncio.run( registry["after_tool_validate"][0].func( - cast(Any, None), + cast("Any", None), call=tool_call, tool_def=tool_def, args={"text": "hello"}, - ) + ), ) == {"text": "hello"} assert asyncio.run( registry["wrap_tool_validate"][0].func( - cast(Any, None), + cast("Any", None), call=tool_call, tool_def=tool_def, args={"text": "hello"}, handler=ok_validate, - ) + ), ) == {"text": "hello"} assert asyncio.run( registry["before_tool_execute"][0].func( - cast(Any, None), + cast("Any", None), call=tool_call, tool_def=tool_def, args={"text": "hello"}, - ) + ), ) == {"text": "hello"} assert asyncio.run( registry["wrap_tool_execute"][0].func( - cast(Any, None), + cast("Any", None), call=tool_call, tool_def=tool_def, args={"text": "hello"}, handler=ok_execute, - ) + ), ) == {"ok": "hello"} assert ( asyncio.run( registry["after_tool_execute"][0].func( - cast(Any, None), + cast("Any", None), call=tool_call, tool_def=tool_def, args={"text": "hello"}, result="done", - ) + ), ) == "done" ) @@ -328,153 +330,156 @@ async def event_stream(): partially_disabled.record_tool_validation = False partially_disabled.record_tool_execution = False - assert asyncio.run(partially_registry["before_run"][0].func(cast(Any, None))) is None + assert asyncio.run(partially_registry["before_run"][0].func(cast("Any", None))) is None assert ( - asyncio.run(partially_registry["before_node_run"][0].func(cast(Any, None), node=tool_call)) + asyncio.run( + partially_registry["before_node_run"][0].func(cast("Any", None), node=tool_call), + ) is tool_call ) assert ( asyncio.run( partially_registry["_on_event"][0].func( - cast(Any, None), cast(Any, SimpleNamespace(event_kind="silent")) - ) + cast("Any", None), + cast("Any", SimpleNamespace(event_kind="silent")), + ), ).event_kind == "silent" ) assert ( asyncio.run( - partially_registry["before_model_request"][0].func(cast(Any, None), request_context) + partially_registry["before_model_request"][0].func(cast("Any", None), request_context), ) is request_context ) assert asyncio.run( - partially_registry["prepare_tools"][0].func(cast(Any, None), [tool_def]) + partially_registry["prepare_tools"][0].func(cast("Any", None), [tool_def]), ) == [tool_def] assert asyncio.run( - partially_registry["prepare_output_tools"][0].func(cast(Any, None), [tool_def]) + partially_registry["prepare_output_tools"][0].func(cast("Any", None), [tool_def]), ) == [tool_def] assert ( asyncio.run( partially_registry["before_output_validate"][0].func( - cast(Any, None), + cast("Any", None), output_context=_HOOK_CONTEXT, output="raw", - ) + ), ) == "raw" ) assert ( asyncio.run( partially_registry["wrap_output_validate"][0].func( - cast(Any, None), + cast("Any", None), output_context=_HOOK_CONTEXT, output="raw", handler=ok_output, - ) + ), ) == "raw" ) with pytest.raises(RuntimeError, match="output failed"): asyncio.run( partially_registry["wrap_output_validate"][0].func( - cast(Any, None), + cast("Any", None), output_context=_HOOK_CONTEXT, output="raw", handler=fail_output, - ) + ), ) assert ( asyncio.run( partially_registry["after_output_validate"][0].func( - cast(Any, None), + cast("Any", None), output_context=_HOOK_CONTEXT, output="checked", - ) + ), ) == "checked" ) with pytest.raises(RuntimeError, match="validate failed"): asyncio.run( partially_registry["on_output_validate_error"][0].func( - cast(Any, None), + cast("Any", None), output_context=_HOOK_CONTEXT, output="raw", error=RuntimeError("validate failed"), - ) + ), ) assert ( asyncio.run( partially_registry["before_output_process"][0].func( - cast(Any, None), + cast("Any", None), output_context=_HOOK_CONTEXT, output="raw", - ) + ), ) == "raw" ) assert ( asyncio.run( partially_registry["wrap_output_process"][0].func( - cast(Any, None), + cast("Any", None), output_context=_HOOK_CONTEXT, output="raw", handler=ok_output, - ) + ), ) == "raw" ) with pytest.raises(RuntimeError, match="output failed"): asyncio.run( partially_registry["wrap_output_process"][0].func( - cast(Any, None), + cast("Any", None), output_context=_HOOK_CONTEXT, output="raw", handler=fail_output, - ) + ), ) assert ( asyncio.run( partially_registry["after_output_process"][0].func( - cast(Any, None), + cast("Any", None), output_context=_HOOK_CONTEXT, output="processed", - ) + ), ) == "processed" ) with pytest.raises(RuntimeError, match="process failed"): asyncio.run( partially_registry["on_output_process_error"][0].func( - cast(Any, None), + cast("Any", None), output_context=_HOOK_CONTEXT, output="raw", error=RuntimeError("process failed"), - ) + ), ) assert ( asyncio.run( partially_registry["handle_deferred_tool_calls"][0].func( - cast(Any, None), - requests=cast(Any, None), - ) + cast("Any", None), + requests=cast("Any", None), + ), ) is None ) assert asyncio.run( partially_registry["before_tool_validate"][0].func( - cast(Any, None), + cast("Any", None), call=tool_call, tool_def=tool_def, args={"text": "hello"}, - ) + ), ) == {"text": "hello"} assert asyncio.run( partially_registry["before_tool_execute"][0].func( - cast(Any, None), + cast("Any", None), call=tool_call, tool_def=tool_def, args={"text": "hello"}, - ) + ), ) == {"text": "hello"} assert partially_disabled.drain_updates(session, Agent(TestModel())) is None @@ -509,68 +514,68 @@ def test_hook_bridge_records_output_and_deferred_hooks() -> None: async def ok_output(output: Any) -> Any: return output - assert asyncio.run(registry["prepare_output_tools"][0].func(cast(Any, None), [tool_def])) == [ - tool_def + assert asyncio.run(registry["prepare_output_tools"][0].func(cast("Any", None), [tool_def])) == [ + tool_def, ] assert ( asyncio.run( registry["before_output_validate"][0].func( - cast(Any, None), + cast("Any", None), output_context=_HOOK_CONTEXT, output="raw", - ) + ), ) == "raw" ) assert ( asyncio.run( registry["wrap_output_validate"][0].func( - cast(Any, None), + cast("Any", None), output_context=_HOOK_CONTEXT, output="raw", handler=ok_output, - ) + ), ) == "raw" ) assert asyncio.run( registry["after_output_validate"][0].func( - cast(Any, None), + cast("Any", None), output_context=_HOOK_CONTEXT, output={"ok": True}, - ) + ), ) == {"ok": True} assert asyncio.run( registry["before_output_process"][0].func( - cast(Any, None), + cast("Any", None), output_context=_HOOK_CONTEXT, output={"ok": True}, - ) + ), ) == {"ok": True} assert asyncio.run( registry["wrap_output_process"][0].func( - cast(Any, None), + cast("Any", None), output_context=_HOOK_CONTEXT, output={"ok": True}, handler=ok_output, - ) + ), ) == {"ok": True} assert ( asyncio.run( registry["after_output_process"][0].func( - cast(Any, None), + cast("Any", None), output_context=_HOOK_CONTEXT, output="done", - ) + ), ) == "done" ) assert ( asyncio.run( registry["handle_deferred_tool_calls"][0].func( - cast(Any, None), - requests=cast(Any, None), - ) + cast("Any", None), + requests=cast("Any", None), + ), ) is None ) @@ -601,38 +606,38 @@ async def fail_output(output: Any) -> Any: with pytest.raises(RuntimeError, match="output failed"): asyncio.run( registry["wrap_output_validate"][0].func( - cast(Any, None), + cast("Any", None), output_context=_HOOK_CONTEXT, output="raw", handler=fail_output, - ) + ), ) with pytest.raises(RuntimeError, match="validate direct"): asyncio.run( registry["on_output_validate_error"][0].func( - cast(Any, None), + cast("Any", None), output_context=_HOOK_CONTEXT, output="raw", error=RuntimeError("validate direct"), - ) + ), ) with pytest.raises(RuntimeError, match="output failed"): asyncio.run( registry["wrap_output_process"][0].func( - cast(Any, None), + cast("Any", None), output_context=_HOOK_CONTEXT, output="raw", handler=fail_output, - ) + ), ) with pytest.raises(RuntimeError, match="process direct"): asyncio.run( registry["on_output_process_error"][0].func( - cast(Any, None), + cast("Any", None), output_context=_HOOK_CONTEXT, output="raw", error=RuntimeError("process direct"), - ) + ), ) updates = bridge.drain_updates(session, Agent(TestModel())) @@ -662,7 +667,7 @@ def test_hook_bridge_skips_recording_when_flags_are_disabled_after_binding() -> registry = capability._registry tool_call = ToolCallPart("echo", {"text": "hello"}) tool_def = ToolDefinition(name="echo") - request_context = cast(Any, SimpleNamespace(messages=[1])) + request_context = cast("Any", SimpleNamespace(messages=[1])) response = ModelResponse(parts=[]) bridge.record_run_lifecycle = False @@ -674,7 +679,7 @@ def test_hook_bridge_skips_recording_when_flags_are_disabled_after_binding() -> bridge.record_tool_execution = False async def ok_run() -> Any: - return cast(Any, "run-result") + return cast("Any", "run-result") async def fail_run() -> Any: raise RuntimeError("run failed") @@ -709,165 +714,170 @@ async def fail_execute(args: Any) -> Any: raise RuntimeError("execute failed") async def event_stream(): - yield cast(Any, SimpleNamespace(event_kind="demo_event")) + yield cast("Any", SimpleNamespace(event_kind="demo_event")) - assert asyncio.run(registry["before_run"][0].func(cast(Any, None))) is None + assert asyncio.run(registry["before_run"][0].func(cast("Any", None))) is None assert ( - asyncio.run(registry["wrap_run"][0].func(cast(Any, None), handler=ok_run)) == "run-result" + asyncio.run(registry["wrap_run"][0].func(cast("Any", None), handler=ok_run)) == "run-result" ) with pytest.raises(RuntimeError, match="run failed"): - asyncio.run(registry["wrap_run"][0].func(cast(Any, None), handler=fail_run)) - assert asyncio.run(registry["after_run"][0].func(cast(Any, None), result="done")) == "done" + asyncio.run(registry["wrap_run"][0].func(cast("Any", None), handler=fail_run)) + assert asyncio.run(registry["after_run"][0].func(cast("Any", None), result="done")) == "done" with pytest.raises(RuntimeError, match="run direct"): asyncio.run( - registry["on_run_error"][0].func(cast(Any, None), error=RuntimeError("run direct")) + registry["on_run_error"][0].func(cast("Any", None), error=RuntimeError("run direct")), ) assert ( - asyncio.run(registry["before_node_run"][0].func(cast(Any, None), node=tool_call)) + asyncio.run(registry["before_node_run"][0].func(cast("Any", None), node=tool_call)) is tool_call ) assert ( asyncio.run( registry["after_node_run"][0].func( - cast(Any, None), node=tool_call, result="node-result" - ) + cast("Any", None), + node=tool_call, + result="node-result", + ), ) == "node-result" ) assert ( asyncio.run( - registry["wrap_node_run"][0].func(cast(Any, None), node=tool_call, handler=ok_node) + registry["wrap_node_run"][0].func(cast("Any", None), node=tool_call, handler=ok_node), ) is tool_call ) with pytest.raises(RuntimeError, match="node failed"): asyncio.run( - registry["wrap_node_run"][0].func(cast(Any, None), node=tool_call, handler=fail_node) + registry["wrap_node_run"][0].func(cast("Any", None), node=tool_call, handler=fail_node), ) assert ( - asyncio.run(registry["_on_event"][0].func(cast(Any, None), cast(Any, tool_call))) + asyncio.run(registry["_on_event"][0].func(cast("Any", None), cast("Any", tool_call))) is tool_call ) wrapped_stream = registry["wrap_run_event_stream"][0].func( - cast(Any, None), stream=event_stream() + cast("Any", None), + stream=event_stream(), ) assert asyncio.run(wrapped_stream.__anext__()).event_kind == "demo_event" assert ( - asyncio.run(registry["before_model_request"][0].func(cast(Any, None), request_context)) + asyncio.run(registry["before_model_request"][0].func(cast("Any", None), request_context)) is request_context ) assert ( asyncio.run( registry["wrap_model_request"][0].func( - cast(Any, None), + cast("Any", None), request_context=request_context, handler=ok_model, - ) + ), ) is response ) with pytest.raises(RuntimeError, match="model failed"): asyncio.run( registry["wrap_model_request"][0].func( - cast(Any, None), + cast("Any", None), request_context=request_context, handler=fail_model, - ) + ), ) assert ( asyncio.run( registry["after_model_request"][0].func( - cast(Any, None), + cast("Any", None), request_context=request_context, response=response, - ) + ), ) is response ) - assert asyncio.run(registry["prepare_tools"][0].func(cast(Any, None), [tool_def])) == [tool_def] + assert asyncio.run(registry["prepare_tools"][0].func(cast("Any", None), [tool_def])) == [ + tool_def, + ] assert asyncio.run( registry["before_tool_validate"][0].func( - cast(Any, None), + cast("Any", None), call=tool_call, tool_def=tool_def, args={"text": "hello"}, - ) + ), ) == {"text": "hello"} assert asyncio.run( registry["after_tool_validate"][0].func( - cast(Any, None), + cast("Any", None), call=tool_call, tool_def=tool_def, args={"text": "hello"}, - ) + ), ) == {"text": "hello"} assert asyncio.run( registry["wrap_tool_validate"][0].func( - cast(Any, None), + cast("Any", None), call=tool_call, tool_def=tool_def, args={"text": "hello"}, handler=ok_validate, - ) + ), ) == {"text": "hello"} with pytest.raises(RuntimeError, match="validate failed"): asyncio.run( registry["wrap_tool_validate"][0].func( - cast(Any, None), + cast("Any", None), call=tool_call, tool_def=tool_def, args={"text": "hello"}, handler=fail_validate, - ) + ), ) assert asyncio.run( registry["before_tool_execute"][0].func( - cast(Any, None), + cast("Any", None), call=tool_call, tool_def=tool_def, args={"text": "hello"}, - ) + ), ) == {"text": "hello"} assert asyncio.run( registry["wrap_tool_execute"][0].func( - cast(Any, None), + cast("Any", None), call=tool_call, tool_def=tool_def, args={"text": "hello"}, handler=ok_execute, - ) + ), ) == {"ok": "hello"} with pytest.raises(RuntimeError, match="execute failed"): asyncio.run( registry["wrap_tool_execute"][0].func( - cast(Any, None), + cast("Any", None), call=tool_call, tool_def=tool_def, args={"text": "hello"}, handler=fail_execute, - ) + ), ) assert ( asyncio.run( registry["after_tool_execute"][0].func( - cast(Any, None), + cast("Any", None), call=tool_call, tool_def=tool_def, args={"text": "hello"}, result="done", - ) + ), ) == "done" ) with pytest.raises(RuntimeError, match="execute direct"): asyncio.run( registry["on_tool_execute_error"][0].func( - cast(Any, None), + cast("Any", None), call=tool_call, tool_def=tool_def, args={"text": "hello"}, error=RuntimeError("execute direct"), - ) + ), ) assert bridge.drain_updates(session, Agent(TestModel(custom_output_text="unused"))) is None diff --git a/tests/pydantic/test_bridge_mcp.py b/tests/pydantic/test_bridge_mcp.py index 08cce1d..2f2a0b1 100644 --- a/tests/pydantic/test_bridge_mcp.py +++ b/tests/pydantic/test_bridge_mcp.py @@ -55,14 +55,14 @@ def test_mcp_bridge_handles_empty_and_prefix_scoped_behaviour() -> None: transport="http", url="https://repo.example/mcp", tool_prefix="mcp.repo.", - ) + ), ], tools=[ McpToolDefinition( tool_name="mcp.explicit.search", server_id="repo", kind="search", - ) + ), ], config_options=[ SessionConfigOptionBoolean( @@ -124,7 +124,7 @@ def test_mcp_bridge_tool_scope_and_config_only_metadata() -> None: server_id="docs", name="Docs", transport="sse", - ) + ), ], config_options=[ SessionConfigOptionBoolean( @@ -132,7 +132,7 @@ def test_mcp_bridge_tool_scope_and_config_only_metadata() -> None: name="Enabled", current_value=True, type="boolean", - ) + ), ], ) @@ -153,8 +153,8 @@ def test_mcp_bridge_tool_scope_and_config_only_metadata() -> None: name="Config Only", current_value=False, type="boolean", - ) - ] + ), + ], ) config_only_metadata = config_only_bridge.get_session_metadata(session, agent) assert config_only_metadata == { @@ -172,7 +172,7 @@ def test_mcp_bridge_tool_scope_and_config_only_metadata() -> None: name="Docs", transport="http", tool_prefix="docs.", - ) + ), ], ) assert server_scope_bridge.get_approval_policy_key("docs.search") == "mcp:server:docs" @@ -185,9 +185,9 @@ def test_mcp_bridge_tool_scope_and_config_only_metadata() -> None: assert prefix_fallback_bridge._find_config_option("missing") is None assert prefix_fallback_bridge._find_server("missing") is None assert prefix_fallback_bridge._sync_config_option( - cast(Any, SimpleNamespace(id="other")), + cast("Any", SimpleNamespace(id="other")), session, - ) == cast(Any, SimpleNamespace(id="other")) + ) == cast("Any", SimpleNamespace(id="other")) select_bridge = McpBridge( config_options=[ @@ -200,7 +200,7 @@ def test_mcp_bridge_tool_scope_and_config_only_metadata() -> None: SessionConfigSelectOption(name="Docs", value="docs"), ], type="select", - ) + ), ], servers=[ McpServerDefinition( @@ -227,7 +227,7 @@ def test_mcp_bridge_tool_scope_and_config_only_metadata() -> None: session, ) assert synced.current_value == "docs" - custom_bridge = McpBridge(config_options=[cast(Any, SimpleNamespace(id="custom"))]) + custom_bridge = McpBridge(config_options=[cast("Any", SimpleNamespace(id="custom"))]) custom_options = custom_bridge.set_config_option(session, agent, "custom", "value") assert custom_options is not None assert session.config_values["custom"] == "value" @@ -263,8 +263,8 @@ def test_mcp_bridge_accepts_grouped_select_options() -> None: ), ], type="select", - ) - ] + ), + ], ) assert bridge.set_config_option(session, agent, "scope", "docs") is not None @@ -285,7 +285,7 @@ async def test_mcp_bridge_exposes_config_and_routes_server_scoped_approval( description="Connect MCP tools automatically.", type="boolean", current_value=False, - ) + ), ], servers=[ McpServerDefinition( @@ -293,7 +293,7 @@ async def test_mcp_bridge_exposes_config_and_routes_server_scoped_approval( name="Repo MCP", transport="http", tool_prefix="mcp.repo.", - ) + ), ], tools=[ McpToolDefinition(tool_name="mcp.repo.alpha", server_id="repo", kind="read"), @@ -393,6 +393,6 @@ def repo_beta(ctx: RunContext[None], path: str) -> str: "tool_prefix": "mcp.repo.", "transport": "http", "url": None, - } + }, ], } diff --git a/tests/pydantic/test_bridge_prepare_tools.py b/tests/pydantic/test_bridge_prepare_tools.py index 5aadcfc..296a3da 100644 --- a/tests/pydantic/test_bridge_prepare_tools.py +++ b/tests/pydantic/test_bridge_prepare_tools.py @@ -34,7 +34,7 @@ def _passthrough_tools( def test_passthrough_tools_helper_returns_a_copy() -> None: tool_defs: list[ToolDefinition] = [] - copied = _passthrough_tools(cast(Any, None), tool_defs) + copied = _passthrough_tools(cast("Any", None), tool_defs) assert copied == [] assert copied is not tool_defs @@ -74,7 +74,7 @@ def keep_public( async def run_prepare() -> list[ToolDefinition]: prepared = bridge.build_prepare_output_tools(session) - result = cast(Awaitable[list[ToolDefinition]], prepared(cast(Any, None), tool_defs)) + result = cast("Awaitable[list[ToolDefinition]]", prepared(cast("Any", None), tool_defs)) return await result capability = bridge.build_capability(session) @@ -125,7 +125,7 @@ def test_prepare_output_tools_bridge_validation_and_failure_paths(tmp_path: Path id="default", name="Default", prepare_func=_passthrough_tools, - ) + ), ], ) with pytest.raises(ValueError, match="reserved slash command names"): @@ -136,7 +136,7 @@ def test_prepare_output_tools_bridge_validation_and_failure_paths(tmp_path: Path id="model", name="Model", prepare_func=_passthrough_tools, - ) + ), ], ) @@ -154,7 +154,7 @@ def boom( id="default", name="Default", prepare_func=boom, - ) + ), ], ) session = AcpSessionContext( @@ -166,7 +166,7 @@ def boom( async def run_prepare() -> None: prepared = bridge.build_prepare_output_tools(session) - result = cast(Awaitable[list[ToolDefinition]], prepared(cast(Any, None), [])) + result = cast("Awaitable[list[ToolDefinition]]", prepared(cast("Any", None), [])) await result with pytest.raises(RuntimeError, match="output boom"): @@ -209,9 +209,9 @@ def test_prepare_tools_bridge_rejects_invalid_default_plan_generation_type() -> name="Plan", prepare_func=_passthrough_tools, plan_mode=True, - ) + ), ], - default_plan_generation_type=cast(Any, "invalid"), + default_plan_generation_type=cast("Any", "invalid"), ) @@ -332,7 +332,7 @@ def boom( name="Plan", prepare_func=boom, plan_mode=True, - ) + ), ], ) session = AcpSessionContext( @@ -344,7 +344,7 @@ def boom( async def run_prepare() -> None: prepared = bridge.build_prepare_tools(session) - result = prepared(cast(Any, None), []) + result = prepared(cast("Any", None), []) if asyncio.iscoroutine(result): await result return # pragma: no cover @@ -366,6 +366,6 @@ def test_prepare_tools_bridge_rejects_reserved_mode_ids() -> None: id="model", name="Model", prepare_func=_passthrough_tools, - ) + ), ], ) diff --git a/tests/pydantic/test_bridge_thinking.py b/tests/pydantic/test_bridge_thinking.py index 9ce14e0..dcc1d6f 100644 --- a/tests/pydantic/test_bridge_thinking.py +++ b/tests/pydantic/test_bridge_thinking.py @@ -109,7 +109,7 @@ def route_with_thinking( config_id="thinking", session_id=session.session_id, value="high", - ) + ), ) assert update_response is not None assert update_response.config_options is not None @@ -120,7 +120,7 @@ def route_with_thinking( adapter.prompt( prompt=[text_block("Use the selected thinking effort.")], session_id=session.session_id, - ) + ), ) assert observed_thinking[-1] == "high" @@ -129,12 +129,12 @@ def route_with_thinking( config_id="thinking", session_id=session.session_id, value="off", - ) + ), ) asyncio.run( adapter.prompt( prompt=[text_block("Disable thinking for this run.")], session_id=session.session_id, - ) + ), ) assert observed_thinking[-1] is False diff --git a/tests/pydantic/test_compat.py b/tests/pydantic/test_compat.py index 44eca86..4335630 100644 --- a/tests/pydantic/test_compat.py +++ b/tests/pydantic/test_compat.py @@ -64,18 +64,18 @@ def test_root_capability_and_override_helpers_handle_missing_and_present_private capability = CombinedCapability(capabilities=[]) override = ContextVar[object]("override") - cast(Any, agent)._root_capability = capability - cast(Any, agent)._override_root_capability = override + cast("Any", agent)._root_capability = capability + cast("Any", agent)._override_root_capability = override override_value = build_capability_override_value(capability) assert root_capability(agent) is capability assert root_capability_override(agent) is override assert type(override_value).__name__ == "_CapabilityOverrideValue" - assert cast(Any, override_value).value is capability + assert cast("Any", override_value).value is capability - cast(Any, agent)._root_capability = "wrong" - cast(Any, agent)._override_root_capability = "wrong" + cast("Any", agent)._root_capability = "wrong" + cast("Any", agent)._override_root_capability = "wrong" assert root_capability(agent) is None assert root_capability_override(agent) is None @@ -85,9 +85,9 @@ def test_hook_registry_and_entry_helpers_normalize_supported_shapes() -> None: valid_entry = _DataclassEntry( func="callable", timeout=1, - tools=cast(Any, frozenset({"b", "a", 1})), + tools=cast("Any", frozenset({"b", "a", 1})), ) - cast(Any, hooks)._registry = { + cast("Any", hooks)._registry = { "before_run": [valid_entry], 1: [valid_entry], "bad": "wrong", @@ -102,7 +102,7 @@ def test_hook_registry_and_entry_helpers_normalize_supported_shapes() -> None: assert entry_timeout(object()) is None assert entry_tool_filters(object()) == () - cast(Any, hooks)._registry = "wrong" + cast("Any", hooks)._registry = "wrong" assert hook_registry(hooks) is None diff --git a/tests/pydantic/test_examples.py b/tests/pydantic/test_examples.py index 3a8b648..61dd48c 100644 --- a/tests/pydantic/test_examples.py +++ b/tests/pydantic/test_examples.py @@ -71,9 +71,9 @@ def __init__(self, **kwargs: Any) -> None: filesystem_module = ModuleType("pydantic_ai_harness.filesystem") shell_module = ModuleType("pydantic_ai_harness.shell") code_mode_module = ModuleType("pydantic_ai_harness.code_mode") - cast(Any, filesystem_module).FileSystem = FakeHarnessCapability - cast(Any, shell_module).Shell = FakeHarnessCapability - cast(Any, code_mode_module).CodeMode = FakeHarnessCapability + cast("Any", filesystem_module).FileSystem = FakeHarnessCapability + cast("Any", shell_module).Shell = FakeHarnessCapability + cast("Any", code_mode_module).CodeMode = FakeHarnessCapability monkeypatch.setitem(sys.modules, "pydantic_ai_harness", ModuleType("pydantic_ai_harness")) monkeypatch.setitem(sys.modules, "pydantic_ai_harness.filesystem", filesystem_module) @@ -117,7 +117,7 @@ def test_finance_example_helpers_cover_workspace_and_plan_paths(tmp_path: Path) assert "watchlist.md" in finance_agent._list_market_files(finance_root) assert finance_agent._read_market_note(finance_root, "watchlist.md", max_chars=64).startswith( - "# Finance Watchlist" + "# Finance Watchlist", ) assert ( finance_agent._save_market_note(finance_root, "notes/rebalance.md", "trim risk") @@ -125,7 +125,7 @@ def test_finance_example_helpers_cover_workspace_and_plan_paths(tmp_path: Path) ) assert ( finance_agent._resolve_market_path(finance_root, "notes/rebalance.md").read_text( - encoding="utf-8" + encoding="utf-8", ) == "trim risk" ) @@ -199,7 +199,7 @@ def test_harness_example_builds_agent_from_harness_capability_bridges( "denied_commands": ["rm", "mv", "cp", "curl", "wget", "git"], }, ] - instructions = cast(list[str], cast(Any, agent)._instructions) + instructions = cast("list[str]", cast("Any", agent)._instructions) assert all("code-mode tools are enabled" not in instruction for instruction in instructions) @@ -223,11 +223,11 @@ def test_harness_example_codemode_factory_includes_code_mode_bridge( ) agent = _resolve_result( - mock_harness_agent._build_agent_factory(include_code_mode=True)(session) + mock_harness_agent._build_agent_factory(include_code_mode=True)(session), ) assert agent.name == "harness-agent" - instructions = cast(list[str], agent._instructions) + instructions = cast("list[str]", agent._instructions) assert any("Code-mode tools are enabled" in instruction for instruction in instructions) assert [capability.kwargs for capability in created_capabilities] == [ { @@ -281,12 +281,12 @@ def test_harness_example_acp_agent_runs_with_test_model_override( adapter.prompt( prompt=[text_block("Use the harness surface.")], session_id=session.session_id, - ) + ), ) assert agent_message_texts(client) == ["Harness agent ready."] - config = cast(Any, adapter)._config - classifier = cast(Any, adapter)._tool_classifier + config = cast("Any", adapter)._config + classifier = cast("Any", adapter)._tool_classifier projection_map_names = { type(projection_map).__name__ for projection_map in config.projection_maps } @@ -402,7 +402,7 @@ def test_finance_example_tools_and_adapter_cover_runtime_paths( monkeypatch.chdir(tmp_path) available_tools = cast( - list[Any], + "list[Any]", [ type("ToolDef", (), {"name": finance_agent._READ_NOTE_TOOL})(), type("ToolDef", (), {"name": finance_agent._WRITE_NOTE_TOOL})(), @@ -411,18 +411,18 @@ def test_finance_example_tools_and_adapter_cover_runtime_paths( assert [ tool.name for tool in finance_agent._read_only_tools( - cast(Any, object()), + cast("Any", object()), available_tools, ) ] == [finance_agent._READ_NOTE_TOOL] - assert finance_agent._trade_tools(cast(Any, object()), available_tools) == available_tools + assert finance_agent._trade_tools(cast("Any", object()), available_tools) == available_tools tools = finance_agent.agent._function_toolset.tools - describe_tool = cast(Any, tools["describe_finance_surface"]) - watchlist_tool = cast(Any, tools[finance_agent._WATCHLIST_TOOL]) - read_tool = cast(Any, tools[finance_agent._READ_NOTE_TOOL]) - write_tool = cast(Any, tools[finance_agent._WRITE_NOTE_TOOL]) - quote_tool = cast(Any, tools[finance_agent._QUOTE_TOOL]) + describe_tool = cast("Any", tools["describe_finance_surface"]) + watchlist_tool = cast("Any", tools[finance_agent._WATCHLIST_TOOL]) + read_tool = cast("Any", tools[finance_agent._READ_NOTE_TOOL]) + write_tool = cast("Any", tools[finance_agent._WRITE_NOTE_TOOL]) + quote_tool = cast("Any", tools[finance_agent._QUOTE_TOOL]) assert "structured native plan generation" in describe_tool.function() assert "Seeded symbols:" in watchlist_tool.function() @@ -439,7 +439,7 @@ def test_finance_example_tools_and_adapter_cover_runtime_paths( created_at=datetime.now(UTC), updated_at=datetime.now(UTC), ) - provider = cast(Any, finance_agent.config.native_plan_persistence_provider) + provider = cast("Any", finance_agent.config.native_plan_persistence_provider) provider.persist_plan_state( session, finance_agent.agent, @@ -466,7 +466,7 @@ def test_finance_example_tools_and_adapter_cover_runtime_paths( adapter.prompt( prompt=[text_block("Describe the finance surface.")], session_id=response.session_id, - ) + ), ) finally: monkeypatch.setattr(finance_agent.agent, "model", original_model) @@ -498,47 +498,47 @@ def test_travel_example_helpers_cover_workspace_and_hooks( assert ( _resolve_result( travel_agent.observe_before_model_request( - cast(Any, object()), - request_context=cast(Any, "ctx"), - ) + cast("Any", object()), + request_context=cast("Any", "ctx"), + ), ) == "ctx" ) assert ( _resolve_result( travel_agent.observe_after_model_request( - cast(Any, object()), - request_context=cast(Any, "ctx"), - response=cast(Any, "response"), - ) + cast("Any", object()), + request_context=cast("Any", "ctx"), + response=cast("Any", "response"), + ), ) == "response" ) assert _resolve_result( travel_agent.observe_read_tool( - cast(Any, object()), - call=cast(Any, object()), - tool_def=cast(Any, object()), + cast("Any", object()), + call=cast("Any", object()), + tool_def=cast("Any", object()), args={"path": "itinerary.md"}, - ) + ), ) == {"path": "itinerary.md"} assert _resolve_result( travel_agent.observe_write_tool( - cast(Any, object()), - call=cast(Any, object()), - tool_def=cast(Any, object()), + cast("Any", object()), + call=cast("Any", object()), + tool_def=cast("Any", object()), args={"path": "scratch.txt"}, - ) + ), ) == {"path": "scratch.txt"} assert ( _resolve_result( travel_agent.observe_write_result( - cast(Any, object()), - call=cast(Any, object()), - tool_def=cast(Any, object()), + cast("Any", object()), + call=cast("Any", object()), + tool_def=cast("Any", object()), args={"path": "scratch.txt"}, result="ok", - ) + ), ) == "ok" ) @@ -587,8 +587,8 @@ def test_travel_prompt_model_provider_covers_media_override_paths( name="notes", uri="file:///notes.txt", mime_type="text/plain", - ) - ] + ), + ], ) is False ) @@ -602,8 +602,8 @@ def test_travel_prompt_model_provider_covers_media_override_paths( blob="aGVsbG8=", mime_type="image/jpeg", ), - ) - ] + ), + ], ) is True ) @@ -615,15 +615,15 @@ def test_travel_prompt_model_provider_covers_media_override_paths( name="cover", uri="file:///cover.png", mime_type="image/png", - ) - ] + ), + ], ) is True ) image_override = provider.get_prompt_model_override( - cast(Any, object()), - cast(Any, object()), + cast("Any", object()), + cast("Any", object()), prompt=[ text_block("describe this hotel"), ImageContentBlock(type="image", data="aGVsbG8=", mime_type="image/png"), @@ -631,8 +631,8 @@ def test_travel_prompt_model_provider_covers_media_override_paths( model_override="openrouter:google/gemini-3-flash-preview", ) audio_override = provider.get_prompt_model_override( - cast(Any, object()), - cast(Any, object()), + cast("Any", object()), + cast("Any", object()), prompt=[ text_block("transcribe this"), AudioContentBlock(type="audio", data="aGVsbG8=", mime_type="audio/wav"), @@ -645,14 +645,14 @@ def test_travel_prompt_model_provider_covers_media_override_paths( monkeypatch.delenv("ACP_TRAVEL_MEDIA_MODEL", raising=False) same_override = provider.get_prompt_model_override( - cast(Any, object()), - cast(Any, object()), + cast("Any", object()), + cast("Any", object()), prompt=[text_block("plain text only")], model_override="existing-model", ) missing_media_override = provider.get_prompt_model_override( - cast(Any, object()), - cast(Any, object()), + cast("Any", object()), + cast("Any", object()), prompt=[ AudioContentBlock(type="audio", data="aGVsbG8=", mime_type="audio/wav"), ], @@ -710,7 +710,7 @@ def test_travel_model_helpers_cover_default_model_and_absolute_paths( mime_type="audio/wav", ), ), - ] + ], ) is False ) @@ -721,15 +721,15 @@ def test_travel_model_provider_preserves_existing_override_without_media_env() - assert ( travel_agent._prompt_has_image_media( - [ImageContentBlock(type="image", data="aGVsbG8=", mime_type="image/png")] + [ImageContentBlock(type="image", data="aGVsbG8=", mime_type="image/png")], ) is True ) assert ( provider.get_prompt_model_override( - cast(Any, object()), - cast(Any, object()), + cast("Any", object()), + cast("Any", object()), prompt=[ EmbeddedResourceContentBlock( type="resource", @@ -738,7 +738,7 @@ def test_travel_model_provider_preserves_existing_override_without_media_env() - text="hello", mime_type="text/plain", ), - ) + ), ], model_override="existing-model", ) @@ -752,8 +752,8 @@ def test_travel_model_provider_preserves_existing_override_without_media_env() - name="unknown", uri="file:///unknown.bin", mime_type=None, - ) - ] + ), + ], ) is False ) @@ -767,8 +767,8 @@ def test_travel_model_provider_preserves_existing_override_without_media_env() - text="hello", mime_type="text/plain", ), - ) - ] + ), + ], ) is False ) diff --git a/tests/pydantic/test_hook_introspection.py b/tests/pydantic/test_hook_introspection.py index d8c60d4..0045f18 100644 --- a/tests/pydantic/test_hook_introspection.py +++ b/tests/pydantic/test_hook_introspection.py @@ -99,7 +99,7 @@ async def annotate_request(ctx, request_context): adapter.prompt( prompt=[text_block("Trigger the hook.")], session_id=session.session_id, - ) + ), ) start_updates = [ @@ -158,7 +158,10 @@ async def empty_stream() -> Any: with pytest.raises(TypeError, match="async iterable"): async def consume() -> None: - async for _ in cast(Any, wrapped_entry).func(cast(Any, None), stream=empty_stream()): + async for _ in cast("Any", wrapped_entry).func( + cast("Any", None), + stream=empty_stream(), + ): pass # pragma: no cover asyncio.run(consume()) @@ -195,7 +198,7 @@ async def second_request_hook(ctx, request_context): adapter.prompt( prompt=[text_block("Trigger the registered hooks.")], session_id=session.session_id, - ) + ), ) start_titles = [ @@ -241,7 +244,7 @@ def echo(text: str) -> str: adapter.prompt( prompt=[text_block("Call the echo tool.")], session_id=session.session_id, - ) + ), ) start_updates = [ @@ -290,7 +293,7 @@ async def annotate_request(ctx, request_context): event_labels={"before_model_request": "Model Hook"}, show_hook_name_in_title=False, include_tool_filters=False, - ) + ), ], ) client = RecordingClient() @@ -301,7 +304,7 @@ async def annotate_request(ctx, request_context): adapter.prompt( prompt=[text_block("Trigger the hook.")], session_id=session.session_id, - ) + ), ) start_update = next(update for _, update in client.updates if isinstance(update, ToolCallStart)) @@ -347,8 +350,8 @@ async def write_update(update: Any) -> None: pass invalid_agent = Agent(TestModel(custom_output_text="invalid")) - cast(Any, invalid_agent)._root_capability = _INVALID_HOOK_VALUE - cast(Any, invalid_agent)._override_root_capability = _INVALID_HOOK_VALUE + cast("Any", invalid_agent)._root_capability = _INVALID_HOOK_VALUE + cast("Any", invalid_agent)._override_root_capability = _INVALID_HOOK_VALUE with observe_agent_hooks( invalid_agent, write_update=write_update, @@ -378,14 +381,13 @@ async def gamma(ctx, *, output_context, output, handler): async def delta(ctx, *, requests): del ctx, requests # pragma: no cover - return None # pragma: no cover skipped = _TestHookEntry(skipped_alpha) skipped.func.__module__ = "pydantic_acp.bridges.hooks" tool_entry = _TestHookEntry(beta, tools=frozenset({"z", "a"})) broken_entry = _TestHookEntry(alpha) - cast(Any, broken_entry).func = None - cast(Any, hooks)._registry = { + cast("Any", broken_entry).func = None + cast("Any", hooks)._registry = { 1: [], "before_model_request": ["bad", broken_entry, skipped, _TestHookEntry(alpha)], "before_tool_execute": [tool_entry], @@ -400,7 +402,7 @@ async def delta(ctx, *, requests): ("deferred_tool_calls", "delta", ()), ("output_validate", "gamma", ()), ] - assert _tool_filters(cast(Any, SimpleNamespace(tools=None))) == () + assert _tool_filters(cast("Any", SimpleNamespace(tools=None))) == () assert _tool_name({"call": _INVALID_HOOK_VALUE}) is None class SilentError(Exception): @@ -414,25 +416,25 @@ def __str__(self) -> str: assert _summarize_result(ModelResponse(parts=[])) == "parts=0" invalid_registry_hooks = Hooks[Any]() - cast(Any, invalid_registry_hooks)._registry = _INVALID_HOOK_VALUE + cast("Any", invalid_registry_hooks)._registry = _INVALID_HOOK_VALUE wrapped_hooks, changed = _wrap_hooks(invalid_registry_hooks, emitter=hidden_emitter) assert wrapped_hooks is invalid_registry_hooks assert changed is False bad_key_hooks = Hooks[Any]() - cast(Any, bad_key_hooks)._registry = {1: []} + cast("Any", bad_key_hooks)._registry = {1: []} wrapped_hooks, changed = _wrap_hooks(bad_key_hooks, emitter=hidden_emitter) assert wrapped_hooks is bad_key_hooks assert changed is False bad_entry_hooks = Hooks[Any]() - cast(Any, bad_entry_hooks)._registry = {"before_run": ["bad"]} + cast("Any", bad_entry_hooks)._registry = {"before_run": ["bad"]} wrapped_hooks, changed = _wrap_hooks(bad_entry_hooks, emitter=hidden_emitter) assert wrapped_hooks is bad_entry_hooks assert changed is False non_callable_entry = _TestHookEntry(alpha) - cast(Any, non_callable_entry).func = None + cast("Any", non_callable_entry).func = None wrapped_entry, changed = _wrap_hook_entry( "before_run", non_callable_entry, @@ -474,12 +476,12 @@ async def exploding(*args: Any, **kwargs: Any) -> Any: assert changed is True with pytest.raises(RuntimeError, match="boom"): asyncio.run( - cast(Any, wrapped_error_entry).func( - cast(Any, None), + cast("Any", wrapped_error_entry).func( + cast("Any", None), call=ToolCallPart("echo", {"text": "ok"}), - tool_def=cast(Any, _INVALID_HOOK_VALUE), + tool_def=cast("Any", _INVALID_HOOK_VALUE), args={"text": "ok"}, - ) + ), ) assert any(getattr(update, "status", None) == "failed" for update in visible_updates) @@ -495,8 +497,8 @@ async def slow() -> None: capabilities=[Hooks[None]()], ) override_var = ContextVar("_override_root_capability", default=None) - cast(Any, real_agent)._override_root_capability = override_var - cast(Any, real_agent)._root_capability = CombinedCapability(capabilities=[]) + cast("Any", real_agent)._override_root_capability = override_var + cast("Any", real_agent)._root_capability = CombinedCapability(capabilities=[]) with observe_agent_hooks( real_agent, write_update=write_update, @@ -522,7 +524,7 @@ async def alpha(ctx, request_context): return request_context # pragma: no cover hooks = Hooks[Any](ordering=CapabilityOrdering(position="outermost")) - cast(Any, hooks)._registry = {"before_model_request": [_TestHookEntry(alpha)]} + cast("Any", hooks)._registry = {"before_model_request": [_TestHookEntry(alpha)]} wrapped_hooks, changed = _wrap_hooks(hooks, emitter=emitter) @@ -553,18 +555,18 @@ async def write_update(update: Any) -> None: tool_filters=(), status=None, ), - ) + ), ) is None ) assert recorded_updates == [] invalid_agent = Agent(TestModel(custom_output_text="plain")) - cast(Any, invalid_agent)._root_capability = _INVALID_HOOK_VALUE + cast("Any", invalid_agent)._root_capability = _INVALID_HOOK_VALUE assert list_agent_hooks(invalid_agent) == [] hooks = Hooks[Any]() - cast(Any, hooks)._registry = _INVALID_HOOK_VALUE + cast("Any", hooks)._registry = _INVALID_HOOK_VALUE agent = Agent(TestModel(custom_output_text="hooked"), capabilities=[hooks]) assert list_agent_hooks(agent) == [] diff --git a/tests/pydantic/test_host.py b/tests/pydantic/test_host.py index a01a31f..3878eb0 100644 --- a/tests/pydantic/test_host.py +++ b/tests/pydantic/test_host.py @@ -41,7 +41,7 @@ def test_client_filesystem_backend_reads_with_session_context() -> None: "notes/todo.txt", line=4, limit=120, - ) + ), ) assert response.content == "file:notes/todo.txt:4:120" @@ -62,12 +62,12 @@ def test_client_filesystem_backend_writes_with_session_context() -> None: backend.write_text_file( "notes/todo.txt", "ship milestone 7 phase 1", - ) + ), ) assert response is not None assert client.write_calls == [ - ("session-filesystem-write", "notes/todo.txt", "ship milestone 7 phase 1") + ("session-filesystem-write", "notes/todo.txt", "ship milestone 7 phase 1"), ] @@ -104,7 +104,7 @@ def test_client_terminal_backend_creates_outputs_and_waits_with_session_context( cwd="/workspace", env=[EnvVariable(name="MODE", value="demo")], output_byte_limit=4096, - ) + ), ) output_response = asyncio.run(backend.terminal_output(create_response.terminal_id)) wait_response = asyncio.run(backend.wait_for_terminal_exit(create_response.terminal_id)) @@ -121,7 +121,7 @@ def test_client_terminal_backend_creates_outputs_and_waits_with_session_context( "/workspace", [EnvVariable(name="MODE", value="demo")], 4096, - ) + ), ] assert client.output_calls == [("session-terminal-ops", "terminal-1")] assert client.wait_calls == [("session-terminal-ops", "terminal-1")] @@ -220,7 +220,7 @@ def test_client_host_context_delegates_filesystem_and_terminal_calls() -> None: read_response = asyncio.run(host_context.filesystem.read_text_file("notes.txt")) create_response = asyncio.run(host_context.terminal.create_terminal("python", args=["-V"])) output_response = asyncio.run( - host_context.terminal.terminal_output(create_response.terminal_id) + host_context.terminal.terminal_output(create_response.terminal_id), ) assert read_response.content == "file:notes.txt:None:None" @@ -260,11 +260,11 @@ async def read_workspace_note(ctx: RunContext[None]) -> str: adapter.prompt( prompt=[text_block("Read the workspace note through the host context.")], session_id=session.session_id, - ) + ), ) assert prompt_response.stop_reason == "end_turn" assert client.read_calls == [(session.session_id, "notes/factory.txt", None, None)] assert agent_message_texts(client) == [ - '{"read_workspace_note":"file:notes/factory.txt:None:None"}' + '{"read_workspace_note":"file:notes/factory.txt:None:None"}', ] diff --git a/tests/pydantic/test_host_policy.py b/tests/pydantic/test_host_policy.py index 2750dee..57e3677 100644 --- a/tests/pydantic/test_host_policy.py +++ b/tests/pydantic/test_host_policy.py @@ -238,7 +238,7 @@ def test_client_terminal_backend_enforces_denying_policy() -> None: host.terminal.create_terminal( "python", args=["/tmp/outside.py"], - ) + ), ) assert client.create_calls == [] diff --git a/tests/pydantic/test_low_level_helpers.py b/tests/pydantic/test_low_level_helpers.py index f6adb77..c375719 100644 --- a/tests/pydantic/test_low_level_helpers.py +++ b/tests/pydantic/test_low_level_helpers.py @@ -182,7 +182,7 @@ def __repr__(self) -> str: ) assert serializer.serialize({"payload": b"hi\xff"}) == '{\n "payload": "hi\\ufffd"\n}' serialized_binary_image = serializer.serialize( - [BinaryImage(data=b"hi", media_type="image/png")] + [BinaryImage(data=b"hi", media_type="image/png")], ) assert "image/png" in serialized_binary_image assert ( @@ -196,8 +196,8 @@ def __repr__(self) -> str: 3, 1.5, "ok", - ) - } + ), + }, ) == '{\n "items": [\n "hi\\ufffd",\n "demo-object",\n null,\n true,\n 3,\n 1.5,\n "ok"\n ]\n}' ) @@ -250,7 +250,9 @@ async def release_terminal(self, *args: Any, **kwargs: Any) -> ReleaseTerminalRe return ReleaseTerminalResponse() async def wait_for_terminal_exit( - self, *args: Any, **kwargs: Any + self, + *args: Any, + **kwargs: Any, ) -> WaitForTerminalExitResponse: self.calls.append(("wait_for_terminal_exit", args, dict(kwargs))) return WaitForTerminalExitResponse(exit_code=0) @@ -260,8 +262,8 @@ async def kill_terminal(self, *args: Any, **kwargs: Any) -> KillTerminalResponse return KillTerminalResponse() client = FakeClient() - filesystem = ClientFilesystemBackend(client=cast(Any, client), session=session) - terminal = ClientTerminalBackend(client=cast(Any, client), session=session) + filesystem = ClientFilesystemBackend(client=cast("Any", client), session=session) + terminal = ClientTerminalBackend(client=cast("Any", client), session=session) assert asyncio.run(filesystem.read_text_file("note.txt", limit=3, line=1)).content == "hello" assert asyncio.run(filesystem.write_text_file("note.txt", "body")) is not None @@ -273,7 +275,7 @@ async def kill_terminal(self, *args: Any, **kwargs: Any) -> KillTerminalResponse cwd=str(tmp_path), env=[EnvVariable(name="X", value="1")], output_byte_limit=10, - ) + ), ).terminal_id == "term-1" ) @@ -287,65 +289,80 @@ async def kill_terminal(self, *args: Any, **kwargs: Any) -> KillTerminalResponse assert client.calls[2][0] == "create_terminal" assert client.calls[2][2]["session_id"] == "protocols" - assert cast(Any, AgentFactory.__call__)(_LOW_LEVEL_SENTINEL, session) is None - assert asyncio.run(cast(Any, AgentSource.get_agent)(_LOW_LEVEL_SENTINEL, session)) is None + assert cast("Any", AgentFactory.__call__)(_LOW_LEVEL_SENTINEL, session) is None + assert asyncio.run(cast("Any", AgentSource.get_agent)(_LOW_LEVEL_SENTINEL, session)) is None assert ( asyncio.run( - cast(Any, AgentSource.get_deps)(_LOW_LEVEL_SENTINEL, session, _LOW_LEVEL_SENTINEL) + cast("Any", AgentSource.get_deps)(_LOW_LEVEL_SENTINEL, session, _LOW_LEVEL_SENTINEL), ) is None ) assert ( - asyncio.run(cast(Any, FilesystemBackend.read_text_file)(_LOW_LEVEL_SENTINEL, "x")) is None + asyncio.run(cast("Any", FilesystemBackend.read_text_file)(_LOW_LEVEL_SENTINEL, "x")) is None + ) + assert ( + asyncio.run(cast("Any", FilesystemBackend.write_text_file)(_LOW_LEVEL_SENTINEL, "x", "y")) + is None ) assert ( - asyncio.run(cast(Any, FilesystemBackend.write_text_file)(_LOW_LEVEL_SENTINEL, "x", "y")) + asyncio.run(cast("Any", TerminalBackend.create_terminal)(_LOW_LEVEL_SENTINEL, "bash")) is None ) assert ( - asyncio.run(cast(Any, TerminalBackend.create_terminal)(_LOW_LEVEL_SENTINEL, "bash")) is None + asyncio.run(cast("Any", TerminalBackend.terminal_output)(_LOW_LEVEL_SENTINEL, "t")) is None ) - assert asyncio.run(cast(Any, TerminalBackend.terminal_output)(_LOW_LEVEL_SENTINEL, "t")) is None assert ( - asyncio.run(cast(Any, TerminalBackend.release_terminal)(_LOW_LEVEL_SENTINEL, "t")) is None + asyncio.run(cast("Any", TerminalBackend.release_terminal)(_LOW_LEVEL_SENTINEL, "t")) is None ) assert ( - asyncio.run(cast(Any, TerminalBackend.wait_for_terminal_exit)(_LOW_LEVEL_SENTINEL, "t")) + asyncio.run(cast("Any", TerminalBackend.wait_for_terminal_exit)(_LOW_LEVEL_SENTINEL, "t")) is None ) - assert asyncio.run(cast(Any, TerminalBackend.kill_terminal)(_LOW_LEVEL_SENTINEL, "t")) is None + assert asyncio.run(cast("Any", TerminalBackend.kill_terminal)(_LOW_LEVEL_SENTINEL, "t")) is None assert ( - cast(Any, SessionModelsProvider.get_model_state)( - _LOW_LEVEL_SENTINEL, session, _LOW_LEVEL_SENTINEL + cast("Any", SessionModelsProvider.get_model_state)( + _LOW_LEVEL_SENTINEL, + session, + _LOW_LEVEL_SENTINEL, ) is None ) assert ( - cast(Any, SessionModelsProvider.set_model)( - _LOW_LEVEL_SENTINEL, session, _LOW_LEVEL_SENTINEL, "m" + cast("Any", SessionModelsProvider.set_model)( + _LOW_LEVEL_SENTINEL, + session, + _LOW_LEVEL_SENTINEL, + "m", ) is None ) assert ( - cast(Any, SessionModesProvider.get_mode_state)( - _LOW_LEVEL_SENTINEL, session, _LOW_LEVEL_SENTINEL + cast("Any", SessionModesProvider.get_mode_state)( + _LOW_LEVEL_SENTINEL, + session, + _LOW_LEVEL_SENTINEL, ) is None ) assert ( - cast(Any, SessionModesProvider.set_mode)( - _LOW_LEVEL_SENTINEL, session, _LOW_LEVEL_SENTINEL, "plan" + cast("Any", SessionModesProvider.set_mode)( + _LOW_LEVEL_SENTINEL, + session, + _LOW_LEVEL_SENTINEL, + "plan", ) is None ) assert ( - cast(Any, ConfigOptionsProvider.get_config_options)( - _LOW_LEVEL_SENTINEL, session, _LOW_LEVEL_SENTINEL + cast("Any", ConfigOptionsProvider.get_config_options)( + _LOW_LEVEL_SENTINEL, + session, + _LOW_LEVEL_SENTINEL, ) is None ) assert ( - cast(Any, ConfigOptionsProvider.set_config_option)( + cast("Any", ConfigOptionsProvider.set_config_option)( _LOW_LEVEL_SENTINEL, session, _LOW_LEVEL_SENTINEL, @@ -355,17 +372,20 @@ async def kill_terminal(self, *args: Any, **kwargs: Any) -> KillTerminalResponse is None ) assert ( - cast(Any, PlanProvider.get_plan)(_LOW_LEVEL_SENTINEL, session, _LOW_LEVEL_SENTINEL) is None + cast("Any", PlanProvider.get_plan)(_LOW_LEVEL_SENTINEL, session, _LOW_LEVEL_SENTINEL) + is None ) assert ( - cast(Any, ApprovalStateProvider.get_approval_state)( - _LOW_LEVEL_SENTINEL, session, _LOW_LEVEL_SENTINEL + cast("Any", ApprovalStateProvider.get_approval_state)( + _LOW_LEVEL_SENTINEL, + session, + _LOW_LEVEL_SENTINEL, ) is None ) - assert cast(Any, SessionStore.delete)(_LOW_LEVEL_SENTINEL, "missing") is None + assert cast("Any", SessionStore.delete)(_LOW_LEVEL_SENTINEL, "missing") is None assert ( - cast(Any, SessionStore.fork)( + cast("Any", SessionStore.fork)( _LOW_LEVEL_SENTINEL, "missing", new_session_id="copy", @@ -373,9 +393,9 @@ async def kill_terminal(self, *args: Any, **kwargs: Any) -> KillTerminalResponse ) is None ) - assert cast(Any, SessionStore.get)(_LOW_LEVEL_SENTINEL, "missing") is None - assert cast(Any, SessionStore.list_sessions)(_LOW_LEVEL_SENTINEL) is None - assert cast(Any, SessionStore.save)(_LOW_LEVEL_SENTINEL, session) is None + assert cast("Any", SessionStore.get)(_LOW_LEVEL_SENTINEL, "missing") is None + assert cast("Any", SessionStore.list_sessions)(_LOW_LEVEL_SENTINEL) is None + assert cast("Any", SessionStore.save)(_LOW_LEVEL_SENTINEL, session) is None def test_file_session_store_covers_delete_fork_missing_and_list_skip( @@ -507,7 +527,7 @@ async def run_plain() -> None: await wrapped_plain(messages) async def run_contextual() -> None: - await wrapped_contextual(cast(RunContext[None], None), messages) + await wrapped_contextual(cast("RunContext[None]", None), messages) with pytest.raises(RuntimeError, match="plain boom"): asyncio.run(run_plain()) @@ -537,14 +557,14 @@ def test_prepare_tools_bridge_covers_validation_none_and_require_mode( PrepareToolsMode( id="chat", name="Chat", - prepare_func=cast(Any, lambda _c, _t: None), - ) + prepare_func=cast("Any", lambda _c, _t: None), + ), ], ) session = _session(tmp_path) async def run_prepare() -> Any: - prepared = bridge.build_prepare_tools(session)(cast(RunContext[None], None), []) + prepared = bridge.build_prepare_tools(session)(cast("RunContext[None]", None), []) if asyncio.iscoroutine(prepared): return await prepared assert prepared is not None # pragma: no cover @@ -646,7 +666,7 @@ def test_hook_projection_map_covers_hidden_fallbacks_and_truncation() -> None: def test_prompt_history_handles_resources_and_usage_paths() -> None: prompt = cast( - list[Any], + "list[Any]", [ ResourceContentBlock(type="resource_link", name="doc", uri="file:///doc"), EmbeddedResourceContentBlock( @@ -674,8 +694,8 @@ def test_prompt_history_handles_resources_and_usage_paths() -> None: parts=[ TextPart("keep"), ToolCallPart("demo_tool", {}, tool_call_id="call-1"), - ] - ) + ], + ), ] sanitized = sanitize_message_history(unresolved, error_text="traceback here") assert len(sanitized) == 2 @@ -687,9 +707,9 @@ def test_prompt_history_handles_resources_and_usage_paths() -> None: history = dump_message_history( [ ModelResponse( - parts=[TextPart("The previous run failed before completion.\n\nTraceback:\nboom")] - ) - ] + parts=[TextPart("The previous run failed before completion.\n\nTraceback:\nboom")], + ), + ], ) error_history = build_error_history( history, @@ -719,7 +739,7 @@ def test_prompt_history_handles_resources_and_usage_paths() -> None: def test_prompt_to_input_maps_resource_links_and_blob_resources() -> None: prompt = cast( - list[Any], + "list[Any]", [ TextContentBlock(type="text", text="hello"), ResourceContentBlock( @@ -758,7 +778,7 @@ def test_prompt_to_input_maps_resource_links_and_blob_resources() -> None: assert prompt_input[3].media_type == "application/pdf" document_prompt = cast( - list[Any], + "list[Any]", [ ResourceContentBlock( type="resource_link", @@ -790,14 +810,14 @@ def test_prompt_to_input_maps_resource_links_and_blob_resources() -> None: def test_prompt_history_covers_cancelled_resource_and_blank_text_edges() -> None: unknown_resource_prompt = cast( - list[Any], + "list[Any]", [ ResourceContentBlock( type="resource_link", name="", uri="resource://opaque-item", mime_type=None, - ) + ), ], ) @@ -820,10 +840,10 @@ def test_prompt_history_covers_cancelled_resource_and_blank_text_edges() -> None assert cancelled_texts == ["User stopped the run.\n\nRun details:\ncancelled"] existing_cancelled = dump_message_history( - [ModelResponse(parts=[TextPart("User stopped the run.\n\nRun details:\ncancelled")])] + [ModelResponse(parts=[TextPart("User stopped the run.\n\nRun details:\ncancelled")])], ) loaded_cancelled = load_message_history( - build_cancelled_history(existing_cancelled, prompt_text="", details_text="cancelled") + build_cancelled_history(existing_cancelled, prompt_text="", details_text="cancelled"), ) repeated_cancelled_texts = [ part.content @@ -841,18 +861,18 @@ def test_prompt_history_covers_cancelled_resource_and_blank_text_edges() -> None assert _find_unprocessed_tool_calls([ModelResponse(parts=[tool_call])]) == [tool_call] assert ( _find_unprocessed_tool_calls( - [ModelResponse(parts=[tool_call]), ModelRequest(parts=[tool_result])] + [ModelResponse(parts=[tool_call]), ModelRequest(parts=[tool_result])], ) == [] ) assert ( _find_unprocessed_tool_calls( - [ModelRequest(parts=[tool_result]), ModelResponse(parts=[tool_call])] + [ModelRequest(parts=[tool_result]), ModelResponse(parts=[tool_call])], ) == [] ) assert _find_unprocessed_tool_calls( - [cast(Any, SimpleNamespace()), ModelResponse(parts=[tool_call])] + [cast("Any", SimpleNamespace()), ModelResponse(parts=[tool_call])], ) == [tool_call] @@ -867,7 +887,7 @@ def test_prompt_to_input_keeps_text_only_prompt_as_string() -> None: def test_prompt_to_input_preserves_zed_git_diff_selection_context() -> None: uri = "zed:///agent/git-diff?base=main" prompt = cast( - list[Any], + "list[Any]", [ EmbeddedResourceContentBlock( type="resource", @@ -876,7 +896,7 @@ def test_prompt_to_input_preserves_zed_git_diff_selection_context() -> None: text="diff --git a/app.py b/app.py\n@@ -1 +1 @@\n-old\n+new", mime_type="text/x-diff", ), - ) + ), ], ) @@ -902,7 +922,7 @@ def test_prompt_to_input_preserves_file_refs_rule_text_and_directory_links() -> coverage_uri = "file:///workspace/acpkit/COVERAGE" repo_uri = "file:///workspace/acpkit" prompt = cast( - list[Any], + "list[Any]", [ TextContentBlock(type="text", text="@rule iyi kod yaz"), EmbeddedResourceContentBlock( @@ -977,7 +997,7 @@ def test_session_state_round_trips_and_rejects_invalid_payloads(tmp_path: Path) session_update="user_message_chunk", content=text_block("hello"), message_id="msg-1", - ) + ), ) restored = update.to_update() assert restored.session_update == "user_message_chunk" @@ -987,7 +1007,7 @@ def test_session_state_round_trips_and_rejects_invalid_payloads(tmp_path: Path) title="Demo", updated_at=utc_now().isoformat(), field_meta={"demo": {"ok": True}}, - ) + ), ) assert session_info_update.to_update().session_update == "session_info_update" @@ -997,7 +1017,7 @@ def model_dump(self, **kwargs): return {"nope": "missing"} with pytest.raises(TypeError, match="missing `sessionUpdate`"): - StoredSessionUpdate.from_update(cast(Any, BadUpdate())) + StoredSessionUpdate.from_update(cast("Any", BadUpdate())) with pytest.raises(TypeError, match="Expected a JSON object"): _coerce_json_object("x") with pytest.raises(TypeError, match="keys must be strings"): @@ -1005,7 +1025,7 @@ def model_dump(self, **kwargs): with pytest.raises(TypeError, match="Unsupported JSON value"): _coerce_json_value(_LOW_LEVEL_SENTINEL) with pytest.raises(AssertionError): - StoredSessionUpdate(kind=cast(Any, "unknown"), payload={}).to_update() + StoredSessionUpdate(kind=cast("Any", "unknown"), payload={}).to_update() def test_session_surface_helpers_handle_missing_state_and_errors() -> None: @@ -1017,7 +1037,7 @@ def test_session_surface_helpers_handle_missing_state_and_errors() -> None: config_option_name="Model", config_option_description="Select", available_models=[model], - ) + ), ) with pytest.raises(RequestError): build_mode_config_option(ModeState(current_mode_id=None, modes=[])) @@ -1030,7 +1050,7 @@ def test_session_surface_helpers_handle_missing_state_and_errors() -> None: ModeState( current_mode_id="plan", modes=[SessionMode(id="plan", name="Plan", description="d")], - ) + ), ) assert mode_state is not None assert mode_state.current_mode_id == "plan" @@ -1089,32 +1109,32 @@ class MetadataOnlyBridge(CapabilityBridge): def get_session_metadata(self, session, agent): del session, agent # pragma: no cover - return cast(Any, {"hidden": True}) # pragma: no cover + return cast("Any", {"hidden": True}) # pragma: no cover class FullBridge(CapabilityBridge): metadata_key = "visible" def drain_updates(self, session, agent): del session, agent - return cast(Any, [_LOW_LEVEL_SENTINEL]) + return cast("Any", [_LOW_LEVEL_SENTINEL]) def get_config_options(self, session, agent): del session, agent return cast( - Any, + "Any", [ SessionConfigOptionBoolean( id="flag", name="Flag", type="boolean", current_value=True, - ) + ), ], ) def get_mcp_capabilities(self, agent=None): del agent - return cast(Any, SimpleNamespace(http=True, sse=False)) + return cast("Any", SimpleNamespace(http=True, sse=False)) def get_mode_state(self, session, agent): del session, agent @@ -1122,21 +1142,21 @@ def get_mode_state(self, session, agent): def get_session_metadata(self, session, agent): del session, agent - return cast(Any, {"ok": True}) + return cast("Any", {"ok": True}) def set_config_option(self, session, agent, config_id, value): del session, agent if config_id != "flag": return None return cast( - Any, + "Any", [ SessionConfigOptionBoolean( id="flag", name="Flag", type="boolean", current_value=bool(value), - ) + ), ], ) @@ -1159,7 +1179,6 @@ class EmptyMetadataBridge(CapabilityBridge): def get_session_metadata(self, session, agent): del session, agent - return None manager = BridgeManager( base_classifier=DefaultToolClassifier(), @@ -1236,11 +1255,11 @@ def test_projection_helpers_handle_fallback_and_edge_paths( assert extract_tool_call_locations({"other": "x"}) is None assert _candidate_keys(None, ("a", "b")) == ("a", "b") assert _candidate_keys("x", ("a", "b")) == ("x", "a", "b") - assert cast(Any, ToolClassifier.classify)(_LOW_LEVEL_SENTINEL, "tool") is None - assert cast(Any, ToolClassifier.approval_policy_key)(_LOW_LEVEL_SENTINEL, "tool") is None - assert cast(Any, ProjectionMap.project_start)(_LOW_LEVEL_SENTINEL, "tool") is None + assert cast("Any", ToolClassifier.classify)(_LOW_LEVEL_SENTINEL, "tool") is None + assert cast("Any", ToolClassifier.approval_policy_key)(_LOW_LEVEL_SENTINEL, "tool") is None + assert cast("Any", ProjectionMap.project_start)(_LOW_LEVEL_SENTINEL, "tool") is None assert ( - cast(Any, ProjectionMap.project_progress)( + cast("Any", ProjectionMap.project_progress)( _LOW_LEVEL_SENTINEL, "tool", serialized_output="x", @@ -1253,7 +1272,7 @@ def test_projection_helpers_handle_fallback_and_edge_paths( [ ToolProjection(title="first"), ToolProjection(status="failed"), - ] + ], ) assert merged is not None assert merged.title == "first" @@ -1276,7 +1295,7 @@ def test_projection_helpers_handle_fallback_and_edge_paths( assert _preserve_file_diff_content( known_start=known_start, projection=ToolProjection( - content=[ContentToolCallContent(type="content", content=text_block("x"))] + content=[ContentToolCallContent(type="content", content=text_block("x"))], ), ) == [ContentToolCallContent(type="content", content=text_block("x"))] assert ( @@ -1365,13 +1384,13 @@ def test_projection_helpers_handle_fallback_and_edge_paths( duplicate_updates = build_tool_updates( [ ModelResponse( - parts=[ToolCallPart("write_file", {"path": "a", "content": "b"}, tool_call_id="1")] + parts=[ToolCallPart("write_file", {"path": "a", "content": "b"}, tool_call_id="1")], ), ModelRequest( parts=[ ToolReturnPart("final_result", "done"), RetryPromptPart("retry", tool_name=None), - ] + ], ), ], classifier=DefaultToolClassifier(), @@ -1398,7 +1417,7 @@ def test_native_approval_bridge_handles_remembered_policies_and_invalid_options( session=session, requests=requests, classifier=classifier, - ) + ), ) assert isinstance(resolution.deferred_tool_results.approvals["1"], ToolApproved) session.metadata["approval_policies"] = {"write_file": "reject"} @@ -1408,7 +1427,7 @@ def test_native_approval_bridge_handles_remembered_policies_and_invalid_options( session=session, requests=requests, classifier=classifier, - ) + ), ) assert isinstance(rejected.deferred_tool_results.approvals["1"], ToolDenied) @@ -1416,7 +1435,7 @@ class InvalidOptionClient(RecordingClient): async def request_permission(self, *args, **kwargs): del args, kwargs return RequestPermissionResponse( - outcome=AllowedOutcome(outcome="selected", option_id="bad-option") + outcome=AllowedOutcome(outcome="selected", option_id="bad-option"), ) session.metadata["approval_policies"] = "bad" @@ -1427,7 +1446,7 @@ async def request_permission(self, *args, **kwargs): session=session, requests=requests, classifier=classifier, - ) + ), ) disabled = NativeApprovalBridge(enable_persistent_choices=False) @@ -1524,7 +1543,7 @@ def test_build_tool_updates_filters_output_parts_and_empty_messages() -> None: updates = build_tool_updates( [ ModelResponse( - parts=[ToolCallPart("final_result", {"value": "done"}, tool_call_id="final-1")] + parts=[ToolCallPart("final_result", {"value": "done"}, tool_call_id="final-1")], ), ModelRequest(parts=[ToolReturnPart("final_result", "done")]), ], diff --git a/tests/pydantic/test_models.py b/tests/pydantic/test_models.py index 8c3046b..22c5ed6 100644 --- a/tests/pydantic/test_models.py +++ b/tests/pydantic/test_models.py @@ -56,7 +56,7 @@ def _passthrough_tools( def test_passthrough_tools_model_helper_returns_a_copy() -> None: tool_defs: list[ToolDefinition] = [] - copied = _passthrough_tools(cast(Any, None), tool_defs) + copied = _passthrough_tools(cast("Any", None), tool_defs) assert copied == [] assert copied is not tool_defs @@ -128,13 +128,13 @@ def test_session_model_override_is_session_local(tmp_path: Path) -> None: adapter.prompt( prompt=[text_block("Use the default model.")], session_id=first_session.session_id, - ) + ), ) asyncio.run( adapter.prompt( prompt=[text_block("Use the overridden model.")], session_id=second_session.session_id, - ) + ), ) assert agent_message_texts(client) == ["default", "switched"] @@ -167,7 +167,7 @@ def test_set_config_option_model_updates_current_model(tmp_path: Path) -> None: config_id="model", session_id=new_session_response.session_id, value="model-b", - ) + ), ) assert config_response is not None @@ -218,7 +218,7 @@ def test_provider_backed_surface_exposes_modes_config_and_plan(tmp_path: Path) - assert session_info_updates assert session_info_updates[-1].field_meta is not None assert session_info_updates[-1].field_meta["pydantic_acp"]["plan_storage"] == { - "directory": str(tmp_path / ".acpkit" / "plans") + "directory": str(tmp_path / ".acpkit" / "plans"), } client.updates.clear() @@ -227,7 +227,7 @@ def test_provider_backed_surface_exposes_modes_config_and_plan(tmp_path: Path) - cwd=str(tmp_path), session_id=new_session_response.session_id, mcp_servers=[], - ) + ), ) assert resume_response.modes is not None @@ -279,9 +279,9 @@ def test_plan_mode_sets_native_plan_from_structured_task_plan_output( description="Native plan mode.", prepare_func=_passthrough_tools, plan_mode=True, - ) + ), ], - ) + ), ], session_store=MemorySessionStore(), ), @@ -296,7 +296,7 @@ def test_plan_mode_sets_native_plan_from_structured_task_plan_output( adapter.prompt( prompt=[text_block("Create a plan for this task.")], session_id=session.session_id, - ) + ), ) plan_updates = [update for _, update in client.updates if isinstance(update, AgentPlanUpdate)] @@ -349,8 +349,8 @@ def route_plan_generation( ], "plan_md": "# Native Plan\n\n- Inspect the repo\n- Save the plan\n", }, - ) - ] + ), + ], ) raise AssertionError("expected a user prompt or tool return") # pragma: no cover @@ -370,9 +370,9 @@ def route_plan_generation( description="Native plan mode.", prepare_func=_passthrough_tools, plan_mode=True, - ) + ), ], - ) + ), ], session_store=MemorySessionStore(), ), @@ -382,7 +382,7 @@ def route_plan_generation( session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) config_response = asyncio.run( - adapter.set_config_option("plan_generation_type", session.session_id, "tools") + adapter.set_config_option("plan_generation_type", session.session_id, "tools"), ) assert config_response is not None assert any( @@ -395,7 +395,7 @@ def route_plan_generation( adapter.prompt( prompt=[text_block("Plan the implementation.")], session_id=session.session_id, - ) + ), ) plan_updates = [update for _, update in client.updates if isinstance(update, AgentPlanUpdate)] @@ -432,8 +432,8 @@ def route_plan_progress( ToolCallPart( "acp_update_plan_entry", {"index": 1, "status": "in_progress"}, - ) - ] + ), + ], ) raise AssertionError("expected a user prompt or tool return") # pragma: no cover @@ -453,9 +453,9 @@ def route_plan_progress( description="Execution mode with plan progress tools.", prepare_func=_passthrough_tools, plan_tools=True, - ) + ), ], - ) + ), ], session_store=MemorySessionStore(), ), @@ -464,7 +464,7 @@ def route_plan_progress( adapter.on_connect(client) session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) - adapter_config = cast(_AdapterWithConfig, adapter)._config + adapter_config = cast("_AdapterWithConfig", adapter)._config stored_session = adapter_config.session_store.get(session.session_id) assert stored_session is not None stored_session.plan_markdown = "# Plan\n\n1. Implement the first item\n2. Verify it\n" @@ -487,7 +487,7 @@ def route_plan_progress( adapter.prompt( prompt=[text_block("Implement the first plan item.")], session_id=session.session_id, - ) + ), ) plan_updates = [update for _, update in client.updates if isinstance(update, AgentPlanUpdate)] @@ -522,20 +522,20 @@ def test_provider_backed_updates_drive_prompt_state(tmp_path: Path) -> None: client.updates.clear() set_mode_response = asyncio.run( - adapter.set_session_mode(mode_id="review", session_id=second_session.session_id) + adapter.set_session_mode(mode_id="review", session_id=second_session.session_id), ) set_stream_response = asyncio.run( adapter.set_config_option( config_id="stream_enabled", session_id=second_session.session_id, value=True, - ) + ), ) asyncio.run( adapter.set_session_model( model_id="provider-model-b", session_id=second_session.session_id, - ) + ), ) assert set_mode_response is not None @@ -564,13 +564,13 @@ def test_provider_backed_updates_drive_prompt_state(tmp_path: Path) -> None: adapter.prompt( prompt=[text_block("Use the provider default model.")], session_id=first_session.session_id, - ) + ), ) asyncio.run( adapter.prompt( prompt=[text_block("Use the provider override.")], session_id=second_session.session_id, - ) + ), ) assert agent_message_texts(client) == ["provider:model-a", "provider:model-b"] @@ -603,7 +603,7 @@ def test_reserved_model_config_option_falls_back_to_provider(tmp_path: Path) -> config_id="model", session_id=session.session_id, value="provider-model-b", - ) + ), ) assert response is not None @@ -628,7 +628,7 @@ def test_freeform_model_provider_omits_select_option_and_accepts_custom_ids( adapter.set_session_model( model_id="custom-model-z", session_id=session.session_id, - ) + ), ) stored_session = session_store.get(session.session_id) @@ -656,14 +656,14 @@ def test_async_mode_config_and_plan_providers_are_supported(tmp_path: Path) -> N session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) set_mode_response = asyncio.run( - adapter.set_session_mode(mode_id="review", session_id=session.session_id) + adapter.set_session_mode(mode_id="review", session_id=session.session_id), ) set_stream_response = asyncio.run( adapter.set_config_option( config_id="stream_enabled", session_id=session.session_id, value=True, - ) + ), ) assert set_mode_response is not None @@ -700,7 +700,7 @@ def test_set_session_model_returns_none_without_model_support(tmp_path: Path) -> session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) response = asyncio.run( - adapter.set_session_model(model_id="openai:gpt-5", session_id=session.session_id) + adapter.set_session_model(model_id="openai:gpt-5", session_id=session.session_id), ) stored_session = session_store.get(session.session_id) @@ -719,7 +719,7 @@ def test_set_session_model_rejects_unknown_model_id(tmp_path: Path) -> None: model_id="model-a", name="Model A", override=TestModel(custom_output_text="default", model_name="model-a"), - ) + ), ], session_store=MemorySessionStore(), ), @@ -728,7 +728,7 @@ def test_set_session_model_rejects_unknown_model_id(tmp_path: Path) -> None: session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) with pytest.raises(RequestError): asyncio.run( - adapter.set_session_model(model_id="missing-model", session_id=session.session_id) + adapter.set_session_model(model_id="missing-model", session_id=session.session_id), ) @@ -752,7 +752,7 @@ def test_set_config_option_rejects_invalid_model_and_mode_value_types( config_id="model", session_id=session.session_id, value=False, - ) + ), ) with pytest.raises(RequestError): asyncio.run( @@ -760,7 +760,7 @@ def test_set_config_option_rejects_invalid_model_and_mode_value_types( config_id="mode", session_id=session.session_id, value=False, - ) + ), ) @@ -776,7 +776,7 @@ def test_set_config_option_returns_none_for_unknown_option(tmp_path: Path) -> No config_id="missing_option", session_id=session.session_id, value=True, - ) + ), ) assert response is None diff --git a/tests/pydantic/test_projection.py b/tests/pydantic/test_projection.py index 3a2677b..b9c76be 100644 --- a/tests/pydantic/test_projection.py +++ b/tests/pydantic/test_projection.py @@ -92,7 +92,7 @@ def write_file(path: str, content: str, old_text: str) -> str: adapter.prompt( prompt=[text_block("Update the file.")], session_id=session.session_id, - ) + ), ) tool_updates = [ @@ -141,7 +141,7 @@ def read_file(path: str) -> str: adapter.prompt( prompt=[text_block("Read the file.")], session_id=session.session_id, - ) + ), ) tool_updates = [ @@ -185,7 +185,7 @@ def read_file(path: str) -> str: adapter.prompt( prompt=[text_block("Read the file.")], session_id=session.session_id, - ) + ), ) tool_updates = [ @@ -228,7 +228,7 @@ def write_file(path: str, content: str) -> str: adapter.prompt( prompt=[text_block("Update the file.")], session_id=session.session_id, - ) + ), ) tool_start = next(update for _, update in client.updates if isinstance(update, ToolCallStart)) @@ -260,7 +260,7 @@ def run_shell(script: str) -> dict[str, str | int]: FileSystemProjectionMap( default_bash_tool="run_shell", command_arg="script", - ) + ), ], ) client = RecordingClient() @@ -271,7 +271,7 @@ def run_shell(script: str) -> dict[str, str | int]: adapter.prompt( prompt=[text_block("Run the shell command.")], session_id=session.session_id, - ) + ), ) tool_updates = [ @@ -309,7 +309,7 @@ def run_shell(script: str) -> dict[str, str | int]: "```text", "hello", "```", - ) + ), ) assert tool_progress.status == "completed" @@ -337,7 +337,7 @@ def run_shell(script: str) -> dict[str, str | int]: FileSystemProjectionMap( default_bash_tool="run_shell", command_arg="script", - ) + ), ], ) client = RecordingClient() @@ -348,7 +348,7 @@ def run_shell(script: str) -> dict[str, str | int]: adapter.prompt( prompt=[text_block("Run the shell command.")], session_id=session.session_id, - ) + ), ) tool_progress = next( @@ -371,7 +371,7 @@ def run_shell(script: str) -> dict[str, str | int]: "```text", "boom", "```", - ) + ), ) @@ -403,7 +403,7 @@ def test_builtin_web_search_projection_renders_query_and_results() -> None: "title": "ACP Kit", "url": "https://example.com/acpkit", "snippet": "Adapter toolkit for truthful ACP servers.", - } + }, ], ), classifier=classifier, @@ -507,8 +507,8 @@ def test_build_tool_updates_supports_builtin_tool_call_and_return_parts() -> Non tool_name="web_search", args={"query": "acpkit"}, tool_call_id="search-1", - ) - ] + ), + ], ), ModelResponse( parts=[ @@ -516,8 +516,8 @@ def test_build_tool_updates_supports_builtin_tool_call_and_return_parts() -> Non tool_name="web_search", tool_call_id="search-1", content={"results": [{"title": "ACP Kit", "href": "https://example.com"}]}, - ) - ] + ), + ], ), ], classifier=DefaultToolClassifier(), @@ -668,10 +668,10 @@ def test_build_compaction_updates_renders_anthropic_summary() -> None: CompactionPart( content="Summary of prior conversation.", provider_name="anthropic", - ) - ] - ) - ] + ), + ], + ), + ], ) assert len(updates) == 2 @@ -688,7 +688,7 @@ def test_build_compaction_updates_renders_anthropic_summary() -> None: "", "Summary:", "Summary of prior conversation.", - ) + ), ) @@ -709,7 +709,7 @@ def run_shell(script: str) -> dict[str, str]: FileSystemProjectionMap( default_bash_tool="run_shell", command_arg="script", - ) + ), ], ) client = RecordingClient() @@ -720,7 +720,7 @@ def run_shell(script: str) -> dict[str, str]: adapter.prompt( prompt=[text_block("Run the shell command.")], session_id=session.session_id, - ) + ), ) tool_progress = next( @@ -902,7 +902,7 @@ def raise_oserror(self: Path, encoding: str = "utf-8", errors: str = "replace") "```bash", "echo hello", "```", - ) + ), ) assert "User location: Istanbul, TR, Europe/Istanbul" in _format_web_search_start( @@ -913,7 +913,7 @@ def raise_oserror(self: Path, encoding: str = "utf-8", errors: str = "replace") "country": "TR", "timezone": "Europe/Istanbul", }, - } + }, ) assert ( _format_web_search_progress( @@ -928,7 +928,7 @@ def raise_oserror(self: Path, encoding: str = "utf-8", errors: str = "replace") ) == ("Fetched binary content.") assert _format_image_generation_start({}) == "Generating image." assert _format_mcp_start("mcp_server:repo", {"action": "list_tools"}) == "\n".join( - ("Server: repo", "Action: list_tools") + ("Server: repo", "Action: list_tools"), ) assert _format_mcp_progress({"tools": [{"id": "search"}]}, "fallback") == "Tools listed: 1" assert _format_mcp_progress("invalid", "fallback") == "fallback" @@ -986,14 +986,15 @@ def test_compaction_helpers_cover_skips_collisions_and_payload_variants() -> Non "compaction_id": "cmp-1", } assert _format_compaction_progress( - provider_details_part, provider_name="anthropic" + provider_details_part, + provider_name="anthropic", ) == "\n".join( ( "Provider: anthropic", "Status: history compacted", "Compaction payload stored for round-trip.", "Compaction id: cmp-1", - ) + ), ) assert _format_compaction_progress(completed_part, provider_name="anthropic") == "\n".join( ( @@ -1001,7 +1002,7 @@ def test_compaction_helpers_cover_skips_collisions_and_payload_variants() -> Non "Status: history compacted", "Compaction completed.", "Compaction id: cmp-2", - ) + ), ) collision_updates = build_compaction_updates( @@ -1060,7 +1061,7 @@ def test_build_tool_updates_skips_final_result_and_projects_retry_prompts() -> N tool_call_id="out-1", content="done", ), - ] + ], ), ModelRequest( parts=[ @@ -1068,8 +1069,8 @@ def test_build_tool_updates_skips_final_result_and_projects_retry_prompts() -> N "retry search", tool_name="web_search", tool_call_id="retry-1", - ) - ] + ), + ], ), ], classifier=DefaultToolClassifier(), @@ -1384,7 +1385,7 @@ def test_projection_aware_tool_classifier_uses_filesystem_projection_names() -> default_write_tool="save_document", default_bash_tool="run_command", default_search_tool="list_files", - ) + ), ], ) @@ -1448,10 +1449,10 @@ def test_projection_aware_tool_classifier_recurses_into_composite_maps() -> None FileSystemProjectionMap(default_read_tool="nested_read"), FileSystemProjectionMap(default_write_tool="nested_write"), FileSystemProjectionMap(default_bash_tool="nested_command"), - ) + ), ), - ) - ) + ), + ), ], ) diff --git a/tests/pydantic/test_runtime.py b/tests/pydantic/test_runtime.py index bfcb89c..171c9f4 100644 --- a/tests/pydantic/test_runtime.py +++ b/tests/pydantic/test_runtime.py @@ -100,7 +100,7 @@ def test_prompt_and_load_session_replay_history(tmp_path: Path) -> None: prompt=[text_block("Summarize the change.")], session_id=new_session_response.session_id, message_id="user-message-1", - ) + ), ) assert prompt_response.stop_reason == "end_turn" @@ -119,7 +119,7 @@ def test_prompt_and_load_session_replay_history(tmp_path: Path) -> None: cwd=str(tmp_path), session_id=new_session_response.session_id, mcp_servers=[], - ) + ), ) assert load_response is not None @@ -157,7 +157,7 @@ def test_initialize_negotiates_protocol_and_exposes_mcp_capabilities() -> None: servers=[ McpServerDefinition(server_id="http-server", name="HTTP", transport="http"), McpServerDefinition(server_id="sse-server", name="SSE", transport="sse"), - ] + ], ) adapter = create_acp_agent( agent=Agent(TestModel()), @@ -204,7 +204,8 @@ def read_file(path: str) -> str: return f"contents:{path}" adapter = create_acp_agent( - agent=agent, config=AdapterConfig(session_store=MemorySessionStore()) + agent=agent, + config=AdapterConfig(session_store=MemorySessionStore()), ) client = RecordingClient() adapter.on_connect(client) @@ -214,7 +215,7 @@ def read_file(path: str) -> str: adapter.prompt( prompt=[text_block("Read the file.")], session_id=new_session_response.session_id, - ) + ), ) tool_updates = [ @@ -248,7 +249,7 @@ def test_prompt_streams_text_chunks_with_shared_message_id(tmp_path: Path) -> No adapter.prompt( prompt=[text_block("Stream the answer.")], session_id=session.session_id, - ) + ), ) agent_updates = [ @@ -272,7 +273,7 @@ def test_optional_text_output_none_does_not_emit_literal_null(tmp_path: Path) -> adapter.prompt( prompt=[text_block("Return nothing if no answer is available.")], session_id=session.session_id, - ) + ), ) assert response.stop_reason == "end_turn" @@ -329,7 +330,7 @@ def review_tools(ctx, tool_defs): prepare_func=review_tools, ), ], - ) + ), ], ) first_adapter = create_acp_agent( @@ -341,14 +342,14 @@ def review_tools(ctx, tool_defs): session = asyncio.run(first_adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) set_mode_response = asyncio.run( - first_adapter.set_session_mode(mode_id="review", session_id=session.session_id) + first_adapter.set_session_mode(mode_id="review", session_id=session.session_id), ) assert set_mode_response is not None prompt_response = asyncio.run( first_adapter.prompt( prompt=[text_block("First run before restart.")], session_id=session.session_id, - ) + ), ) assert prompt_response.stop_reason == "end_turn" @@ -367,7 +368,7 @@ def review_tools(ctx, tool_defs): cwd=str(tmp_path), session_id=session.session_id, mcp_servers=[], - ) + ), ) assert loaded is not None assert loaded.modes is not None @@ -378,7 +379,7 @@ def review_tools(ctx, tool_defs): restarted_adapter.prompt( prompt=[text_block("Continue after restart.")], session_id=session.session_id, - ) + ), ) assert follow_up.stop_reason == "end_turn" assert agent_message_texts(restarted_client) == [ @@ -403,7 +404,7 @@ def test_file_session_store_skips_malformed_sessions_in_public_flows( assert [session.session_id for session in listed.sessions] == [valid_session.session_id] loaded = asyncio.run( - adapter.load_session(cwd=str(tmp_path), session_id="broken", mcp_servers=[]) + adapter.load_session(cwd=str(tmp_path), session_id="broken", mcp_servers=[]), ) assert loaded is None @@ -438,10 +439,10 @@ def test_interleaved_sessions_keep_selected_models_isolated(tmp_path: Path) -> N asyncio.run(adapter.prompt(prompt=[text_block("Run first once.")], session_id=first.session_id)) asyncio.run( - adapter.prompt(prompt=[text_block("Run second once.")], session_id=second.session_id) + adapter.prompt(prompt=[text_block("Run second once.")], session_id=second.session_id), ) asyncio.run( - adapter.prompt(prompt=[text_block("Run first again.")], session_id=first.session_id) + adapter.prompt(prompt=[text_block("Run first again.")], session_id=first.session_id), ) first_updates = [ @@ -483,7 +484,7 @@ def test_list_sessions_filters_by_cwd_and_orders_latest_first(tmp_path: Path) -> adapter.prompt( prompt=[text_block("Refresh alpha ordering.")], session_id=alpha_session.session_id, - ) + ), ) listed_all = asyncio.run(adapter.list_sessions()) diff --git a/tests/pydantic/test_session_runtime_helpers.py b/tests/pydantic/test_session_runtime_helpers.py index 979324a..6094f1f 100644 --- a/tests/pydantic/test_session_runtime_helpers.py +++ b/tests/pydantic/test_session_runtime_helpers.py @@ -36,7 +36,7 @@ def test_list_sessions_filters_by_cwd_and_close_session_handles_missing( agent=Agent(TestModel(custom_output_text="ok")), config=AdapterConfig(session_store=MemorySessionStore()), ) - adapter_any = cast(Any, adapter) + adapter_any = cast("Any", adapter) first = asyncio.run(adapter.new_session(cwd=str(tmp_path / "a"), mcp_servers=[])) second = asyncio.run(adapter.new_session(cwd=str(tmp_path / "b"), mcp_servers=[])) @@ -63,14 +63,14 @@ def keep_tools(_ctx: Any, tool_defs: list[Any]) -> list[Any]: AdapterModel( model_id="test:model", name="Test Model", - override=cast(Any, agent.model), - ) + override=cast("Any", agent.model), + ), ], capability_bridges=[ PrepareToolsBridge( default_mode_id="chat", modes=[PrepareToolsMode(id="chat", name="Chat", prepare_func=keep_tools)], - ) + ), ], session_store=MemorySessionStore(), ), @@ -108,7 +108,7 @@ def test_session_runtime_helper_inventory_and_missing_session_paths( config=AdapterConfig(session_store=MemorySessionStore()), ) session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) - adapter_any = cast(Any, adapter) + adapter_any = cast("Any", adapter) stored_session = adapter_any._config.session_store.get(session.session_id) assert stored_session is not None adapter_any._update_session_mcp_servers(stored_session, []) @@ -126,7 +126,7 @@ def test_set_session_model_covers_missing_state_and_unconfigured_selection( agent=Agent(TestModel(custom_output_text="ok")), config=AdapterConfig(session_store=MemorySessionStore()), ) - adapter_any = cast(Any, adapter) + adapter_any = cast("Any", adapter) runtime = adapter_any._session_runtime session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) @@ -162,7 +162,9 @@ async def fake_emit_updates(*_args: Any, **_kwargs: Any) -> None: monkeypatch.setattr(runtime, "_get_model_selection_state", permissive_model_state) monkeypatch.setattr( - runtime, "_resolve_unconfigured_model_id", lambda model_id: model_id.strip() + runtime, + "_resolve_unconfigured_model_id", + lambda model_id: model_id.strip(), ) monkeypatch.setattr(runtime, "_remember_default_model", lambda _agent: None) monkeypatch.setattr(runtime, "_build_session_surface", fake_build_surface) @@ -198,10 +200,10 @@ def set_config_option( agent=Agent(TestModel(custom_output_text="ok")), config=AdapterConfig( session_store=MemorySessionStore(), - capability_bridges=[cast(Any, BridgeConfigOptionHandler())], + capability_bridges=[cast("Any", BridgeConfigOptionHandler())], ), ) - adapter_any = cast(Any, adapter) + adapter_any = cast("Any", adapter) runtime = adapter_any._session_runtime session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) @@ -238,7 +240,7 @@ def test_session_runtime_misc_runtime_helpers_and_serialization( agent=agent, config=AdapterConfig(session_store=MemorySessionStore()), ) - adapter_any = cast(Any, adapter) + adapter_any = cast("Any", adapter) runtime = adapter_any._session_runtime session = asyncio.run(adapter.new_session(cwd=str(tmp_path), mcp_servers=[])) stored_session = adapter_any._config.session_store.get(session.session_id) @@ -274,7 +276,7 @@ def test_session_runtime_misc_runtime_helpers_and_serialization( "command": "python", "name": "repo", "transport": "stdio", - } + }, ] current_model = " " @@ -283,8 +285,11 @@ def test_session_runtime_misc_runtime_helpers_and_serialization( assert ( asyncio.run( runtime._build_config_options( - stored_session, agent, model_selection_state=None, mode_state=None - ) + stored_session, + agent, + model_selection_state=None, + mode_state=None, + ), ) is None ) diff --git a/tests/pydantic/test_slash_commands.py b/tests/pydantic/test_slash_commands.py index 216df07..6f86fbf 100644 --- a/tests/pydantic/test_slash_commands.py +++ b/tests/pydantic/test_slash_commands.py @@ -153,8 +153,8 @@ def test_slash_command_render_helpers_cover_empty_states() -> None: transport="http", source="session", target="https://repo.example/mcp", - ) - ] + ), + ], ) == "MCP servers:\n- repo (http, session): https://repo.example/mcp" ) @@ -186,7 +186,7 @@ def test_build_available_commands_skips_optional_commands_when_state_is_missing( name="Thinking", current_value=False, type="boolean", - ) + ), ], ) assert [command.name for command in thinking_commands] == [ @@ -214,7 +214,7 @@ def test_validate_mode_command_ids_rejects_invalid_duplicate_and_reserved_values def test_list_agent_tools_skips_internal_invalid_and_non_tool_entries() -> None: agent = Agent(TestModel(custom_output_text="unused")) function_toolset = agent._function_toolset - cast(Any, function_toolset).tools = { + cast("Any", function_toolset).tools = { "acp_hidden": Tool(lambda: "x", takes_ctx=False, name="acp_hidden"), 1: Tool(lambda: "x", takes_ctx=False, name="bad"), # type: ignore[dict-item] "plain": _INVALID_SLASH_VALUE, @@ -224,7 +224,7 @@ def test_list_agent_tools_skips_internal_invalid_and_non_tool_entries() -> None: tool_infos = list_agent_tools(agent) assert [tool_info.name for tool_info in tool_infos] == ["visible"] - assert list_agent_tools(cast(Any, SimpleNamespace())) == [] + assert list_agent_tools(cast("Any", SimpleNamespace())) == [] def test_model_slash_command_reports_current_model_and_sets_new_model( @@ -243,7 +243,7 @@ def test_model_slash_command_reports_current_model_and_sets_new_model( adapter.prompt( prompt=[text_block("/model openai:gpt-5")], session_id=session.session_id, - ) + ), ) asyncio.run(adapter.prompt(prompt=[text_block("/model")], session_id=session.session_id)) @@ -288,7 +288,7 @@ def passthrough_tools( prepare_func=lambda _ctx, tool_defs: passthrough_tools(tool_defs), ), ], - ) + ), ], session_store=MemorySessionStore(), ), @@ -418,14 +418,14 @@ def route_with_thinking( asyncio.run(adapter.prompt(prompt=[text_block("/thinking")], session_id=session.session_id)) asyncio.run( - adapter.prompt(prompt=[text_block("/thinking HIGH")], session_id=session.session_id) + adapter.prompt(prompt=[text_block("/thinking HIGH")], session_id=session.session_id), ) asyncio.run(adapter.prompt(prompt=[text_block("/thinking")], session_id=session.session_id)) asyncio.run( adapter.prompt( prompt=[text_block("Use the configured thinking effort.")], session_id=session.session_id, - ) + ), ) assert agent_message_texts(client) == [ @@ -472,7 +472,7 @@ def create_codex_responses_model(model_id: str, *, instructions: str) -> TestMod adapter.prompt( prompt=[text_block("/model codex:gpt-5")], session_id=session.session_id, - ) + ), ) stored_session = session_store.get(session.session_id) @@ -493,7 +493,7 @@ def test_invalid_selected_model_falls_back_to_default_model(tmp_path: Path) -> N adapter.prompt( prompt=[text_block("/model broken:model")], session_id=session.session_id, - ) + ), ) client.updates.clear() @@ -501,7 +501,7 @@ def test_invalid_selected_model_falls_back_to_default_model(tmp_path: Path) -> N adapter.prompt( prompt=[text_block("Run after invalid model selection.")], session_id=session.session_id, - ) + ), ) asyncio.run(adapter.prompt(prompt=[text_block("/model")], session_id=session.session_id)) @@ -520,8 +520,8 @@ def read_repo(path: str) -> str: Args: path: Relative path to read. - """ + """ return path # pragma: no cover @agent.tool_plain(requires_approval=True) @@ -539,7 +539,7 @@ def delete_repo(path: str) -> str: asyncio.run(adapter.prompt(prompt=[text_block("/tools")], session_id=session.session_id)) assert agent_message_texts(client) == [ - "Available tools:\n- delete_repo [approval]\n- read_repo: Read a repository file." + "Available tools:\n- delete_repo [approval]\n- read_repo: Read a repository file.", ] @@ -579,7 +579,7 @@ def echo(text: str) -> str: assert agent_message_texts(client) == [ "Registered hooks:\n" "- Before Model: annotate_request\n" - "- Before Tool: audit_echo [tools: echo]" + "- Before Tool: audit_echo [tools: echo]", ] @@ -628,7 +628,7 @@ def test_mcp_servers_slash_command_extracts_servers_from_agent_toolsets( adapter.prompt( prompt=[text_block("/mcp-servers")], session_id=session.session_id, - ) + ), ) finally: monkeypatch.undo() @@ -637,7 +637,7 @@ def test_mcp_servers_slash_command_extracts_servers_from_agent_toolsets( "MCP servers:\n" "- remote-sse (sse, agent): https://example.com/sse | prefix=docs\n" "- local-stdio (stdio, agent): python server.py | prefix=fs\n" - "- https://example.com/mcp (http, agent): https://example.com/mcp" + "- https://example.com/mcp (http, agent): https://example.com/mcp", ] @@ -662,7 +662,7 @@ def test_extract_session_mcp_servers_skips_invalid_and_dedupes_sources() -> None }, ], metadata=cast( - dict[str, JsonValue], + "dict[str, JsonValue]", { "pydantic_acp": { "mcp": { @@ -679,9 +679,9 @@ def test_extract_session_mcp_servers_skips_invalid_and_dedupes_sources() -> None "description": "remote docs", }, {1: "invalid"}, - ] - } - } + ], + }, + }, }, ), ) @@ -699,10 +699,10 @@ def test_extract_session_mcp_servers_covers_agent_dedupes_and_invalid_metadata_s http_cls = type("MCPServerStreamableHTTP", (), {}) http_cls.__module__ = "pydantic_ai.mcp" http_toolset = http_cls() - cast(Any, http_toolset).url = "https://repo.example/mcp" - cast(Any, http_toolset).id = "repo-http" + cast("Any", http_toolset).url = "https://repo.example/mcp" + cast("Any", http_toolset).id = "repo-http" - agent = cast(Any, SimpleNamespace(toolsets=[http_toolset, http_toolset])) + agent = cast("Any", SimpleNamespace(toolsets=[http_toolset, http_toolset])) expected_agent_infos = list_agent_mcp_servers(agent) assert len(expected_agent_infos) == 1 @@ -750,10 +750,10 @@ def test_extract_session_mcp_servers_covers_agent_dedupes_and_invalid_metadata_s "name": "repo-http", "transport": "http", "url": "https://repo.example/mcp", - } - ] - } - } + }, + ], + }, + }, }, ) infos = extract_session_mcp_servers(session_with_duplicates, agent=agent) @@ -764,17 +764,17 @@ def test_mcp_helper_parsers_cover_invalid_and_fallback_paths() -> None: assert _mcp_server_info_from_session_payload({"transport": "stdio"}) is None assert _mcp_server_info_from_session_payload({"name": "demo"}) is None stdio_info = _mcp_server_info_from_session_payload( - {"name": "stdio", "transport": "stdio", "args": ["--serve"]} + {"name": "stdio", "transport": "stdio", "args": ["--serve"]}, ) assert stdio_info is not None assert stdio_info.target == " --serve" stdio_command_info = _mcp_server_info_from_session_payload( - {"name": "stdio", "transport": "stdio", "command": "python", "args": []} + {"name": "stdio", "transport": "stdio", "command": "python", "args": []}, ) assert stdio_command_info is not None assert stdio_command_info.target == "python" http_info = _mcp_server_info_from_session_payload( - {"name": "http", "transport": "http", "url": "https://demo.test/mcp"} + {"name": "http", "transport": "http", "url": "https://demo.test/mcp"}, ) assert http_info is not None assert http_info.target == "https://demo.test/mcp" @@ -788,11 +788,11 @@ def test_mcp_helper_parsers_cover_invalid_and_fallback_paths() -> None: stdio_cls = type("MCPServerStdio", (), {}) stdio_cls.__module__ = "pydantic_ai.mcp" stdio_toolset = stdio_cls() - cast(Any, stdio_toolset).command = "" - cast(Any, stdio_toolset).args = [] + cast("Any", stdio_toolset).command = "" + cast("Any", stdio_toolset).args = [] assert _mcp_server_info_from_stdio_toolset(stdio_toolset) is None - cast(Any, stdio_toolset).command = "python" - cast(Any, stdio_toolset).tool_prefix = None + cast("Any", stdio_toolset).command = "python" + cast("Any", stdio_toolset).tool_prefix = None stdio_result = _mcp_server_info_from_stdio_toolset(stdio_toolset) assert stdio_result is not None assert stdio_result.target == "python" @@ -800,13 +800,13 @@ def test_mcp_helper_parsers_cover_invalid_and_fallback_paths() -> None: http_cls = type("MCPServerStreamableHTTP", (), {}) http_cls.__module__ = "pydantic_ai.mcp" http_toolset = http_cls() - cast(Any, http_toolset).url = "https://demo.test/mcp" - cast(Any, http_toolset).tool_prefix = "repo." - cast(Any, http_toolset)._id = "toolset-id" + cast("Any", http_toolset).url = "https://demo.test/mcp" + cast("Any", http_toolset).tool_prefix = "repo." + cast("Any", http_toolset)._id = "toolset-id" http_result = _mcp_server_info_from_http_toolset(http_toolset) assert http_result is not None assert http_result.target == "https://demo.test/mcp | prefix=repo." - cast(Any, http_toolset).url = "" + cast("Any", http_toolset).url = "" assert _mcp_server_info_from_http_toolset(http_toolset) is None assert _toolset_name(SimpleNamespace(), fallback="fallback") == "fallback" @@ -815,20 +815,20 @@ def test_list_agent_mcp_servers_handles_fake_toolsets_and_nested_wrappers() -> N stdio_cls = type("MCPServerStdio", (), {}) stdio_cls.__module__ = "pydantic_ai.mcp" stdio_toolset = stdio_cls() - cast(Any, stdio_toolset).command = "python" - cast(Any, stdio_toolset).args = ["server.py"] - cast(Any, stdio_toolset).tool_prefix = "fs" - cast(Any, stdio_toolset).id = "local-stdio" + cast("Any", stdio_toolset).command = "python" + cast("Any", stdio_toolset).args = ["server.py"] + cast("Any", stdio_toolset).tool_prefix = "fs" + cast("Any", stdio_toolset).id = "local-stdio" http_cls = type("MCPServerStreamableHTTP", (), {}) http_cls.__module__ = "pydantic_ai.mcp" http_toolset = http_cls() - cast(Any, http_toolset).url = "https://example.com/mcp" - cast(Any, http_toolset).tool_prefix = "docs" - cast(Any, http_toolset)._id = "remote-http" + cast("Any", http_toolset).url = "https://example.com/mcp" + cast("Any", http_toolset).tool_prefix = "docs" + cast("Any", http_toolset)._id = "remote-http" dummy_agent = types.SimpleNamespace(toolsets=[stdio_toolset, http_toolset]) - server_infos = list_agent_mcp_servers(cast(Any, dummy_agent)) + server_infos = list_agent_mcp_servers(cast("Any", dummy_agent)) assert [(info.name, info.transport, info.target) for info in server_infos] == [ ("local-stdio", "stdio", "python server.py | prefix=fs"), @@ -836,23 +836,23 @@ def test_list_agent_mcp_servers_handles_fake_toolsets_and_nested_wrappers() -> N ] dup_agent = types.SimpleNamespace(toolsets=[stdio_toolset, stdio_toolset]) - deduped = list_agent_mcp_servers(cast(Any, dup_agent)) + deduped = list_agent_mcp_servers(cast("Any", dup_agent)) assert [(info.name, info.target) for info in deduped] == [ - ("local-stdio", "python server.py | prefix=fs") + ("local-stdio", "python server.py | prefix=fs"), ] assert _iter_mcp_server_infos(CombinedToolset([])) == [] assert _iter_mcp_server_infos(WrapperToolset(CombinedToolset([]))) == [] assert _iter_mcp_server_infos(DynamicToolset(lambda _ctx: None)) == [] combined_infos = _iter_mcp_server_infos( - CombinedToolset(cast(Any, [http_toolset, stdio_toolset])) + CombinedToolset(cast("Any", [http_toolset, stdio_toolset])), ) assert [(info.name, info.transport) for info in combined_infos] == [ ("remote-http", "http"), ("local-stdio", "stdio"), ] dynamic_toolset = DynamicToolset(lambda _ctx: None) - dynamic_toolset._toolset = cast(Any, http_toolset) + dynamic_toolset._toolset = cast("Any", http_toolset) dynamic_infos = _iter_mcp_server_infos(dynamic_toolset) assert [(info.name, info.transport) for info in dynamic_infos] == [("remote-http", "http")] assert _iter_mcp_server_infos(object()) == [] @@ -861,7 +861,7 @@ def test_list_agent_mcp_servers_handles_fake_toolsets_and_nested_wrappers() -> N def _make_named_transport(class_name: str, url: str) -> Any: transport_cls = type(class_name, (), {}) transport = transport_cls() - cast(Any, transport).url = url + cast("Any", transport).url = url return transport @@ -869,22 +869,22 @@ def test_list_agent_mcp_servers_handles_mcp_toolset() -> None: mcp_toolset_cls = type("MCPToolset", (), {}) mcp_toolset_cls.__module__ = "pydantic_ai.mcp" http_toolset = mcp_toolset_cls() - cast(Any, http_toolset).id = "remote-mcp" - cast(Any, http_toolset).client = SimpleNamespace(url="https://example.com/mcp") + cast("Any", http_toolset).id = "remote-mcp" + cast("Any", http_toolset).client = SimpleNamespace(url="https://example.com/mcp") http_agent = types.SimpleNamespace(toolsets=[http_toolset]) - http_infos = list_agent_mcp_servers(cast(Any, http_agent)) + http_infos = list_agent_mcp_servers(cast("Any", http_agent)) assert [(info.name, info.transport, info.target) for info in http_infos] == [ ("remote-mcp", "http", "https://example.com/mcp"), ] stdio_toolset = mcp_toolset_cls() - cast(Any, stdio_toolset)._id = "local-mcp" - cast(Any, stdio_toolset).client = SimpleNamespace( - transport=SimpleNamespace(command="python", args=["server.py"]) + cast("Any", stdio_toolset)._id = "local-mcp" + cast("Any", stdio_toolset).client = SimpleNamespace( + transport=SimpleNamespace(command="python", args=["server.py"]), ) stdio_agent = types.SimpleNamespace(toolsets=[stdio_toolset]) - stdio_infos = list_agent_mcp_servers(cast(Any, stdio_agent)) + stdio_infos = list_agent_mcp_servers(cast("Any", stdio_agent)) assert [(info.name, info.transport, info.target) for info in stdio_infos] == [ ("local-mcp", "stdio", "python server.py"), ] @@ -903,15 +903,16 @@ def test_list_agent_mcp_servers_handles_mcp_toolset() -> None: ( SimpleNamespace( transport=_make_named_transport( - "StreamableHttpSseTransport", "https://example.com/sse" - ) + "StreamableHttpSseTransport", + "https://example.com/sse", + ), ), "sse", "https://example.com/sse", ), ( SimpleNamespace( - transport=SimpleNamespace(command="python", args=["server.py", "--serve"]) + transport=SimpleNamespace(command="python", args=["server.py", "--serve"]), ), "stdio", "python server.py --serve", @@ -957,9 +958,9 @@ def test_mcp_server_info_from_mcp_toolset_builds_server_info_from_client() -> No mcp_toolset_cls = type("MCPToolset", (), {}) mcp_toolset_cls.__module__ = "pydantic_ai.mcp" toolset = mcp_toolset_cls() - cast(Any, toolset).id = "remote-mcp" - cast(Any, toolset).client = SimpleNamespace( - transport=_make_named_transport("StreamableHttpSseTransport", "https://example.com/sse") + cast("Any", toolset).id = "remote-mcp" + cast("Any", toolset).client = SimpleNamespace( + transport=_make_named_transport("StreamableHttpSseTransport", "https://example.com/sse"), ) server_info = _mcp_server_info_from_mcp_toolset(toolset) @@ -998,7 +999,7 @@ def test_mcp_servers_slash_command_renders_attached_servers(tmp_path: Path) -> N assert agent_message_texts(client) == [ "MCP servers:\n" "- repo-http (http, session): https://repo.example/mcp\n" - "- repo-stdio (stdio, session): python server.py" + "- repo-stdio (stdio, session): python server.py", ] @@ -1034,7 +1035,7 @@ def test_extract_session_mcp_servers_dedupes_agent_and_session_duplicates( ], ) - infos = extract_session_mcp_servers(session, agent=cast(Any, _INVALID_SLASH_VALUE)) + infos = extract_session_mcp_servers(session, agent=cast("Any", _INVALID_SLASH_VALUE)) assert [(info.name, info.source) for info in infos] == [ ("docs", "agent"), @@ -1057,7 +1058,7 @@ def test_invalid_selected_model_does_not_leave_failed_tool_updates( adapter.prompt( prompt=[text_block("/model broken:model")], session_id=session.session_id, - ) + ), ) client.updates.clear() @@ -1065,7 +1066,7 @@ def test_invalid_selected_model_does_not_leave_failed_tool_updates( adapter.prompt( prompt=[text_block("Run after invalid model selection.")], session_id=session.session_id, - ) + ), ) tool_failures = [ @@ -1090,11 +1091,11 @@ def test_static_custom_slash_command_is_advertised_and_handled(tmp_path: Path) - title="Custom command", kind="execute", status="completed", - ) + ), ], ), - ) - ] + ), + ], ) adapter = create_acp_agent( agent=Agent(TestModel(custom_output_text="model-output")), @@ -1135,12 +1136,12 @@ def test_custom_slash_command_can_skip_text_and_surface_refresh(tmp_path: Path) title="Silent command", kind="execute", status="completed", - ) + ), ], refresh_session_surface=False, ), - ) - ] + ), + ], ) adapter = create_acp_agent( agent=Agent(TestModel(custom_output_text="model-output")), @@ -1198,8 +1199,8 @@ def test_custom_slash_command_collisions_are_rejected(tmp_path: Path) -> None: StaticSlashCommand( command=AvailableCommand(name="tools", description="Collides."), handler=lambda request: SlashCommandResult(text=request.name), - ) - ] + ), + ], ) adapter = create_acp_agent( agent=Agent(TestModel(custom_output_text="unused")), diff --git a/tests/pydantic/test_sources.py b/tests/pydantic/test_sources.py index 68455b9..a4155be 100644 --- a/tests/pydantic/test_sources.py +++ b/tests/pydantic/test_sources.py @@ -43,7 +43,6 @@ async def get_deps( agent: Agent[None, str], ) -> None: del session, agent - return None adapter = create_acp_agent( agent_source=SessionAwareAgentSource(), @@ -57,7 +56,7 @@ async def get_deps( adapter.prompt( prompt=[text_block("Use the custom agent source.")], session_id=session.session_id, - ) + ), ) assert agent_message_texts(client) == ["source:source-demo"] @@ -98,7 +97,7 @@ async def get_deps( adapter.prompt( prompt=[text_block("Show the deps value.")], session_id=session.session_id, - ) + ), ) tool_updates = [ @@ -130,7 +129,6 @@ async def get_deps( agent: Agent[None, str], ) -> None: del session, agent - return None adapter = create_acp_agent( agent_source=ClientAwareSource(), @@ -146,7 +144,7 @@ async def get_deps( adapter.prompt( prompt=[text_block("Use the client-aware agent source.")], session_id=session.session_id, - ) + ), ) session_info_updates = [ @@ -154,7 +152,7 @@ async def get_deps( ] assert session_info_updates assert session_info_updates[-1].field_meta == { - "pydantic_acp": {"approval_state": {"connected": True}} + "pydantic_acp": {"approval_state": {"connected": True}}, } assert agent_message_texts(client) == ["client:connected"] @@ -177,13 +175,13 @@ def factory(session: AcpSessionContext) -> Agent[None, str]: adapter.prompt( prompt=[text_block("Use the first session agent.")], session_id=first_session.session_id, - ) + ), ) asyncio.run( adapter.prompt( prompt=[text_block("Use the second session agent.")], session_id=second_session.session_id, - ) + ), ) assert agent_message_texts(client) == ["factory:alpha", "factory:beta"] @@ -213,7 +211,7 @@ def factory(session: AcpSessionContext) -> Agent[None, str]: adapter.prompt( prompt=[text_block("Show the current session-aware factory state.")], session_id=session.session_id, - ) + ), ) assert agent_message_texts(client) == ["factory:enabled:from-store"] @@ -235,7 +233,7 @@ async def factory(session: AcpSessionContext) -> Agent[None, str]: adapter.prompt( prompt=[text_block("Use the async factory agent.")], session_id=session.session_id, - ) + ), ) assert agent_message_texts(client) == ["async-factory:gamma"] @@ -250,7 +248,7 @@ def test_load_missing_session_returns_none_and_resume_or_fork_raise( ) load_response = asyncio.run( - adapter.load_session(cwd=str(tmp_path), session_id="missing", mcp_servers=[]) + adapter.load_session(cwd=str(tmp_path), session_id="missing", mcp_servers=[]), ) close_response = asyncio.run(adapter.close_session(session_id="missing")) @@ -291,7 +289,7 @@ def test_fork_session_clones_transcript_and_model_override(tmp_path: Path) -> No adapter.prompt( prompt=[text_block("Prime the original session.")], session_id=original.session_id, - ) + ), ) client.updates.clear() @@ -300,14 +298,14 @@ def test_fork_session_clones_transcript_and_model_override(tmp_path: Path) -> No cwd=str(tmp_path / "forked"), session_id=original.session_id, mcp_servers=[], - ) + ), ) resume_response = asyncio.run( adapter.resume_session( cwd=str(tmp_path / "forked"), session_id=forked.session_id, mcp_servers=[], - ) + ), ) assert resume_response.models is not None @@ -347,19 +345,19 @@ def test_provider_backed_fork_preserves_session_state(tmp_path: Path) -> None: config_id="stream_enabled", session_id=original.session_id, value=True, - ) + ), ) asyncio.run( adapter.set_session_model( model_id="provider-model-b", session_id=original.session_id, - ) + ), ) asyncio.run( adapter.prompt( prompt=[text_block("Prime the provider-backed session.")], session_id=original.session_id, - ) + ), ) client.updates.clear() @@ -368,14 +366,14 @@ def test_provider_backed_fork_preserves_session_state(tmp_path: Path) -> None: cwd=str(tmp_path / "forked"), session_id=original.session_id, mcp_servers=[], - ) + ), ) resume_response = asyncio.run( adapter.resume_session( cwd=str(tmp_path / "forked"), session_id=forked.session_id, mcp_servers=[], - ) + ), ) assert forked.models is not None @@ -417,7 +415,7 @@ def test_close_session_removes_session_from_listing(tmp_path: Path) -> None: cwd=str(tmp_path), session_id=session.session_id, mcp_servers=[], - ) + ), ) assert close_response is not None @@ -442,12 +440,12 @@ def test_load_session_can_skip_history_replay(tmp_path: Path) -> None: adapter.prompt( prompt=[text_block("Prime the transcript without replay.")], session_id=session.session_id, - ) + ), ) client.updates.clear() load_response = asyncio.run( - adapter.load_session(cwd=str(tmp_path), session_id=session.session_id, mcp_servers=[]) + adapter.load_session(cwd=str(tmp_path), session_id=session.session_id, mcp_servers=[]), ) assert load_response is not None diff --git a/tests/pydantic/test_support.py b/tests/pydantic/test_support.py index 30c0aae..cb0f914 100644 --- a/tests/pydantic/test_support.py +++ b/tests/pydantic/test_support.py @@ -43,7 +43,7 @@ def _session() -> AcpSessionContext: async def test_pydantic_support_recording_clients_cover_helpers_and_error_paths() -> None: client = RecordingClient() option = PermissionOption(option_id="allow_once", name="Allow once", kind="allow_once") - tool_call = cast(Any, object()) + tool_call = cast("Any", object()) with pytest.raises(AssertionError, match="unexpected permission request"): await client.request_permission([option], "session-1", tool_call) @@ -83,7 +83,7 @@ async def test_pydantic_support_recording_clients_cover_helpers_and_error_paths( await client.ext_method("demo.echo", {"value": 1}) with pytest.raises(AssertionError, match="unexpected extension notification"): await client.ext_notification("demo.note", {"value": 2}) - assert client.on_connect(cast(Any, object())) is None + assert client.on_connect(cast("Any", object())) is None fs_client = FilesystemRecordingClient() assert ( diff --git a/tests/pydantic/test_testing_fakes.py b/tests/pydantic/test_testing_fakes.py index de83604..6dfb4cb 100644 --- a/tests/pydantic/test_testing_fakes.py +++ b/tests/pydantic/test_testing_fakes.py @@ -28,7 +28,7 @@ def test_recording_acp_client_records_permission_file_and_terminal_calls() -> No terminal_output_response=TerminalOutputResponse(output="captured", truncated=True), ) permission_options = [ - PermissionOption(option_id="allow_once", name="Allow once", kind="allow_once") + PermissionOption(option_id="allow_once", name="Allow once", kind="allow_once"), ] tool_call = ToolCallProgress( session_update="tool_call_update", @@ -94,7 +94,7 @@ async def exercise_client() -> None: await client.ext_notification("ext/test", {}) asyncio.run(exercise_client()) - client.on_connect(cast(Any, object())) + client.on_connect(cast("Any", object())) assert client.permission_option_ids == [ ("session-1", ["allow_once"], tool_call), @@ -158,7 +158,7 @@ def test_agent_message_texts_groups_streamed_and_anonymous_messages() -> None: content=text_block("second"), ), ), - ] + ], ) assert agent_message_texts(client) == ["hello", "anon", "second"] diff --git a/tests/pydantic/test_testing_harness.py b/tests/pydantic/test_testing_harness.py index b56c8f3..8670c15 100644 --- a/tests/pydantic/test_testing_harness.py +++ b/tests/pydantic/test_testing_harness.py @@ -83,7 +83,7 @@ async def test_black_box_harness_covers_initialize_mode_model_and_default_filter ), ) missing_session_harness = BlackBoxHarness.create( - agent=Agent(TestModel(custom_output_text="unused")) + agent=Agent(TestModel(custom_output_text="unused")), ) initialize_response = await harness.initialize() diff --git a/tests/test_acpkit_cli.py b/tests/test_acpkit_cli.py index 824b14d..e3af968 100644 --- a/tests/test_acpkit_cli.py +++ b/tests/test_acpkit_cli.py @@ -140,7 +140,7 @@ async def test_native_acp_agent_stub_methods_and_adapter_module_patch_fallback( monkeypatch: pytest.MonkeyPatch, ) -> None: _patch_adapter_modules(monkeypatch, available_modules={"acp"}) - patched_find_spec = cast(Any, importlib.import_module("acpkit.adapters")).find_spec + patched_find_spec = cast("Any", importlib.import_module("acpkit.adapters")).find_spec assert patched_find_spec("sys") is not None agent = _NativeAcpAgent() @@ -164,7 +164,8 @@ async def test_native_acp_agent_stub_methods_and_adapter_module_patch_fallback( def test_load_target_resolves_module_attribute( - tmp_path: Path, monkeypatch: pytest.MonkeyPatch + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, ) -> None: _write_module( tmp_path, @@ -175,7 +176,7 @@ def test_load_target_resolves_module_attribute( "from pydantic_ai.models.test import TestModel", "", 'agent = Agent(TestModel(custom_output_text="loaded"))', - ) + ), ), ) monkeypatch.syspath_prepend(str(tmp_path)) @@ -186,7 +187,8 @@ def test_load_target_resolves_module_attribute( def test_load_target_uses_current_working_directory( - tmp_path: Path, monkeypatch: pytest.MonkeyPatch + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, ) -> None: _write_module( tmp_path, @@ -197,7 +199,7 @@ def test_load_target_uses_current_working_directory( "from pydantic_ai.models.test import TestModel", "", 'agent = Agent(TestModel(custom_output_text="cwd"))', - ) + ), ), ) monkeypatch.chdir(tmp_path) @@ -208,7 +210,8 @@ def test_load_target_uses_current_working_directory( def test_load_target_resolves_latest_agent_when_attribute_is_omitted( - tmp_path: Path, monkeypatch: pytest.MonkeyPatch + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, ) -> None: _write_module( tmp_path, @@ -220,7 +223,7 @@ def test_load_target_resolves_latest_agent_when_attribute_is_omitted( "", 'first_agent = Agent(TestModel(custom_output_text="first"))', 'second_agent = Agent(TestModel(custom_output_text="second"))', - ) + ), ), ) monkeypatch.syspath_prepend(str(tmp_path)) @@ -232,7 +235,8 @@ def test_load_target_resolves_latest_agent_when_attribute_is_omitted( def test_load_target_uses_explicit_import_roots( - tmp_path: Path, monkeypatch: pytest.MonkeyPatch + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, ) -> None: agent_home = tmp_path / "agent_home" agent_home.mkdir() @@ -245,7 +249,7 @@ def test_load_target_uses_explicit_import_roots( "from pydantic_ai.models.test import TestModel", "", 'agent = Agent(TestModel(custom_output_text="external"))', - ) + ), ), ) monkeypatch.chdir(tmp_path) @@ -264,7 +268,8 @@ def test_parse_target_ref_rejects_empty_module_and_attribute() -> None: def test_run_target_dispatches_to_pydantic_adapter( - tmp_path: Path, monkeypatch: pytest.MonkeyPatch + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, ) -> None: _write_module( tmp_path, @@ -275,7 +280,7 @@ def test_run_target_dispatches_to_pydantic_adapter( "from pydantic_ai.models.test import TestModel", "", 'agent = Agent(TestModel(custom_output_text="run"))', - ) + ), ), ) monkeypatch.syspath_prepend(str(tmp_path)) @@ -290,7 +295,8 @@ def record_run(agent: Agent[Any, Any]) -> None: def test_run_target_reports_missing_pydantic_adapter( - tmp_path: Path, monkeypatch: pytest.MonkeyPatch + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, ) -> None: _write_module( tmp_path, @@ -301,7 +307,7 @@ def test_run_target_reports_missing_pydantic_adapter( "from pydantic_ai.models.test import TestModel", "", 'agent = Agent(TestModel(custom_output_text="missing"))', - ) + ), ), ) monkeypatch.syspath_prepend(str(tmp_path)) @@ -335,7 +341,8 @@ def fake_import_module(name: str, package: str | None = None) -> ModuleType: def test_run_target_reports_when_no_adapters_are_installed( - tmp_path: Path, monkeypatch: pytest.MonkeyPatch + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, ) -> None: _write_module( tmp_path, @@ -380,7 +387,8 @@ def record_run(command: list[str], *, check: bool) -> CompletedProcess: monkeypatch.setattr("acpkit.runtime.subprocess.run", record_run) exit_code = launch_target( - "sample_launch_app:agent", import_roots=("/tmp/one", "/tmp/two words") + "sample_launch_app:agent", + import_roots=("/tmp/one", "/tmp/two words"), ) assert exit_code == 0 @@ -394,7 +402,7 @@ def record_run(command: list[str], *, check: bool) -> CompletedProcess: "toad", "acp", "acpkit run sample_launch_app:agent -p /tmp/one -p '/tmp/two words'", - ] + ], ] @@ -441,7 +449,7 @@ def record_run(command: list[str], *, check: bool) -> CompletedProcess: "toad", "acp", "python3.11 finance_agent.py", - ] + ], ] @@ -530,7 +538,7 @@ def record_serve_target( "port": port, "mount_path": mount_path, "token_env": token_env, - } + }, ) monkeypatch.setattr("acpkit.cli.serve_target", record_serve_target) @@ -562,7 +570,7 @@ def record_serve_target( "port": 9000, "mount_path": "/remote", "token_env": "ACP_TOKEN", - } + }, ] @@ -632,7 +640,7 @@ def test_run_target_routes_pydantic_agent_through_adapter_entrypoint( "from pydantic_ai.models.test import TestModel", "", 'agent = Agent(TestModel(custom_output_text="runtime"))', - ) + ), ), ) monkeypatch.syspath_prepend(str(tmp_path)) @@ -696,7 +704,7 @@ def test_run_target_dispatches_native_acp_target_through_acp_runner( " return None", "", "agent = DemoAgent()", - ) + ), ), ) monkeypatch.syspath_prepend(str(tmp_path)) @@ -764,9 +772,9 @@ def fake_connect_acp(addr: str, **kwargs: Any) -> object: def fake_import_module(name: str, package: str | None = None) -> ModuleType: if name == "acpremote": - return cast(ModuleType, SimpleNamespace(connect_acp=fake_connect_acp)) + return cast("ModuleType", SimpleNamespace(connect_acp=fake_connect_acp)) if name == "acp": - return cast(ModuleType, SimpleNamespace(run_agent=fake_run_agent)) + return cast("ModuleType", SimpleNamespace(run_agent=fake_run_agent)) return original_import_module(name, package) # pragma: no cover monkeypatch.setattr("acpkit.runtime.importlib.import_module", fake_import_module) @@ -794,7 +802,7 @@ def test_serve_target_materializes_adapter_backed_agent_and_runs_remote_server( "from pydantic_ai.models.test import TestModel", "", "agent = Agent(TestModel(custom_output_text='serve'))", - ) + ), ), ) monkeypatch.syspath_prepend(str(tmp_path)) @@ -822,9 +830,9 @@ async def fake_serve_acp(agent: Any, **kwargs: Any) -> _FakeServer: def fake_import_module(name: str, package: str | None = None) -> ModuleType: if name == "pydantic_acp": - return cast(ModuleType, SimpleNamespace(create_acp_agent=fake_create_acp_agent)) + return cast("ModuleType", SimpleNamespace(create_acp_agent=fake_create_acp_agent)) if name == "acpremote": - return cast(ModuleType, SimpleNamespace(serve_acp=fake_serve_acp)) + return cast("ModuleType", SimpleNamespace(serve_acp=fake_serve_acp)) return original_import_module(name, package) # pragma: no cover monkeypatch.setattr("acpkit.runtime.importlib.import_module", fake_import_module) @@ -881,7 +889,7 @@ def test_serve_target_accepts_native_acp_agent_without_materialization( " def on_connect(self, conn): return None", "", "agent = DemoAgent()", - ) + ), ), ) monkeypatch.syspath_prepend(str(tmp_path)) @@ -905,7 +913,7 @@ async def fake_serve_acp(agent: Any, **kwargs: Any) -> _FakeServer: def fake_import_module(name: str, package: str | None = None) -> ModuleType: if name == "acpremote": - return cast(ModuleType, SimpleNamespace(serve_acp=fake_serve_acp)) + return cast("ModuleType", SimpleNamespace(serve_acp=fake_serve_acp)) return original_import_module(name, package) # pragma: no cover monkeypatch.setattr("acpkit.runtime.importlib.import_module", fake_import_module) @@ -934,7 +942,7 @@ def test_target_resolution_reports_import_and_attribute_errors( " self.child = object()", "", "root = Namespace()", - ) + ), ), ) monkeypatch.syspath_prepend(str(tmp_path)) @@ -977,7 +985,7 @@ def test_target_resolution_reports_when_module_has_no_supported_agent( def test_runtime_helpers_cover_remote_module_and_token_error_paths( monkeypatch: pytest.MonkeyPatch, ) -> None: - runtime_module = cast(Any, importlib.import_module("acpkit.runtime")) + runtime_module = cast("Any", importlib.import_module("acpkit.runtime")) monkeypatch.setattr("acpkit.runtime.find_adapter_by_module_name", lambda name: None) with pytest.raises(AcpKitError, match="metadata is not registered"): @@ -1004,20 +1012,21 @@ def test_runtime_helpers_cover_remote_module_and_token_error_paths( def test_runtime_materialize_acp_agent_covers_langchain_and_failure_paths( monkeypatch: pytest.MonkeyPatch, ) -> None: - runtime_module = cast(Any, importlib.import_module("acpkit.runtime")) + runtime_module = cast("Any", importlib.import_module("acpkit.runtime")) sentinel_graph = object() original_import_module = importlib.import_module monkeypatch.setattr("acpkit.runtime.is_acp_target", lambda target: False) monkeypatch.setattr("acpkit.runtime.is_pydantic_target", lambda target: False) monkeypatch.setattr( - "acpkit.runtime.is_langchain_target", lambda target: target is sentinel_graph + "acpkit.runtime.is_langchain_target", + lambda target: target is sentinel_graph, ) def fake_import_module(name: str, package: str | None = None) -> ModuleType: if name == "langchain_acp": return cast( - ModuleType, + "ModuleType", SimpleNamespace(create_acp_agent=lambda *, graph: ("langchain-agent", graph)), ) return original_import_module(name, package) # pragma: no cover @@ -1150,7 +1159,7 @@ def fake_import_module(name: str, package: str | None = None) -> ModuleType: del package assert name == "acpremote" return cast( - ModuleType, + "ModuleType", SimpleNamespace( connect_acp=lambda url, **kwargs: observed.setdefault("connect", (url, kwargs)), serve_acp=lambda agent, **kwargs: observed.setdefault("serve", (agent, kwargs)), @@ -1235,11 +1244,11 @@ async def fake_run_agent(agent: Any) -> None: def fake_import_module(name: str, package: str | None = None) -> ModuleType: if name == "langchain_acp": return cast( - ModuleType, + "ModuleType", SimpleNamespace(run_acp=lambda *, graph: observed.setdefault("graph", graph)), ) if name == "acp": - return cast(ModuleType, SimpleNamespace(run_agent=fake_run_agent)) + return cast("ModuleType", SimpleNamespace(run_agent=fake_run_agent)) return original_import_module(name, package) # pragma: no cover monkeypatch.setattr("acpkit.adapters.importlib.import_module", fake_import_module) @@ -1269,7 +1278,7 @@ def fake_run_acp(*, graph_factory: Any, config: Any) -> None: codex_auth_helper, "create_codex_chat_openai", lambda _model_name, **_kwargs: GenericFakeChatModel( - messages=cycle([AIMessage(content="codex-ready")]) + messages=cycle([AIMessage(content="codex-ready")]), ), ) monkeypatch.setattr(langchain_acp, "run_acp", fake_run_acp) diff --git a/tests/test_native_langchain_agent.py b/tests/test_native_langchain_agent.py index 3b0d06e..aeef233 100644 --- a/tests/test_native_langchain_agent.py +++ b/tests/test_native_langchain_agent.py @@ -42,7 +42,8 @@ def read_file(path: str) -> str: def test_load_target_resolves_langchain_graph_targets( - tmp_path: Path, monkeypatch: pytest.MonkeyPatch + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, ) -> None: _write_module( tmp_path, @@ -63,7 +64,7 @@ def test_load_target_resolves_langchain_graph_targets( " tools=[read_file],", ' name="langchain-demo",', ")", - ) + ), ), ) monkeypatch.syspath_prepend(str(tmp_path)) @@ -74,7 +75,8 @@ def test_load_target_resolves_langchain_graph_targets( def test_load_target_uses_latest_langchain_graph_when_attribute_is_omitted( - tmp_path: Path, monkeypatch: pytest.MonkeyPatch + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, ) -> None: _write_module( tmp_path, @@ -100,7 +102,7 @@ def test_load_target_uses_latest_langchain_graph_when_attribute_is_omitted( " tools=[read_file],", ' name="second-graph",', ")", - ) + ), ), ) monkeypatch.syspath_prepend(str(tmp_path)) @@ -134,7 +136,7 @@ def test_run_target_dispatches_langchain_graph_through_adapter( " tools=[read_file],", ' name="run-graph",', ")", - ) + ), ), ) monkeypatch.syspath_prepend(str(tmp_path)) @@ -145,7 +147,7 @@ def test_run_target_dispatches_langchain_graph_through_adapter( def fake_import_module(name: str, package: str | None = None) -> ModuleType: if name == "langchain_acp": return cast( - ModuleType, + "ModuleType", SimpleNamespace(run_acp=lambda *, graph: captured_graphs.append(graph)), ) return original_import_module(name, package) @@ -174,13 +176,17 @@ def fake_import_module(name: str, package: str | None = None) -> ModuleType: "sample_present_langchain_dependency" ) - monkeypatch.setattr("acpkit.runtime.importlib.import_module", fake_import_module) + from acpkit import adapters as adapters_module + + monkeypatch.setattr(importlib, "import_module", fake_import_module) + original_find_spec = adapters_module.find_spec monkeypatch.setattr( - "acpkit.adapters.find_spec", + adapters_module, + "find_spec", lambda name: ( None if name in {"langchain", "langgraph", "langchain_acp"} - else importlib.util.find_spec(name) + else original_find_spec(name) ), ) diff --git a/tests/test_native_pydantic_agent.py b/tests/test_native_pydantic_agent.py index 392b74e..1c42bae 100644 --- a/tests/test_native_pydantic_agent.py +++ b/tests/test_native_pydantic_agent.py @@ -42,7 +42,8 @@ def _latest_user_prompt(messages: list[ModelRequest | ModelResponse]) -> str: def _travel_demo_model( - messages: list[ModelRequest | ModelResponse], info: AgentInfo + messages: list[ModelRequest | ModelResponse], + info: AgentInfo, ) -> ModelResponse: del info latest_message = messages[-1] @@ -54,7 +55,7 @@ def _travel_demo_model( prompt = _latest_user_prompt(messages) if prompt == "read trip file itinerary.md": return ModelResponse( - parts=[ToolCallPart("read_trip_file", {"path": "itinerary.md", "max_chars": 4000})] + parts=[ToolCallPart("read_trip_file", {"path": "itinerary.md", "max_chars": 4000})], ) if prompt == "write trip file scratch.txt: hello from the native demo": return ModelResponse( @@ -62,8 +63,8 @@ def _travel_demo_model( ToolCallPart( "write_trip_file", {"path": "scratch.txt", "content": "hello from the native demo"}, - ) - ] + ), + ], ) return ModelResponse(parts=[TextPart("Travel demo mode is active.")]) @@ -77,7 +78,7 @@ def test_native_pydantic_agent_helpers_cover_text_and_fallback_paths() -> None: [ ModelRequest(parts=[UserPromptPart(content=["not-a-string"])]), ModelResponse(parts=[TextPart("ignored")]), - ] + ], ) plain_prompt = _latest_user_prompt([ModelRequest(parts=[UserPromptPart(content="hello")])]) @@ -87,15 +88,15 @@ def test_native_pydantic_agent_helpers_cover_text_and_fallback_paths() -> None: tool_return_response = _travel_demo_model( [ModelRequest(parts=[ToolReturnPart(tool_name="read_trip_file", content="done")])], - cast(Any, object()), + cast("Any", object()), ) fallback_response = _travel_demo_model( [ModelRequest(parts=[UserPromptPart(content="something else")])], - cast(Any, object()), + cast("Any", object()), ) response_passthrough = _travel_demo_model( [ModelResponse(parts=[TextPart("already done")])], - cast(Any, object()), + cast("Any", object()), ) assert tool_return_response.parts == [TextPart("read_trip_file: done")] @@ -125,7 +126,7 @@ def test_native_pydantic_agent_read_prompt_emits_hook_and_diff( adapter.prompt( prompt=[text_block("read trip file itinerary.md")], session_id=session.session_id, - ) + ), ) hook_titles = [ @@ -170,11 +171,11 @@ def test_native_pydantic_agent_write_prompt_emits_hook_and_diff( adapter.prompt( prompt=[text_block("write trip file scratch.txt: hello from the native demo")], session_id=session.session_id, - ) + ), ) write_start = next( - cast(Any, update) + cast("Any", update) for _, update in client.updates if isinstance(update, ToolCallStart) and update.title == "write_trip_file" ) diff --git a/uv.lock b/uv.lock index 9f4e94d..c8c30f3 100644 --- a/uv.lock +++ b/uv.lock @@ -1,6 +1,12 @@ version = 1 revision = 3 requires-python = ">=3.11" +resolution-markers = [ + "python_full_version >= '3.14' and sys_platform == 'win32'", + "python_full_version >= '3.14' and sys_platform != 'win32'", + "python_full_version < '3.14' and sys_platform == 'win32'", + "python_full_version < '3.14' and sys_platform != 'win32'", +] [manifest] members = [ @@ -16,6 +22,7 @@ name = "acpkit" source = { editable = "." } dependencies = [ { name = "click" }, + { name = "pydantic-ai" }, { name = "typing-extensions" }, ] @@ -193,6 +200,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8f/ed/c284543c08aa443a4ef2c8bd120be51da8433dd174c01749b5d87c333f22/agent_client_protocol-0.9.0-py3-none-any.whl", hash = "sha256:06911500b51d8cb69112544e2be01fc5e7db39ef88fecbc3848c5c6f194798ee", size = 56850, upload-time = "2026-03-26T01:20:59.252Z" }, ] +[[package]] +name = "aiofile" +version = "3.11.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "caio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/48/41/2fea7e193e061ce54eacc3b7bc0e6a99e4fcff43c78cf0a76dd781ed8334/aiofile-3.11.1.tar.gz", hash = "sha256:1f91912c6643d2a4e49ca4ae3514f0bf3867ce948a36d99a6411b8f4755f4cf9", size = 19342, upload-time = "2026-05-16T08:18:33.538Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/67/cd/0d76dfc5de72bde52f55f53e925c7d152d9c7906634ec1e0cbc7e8d4ad93/aiofile-3.11.1-py3-none-any.whl", hash = "sha256:ce77d14ac07f77bc2b757834a5c129321f3f705c474593deed5ab209079a52c9", size = 20446, upload-time = "2026-05-16T08:18:32.051Z" }, +] + [[package]] name = "annotated-types" version = "0.7.0" @@ -204,7 +223,7 @@ wheels = [ [[package]] name = "anthropic" -version = "0.100.0" +version = "0.116.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -216,22 +235,53 @@ dependencies = [ { name = "sniffio" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9c/2d/24caf0ff727cba2ed863925017c8f93463a2ea6224a0efe5626e672bc3d2/anthropic-0.100.0.tar.gz", hash = "sha256:650dee9e023afb16395939ee4104bbc21f966b380210119fb91122c12099c79a", size = 758255, upload-time = "2026-05-06T15:07:13.578Z" } +sdist = { url = "https://files.pythonhosted.org/packages/66/a2/d31f14e28d49bae983a3634e38dfb4b31c50110b5e403596c5c6a20b23f8/anthropic-0.116.0.tar.gz", hash = "sha256:5fc248fbb9fe03ef686f8a774f81586bca31a043260aab88b387ea3660f4a396", size = 949149, upload-time = "2026-07-02T19:08:10.534Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5d/a0/c775c59ab9445ecabb57ef3d5c24027de060139189a9e312ef9ef889a665/anthropic-0.100.0-py3-none-any.whl", hash = "sha256:1c15769efa15d8fd5c1ebf900e25c57e3ee540f8554a29aa56e4edefffe2951d", size = 753596, upload-time = "2026-05-06T15:07:12.106Z" }, + { url = "https://files.pythonhosted.org/packages/c7/dd/2a1e81cf1b163acc340afc4ec74ed1d86f5eed1a809fabdeed3e0997b346/anthropic-0.116.0-py3-none-any.whl", hash = "sha256:6c0a7698e8d652455da3499978279bb2588c7264d0a35be3666009a4258c8256", size = 956896, upload-time = "2026-07-02T19:08:08.756Z" }, ] [[package]] name = "anyio" -version = "4.13.0" +version = "4.14.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "idna" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/19/14/2c5dd9f512b66549ae92767a9c7b330ae88e1932ca57876909410251fe13/anyio-4.13.0.tar.gz", hash = "sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc", size = 231622, upload-time = "2026-03-24T12:59:09.671Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/72/5562aabb8dd7181e8e860622a38bea08d17842b99ecd4c91f84ac95251b0/anyio-4.14.1.tar.gz", hash = "sha256:8d648a3544c1a700e3ff78615cd679e4c5c3f149904287e73687b2596963629e", size = 254831, upload-time = "2026-06-24T20:56:06.017Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b0/7b/90df4a0a816d98d6ea26f559d87836d494a2cf1fcf063be67df50a7bcc30/anyio-4.14.1-py3-none-any.whl", hash = "sha256:4e5533c5b8ff0a24f5d7a176cbe6877129cd183893f66b537f8f227d10527d72", size = 124875, upload-time = "2026-06-24T20:56:04.413Z" }, +] + +[[package]] +name = "argcomplete" +version = "3.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/95/c0/c8e94135e66fabf89a120d9b4b123fe6993506beca6c1938a74c24cfa5fd/argcomplete-3.7.0.tar.gz", hash = "sha256:afde224f753f874807b1dc1414e883ab8fe0cda9c04807b6047dcb8e1ac23913", size = 73284, upload-time = "2026-06-30T22:28:22.249Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/f6/5b8ec087cd9cfa9449491ec83f76fb6b7006b4dff57d2ba8aaab330fe8e4/argcomplete-3.7.0-py3-none-any.whl", hash = "sha256:d8f0f22d2a8a7caa383be1e22b6caf1ecaf0ebd10d8f83cc125e36540c95830c", size = 42575, upload-time = "2026-06-30T22:28:20.547Z" }, +] + +[[package]] +name = "attrs" +version = "26.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9a/8e/82a0fe20a541c03148528be8cac2408564a6c9a0cc7e9171802bc1d26985/attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32", size = 952055, upload-time = "2026-03-19T14:22:25.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" }, +] + +[[package]] +name = "authlib" +version = "1.7.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cryptography" }, + { name = "joserfc" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/36/98/7d93f30d029643c0275dbc0bd6d5a6f670661ee6c9a94d93af7ab4887600/authlib-1.7.2.tar.gz", hash = "sha256:2cea25fefcd4e7173bdf1372c0afc265c8034b23a8cd5dcb6a9164b826c64231", size = 176511, upload-time = "2026-05-06T08:10:23.116Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl", hash = "sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708", size = 114353, upload-time = "2026-03-24T12:59:08.246Z" }, + { url = "https://files.pythonhosted.org/packages/fb/95/adcb68e20c34162e9135f370d6e31737719c2b6f94bc953fe7ed1f10fe21/authlib-1.7.2-py2.py3-none-any.whl", hash = "sha256:3e1faedc9d87e7d56a164eca3ccb6ace0d61b94abe83e92242f8dc8bba9b4a9f", size = 259548, upload-time = "2026-05-06T08:10:21.436Z" }, ] [[package]] @@ -243,6 +293,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl", hash = "sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35", size = 10196845, upload-time = "2026-02-01T12:30:53.445Z" }, ] +[[package]] +name = "backports-tarfile" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/86/72/cd9b395f25e290e633655a100af28cb253e4393396264a98bd5f5951d50f/backports_tarfile-1.2.0.tar.gz", hash = "sha256:d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991", size = 86406, upload-time = "2024-05-28T17:01:54.731Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/fa/123043af240e49752f1c4bd24da5053b6bd00cad78c2be53c0d1e8b975bc/backports.tarfile-1.2.0-py3-none-any.whl", hash = "sha256:77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34", size = 30181, upload-time = "2024-05-28T17:01:53.112Z" }, +] + [[package]] name = "backrefs" version = "7.0" @@ -258,102 +317,173 @@ wheels = [ [[package]] name = "basedpyright" -version = "1.39.3" +version = "1.39.9" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "nodejs-wheel-binaries" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/04/19/5a5b9b9197973da732638957be3a65cf514d2f5a4964eeedbf33b6c65bbd/basedpyright-1.39.3.tar.gz", hash = "sha256:2f794e6b5f4260fb89f614ca6cd23c6f305373bb6b50c4ed7794ff2ae647fb14", size = 25503187, upload-time = "2026-04-20T22:14:47.424Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7a/4b/c1f4e211e50389304d6af32b9280e026a7133e3ad59bbdf8f7a3250f8bee/basedpyright-1.39.9.tar.gz", hash = "sha256:32cbea5fc8273e89df3db20daea56cb7286e419ccdfdc479c64759d2dc071901", size = 24412216, upload-time = "2026-06-27T02:19:49.834Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/d4/e1fa108710d0498a18c77b1e13897f31eab47c69aa8cfe2d2a4df746541e/basedpyright-1.39.9-py3-none-any.whl", hash = "sha256:6b0837b9eba972c71895167ab9b127e6afdbc17abc92312e3f8d15ca82a5611c", size = 13374276, upload-time = "2026-06-27T02:19:54.431Z" }, +] + +[[package]] +name = "beartype" +version = "0.22.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c7/94/1009e248bbfbab11397abca7193bea6626806be9a327d399810d523a07cb/beartype-0.22.9.tar.gz", hash = "sha256:8f82b54aa723a2848a56008d18875f91c1db02c32ef6a62319a002e3e25a975f", size = 1608866, upload-time = "2025-12-13T06:50:30.72Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/54/5c/f950c1239ad26f3bb453e665428a2cf1893995de725a5eb0b64a2520b366/basedpyright-1.39.3-py3-none-any.whl", hash = "sha256:aba760dc83307727554f936d6b4381caa14482f30dbc2173167710e217c1f7ab", size = 12419181, upload-time = "2026-04-20T22:14:51.975Z" }, + { url = "https://files.pythonhosted.org/packages/71/cc/18245721fa7747065ab478316c7fea7c74777d07f37ae60db2e84f8172e8/beartype-0.22.9-py3-none-any.whl", hash = "sha256:d16c9bbc61ea14637596c5f6fbff2ee99cbe3573e46a716401734ef50c3060c2", size = 1333658, upload-time = "2025-12-13T06:50:28.266Z" }, ] [[package]] name = "bracex" -version = "2.6" +version = "3.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/63/9a/fec38644694abfaaeca2798b58e276a8e61de49e2e37494ace423395febc/bracex-2.6.tar.gz", hash = "sha256:98f1347cd77e22ee8d967a30ad4e310b233f7754dbf31ff3fceb76145ba47dc7", size = 26642, upload-time = "2025-06-22T19:12:31.254Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/f5/4473ad9b48cd0420a2d762a3750fa0e078e23e060b1af72662e5987e5530/bracex-3.0.tar.gz", hash = "sha256:b73f718d6bd98d8419e45df02426c86e9967c179949f779340d6c3a8c83b9111", size = 43162, upload-time = "2026-06-30T00:43:35.279Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9d/2a/9186535ce58db529927f6cf5990a849aa9e052eea3e2cfefe20b9e1802da/bracex-2.6-py3-none-any.whl", hash = "sha256:0b0049264e7340b3ec782b5cb99beb325f36c3782a32e36e876452fd49a09952", size = 11508, upload-time = "2025-06-22T19:12:29.781Z" }, + { url = "https://files.pythonhosted.org/packages/f5/2e/68781b78e764e5ccc4af1e3d27e060069c73af90234853fa80000e7ee79d/bracex-3.0-py3-none-any.whl", hash = "sha256:3833e61c2f092d5aa0468fa2e6c6e990a306185abf763b6d122f0158e59c58a5", size = 11738, upload-time = "2026-06-30T00:43:34.196Z" }, +] + +[[package]] +name = "cachetools" +version = "7.1.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f4/8b/0d3945a13955303b81272f759a0331e54c5c793da455e6f5706b89d2639c/cachetools-7.1.4.tar.gz", hash = "sha256:437f55a4e0c1b01a4f3077cc470e6991d47430970e36fbcb77e2be0df4fc1cd6", size = 40085, upload-time = "2026-05-21T22:40:43.376Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8c/7b/1fc1c09cc0756cf25861a3be10565915953876da48bb228fb9a672b20a42/cachetools-7.1.4-py3-none-any.whl", hash = "sha256:323dc4127934744db5b54eb4924482d7edafbf9554e820d1531c2e08c0e4ef54", size = 16761, upload-time = "2026-05-21T22:40:41.845Z" }, +] + +[[package]] +name = "caio" +version = "0.9.25" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/92/88/b8527e1b00c1811db339a1df8bd1ae49d146fcea9d6a5c40e3a80aaeb38d/caio-0.9.25.tar.gz", hash = "sha256:16498e7f81d1d0f5a4c0ad3f2540e65fe25691376e0a5bd367f558067113ed10", size = 26781, upload-time = "2025-12-26T15:21:36.501Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/90/543f556fcfcfa270713eef906b6352ab048e1e557afec12925c991dc93c2/caio-0.9.25-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d6956d9e4a27021c8bd6c9677f3a59eb1d820cc32d0343cea7961a03b1371965", size = 36839, upload-time = "2025-12-26T15:21:40.267Z" }, + { url = "https://files.pythonhosted.org/packages/51/3b/36f3e8ec38dafe8de4831decd2e44c69303d2a3892d16ceda42afed44e1b/caio-0.9.25-cp311-cp311-manylinux2010_x86_64.manylinux2014_x86_64.manylinux_2_12_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bf84bfa039f25ad91f4f52944452a5f6f405e8afab4d445450978cd6241d1478", size = 80255, upload-time = "2025-12-26T15:22:20.271Z" }, + { url = "https://files.pythonhosted.org/packages/df/ce/65e64867d928e6aff1b4f0e12dba0ef6d5bf412c240dc1df9d421ac10573/caio-0.9.25-cp311-cp311-manylinux_2_34_aarch64.whl", hash = "sha256:ae3d62587332bce600f861a8de6256b1014d6485cfd25d68c15caf1611dd1f7c", size = 80052, upload-time = "2026-03-04T22:08:20.402Z" }, + { url = "https://files.pythonhosted.org/packages/46/90/e278863c47e14ec58309aa2e38a45882fbe67b4cc29ec9bc8f65852d3e45/caio-0.9.25-cp311-cp311-manylinux_2_34_x86_64.whl", hash = "sha256:fc220b8533dcf0f238a6b1a4a937f92024c71e7b10b5a2dfc1c73604a25709bc", size = 78273, upload-time = "2026-03-04T22:08:21.368Z" }, + { url = "https://files.pythonhosted.org/packages/d3/25/79c98ebe12df31548ba4eaf44db11b7cad6b3e7b4203718335620939083c/caio-0.9.25-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:fb7ff95af4c31ad3f03179149aab61097a71fd85e05f89b4786de0359dffd044", size = 36983, upload-time = "2025-12-26T15:21:36.075Z" }, + { url = "https://files.pythonhosted.org/packages/a3/2b/21288691f16d479945968a0a4f2856818c1c5be56881d51d4dac9b255d26/caio-0.9.25-cp312-cp312-manylinux2010_x86_64.manylinux2014_x86_64.manylinux_2_12_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:97084e4e30dfa598449d874c4d8e0c8d5ea17d2f752ef5e48e150ff9d240cd64", size = 82012, upload-time = "2025-12-26T15:22:20.983Z" }, + { url = "https://files.pythonhosted.org/packages/03/c4/8a1b580875303500a9c12b9e0af58cb82e47f5bcf888c2457742a138273c/caio-0.9.25-cp312-cp312-manylinux_2_34_aarch64.whl", hash = "sha256:4fa69eba47e0f041b9d4f336e2ad40740681c43e686b18b191b6c5f4c5544bfb", size = 81502, upload-time = "2026-03-04T22:08:22.381Z" }, + { url = "https://files.pythonhosted.org/packages/d1/1c/0fe770b8ffc8362c48134d1592d653a81a3d8748d764bec33864db36319d/caio-0.9.25-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:6bebf6f079f1341d19f7386db9b8b1f07e8cc15ae13bfdaff573371ba0575d69", size = 80200, upload-time = "2026-03-04T22:08:23.382Z" }, + { url = "https://files.pythonhosted.org/packages/31/57/5e6ff127e6f62c9f15d989560435c642144aa4210882f9494204bc892305/caio-0.9.25-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d6c2a3411af97762a2b03840c3cec2f7f728921ff8adda53d7ea2315a8563451", size = 36979, upload-time = "2025-12-26T15:21:35.484Z" }, + { url = "https://files.pythonhosted.org/packages/a3/9f/f21af50e72117eb528c422d4276cbac11fb941b1b812b182e0a9c70d19c5/caio-0.9.25-cp313-cp313-manylinux2010_x86_64.manylinux2014_x86_64.manylinux_2_12_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0998210a4d5cd5cb565b32ccfe4e53d67303f868a76f212e002a8554692870e6", size = 81900, upload-time = "2025-12-26T15:22:21.919Z" }, + { url = "https://files.pythonhosted.org/packages/9c/12/c39ae2a4037cb10ad5eb3578eb4d5f8c1a2575c62bba675f3406b7ef0824/caio-0.9.25-cp313-cp313-manylinux_2_34_aarch64.whl", hash = "sha256:1a177d4777141b96f175fe2c37a3d96dec7911ed9ad5f02bac38aaa1c936611f", size = 81523, upload-time = "2026-03-04T22:08:25.187Z" }, + { url = "https://files.pythonhosted.org/packages/22/59/f8f2e950eb4f1a5a3883e198dca514b9d475415cb6cd7b78b9213a0dd45a/caio-0.9.25-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:9ed3cfb28c0e99fec5e208c934e5c157d0866aa9c32aa4dc5e9b6034af6286b7", size = 80243, upload-time = "2026-03-04T22:08:26.449Z" }, + { url = "https://files.pythonhosted.org/packages/69/ca/a08fdc7efdcc24e6a6131a93c85be1f204d41c58f474c42b0670af8c016b/caio-0.9.25-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fab6078b9348e883c80a5e14b382e6ad6aabbc4429ca034e76e730cf464269db", size = 36978, upload-time = "2025-12-26T15:21:41.055Z" }, + { url = "https://files.pythonhosted.org/packages/5e/6c/d4d24f65e690213c097174d26eda6831f45f4734d9d036d81790a27e7b78/caio-0.9.25-cp314-cp314-manylinux2010_x86_64.manylinux2014_x86_64.manylinux_2_12_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:44a6b58e52d488c75cfaa5ecaa404b2b41cc965e6c417e03251e868ecd5b6d77", size = 81832, upload-time = "2025-12-26T15:22:22.757Z" }, + { url = "https://files.pythonhosted.org/packages/87/a4/e534cf7d2d0e8d880e25dd61e8d921ffcfe15bd696734589826f5a2df727/caio-0.9.25-cp314-cp314-manylinux_2_34_aarch64.whl", hash = "sha256:628a630eb7fb22381dd8e3c8ab7f59e854b9c806639811fc3f4310c6bd711d79", size = 81565, upload-time = "2026-03-04T22:08:27.483Z" }, + { url = "https://files.pythonhosted.org/packages/3f/ed/bf81aeac1d290017e5e5ac3e880fd56ee15e50a6d0353986799d1bc5cfd5/caio-0.9.25-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:0ba16aa605ccb174665357fc729cf500679c2d94d5f1458a6f0d5ca48f2060a7", size = 80071, upload-time = "2026-03-04T22:08:28.751Z" }, + { url = "https://files.pythonhosted.org/packages/86/93/1f76c8d1bafe3b0614e06b2195784a3765bbf7b0a067661af9e2dd47fc33/caio-0.9.25-py3-none-any.whl", hash = "sha256:06c0bb02d6b929119b1cfbe1ca403c768b2013a369e2db46bfa2a5761cf82e40", size = 19087, upload-time = "2025-12-26T15:22:00.221Z" }, ] [[package]] name = "certifi" -version = "2026.4.22" +version = "2026.6.17" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/25/ee/6caf7a40c36a1220410afe15a1cc64993a1f864871f698c0f93acb72842a/certifi-2026.4.22.tar.gz", hash = "sha256:8d455352a37b71bf76a79caa83a3d6c25afee4a385d632127b6afb3963f1c580", size = 137077, upload-time = "2026-04-22T11:26:11.191Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/c7/424b75da314c1045981bd9777432fad05a9e0c69daa4ed7e308bbaffe405/certifi-2026.6.17.tar.gz", hash = "sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432", size = 134594, upload-time = "2026-06-17T10:31:07.894Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/22/30/7cd8fdcdfbc5b869528b079bfb76dcdf6056b1a2097a662e5e8c04f42965/certifi-2026.4.22-py3-none-any.whl", hash = "sha256:3cb2210c8f88ba2318d29b0388d1023c8492ff72ecdde4ebdaddbb13a31b1c4a", size = 135707, upload-time = "2026-04-22T11:26:09.372Z" }, + { url = "https://files.pythonhosted.org/packages/ef/2f/c5464532e965badff2f4c4c1a3a83f5697f0d7c407ed0cda44aaa99bb451/certifi-2026.6.17-py3-none-any.whl", hash = "sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db", size = 133289, upload-time = "2026-06-17T10:31:06.348Z" }, ] [[package]] name = "cffi" -version = "2.0.0" +version = "2.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pycparser", marker = "implementation_name != 'PyPy'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/12/4a/3dfd5f7850cbf0d06dc84ba9aa00db766b52ca38d8b86e3a38314d52498c/cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe", size = 184344, upload-time = "2025-09-08T23:22:26.456Z" }, - { url = "https://files.pythonhosted.org/packages/4f/8b/f0e4c441227ba756aafbe78f117485b25bb26b1c059d01f137fa6d14896b/cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c", size = 180560, upload-time = "2025-09-08T23:22:28.197Z" }, - { url = "https://files.pythonhosted.org/packages/b1/b7/1200d354378ef52ec227395d95c2576330fd22a869f7a70e88e1447eb234/cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92", size = 209613, upload-time = "2025-09-08T23:22:29.475Z" }, - { url = "https://files.pythonhosted.org/packages/b8/56/6033f5e86e8cc9bb629f0077ba71679508bdf54a9a5e112a3c0b91870332/cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93", size = 216476, upload-time = "2025-09-08T23:22:31.063Z" }, - { url = "https://files.pythonhosted.org/packages/dc/7f/55fecd70f7ece178db2f26128ec41430d8720f2d12ca97bf8f0a628207d5/cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5", size = 203374, upload-time = "2025-09-08T23:22:32.507Z" }, - { url = "https://files.pythonhosted.org/packages/84/ef/a7b77c8bdc0f77adc3b46888f1ad54be8f3b7821697a7b89126e829e676a/cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664", size = 202597, upload-time = "2025-09-08T23:22:34.132Z" }, - { url = "https://files.pythonhosted.org/packages/d7/91/500d892b2bf36529a75b77958edfcd5ad8e2ce4064ce2ecfeab2125d72d1/cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26", size = 215574, upload-time = "2025-09-08T23:22:35.443Z" }, - { url = "https://files.pythonhosted.org/packages/44/64/58f6255b62b101093d5df22dcb752596066c7e89dd725e0afaed242a61be/cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9", size = 218971, upload-time = "2025-09-08T23:22:36.805Z" }, - { url = "https://files.pythonhosted.org/packages/ab/49/fa72cebe2fd8a55fbe14956f9970fe8eb1ac59e5df042f603ef7c8ba0adc/cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414", size = 211972, upload-time = "2025-09-08T23:22:38.436Z" }, - { url = "https://files.pythonhosted.org/packages/0b/28/dd0967a76aab36731b6ebfe64dec4e981aff7e0608f60c2d46b46982607d/cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743", size = 217078, upload-time = "2025-09-08T23:22:39.776Z" }, - { url = "https://files.pythonhosted.org/packages/2b/c0/015b25184413d7ab0a410775fdb4a50fca20f5589b5dab1dbbfa3baad8ce/cffi-2.0.0-cp311-cp311-win32.whl", hash = "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5", size = 172076, upload-time = "2025-09-08T23:22:40.95Z" }, - { url = "https://files.pythonhosted.org/packages/ae/8f/dc5531155e7070361eb1b7e4c1a9d896d0cb21c49f807a6c03fd63fc877e/cffi-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5", size = 182820, upload-time = "2025-09-08T23:22:42.463Z" }, - { url = "https://files.pythonhosted.org/packages/95/5c/1b493356429f9aecfd56bc171285a4c4ac8697f76e9bbbbb105e537853a1/cffi-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d", size = 177635, upload-time = "2025-09-08T23:22:43.623Z" }, - { url = "https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d", size = 185271, upload-time = "2025-09-08T23:22:44.795Z" }, - { url = "https://files.pythonhosted.org/packages/df/a2/781b623f57358e360d62cdd7a8c681f074a71d445418a776eef0aadb4ab4/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c", size = 181048, upload-time = "2025-09-08T23:22:45.938Z" }, - { url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z" }, - { url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z" }, - { url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983, upload-time = "2025-09-08T23:22:50.06Z" }, - { url = "https://files.pythonhosted.org/packages/3a/c8/15cb9ada8895957ea171c62dc78ff3e99159ee7adb13c0123c001a2546c1/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037", size = 206519, upload-time = "2025-09-08T23:22:51.364Z" }, - { url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z" }, - { url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z" }, - { url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z" }, - { url = "https://files.pythonhosted.org/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", size = 172932, upload-time = "2025-09-08T23:22:57.188Z" }, - { url = "https://files.pythonhosted.org/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", size = 183557, upload-time = "2025-09-08T23:22:58.351Z" }, - { url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762, upload-time = "2025-09-08T23:22:59.668Z" }, - { url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" }, - { url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" }, - { url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" }, - { url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" }, - { url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" }, - { url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" }, - { url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" }, - { url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" }, - { url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" }, - { url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" }, - { url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" }, - { url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" }, - { url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" }, - { url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" }, - { url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" }, - { url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" }, - { url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" }, - { url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" }, - { url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" }, - { url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" }, - { url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" }, - { url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" }, - { url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" }, - { url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773, upload-time = "2025-09-08T23:23:29.347Z" }, - { url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013, upload-time = "2025-09-08T23:23:30.63Z" }, - { url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" }, - { url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" }, - { url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" }, - { url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" }, - { url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" }, - { url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" }, - { url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" }, - { url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" }, - { url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/57/5f/ff100cae70ebe9d8df1c01a00e510e45d9adb5c1fdda84791b199141de97/cffi-2.1.0.tar.gz", hash = "sha256:efc1cdd798b1aaf39b4610bba7aad28c9bea9b910f25c784ccf9ec1fa719d1f9", size = 531036, upload-time = "2026-07-06T21:34:30.382Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d3/67/85c89a59ba36a671e79638f44d466749f08179266a57e4f2ffdf92174072/cffi-2.1.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:02cb7ff33ded4f1532476731f89ede53e2e488a8e6205515a82144246ffa7dcc", size = 183845, upload-time = "2026-07-06T21:32:26.32Z" }, + { url = "https://files.pythonhosted.org/packages/ea/dd/e3b0baa2d3d6a857ac72b7efbf18e32e487c9cdafcc13049ad765495b15e/cffi-2.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f5bce581e6b8c235e566a14768a943b172ada3ed73537bb0c0be1edee312d4e7", size = 184186, upload-time = "2026-07-06T21:32:28.025Z" }, + { url = "https://files.pythonhosted.org/packages/65/68/9f3ef890cf3c6ab97bd531c5677f67613d302165d16f8142b2811782a614/cffi-2.1.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:30b65779d598c370374fefabf138d456fd6f3216bfa7bedfab1ba82025b0cd93", size = 211892, upload-time = "2026-07-06T21:32:29.565Z" }, + { url = "https://files.pythonhosted.org/packages/22/d7/1a74539db16d8bfd839ff1515948948efbb162e574650fd3d846896eea95/cffi-2.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:88023dfe18799507b73f1dbb0d14326a17465de1bc9c9c7655c22845e9ddc3a2", size = 218793, upload-time = "2026-07-06T21:32:30.951Z" }, + { url = "https://files.pythonhosted.org/packages/ec/d1/9a5b7169499e8e8d8e636de70b97ac7c9447104d2ff1a2cd94790cea5162/cffi-2.1.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:0a96b74cda968eebbad56d973efe5098974f0a9fb323865bf99ea1fd24e3e64c", size = 205737, upload-time = "2026-07-06T21:32:32.216Z" }, + { url = "https://files.pythonhosted.org/packages/ba/b0/e131a9c41f10607926278453d9596163594fe1c4ebc46efe3b5e5b34eb84/cffi-2.1.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:a5781494d4d400a3f47f8f1da94b324f6e6b440a53387774002890a2a2f4b50f", size = 204909, upload-time = "2026-07-06T21:32:33.655Z" }, + { url = "https://files.pythonhosted.org/packages/fb/d2/4398416cd699b35167947c6e22aca52c47e69ad5695073c9f1f2c52e04aa/cffi-2.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aa7a1b53a2a4452ada2d1b5dade9960b2522f1e61293a811a077439e39029565", size = 217883, upload-time = "2026-07-06T21:32:35.173Z" }, + { url = "https://files.pythonhosted.org/packages/a2/a5/d4fe77b589e5e82d43ebc809bf2e6474afe8e48e32ea050b9357645b6471/cffi-2.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9d8272c0e483b024e1b9ad029821470ed8ec65631dbd90217469da0e7cd89f1c", size = 221251, upload-time = "2026-07-06T21:32:36.527Z" }, + { url = "https://files.pythonhosted.org/packages/22/f0/a2fc43084c0433caf7f461bccc013e28f848d04ee1c5ed7fce71423cf4d9/cffi-2.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7762faa47e8ff7eb80bd261d9a7d8eea2d8baa69de5e95b70c1f338bbe712f02", size = 214250, upload-time = "2026-07-06T21:32:37.852Z" }, + { url = "https://files.pythonhosted.org/packages/04/8c/b925975448cf20634a9fbd5efceb807219db452653648d2897c0989cab2d/cffi-2.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:89095c1968b4ba8285840e131bf2891b09ae137fe2146905acae0354fbce1b5e", size = 219441, upload-time = "2026-07-06T21:32:39.146Z" }, + { url = "https://files.pythonhosted.org/packages/eb/da/5c4918a2d61d86fa927d716cb3d8e4626ef8dc8f605a599d32f33897f59a/cffi-2.1.0-cp311-cp311-win32.whl", hash = "sha256:64c753a0f87a256020004f37a1c8c02c480e725f910f0b2a0f3f07debd1b2479", size = 174496, upload-time = "2026-07-06T21:32:40.467Z" }, + { url = "https://files.pythonhosted.org/packages/f9/c8/6c2de1d55cf35ef8b92885d5ef280790f0fb9634d87ea1cc315176aecd61/cffi-2.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:4f26194e3d95e06501b942642855aed4f953d55e95d7d01b7c4483db3ecff458", size = 185113, upload-time = "2026-07-06T21:32:41.761Z" }, + { url = "https://files.pythonhosted.org/packages/9e/4e/e8d7cb5783f1841a3c8fb3a7735838d7484d08ec08c9f984b14cac1ac0e9/cffi-2.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:35aaea0c7ee0e58a5cd8c2fd1a48fdf7ece0d2699b7ecdda08194e9ce5dd9b3d", size = 179927, upload-time = "2026-07-06T21:32:42.961Z" }, + { url = "https://files.pythonhosted.org/packages/1e/85/990925db5df586ec90beb97529c853497e7f85ba0234830447faf41c3057/cffi-2.1.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:df2b82571a1b30f58a87bf4e5a9e78d2b1eff6c6ce8fd3aa3757221f93f0863f", size = 184829, upload-time = "2026-07-06T21:32:44.324Z" }, + { url = "https://files.pythonhosted.org/packages/4b/92/e7bb136ad6b5352603732cf907ef862ca103f20f2031c1735a46300c20c9/cffi-2.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78474632761faa0fb96f30b1c928c84ebcf68713cbb80d15bab09dfe61640fde", size = 184728, upload-time = "2026-07-06T21:32:45.683Z" }, + { url = "https://files.pythonhosted.org/packages/c3/c0/d1ec30ffb370f748f2fb54425972bfef9871e0132e82fb589c46b6676049/cffi-2.1.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:5972433ad71a9e46516584ef60a0fda12d9dc459938d1539c3ddecf9bdc1368d", size = 214815, upload-time = "2026-07-06T21:32:48.557Z" }, + { url = "https://files.pythonhosted.org/packages/1b/dc/5620cf930688be01f2d673804291de757a934c90b946dbdc3d84130c2ea4/cffi-2.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b6422532152adf4e59b110cb2808cee7a033800952f5c036b4af047ee43199e7", size = 222429, upload-time = "2026-07-06T21:32:49.848Z" }, + { url = "https://files.pythonhosted.org/packages/4b/a4/77b53abbf7a1e0beb9637edbef2a94d15f9c822f591e85d439ffd91519a6/cffi-2.1.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:46b1c8db8f6122420f32d02fffb924c2fe9bc772d228c7c711748fff56aabb2b", size = 210315, upload-time = "2026-07-06T21:32:51.221Z" }, + { url = "https://files.pythonhosted.org/packages/58/0c/f528df19cc94b675087324d4760d9e6d5bfae97d6217aa4fac43de4f5fcc/cffi-2.1.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9fafc5aa2e2a39aaf7f8cc0c1f044a9b07fca12e558dca53a3cc5c654ad67a7", size = 208859, upload-time = "2026-07-06T21:32:52.512Z" }, + { url = "https://files.pythonhosted.org/packages/62/f2/c9522a81c32132799a1972c39f5c5f8b4c8b9f00488a23feaa6c06f07741/cffi-2.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1e9f50d192a3e525b15a75ab5114e442d83d657b7ec29182a991bc9a88fd3a66", size = 221844, upload-time = "2026-07-06T21:32:53.704Z" }, + { url = "https://files.pythonhosted.org/packages/6e/28/bd53988b9833e8f8ad539d26f4c07a6b3f6bcb1e9e02e7ca038250b3428d/cffi-2.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98fff996e983a36d3aa2eca83af40c5821202e7e6f32d13ae94e3d2286f10cfe", size = 225287, upload-time = "2026-07-06T21:32:54.907Z" }, + { url = "https://files.pythonhosted.org/packages/79/99/0d0fd37f055224085f42bbb2c022d002e17dde4a97972822327b07d84101/cffi-2.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:379de10ce1ba048b1448599d1b37b24caee16309d1ac98d3982fc997f768700b", size = 223681, upload-time = "2026-07-06T21:32:56.329Z" }, + { url = "https://files.pythonhosted.org/packages/b0/80/c138990aa2a70b1a269f6e06348729836d733d6f970867943f61d367f8cc/cffi-2.1.0-cp312-cp312-win32.whl", hash = "sha256:9b8f0f26ca4e7513c534d351eca551947d053fac438f2a04ac96d882909b0d3a", size = 175269, upload-time = "2026-07-06T21:32:57.777Z" }, + { url = "https://files.pythonhosted.org/packages/a8/eb/f636456ff21a83fc13c032b58cc5dde061691546ac79efa284b2989b7982/cffi-2.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:c97f080ea627e2863524c5af3836e2270b5f5dfff1f104392b959f8df0c5d384", size = 185881, upload-time = "2026-07-06T21:32:59.253Z" }, + { url = "https://files.pythonhosted.org/packages/dd/2c/400ea43e721727dca8a65c4521390e9196757caba4a45643acb2b63271b8/cffi-2.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:6d194185eabd279f1c05ebe3504265ddfc5ad2b58d0714f7db9f01da592e9eb6", size = 180088, upload-time = "2026-07-06T21:33:02.278Z" }, + { url = "https://files.pythonhosted.org/packages/96/88/a996879e2eeccb815f6e3a5967b12a308257412acec882039d386bd2aa7b/cffi-2.1.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:10537b1df4967ca26d21e5072d7d54188354483b91dc75058968d3f0cf13fbda", size = 194331, upload-time = "2026-07-06T21:33:03.697Z" }, + { url = "https://files.pythonhosted.org/packages/58/85/7ae00d5c8dd6266f4e944c3db630f3c5c9a98b61d469c714d848b1d8138a/cffi-2.1.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:a95b05f9baf29b91171b3a8bd2020b028835243e7b0ff6bb23e2a3c228518b1b", size = 196966, upload-time = "2026-07-06T21:33:05.353Z" }, + { url = "https://files.pythonhosted.org/packages/8c/e9/45c3a76ad8d43ad9261f4c95436da61128d3ca545d72b9612c0ab5be0b1c/cffi-2.1.0-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:15faec4adfff450819f3aee0e2e02c812de6edb88203aa58807955db2003472a", size = 184795, upload-time = "2026-07-06T21:33:06.699Z" }, + { url = "https://files.pythonhosted.org/packages/84/4c/82f132cb4418ee6d953d982b19191e87e2a6372c8a4ce36e50b69d6ade4a/cffi-2.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:716ff8ec22f20b4d988b12884086bcef0fc99737043e503f7a3935a6be99b1ea", size = 184746, upload-time = "2026-07-06T21:33:08.071Z" }, + { url = "https://files.pythonhosted.org/packages/a0/1c/4ed5a0e5bdca6cbc275556de3328dd1b76fd0c11cc13c88fe66d1d8715f2/cffi-2.1.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:63960549e4f8dc41e31accb97b975abaecfc44c03e396c093a6436763c2ea7db", size = 214747, upload-time = "2026-07-06T21:33:09.671Z" }, + { url = "https://files.pythonhosted.org/packages/3a/a6/e879bb68cc23a2bc9ba8f4b7d8019f0c2694bad2ab6c4a3701d429439f58/cffi-2.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ff067a8d8d880e7809e4ac88eb009bb848870115317b306666502ccad30b147f", size = 222392, upload-time = "2026-07-06T21:33:10.896Z" }, + { url = "https://files.pythonhosted.org/packages/88/f6/01890cfd63c08f8eb96a8319b0443690197d240a8bd6346048cf7bde9190/cffi-2.1.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:3b926723c13eba9f81d2ef3820d63aeceec3b2d4639906047bf675cb8a7a500d", size = 210285, upload-time = "2026-07-06T21:33:12.251Z" }, + { url = "https://files.pythonhosted.org/packages/a6/cf/2b684132056f438567b61e19d690dd31cd0921ace051e0a458be6074369e/cffi-2.1.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:47ff3a8bfd8cb9da1af7524b965127095055654c177fcfc7578debcb015eecd0", size = 208801, upload-time = "2026-07-06T21:33:13.617Z" }, + { url = "https://files.pythonhosted.org/packages/6f/08/f2e7d62c460faae0926f2d6e423694aa409ced3bc1fe2927a0a6e5f05416/cffi-2.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:799416bae98336e400981ff6e532d67d5c709cfb30afb79865a1315f94b0e224", size = 221808, upload-time = "2026-07-06T21:33:15.466Z" }, + { url = "https://files.pythonhosted.org/packages/38/37/04f54b8e63a02f3d908332c9effbf8c366167c6f733ed8a3d4f79b7e2a1e/cffi-2.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:961be50688f7fba2fa65f63712d3b9b341a22311f5253460ce933f52f0de1c8c", size = 225241, upload-time = "2026-07-06T21:33:16.869Z" }, + { url = "https://files.pythonhosted.org/packages/a9/d6/c72eecca433cd3e681c65ed313ab4835d9d4a379704d0f628a6a05f51c2e/cffi-2.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bf5c6cf48238b0eb4c086978c492ad1cbc22373fc5b2d7353b3a598ce6db887a", size = 223588, upload-time = "2026-07-06T21:33:18.239Z" }, + { url = "https://files.pythonhosted.org/packages/c6/4b/e706f67279140f92939da3475ad610df18bfd52d50f14953a8e5fede71d5/cffi-2.1.0-cp313-cp313-win32.whl", hash = "sha256:db3eb7d46527159a878ec3460e9d40615bc25ba337d477db681aea6e4f05c5d2", size = 175248, upload-time = "2026-07-06T21:33:19.799Z" }, + { url = "https://files.pythonhosted.org/packages/5a/47/59eb7975cb0e4ef0afa764ea945b29a5bb4537a9f771cb7d6c8a5dd74c95/cffi-2.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:8e74a6135550c4748af665b1b1118b6aab33b1fc6a16f9aff630af107c3b4512", size = 185717, upload-time = "2026-07-06T21:33:21.47Z" }, + { url = "https://files.pythonhosted.org/packages/5a/af/34fee85c48f8d94efc8597bc09470c9dd274c145f1c12e0fbc6ab6d38d74/cffi-2.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:2282cd5e38aa8accd03e99d1256af8411c84cdbee6a89d841b563fdbd1f3e50f", size = 180114, upload-time = "2026-07-06T21:33:22.515Z" }, + { url = "https://files.pythonhosted.org/packages/d8/f0/81478e482afa03f6d18dc8f2afb5edc45b3080853b634b5ed91961be0998/cffi-2.1.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d2117334c3af3bdcb9a88522b844a2bdb5efdc4f71c6c822df55486ae1c3347a", size = 194142, upload-time = "2026-07-06T21:33:23.657Z" }, + { url = "https://files.pythonhosted.org/packages/7d/95/8de304305cd9204974b0ca051b86d307cafca13aa575a0ef1b44d92c0d8c/cffi-2.1.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:702c436735fbe99d59ada02a1f65cfc0d31c0ee8b7290912f8fbc5cd1e4b16c3", size = 196819, upload-time = "2026-07-06T21:33:25.007Z" }, + { url = "https://files.pythonhosted.org/packages/20/71/7c8372d30e42415602ed9f268f7cfd66f1b855fed881ecd168bcb45dbc0b/cffi-2.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:1ff3456eab0d889592d1936d6125bbfbc7ae4d3354a700f8bd80450a66445d4d", size = 184965, upload-time = "2026-07-06T21:33:26.605Z" }, + { url = "https://files.pythonhosted.org/packages/d6/5c/584e626835f0375c928176c04137c96927165cb8733cdb3150ec04e5ee5e/cffi-2.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c4165821e131d6d4ca444347c2b694e2311bcfa3fe5a861cc72968f28867beac", size = 184952, upload-time = "2026-07-06T21:33:27.823Z" }, + { url = "https://files.pythonhosted.org/packages/2e/d2/065fcae1c73979fac8e054462478d0ff8a29c40cdc2ed7ea5676a061df53/cffi-2.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:276f20fffd7b396e12516ba8edf9509210ac248cbbc5acbc39cd512f9f59ebe6", size = 222353, upload-time = "2026-07-06T21:33:29.178Z" }, + { url = "https://files.pythonhosted.org/packages/ed/a5/e8bbb1ce5b3ac2f53ad6a10bde44318a5a8d99d4f4a000d44a6e39aeb3e4/cffi-2.1.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:7d5980a3433d4b71a5e120f9dd551403d7824e31e2e67124fe2769c404c06913", size = 210051, upload-time = "2026-07-06T21:33:30.534Z" }, + { url = "https://files.pythonhosted.org/packages/28/ed/c127d3ac36e899c965e3361357c3befacd6578c03f40125183e41c3b219e/cffi-2.1.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:6ca4919c6e4f89aa99c42510b42cf54596892c00b3f9077f6bdd1505e24b9c8d", size = 208630, upload-time = "2026-07-06T21:33:31.753Z" }, + { url = "https://files.pythonhosted.org/packages/cc/d7/97d3136f81db489ec8d1d67748c110d6c994268fd7528014aa9f2b085e4e/cffi-2.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d53d10f7da99ae46f7373b9150393e9c5eab9b224909982b43832668de4779f5", size = 221593, upload-time = "2026-07-06T21:33:33.044Z" }, + { url = "https://files.pythonhosted.org/packages/d3/27/93195977168ee63aed233a1a0993a2178798654d1f4bddcdd321d6fd3b21/cffi-2.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c351efb95e832a853a29361675f33a7ce53de1a109cd73fd47af0712213aa4ce", size = 225146, upload-time = "2026-07-06T21:33:34.224Z" }, + { url = "https://files.pythonhosted.org/packages/b3/c1/6dbd291ee2ae5a50a034aa057207081f545923bbf15dad4511e985aafff5/cffi-2.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:dbf7c7a88e2bac086f06d14577332760bdeecc42bdec8ac4077f6260557d9326", size = 223240, upload-time = "2026-07-06T21:33:35.57Z" }, + { url = "https://files.pythonhosted.org/packages/0f/6f/ade5ce9863a57992a6ea3d0d10d7e29b8749fc127204b3d493d667b2815f/cffi-2.1.0-cp314-cp314-win32.whl", hash = "sha256:1854b724d00f6654c742097d5387569021be12d3a0f770eae1df8f8acfcc6acd", size = 177723, upload-time = "2026-07-06T21:33:51.626Z" }, + { url = "https://files.pythonhosted.org/packages/41/de/92b9eeed4ae4a21d6fd9b2a2c8505cbed573299902ea73981cc13f7ff62c/cffi-2.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:1b96bfe2c4bd825681b7d311ad6d9b7280a091f43e8f63da5729638083cd3bfb", size = 187937, upload-time = "2026-07-06T21:33:53.403Z" }, + { url = "https://files.pythonhosted.org/packages/2e/1a/cc6ae6c2913a03aab8898eee57963cf1035b8df5872ed8b9115fcc7e2be8/cffi-2.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:7d28dff1db6764108bc30788d85d61c876beff416d9a49cb9dd7c5a9f34f5804", size = 183001, upload-time = "2026-07-06T21:33:54.74Z" }, + { url = "https://files.pythonhosted.org/packages/14/f0/134c00ce0779ec86dea2aa1aac69339c2741a8045072676763512363a2ea/cffi-2.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7ea6b3e2c4250ff1de21c630fe72d0f63eb95c2c32ffbf64a358cf4a8836d714", size = 188538, upload-time = "2026-07-06T21:33:36.792Z" }, + { url = "https://files.pythonhosted.org/packages/50/d8/3b86aba791cb610d24e8a3e1b2cd529e71fa15096b04e4d4e360049d4a4c/cffi-2.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6af371f3767faeffc6ac1ef57cdfd25844403e9d3f476c5537caee499de96376", size = 188230, upload-time = "2026-07-06T21:33:38.011Z" }, + { url = "https://files.pythonhosted.org/packages/14/d0/117dcd9209255ad8571fbc8c92ef32593a1d294dcec91ddc4e4db50606f2/cffi-2.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:eb4e8997a49aa2c08a3e43c9045d224448b8941d88e7ac163c7d383e560cbf98", size = 223899, upload-time = "2026-07-06T21:33:39.514Z" }, + { url = "https://files.pythonhosted.org/packages/b6/3d/f20f8b886b254e3ad10e15cd4186d3aed49f3e6a35ab37aab9f8f25f7c03/cffi-2.1.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:bf01d8c84cbea96b944c73b22182e6c7c432b3475632b8111dbfdc95ddad6e13", size = 211652, upload-time = "2026-07-06T21:33:40.851Z" }, + { url = "https://files.pythonhosted.org/packages/28/3b/fad54de07260b93ddeef4b96d0131d57ea900675df1d410ae1deee52d7a6/cffi-2.1.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:33eb1ad83ebe8f313e0df035c406227d55a79456704a863fad9842136af5ad7d", size = 210755, upload-time = "2026-07-06T21:33:42.183Z" }, + { url = "https://files.pythonhosted.org/packages/cc/82/3d5c705acb7abbba9bbd7d79b8e62e0f25b6120eb7ae6ac49f1b721722fe/cffi-2.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ac0f1a2d0cfa7eea3f2aaf006ab6e70e8feeb16b75d65b7e5939982ca2f11056", size = 223933, upload-time = "2026-07-06T21:33:43.603Z" }, + { url = "https://files.pythonhosted.org/packages/6c/d0/47e338384ab6b1004241002fa616301020cea4fc95f283506565d252f276/cffi-2.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c16914df9fb7f500e440e6875fa23ff5e0b31db01fa9c06af98d59a91f0dc2e4", size = 226749, upload-time = "2026-07-06T21:33:45.046Z" }, + { url = "https://files.pythonhosted.org/packages/70/25/65bd5b58ea4bfdfc15cde02cb5365f89ef8ab8b2adfb8fe5c4bd4233382f/cffi-2.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5ecbd0499275d57506d397eebe1981cee87b47fcd9ef5c22cab7ed7644a39a94", size = 225703, upload-time = "2026-07-06T21:33:46.374Z" }, + { url = "https://files.pythonhosted.org/packages/dc/78/aa01ac599a8a4322533d45a1f9bc93b338276d2d59dabbe7c6d92a775c81/cffi-2.1.0-cp314-cp314t-win32.whl", hash = "sha256:7d034dcffa09e9a46c93fa3a3be402096cb5354ac6e41ab8e5cc9cd8b642ad76", size = 182857, upload-time = "2026-07-06T21:33:47.696Z" }, + { url = "https://files.pythonhosted.org/packages/b9/26/d00496b22de4d4228f32dde94ad996f350c8aad676d63bcca0743c8dea4d/cffi-2.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0582a58f3051372229ca8e7f5f589f9e5632678208d8636fea3676711fdf7fe5", size = 194065, upload-time = "2026-07-06T21:33:48.953Z" }, + { url = "https://files.pythonhosted.org/packages/d5/dd/0c7dbf815a579ff005008a2d815a55d6bb047c349eef536d9dc53d3f0a8d/cffi-2.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:510aeeeac94811b138077451da1fb18b308a5feab47dd2b603af55804155e1c8", size = 186404, upload-time = "2026-07-06T21:33:50.309Z" }, + { url = "https://files.pythonhosted.org/packages/55/c7/8c8c50cb11c6750051daf12164098a9a6f027ac4356967fd4d800a07f242/cffi-2.1.0-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:2e9dabb9abcb7ad15938c7196ad5c1718a4e6d33cc79b4c0209bdb64c4a54a5c", size = 194121, upload-time = "2026-07-06T21:33:56.109Z" }, + { url = "https://files.pythonhosted.org/packages/99/e2/67680bf19a6b60d2bb7ff83baefa2a4c3d2d7dc0f3277034b802e1fc504c/cffi-2.1.0-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:37f525a7e7e50c017fdebe58b787be310ad59357ae43a053943a6e1a6c526001", size = 196820, upload-time = "2026-07-06T21:33:57.288Z" }, + { url = "https://files.pythonhosted.org/packages/ed/da/4bbe583a3b3a5c8c60892124fe17f3fa3656523faf0d3484eae90f091853/cffi-2.1.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:95f2954c2c9473d892eca6e0409f3568b37ab62a8eedb122461f73cc273476e3", size = 184936, upload-time = "2026-07-06T21:33:58.765Z" }, + { url = "https://files.pythonhosted.org/packages/e5/4b/1f4c36ab273980d7aa75bb126ea4f8971f24a96108acad3a0a084028c57b/cffi-2.1.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:cdf2448aab5f661c9315308ec8b93f4e8a1a67a3c733f8631067a2b67d5913dc", size = 185045, upload-time = "2026-07-06T21:34:00.085Z" }, + { url = "https://files.pythonhosted.org/packages/ef/c3/ad299dc38f3583f8d916b299f028af418a9ec98bc695fcbebeae7420691c/cffi-2.1.0-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:90bec57cf82089383bd06a605b3eb8daebf7e5a668520beaf6e327a83a947699", size = 222342, upload-time = "2026-07-06T21:34:01.814Z" }, + { url = "https://files.pythonhosted.org/packages/eb/d8/df4543cc087245044ed02ef3ad8e0a26619d0075ac7a77a12dc81177851b/cffi-2.1.0-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6274dcb2d15cef48daa73ed1be5a40d501d74dccd0cd6db364776d12cb6ba022", size = 210073, upload-time = "2026-07-06T21:34:03.255Z" }, + { url = "https://files.pythonhosted.org/packages/2c/0e/fac738d73728c6cea2a88a2883dca54892496cbba88a1dc1f2909cb8a6f5/cffi-2.1.0-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:2b71d409cccee78310ab5dec549aed052aaea483346e282c7b02362596e01bb0", size = 208551, upload-time = "2026-07-06T21:34:04.433Z" }, + { url = "https://files.pythonhosted.org/packages/e6/3f/0b04a700dd64f465c93020253a793a82c9b4dff9961f48facd0df945d9b8/cffi-2.1.0-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7d3538f9c0e50670f4deb93dbb696576e60590369cae2faf7de681e597a8a1f1", size = 221649, upload-time = "2026-07-06T21:34:06.157Z" }, + { url = "https://files.pythonhosted.org/packages/5d/7c/b7379a5704c79eda57ce075869ba70a0368d1c850f803b3c0d078d39dcaf/cffi-2.1.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:8f9ec95b8a043d3dfbc74d9abc6f7baf524dd27a8dc160b0a32ff9cdab650c28", size = 225203, upload-time = "2026-07-06T21:34:07.489Z" }, + { url = "https://files.pythonhosted.org/packages/5a/02/d5e6c43ea85c41bda2a184a3418f195fe7cf602967a8d2b94e085b83deef/cffi-2.1.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:af5e2915d41fe6c961694d7bfdc8562942638200f3ce2765dfb8b745cf997629", size = 223263, upload-time = "2026-07-06T21:34:08.712Z" }, + { url = "https://files.pythonhosted.org/packages/2c/d8/772b8259bf75749adffb1c546828978381fb516f60cf701f6c83daf60c85/cffi-2.1.0-cp315-cp315-win32.whl", hash = "sha256:0a42c688d19fca6e095a53c6a6e2295a5b050a8b289f109adab02a9e61a25de6", size = 177696, upload-time = "2026-07-06T21:34:26.355Z" }, + { url = "https://files.pythonhosted.org/packages/2f/dd/afa2191fc6d57fedd26e5844a2fe2fcc0bbfa00961bbaa5a41e4921e7cca/cffi-2.1.0-cp315-cp315-win_amd64.whl", hash = "sha256:bccbbb5ee76a61f9d99b5bf3846a51d7fca4b6a732fe46f89295610edaf41853", size = 187914, upload-time = "2026-07-06T21:34:27.58Z" }, + { url = "https://files.pythonhosted.org/packages/05/ef/6cd4f8c671517162379dc79cfae5aea9106bc38abb89628d5c16adf6a838/cffi-2.1.0-cp315-cp315-win_arm64.whl", hash = "sha256:8d35c139744adb3e727cd51b1a18324bbe44b8bd41bf8322bca4d41289f48eda", size = 183004, upload-time = "2026-07-06T21:34:28.905Z" }, + { url = "https://files.pythonhosted.org/packages/11/b6/12fc55092817a5faa26fb8c40c7f9d662e11a46ee248c137aafc42517d92/cffi-2.1.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:f9912624a0c0b834b7520d7769b3644453aabc0a7e1c839da7359f050750e9bc", size = 188378, upload-time = "2026-07-06T21:34:09.926Z" }, + { url = "https://files.pythonhosted.org/packages/8d/2e/cdac88979f295fde5daa69622c7d2111e56e7ceb94f211357fbe452339e4/cffi-2.1.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:df92f2aba50eb4d96718b68ef76f2e57a57b54f2fa62333496d16c6d585a85ca", size = 188319, upload-time = "2026-07-06T21:34:11.101Z" }, + { url = "https://files.pythonhosted.org/packages/e0/27/1d0b408497e41a74795af122d7b603c418c5fed0171450f899afd04e594f/cffi-2.1.0-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0520e1f4c35f44e209cbbb421b67eec42e6a157f59444dfb6058874ff3610e5d", size = 223904, upload-time = "2026-07-06T21:34:12.606Z" }, + { url = "https://files.pythonhosted.org/packages/8b/31/e115c985105dd7ffb32444505f18ceb874bb42d992af05d5dced7ecf1980/cffi-2.1.0-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:3681e031db29958a7502f5c0c9d6bbc4c36cb20f7b104086fa642d1799631ff8", size = 211554, upload-time = "2026-07-06T21:34:13.987Z" }, + { url = "https://files.pythonhosted.org/packages/5a/67/9e6e09409336d9e515c58367e7cfcf4f89df06ad25252675595a58eb59d5/cffi-2.1.0-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:762f99479dcb369f60ab9017ad4ab97a36a1dd7c1ee5a3b15db0f4b8659120cd", size = 210795, upload-time = "2026-07-06T21:34:15.972Z" }, + { url = "https://files.pythonhosted.org/packages/19/e5/d3cc82a4a0be7902af279c04181ad038449c096734464a5ae1de3e1401bd/cffi-2.1.0-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0611e7ebf90573a535ebdc33ae9da222d037853983e13359f580fab781ca017f", size = 223843, upload-time = "2026-07-06T21:34:17.509Z" }, + { url = "https://files.pythonhosted.org/packages/b9/65/b434abc97ce7cecc2c640fde160507c0ecc7e21544b483ba3325d2e2ea17/cffi-2.1.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:86cf8755a791f72c85dc287128cc62d4f24d392e3f1e15837245623f4a33cccc", size = 226773, upload-time = "2026-07-06T21:34:19.05Z" }, + { url = "https://files.pythonhosted.org/packages/b5/9f/d4dc66ca651eb1145a133314cda721abf13cfac3d28c4a0402263ae6ad75/cffi-2.1.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:ba00f661f8ba35d075c937174e27c2c421cec3942fd2e0ea3e66996757c0fdd9", size = 225719, upload-time = "2026-07-06T21:34:20.576Z" }, + { url = "https://files.pythonhosted.org/packages/68/5a/e536c528bc8057496c360c0978559a2dc45653f89dd6151078aa7d8fca1a/cffi-2.1.0-cp315-cp315t-win32.whl", hash = "sha256:cb96698e3c7413d906ce83f8ffd245ec1bd94707541f299d0ce4d6b0193e982b", size = 182760, upload-time = "2026-07-06T21:34:22.059Z" }, + { url = "https://files.pythonhosted.org/packages/d3/0b/0ffe8b82d3875bced5fa1e7986a7a46b748262a40ab7f60b475eb9fb1bb3/cffi-2.1.0-cp315-cp315t-win_amd64.whl", hash = "sha256:f146d154428a2523f9cc7936c02353c2459b8f6cf07d3cd1ee1c0a611109c5d5", size = 193769, upload-time = "2026-07-06T21:34:23.589Z" }, + { url = "https://files.pythonhosted.org/packages/a0/17/1073b53b68c9b5ca6914adf5f8bf55aacc2d3be102418c90700160ea8605/cffi-2.1.0-cp315-cp315t-win_arm64.whl", hash = "sha256:cbb7640ce37159548d2147b5b8c241f962143d4c71231431820783f4dc78f210", size = 186405, upload-time = "2026-07-06T21:34:24.857Z" }, ] [[package]] @@ -367,103 +497,88 @@ wheels = [ [[package]] name = "charset-normalizer" -version = "3.4.7" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e7/a1/67fe25fac3c7642725500a3f6cfe5821ad557c3abb11c9d20d12c7008d3e/charset_normalizer-3.4.7.tar.gz", hash = "sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5", size = 144271, upload-time = "2026-04-02T09:28:39.342Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c2/d7/b5b7020a0565c2e9fa8c09f4b5fa6232feb326b8c20081ccded47ea368fd/charset_normalizer-3.4.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7", size = 309705, upload-time = "2026-04-02T09:26:02.191Z" }, - { url = "https://files.pythonhosted.org/packages/5a/53/58c29116c340e5456724ecd2fff4196d236b98f3da97b404bc5e51ac3493/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7", size = 206419, upload-time = "2026-04-02T09:26:03.583Z" }, - { url = "https://files.pythonhosted.org/packages/b2/02/e8146dc6591a37a00e5144c63f29fb7c97a734ea8a111190783c0e60ab63/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e", size = 227901, upload-time = "2026-04-02T09:26:04.738Z" }, - { url = "https://files.pythonhosted.org/packages/fb/73/77486c4cd58f1267bf17db420e930c9afa1b3be3fe8c8b8ebbebc9624359/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c", size = 222742, upload-time = "2026-04-02T09:26:06.36Z" }, - { url = "https://files.pythonhosted.org/packages/a1/fa/f74eb381a7d94ded44739e9d94de18dc5edc9c17fb8c11f0a6890696c0a9/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df", size = 214061, upload-time = "2026-04-02T09:26:08.347Z" }, - { url = "https://files.pythonhosted.org/packages/dc/92/42bd3cefcf7687253fb86694b45f37b733c97f59af3724f356fa92b8c344/charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265", size = 199239, upload-time = "2026-04-02T09:26:09.823Z" }, - { url = "https://files.pythonhosted.org/packages/4c/3d/069e7184e2aa3b3cddc700e3dd267413dc259854adc3380421c805c6a17d/charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4", size = 210173, upload-time = "2026-04-02T09:26:10.953Z" }, - { url = "https://files.pythonhosted.org/packages/62/51/9d56feb5f2e7074c46f93e0ebdbe61f0848ee246e2f0d89f8e20b89ebb8f/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e", size = 209841, upload-time = "2026-04-02T09:26:12.142Z" }, - { url = "https://files.pythonhosted.org/packages/d2/59/893d8f99cc4c837dda1fe2f1139079703deb9f321aabcb032355de13b6c7/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38", size = 200304, upload-time = "2026-04-02T09:26:13.711Z" }, - { url = "https://files.pythonhosted.org/packages/7d/1d/ee6f3be3464247578d1ed5c46de545ccc3d3ff933695395c402c21fa6b77/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c", size = 229455, upload-time = "2026-04-02T09:26:14.941Z" }, - { url = "https://files.pythonhosted.org/packages/54/bb/8fb0a946296ea96a488928bdce8ef99023998c48e4713af533e9bb98ef07/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b", size = 210036, upload-time = "2026-04-02T09:26:16.478Z" }, - { url = "https://files.pythonhosted.org/packages/9a/bc/015b2387f913749f82afd4fcba07846d05b6d784dd16123cb66860e0237d/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c", size = 224739, upload-time = "2026-04-02T09:26:17.751Z" }, - { url = "https://files.pythonhosted.org/packages/17/ab/63133691f56baae417493cba6b7c641571a2130eb7bceba6773367ab9ec5/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d", size = 216277, upload-time = "2026-04-02T09:26:18.981Z" }, - { url = "https://files.pythonhosted.org/packages/06/6d/3be70e827977f20db77c12a97e6a9f973631a45b8d186c084527e53e77a4/charset_normalizer-3.4.7-cp311-cp311-win32.whl", hash = "sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad", size = 147819, upload-time = "2026-04-02T09:26:20.295Z" }, - { url = "https://files.pythonhosted.org/packages/20/d9/5f67790f06b735d7c7637171bbfd89882ad67201891b7275e51116ed8207/charset_normalizer-3.4.7-cp311-cp311-win_amd64.whl", hash = "sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00", size = 159281, upload-time = "2026-04-02T09:26:21.74Z" }, - { url = "https://files.pythonhosted.org/packages/ca/83/6413f36c5a34afead88ce6f66684d943d91f233d76dd083798f9602b75ae/charset_normalizer-3.4.7-cp311-cp311-win_arm64.whl", hash = "sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1", size = 147843, upload-time = "2026-04-02T09:26:22.901Z" }, - { url = "https://files.pythonhosted.org/packages/0c/eb/4fc8d0a7110eb5fc9cc161723a34a8a6c200ce3b4fbf681bc86feee22308/charset_normalizer-3.4.7-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46", size = 311328, upload-time = "2026-04-02T09:26:24.331Z" }, - { url = "https://files.pythonhosted.org/packages/f8/e3/0fadc706008ac9d7b9b5be6dc767c05f9d3e5df51744ce4cc9605de7b9f4/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2", size = 208061, upload-time = "2026-04-02T09:26:25.568Z" }, - { url = "https://files.pythonhosted.org/packages/42/f0/3dd1045c47f4a4604df85ec18ad093912ae1344ac706993aff91d38773a2/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b", size = 229031, upload-time = "2026-04-02T09:26:26.865Z" }, - { url = "https://files.pythonhosted.org/packages/dc/67/675a46eb016118a2fbde5a277a5d15f4f69d5f3f5f338e5ee2f8948fcf43/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a", size = 225239, upload-time = "2026-04-02T09:26:28.044Z" }, - { url = "https://files.pythonhosted.org/packages/4b/f8/d0118a2f5f23b02cd166fa385c60f9b0d4f9194f574e2b31cef350ad7223/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116", size = 216589, upload-time = "2026-04-02T09:26:29.239Z" }, - { url = "https://files.pythonhosted.org/packages/b1/f1/6d2b0b261b6c4ceef0fcb0d17a01cc5bc53586c2d4796fa04b5c540bc13d/charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb", size = 202733, upload-time = "2026-04-02T09:26:30.5Z" }, - { url = "https://files.pythonhosted.org/packages/6f/c0/7b1f943f7e87cc3db9626ba17807d042c38645f0a1d4415c7a14afb5591f/charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1", size = 212652, upload-time = "2026-04-02T09:26:31.709Z" }, - { url = "https://files.pythonhosted.org/packages/38/dd/5a9ab159fe45c6e72079398f277b7d2b523e7f716acc489726115a910097/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15", size = 211229, upload-time = "2026-04-02T09:26:33.282Z" }, - { url = "https://files.pythonhosted.org/packages/d5/ff/531a1cad5ca855d1c1a8b69cb71abfd6d85c0291580146fda7c82857caa1/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5", size = 203552, upload-time = "2026-04-02T09:26:34.845Z" }, - { url = "https://files.pythonhosted.org/packages/c1/4c/a5fb52d528a8ca41f7598cb619409ece30a169fbdf9cdce592e53b46c3a6/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d", size = 230806, upload-time = "2026-04-02T09:26:36.152Z" }, - { url = "https://files.pythonhosted.org/packages/59/7a/071feed8124111a32b316b33ae4de83d36923039ef8cf48120266844285b/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7", size = 212316, upload-time = "2026-04-02T09:26:37.672Z" }, - { url = "https://files.pythonhosted.org/packages/fd/35/f7dba3994312d7ba508e041eaac39a36b120f32d4c8662b8814dab876431/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464", size = 227274, upload-time = "2026-04-02T09:26:38.93Z" }, - { url = "https://files.pythonhosted.org/packages/8a/2d/a572df5c9204ab7688ec1edc895a73ebded3b023bb07364710b05dd1c9be/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49", size = 218468, upload-time = "2026-04-02T09:26:40.17Z" }, - { url = "https://files.pythonhosted.org/packages/86/eb/890922a8b03a568ca2f336c36585a4713c55d4d67bf0f0c78924be6315ca/charset_normalizer-3.4.7-cp312-cp312-win32.whl", hash = "sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c", size = 148460, upload-time = "2026-04-02T09:26:41.416Z" }, - { url = "https://files.pythonhosted.org/packages/35/d9/0e7dffa06c5ab081f75b1b786f0aefc88365825dfcd0ac544bdb7b2b6853/charset_normalizer-3.4.7-cp312-cp312-win_amd64.whl", hash = "sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6", size = 159330, upload-time = "2026-04-02T09:26:42.554Z" }, - { url = "https://files.pythonhosted.org/packages/9e/5d/481bcc2a7c88ea6b0878c299547843b2521ccbc40980cb406267088bc701/charset_normalizer-3.4.7-cp312-cp312-win_arm64.whl", hash = "sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d", size = 147828, upload-time = "2026-04-02T09:26:44.075Z" }, - { url = "https://files.pythonhosted.org/packages/c1/3b/66777e39d3ae1ddc77ee606be4ec6d8cbd4c801f65e5a1b6f2b11b8346dd/charset_normalizer-3.4.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063", size = 309627, upload-time = "2026-04-02T09:26:45.198Z" }, - { url = "https://files.pythonhosted.org/packages/2e/4e/b7f84e617b4854ade48a1b7915c8ccfadeba444d2a18c291f696e37f0d3b/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c", size = 207008, upload-time = "2026-04-02T09:26:46.824Z" }, - { url = "https://files.pythonhosted.org/packages/c4/bb/ec73c0257c9e11b268f018f068f5d00aa0ef8c8b09f7753ebd5f2880e248/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66", size = 228303, upload-time = "2026-04-02T09:26:48.397Z" }, - { url = "https://files.pythonhosted.org/packages/85/fb/32d1f5033484494619f701e719429c69b766bfc4dbc61aa9e9c8c166528b/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18", size = 224282, upload-time = "2026-04-02T09:26:49.684Z" }, - { url = "https://files.pythonhosted.org/packages/fa/07/330e3a0dda4c404d6da83b327270906e9654a24f6c546dc886a0eb0ffb23/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd", size = 215595, upload-time = "2026-04-02T09:26:50.915Z" }, - { url = "https://files.pythonhosted.org/packages/e3/7c/fc890655786e423f02556e0216d4b8c6bcb6bdfa890160dc66bf52dee468/charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215", size = 201986, upload-time = "2026-04-02T09:26:52.197Z" }, - { url = "https://files.pythonhosted.org/packages/d8/97/bfb18b3db2aed3b90cf54dc292ad79fdd5ad65c4eae454099475cbeadd0d/charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859", size = 211711, upload-time = "2026-04-02T09:26:53.49Z" }, - { url = "https://files.pythonhosted.org/packages/6f/a5/a581c13798546a7fd557c82614a5c65a13df2157e9ad6373166d2a3e645d/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8", size = 210036, upload-time = "2026-04-02T09:26:54.975Z" }, - { url = "https://files.pythonhosted.org/packages/8c/bf/b3ab5bcb478e4193d517644b0fb2bf5497fbceeaa7a1bc0f4d5b50953861/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5", size = 202998, upload-time = "2026-04-02T09:26:56.303Z" }, - { url = "https://files.pythonhosted.org/packages/e7/4e/23efd79b65d314fa320ec6017b4b5834d5c12a58ba4610aa353af2e2f577/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832", size = 230056, upload-time = "2026-04-02T09:26:57.554Z" }, - { url = "https://files.pythonhosted.org/packages/b9/9f/1e1941bc3f0e01df116e68dc37a55c4d249df5e6fa77f008841aef68264f/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6", size = 211537, upload-time = "2026-04-02T09:26:58.843Z" }, - { url = "https://files.pythonhosted.org/packages/80/0f/088cbb3020d44428964a6c97fe1edfb1b9550396bf6d278330281e8b709c/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48", size = 226176, upload-time = "2026-04-02T09:27:00.437Z" }, - { url = "https://files.pythonhosted.org/packages/6a/9f/130394f9bbe06f4f63e22641d32fc9b202b7e251c9aef4db044324dac493/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a", size = 217723, upload-time = "2026-04-02T09:27:02.021Z" }, - { url = "https://files.pythonhosted.org/packages/73/55/c469897448a06e49f8fa03f6caae97074fde823f432a98f979cc42b90e69/charset_normalizer-3.4.7-cp313-cp313-win32.whl", hash = "sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e", size = 148085, upload-time = "2026-04-02T09:27:03.192Z" }, - { url = "https://files.pythonhosted.org/packages/5d/78/1b74c5bbb3f99b77a1715c91b3e0b5bdb6fe302d95ace4f5b1bec37b0167/charset_normalizer-3.4.7-cp313-cp313-win_amd64.whl", hash = "sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110", size = 158819, upload-time = "2026-04-02T09:27:04.454Z" }, - { url = "https://files.pythonhosted.org/packages/68/86/46bd42279d323deb8687c4a5a811fd548cb7d1de10cf6535d099877a9a9f/charset_normalizer-3.4.7-cp313-cp313-win_arm64.whl", hash = "sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b", size = 147915, upload-time = "2026-04-02T09:27:05.971Z" }, - { url = "https://files.pythonhosted.org/packages/97/c8/c67cb8c70e19ef1960b97b22ed2a1567711de46c4ddf19799923adc836c2/charset_normalizer-3.4.7-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0", size = 309234, upload-time = "2026-04-02T09:27:07.194Z" }, - { url = "https://files.pythonhosted.org/packages/99/85/c091fdee33f20de70d6c8b522743b6f831a2f1cd3ff86de4c6a827c48a76/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a", size = 208042, upload-time = "2026-04-02T09:27:08.749Z" }, - { url = "https://files.pythonhosted.org/packages/87/1c/ab2ce611b984d2fd5d86a5a8a19c1ae26acac6bad967da4967562c75114d/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b", size = 228706, upload-time = "2026-04-02T09:27:09.951Z" }, - { url = "https://files.pythonhosted.org/packages/a8/29/2b1d2cb00bf085f59d29eb773ce58ec2d325430f8c216804a0a5cd83cbca/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41", size = 224727, upload-time = "2026-04-02T09:27:11.175Z" }, - { url = "https://files.pythonhosted.org/packages/47/5c/032c2d5a07fe4d4855fea851209cca2b6f03ebeb6d4e3afdb3358386a684/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e", size = 215882, upload-time = "2026-04-02T09:27:12.446Z" }, - { url = "https://files.pythonhosted.org/packages/2c/c2/356065d5a8b78ed04499cae5f339f091946a6a74f91e03476c33f0ab7100/charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae", size = 200860, upload-time = "2026-04-02T09:27:13.721Z" }, - { url = "https://files.pythonhosted.org/packages/0c/cd/a32a84217ced5039f53b29f460962abb2d4420def55afabe45b1c3c7483d/charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18", size = 211564, upload-time = "2026-04-02T09:27:15.272Z" }, - { url = "https://files.pythonhosted.org/packages/44/86/58e6f13ce26cc3b8f4a36b94a0f22ae2f00a72534520f4ae6857c4b81f89/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b", size = 211276, upload-time = "2026-04-02T09:27:16.834Z" }, - { url = "https://files.pythonhosted.org/packages/8f/fe/d17c32dc72e17e155e06883efa84514ca375f8a528ba2546bee73fc4df81/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356", size = 201238, upload-time = "2026-04-02T09:27:18.229Z" }, - { url = "https://files.pythonhosted.org/packages/6a/29/f33daa50b06525a237451cdb6c69da366c381a3dadcd833fa5676bc468b3/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab", size = 230189, upload-time = "2026-04-02T09:27:19.445Z" }, - { url = "https://files.pythonhosted.org/packages/b6/6e/52c84015394a6a0bdcd435210a7e944c5f94ea1055f5cc5d56c5fe368e7b/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46", size = 211352, upload-time = "2026-04-02T09:27:20.79Z" }, - { url = "https://files.pythonhosted.org/packages/8c/d7/4353be581b373033fb9198bf1da3cf8f09c1082561e8e922aa7b39bf9fe8/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44", size = 227024, upload-time = "2026-04-02T09:27:22.063Z" }, - { url = "https://files.pythonhosted.org/packages/30/45/99d18aa925bd1740098ccd3060e238e21115fffbfdcb8f3ece837d0ace6c/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72", size = 217869, upload-time = "2026-04-02T09:27:23.486Z" }, - { url = "https://files.pythonhosted.org/packages/5c/05/5ee478aa53f4bb7996482153d4bfe1b89e0f087f0ab6b294fcf92d595873/charset_normalizer-3.4.7-cp314-cp314-win32.whl", hash = "sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10", size = 148541, upload-time = "2026-04-02T09:27:25.146Z" }, - { url = "https://files.pythonhosted.org/packages/48/77/72dcb0921b2ce86420b2d79d454c7022bf5be40202a2a07906b9f2a35c97/charset_normalizer-3.4.7-cp314-cp314-win_amd64.whl", hash = "sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f", size = 159634, upload-time = "2026-04-02T09:27:26.642Z" }, - { url = "https://files.pythonhosted.org/packages/c6/a3/c2369911cd72f02386e4e340770f6e158c7980267da16af8f668217abaa0/charset_normalizer-3.4.7-cp314-cp314-win_arm64.whl", hash = "sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246", size = 148384, upload-time = "2026-04-02T09:27:28.271Z" }, - { url = "https://files.pythonhosted.org/packages/94/09/7e8a7f73d24dba1f0035fbbf014d2c36828fc1bf9c88f84093e57d315935/charset_normalizer-3.4.7-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24", size = 330133, upload-time = "2026-04-02T09:27:29.474Z" }, - { url = "https://files.pythonhosted.org/packages/8d/da/96975ddb11f8e977f706f45cddd8540fd8242f71ecdb5d18a80723dcf62c/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79", size = 216257, upload-time = "2026-04-02T09:27:30.793Z" }, - { url = "https://files.pythonhosted.org/packages/e5/e8/1d63bf8ef2d388e95c64b2098f45f84758f6d102a087552da1485912637b/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960", size = 234851, upload-time = "2026-04-02T09:27:32.44Z" }, - { url = "https://files.pythonhosted.org/packages/9b/40/e5ff04233e70da2681fa43969ad6f66ca5611d7e669be0246c4c7aaf6dc8/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4", size = 233393, upload-time = "2026-04-02T09:27:34.03Z" }, - { url = "https://files.pythonhosted.org/packages/be/c1/06c6c49d5a5450f76899992f1ee40b41d076aee9279b49cf9974d2f313d5/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e", size = 223251, upload-time = "2026-04-02T09:27:35.369Z" }, - { url = "https://files.pythonhosted.org/packages/2b/9f/f2ff16fb050946169e3e1f82134d107e5d4ae72647ec8a1b1446c148480f/charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1", size = 206609, upload-time = "2026-04-02T09:27:36.661Z" }, - { url = "https://files.pythonhosted.org/packages/69/d5/a527c0cd8d64d2eab7459784fb4169a0ac76e5a6fc5237337982fd61347e/charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44", size = 220014, upload-time = "2026-04-02T09:27:38.019Z" }, - { url = "https://files.pythonhosted.org/packages/7e/80/8a7b8104a3e203074dc9aa2c613d4b726c0e136bad1cc734594b02867972/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e", size = 218979, upload-time = "2026-04-02T09:27:39.37Z" }, - { url = "https://files.pythonhosted.org/packages/02/9a/b759b503d507f375b2b5c153e4d2ee0a75aa215b7f2489cf314f4541f2c0/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3", size = 209238, upload-time = "2026-04-02T09:27:40.722Z" }, - { url = "https://files.pythonhosted.org/packages/c2/4e/0f3f5d47b86bdb79256e7290b26ac847a2832d9a4033f7eb2cd4bcf4bb5b/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0", size = 236110, upload-time = "2026-04-02T09:27:42.33Z" }, - { url = "https://files.pythonhosted.org/packages/96/23/bce28734eb3ed2c91dcf93abeb8a5cf393a7b2749725030bb630e554fdd8/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e", size = 219824, upload-time = "2026-04-02T09:27:43.924Z" }, - { url = "https://files.pythonhosted.org/packages/2c/6f/6e897c6984cc4d41af319b077f2f600fc8214eb2fe2d6bcb79141b882400/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb", size = 233103, upload-time = "2026-04-02T09:27:45.348Z" }, - { url = "https://files.pythonhosted.org/packages/76/22/ef7bd0fe480a0ae9b656189ec00744b60933f68b4f42a7bb06589f6f576a/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe", size = 225194, upload-time = "2026-04-02T09:27:46.706Z" }, - { url = "https://files.pythonhosted.org/packages/c5/a7/0e0ab3e0b5bc1219bd80a6a0d4d72ca74d9250cb2382b7c699c147e06017/charset_normalizer-3.4.7-cp314-cp314t-win32.whl", hash = "sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0", size = 159827, upload-time = "2026-04-02T09:27:48.053Z" }, - { url = "https://files.pythonhosted.org/packages/7a/1d/29d32e0fb40864b1f878c7f5a0b343ae676c6e2b271a2d55cc3a152391da/charset_normalizer-3.4.7-cp314-cp314t-win_amd64.whl", hash = "sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c", size = 174168, upload-time = "2026-04-02T09:27:49.795Z" }, - { url = "https://files.pythonhosted.org/packages/de/32/d92444ad05c7a6e41fb2036749777c163baf7a0301a040cb672d6b2b1ae9/charset_normalizer-3.4.7-cp314-cp314t-win_arm64.whl", hash = "sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d", size = 153018, upload-time = "2026-04-02T09:27:51.116Z" }, - { url = "https://files.pythonhosted.org/packages/db/8f/61959034484a4a7c527811f4721e75d02d653a35afb0b6054474d8185d4c/charset_normalizer-3.4.7-py3-none-any.whl", hash = "sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d", size = 61958, upload-time = "2026-04-02T09:28:37.794Z" }, +version = "3.4.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bd/2a/23f34ec9d04624958e137efdc394888716353190e75f25dd22c7a2c7a8aa/charset_normalizer-3.4.9.tar.gz", hash = "sha256:673611bbd43f0810bec0b0f028ddeaaa501190339cac411f347ac76917c3ae7b", size = 152439, upload-time = "2026-07-07T14:34:58.454Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/e3/85ec501f206fb049259288c1f3506e53876937fb00edb47009348e66756b/charset_normalizer-3.4.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0e94703ec9684807f20cfb5eed95c70f67f2a8f21ad620146d7b5a13677b93e5", size = 317075, upload-time = "2026-07-07T14:32:56.021Z" }, + { url = "https://files.pythonhosted.org/packages/c3/69/2a5385192e67175f7d8bd5ce4f57c24bc956439adeae5c13a99aa28a53d1/charset_normalizer-3.4.9-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2a441ea71902098ffe78c5abe6c494f44160b4af614ed16c3d9a3b1d17fd8ee2", size = 213837, upload-time = "2026-07-07T14:32:57.78Z" }, + { url = "https://files.pythonhosted.org/packages/b3/46/03ddc7da576d814fe0a36dd1f0fd3258e95404b4b2e3c026b7923d7e133f/charset_normalizer-3.4.9-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:304b13570067b2547562e308af560b3963857b1fa90bd6afd978130130fe2d6a", size = 235503, upload-time = "2026-07-07T14:32:59.205Z" }, + { url = "https://files.pythonhosted.org/packages/4e/6e/de0229a7ef40f6f9d28a837eebf4ec47bdca5dab4e900c84f22919af636a/charset_normalizer-3.4.9-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4773092f8019072343a7447203308b176e10199920eb02d6195e81bbb3274c29", size = 229944, upload-time = "2026-07-07T14:33:00.803Z" }, + { url = "https://files.pythonhosted.org/packages/a5/34/49b9060e8418b14fb5cba9cf6bfb383111e2538a03a1fb18e66a95aeb3d5/charset_normalizer-3.4.9-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:04ce310cb89c15df659582aee80a0603788732a5e017d5bd5c81158106ce249c", size = 221276, upload-time = "2026-07-07T14:33:02.199Z" }, + { url = "https://files.pythonhosted.org/packages/44/95/80282cce0fae9c3061203d723ee87da996aed79679e65d8935050ee7ca1f/charset_normalizer-3.4.9-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:c0323c9daef75ef2e5083624b4585018a0c9d5e3b40f607eed81a311270b934b", size = 205260, upload-time = "2026-07-07T14:33:03.698Z" }, + { url = "https://files.pythonhosted.org/packages/0c/74/2f62c8821b969ea3bd67cc2e6976834f48ca5d12664d2559ebcd9bcfbed7/charset_normalizer-3.4.9-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:871ff67ea1aad4dfd91736464934d56b32dac49f9fbe16cddba36198a7b3a0db", size = 217786, upload-time = "2026-07-07T14:33:05.12Z" }, + { url = "https://files.pythonhosted.org/packages/d9/8d/feabb82cb49fcad14515b1d7d1ca4787b0da7fc723a212bf89bc9e0fac52/charset_normalizer-3.4.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:67830fc78e67501f47bb950471b2dcb9b35b140084429318e862895a8e89c993", size = 216798, upload-time = "2026-07-07T14:33:06.629Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ff/c946d63bc3786d5b84d960b0f7ab7e25b828486a946b5aa997625bcaf6a6/charset_normalizer-3.4.9-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:3d92613ec25e43b05f042302531ec0f00b8445190e43325880cbd6ab7c2581da", size = 206429, upload-time = "2026-07-07T14:33:08.006Z" }, + { url = "https://files.pythonhosted.org/packages/af/ba/5e5007c370702f85d2ef75791fac7943ed41e080364a673b20142e430e3e/charset_normalizer-3.4.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:280081916dc341820640489a66e4696049401ef1cf6dd672f672e70ad915aca3", size = 223066, upload-time = "2026-07-07T14:33:09.783Z" }, + { url = "https://files.pythonhosted.org/packages/83/d5/9096aa3cf532dfad237861544eb47a0f20d5adbf1039760fed8eaae935d9/charset_normalizer-3.4.9-cp311-cp311-win32.whl", hash = "sha256:ac351b3b8014eead140e77e9717e2992c6bbe30b63bc3422422eb84865412e3d", size = 150456, upload-time = "2026-07-07T14:33:11.217Z" }, + { url = "https://files.pythonhosted.org/packages/ed/a1/e29995109e455dc8eff8d0fac6ae509be39561318a7cfeac5d33ad029213/charset_normalizer-3.4.9-cp311-cp311-win_amd64.whl", hash = "sha256:6366a16e1a25018694d6a5d784d09b046edc9eac40ea2b54065c3052672516a1", size = 161410, upload-time = "2026-07-07T14:33:12.743Z" }, + { url = "https://files.pythonhosted.org/packages/4f/8d/1569f4d0032d6ba2a4fe4591c35bf87868c600c41a71eb5c2e1ffa8464c2/charset_normalizer-3.4.9-cp311-cp311-win_arm64.whl", hash = "sha256:1d22856ffbe153a602df38e4a5464f0b748a54002e0d69ac6d2ad0a197cc99ec", size = 152649, upload-time = "2026-07-07T14:33:14.173Z" }, + { url = "https://files.pythonhosted.org/packages/70/4a/ecbd131485c07fcdfad54e28946d513e3da22ef3b4bd854dcafae54ec739/charset_normalizer-3.4.9-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:45b0cc4e3556cd875e09102988d1ab8356c998b596c9fced84547c8138b487a0", size = 319300, upload-time = "2026-07-07T14:33:15.666Z" }, + { url = "https://files.pythonhosted.org/packages/ec/96/5d9364e3342d69f3a045e1777bc47c85c383e6e9466d561b33fdb419d1f9/charset_normalizer-3.4.9-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9b2aff1c7b3884512b9512c3eaadd9bab39fb45042ffaaa1dd08ff2b9f8109d9", size = 215802, upload-time = "2026-07-07T14:33:17.031Z" }, + { url = "https://files.pythonhosted.org/packages/4b/4c/5361f9aa7f2cb58d94f2ab831b3d493f69efb1d239654b4744e3c09527cb/charset_normalizer-3.4.9-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9104ed0bd76a429d46f9ec0dbc9b08ad1d2dcdf2b00a5a0daa1c145329b35b44", size = 237171, upload-time = "2026-07-07T14:33:18.576Z" }, + { url = "https://files.pythonhosted.org/packages/50/78/ce342ca4ff30b2eb49fe6d9578df85974f90c67d294113e94efdd9664cbd/charset_normalizer-3.4.9-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7b86a2b16095d250c6f58b3d9b2eee6f4147754344f3dab0922f7c9bf7d226c9", size = 233075, upload-time = "2026-07-07T14:33:20.084Z" }, + { url = "https://files.pythonhosted.org/packages/01/c4/4fa4c8b3097a11f3c5f09a35b72ed6855fb1d332469504962ab7bafcc702/charset_normalizer-3.4.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e226f6218febc71f6c1fc2fafb91c226f75bdc1d8fb12d66823716e891608fd", size = 224256, upload-time = "2026-07-07T14:33:21.747Z" }, + { url = "https://files.pythonhosted.org/packages/87/3a/ad914516df7e358a81aae018caa5e0470ba827fa6d763b1d2e87d920a5f6/charset_normalizer-3.4.9-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:90c44bc373b7687f6948b693cceaea1348ae0975d7474746559494468e3c1d84", size = 208784, upload-time = "2026-07-07T14:33:23.313Z" }, + { url = "https://files.pythonhosted.org/packages/d7/74/3c12f9755717dfe5c5c87da63f35d765fa0c00382ec26bf23f7fae34f2ba/charset_normalizer-3.4.9-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9cdef90ae47919cae358d8ab15797a800ed41da7aba5d72419fb510729e2ed4b", size = 219928, upload-time = "2026-07-07T14:33:24.814Z" }, + { url = "https://files.pythonhosted.org/packages/33/9a/895095b83e7907abd6d3d99aad3a38ad0d9686cc186cb0c94c24320fe63e/charset_normalizer-3.4.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:60f44ade2cf573dad7a277e6f8ca9a51a21dda572b13bd7d8539bb3cd5dbedde", size = 218489, upload-time = "2026-07-07T14:33:26.42Z" }, + { url = "https://files.pythonhosted.org/packages/a1/34/ef5c05f412f42520d7709b7d3784d19640839eb7366ded1755511585429f/charset_normalizer-3.4.9-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:a1786910334ed46ab1dd73222f2cd1e05c2c3bb39f6dddb4f8b36fc382058a39", size = 210267, upload-time = "2026-07-07T14:33:27.952Z" }, + { url = "https://files.pythonhosted.org/packages/83/dc/9b29fa4412b318bf3bfea985c35d67eb55e04b59a7c3f2237168b0e0be6f/charset_normalizer-3.4.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:03d07803992c6c7bbc976327f34b18b6160327fc81cb82c9d504720ac0be3b62", size = 226030, upload-time = "2026-07-07T14:33:29.397Z" }, + { url = "https://files.pythonhosted.org/packages/0e/42/6dbc00b8cd16011691203e33570fa42ed5746599a2e878112d16eab403a3/charset_normalizer-3.4.9-cp312-cp312-win32.whl", hash = "sha256:78841cccf1af7b40f6f716338d50c0902dbe88d9f800b3c973b7a9a0a693a642", size = 151185, upload-time = "2026-07-07T14:33:30.781Z" }, + { url = "https://files.pythonhosted.org/packages/80/cc/f920afd1a23c58ccd53c1d36085a71893a4737ff5e66e0371efab6809850/charset_normalizer-3.4.9-cp312-cp312-win_amd64.whl", hash = "sha256:4b3dac63058cc36820b0dd072f89898604e2d39686fe05321729d00d8ac185a0", size = 162557, upload-time = "2026-07-07T14:33:32.176Z" }, + { url = "https://files.pythonhosted.org/packages/f0/e6/0386d43a261ff4e4b30c5857af7df877254b46bec7b9d1b74b6bf969a90b/charset_normalizer-3.4.9-cp312-cp312-win_arm64.whl", hash = "sha256:78fa18e436a1a0e58dbd7e02fc4473f3f32cceb12df9dfca542d075961c307d2", size = 152665, upload-time = "2026-07-07T14:33:33.711Z" }, + { url = "https://files.pythonhosted.org/packages/b2/06/97ec2aeae780b31d742b6352218b43841a6871e2564578ca522dce4a45c3/charset_normalizer-3.4.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:440eede837960000d74978f0eba527be106b5b9aee0daf779d395276ed0b0614", size = 317688, upload-time = "2026-07-07T14:33:35.408Z" }, + { url = "https://files.pythonhosted.org/packages/d0/39/8ff066c672434225f8d25f8b739f992af250944392173dcc88362681c9bf/charset_normalizer-3.4.9-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21e764fd1e70b6a3e205a0e46f3051701f98a8cb3fad66eeb80e48bb502f8698", size = 214982, upload-time = "2026-07-07T14:33:36.996Z" }, + { url = "https://files.pythonhosted.org/packages/92/8f/3a47a3667c83c2df9483d91644c6c107de3bf8874aa1793da9d3012eb986/charset_normalizer-3.4.9-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e4fd89cc178bced6ad29cb3e6dd4aa63fa5017c3524dbd0b25998fb64a87cc8b", size = 236460, upload-time = "2026-07-07T14:33:38.536Z" }, + { url = "https://files.pythonhosted.org/packages/f1/60/b22cdbee7e4013dab8b0d7647fc6181120fbbbc8f7025c226d15bd5a47fc/charset_normalizer-3.4.9-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bd47ba7fc3ca94896759ea0109775132d3e7ab921fbf54038e1bab2e46c313c9", size = 232003, upload-time = "2026-07-07T14:33:40.059Z" }, + { url = "https://files.pythonhosted.org/packages/ea/f8/72eb13dcabe7257035cea8aefd922caad2f110d252bf9f67c4c2ca763aee/charset_normalizer-3.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:84fd18bcc17526fc2b3c1af7d2b9217d32c9c04448c16ec693b9b4f1985c3d33", size = 223149, upload-time = "2026-07-07T14:33:41.631Z" }, + { url = "https://files.pythonhosted.org/packages/b0/3e/faee8f9de92b14ee1198e9163252bb15efee7301b31256a3b6d9ebfdd0dd/charset_normalizer-3.4.9-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:5b10cd92fc5c498b35a8635df6d5a100207f88b63a4dc1de7ef9a548e1e2cd63", size = 207901, upload-time = "2026-07-07T14:33:43.209Z" }, + { url = "https://files.pythonhosted.org/packages/3a/25/45f30093ae27dd7b92a793b61882a38685f993700113ca36e0c9c14965e1/charset_normalizer-3.4.9-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a4fbdde9dd4a9ce5fd52c2b3a347bb50cc89483ef783f1cb00d408c13f7a96c0", size = 219176, upload-time = "2026-07-07T14:33:44.725Z" }, + { url = "https://files.pythonhosted.org/packages/48/18/c8f397329c35e32f6a837e488986f4ae03bd2abebc453b48714991630c2f/charset_normalizer-3.4.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:416c229f77e5ea25b3dfd4b582f8d73d7e43c22320302b9ab128a2d3a0b38efe", size = 217356, upload-time = "2026-07-07T14:33:46.192Z" }, + { url = "https://files.pythonhosted.org/packages/86/7e/5ce0bba863470fd1902d5e5843968951bddf38abe4742fc97116ef4598b3/charset_normalizer-3.4.9-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:75286256590a6320cf106a0d28970d3560aad9ee09aa7b34fb40524792436d35", size = 209614, upload-time = "2026-07-07T14:33:47.705Z" }, + { url = "https://files.pythonhosted.org/packages/6c/ef/2473d3c4d869155be4af1191111d59c4d5c4e0173026f7e85b176e23bf65/charset_normalizer-3.4.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:69b157c5d3292bcd443faca052f3096f637f1e074b98212a933c074ae23dc3b8", size = 224991, upload-time = "2026-07-07T14:33:49.238Z" }, + { url = "https://files.pythonhosted.org/packages/d0/a3/53ddae3db108a088156aa8ddfafd411ebbc1340f48c5573f697b27f69a39/charset_normalizer-3.4.9-cp313-cp313-win32.whl", hash = "sha256:51307f5c71007673a2bf8232ad973483d281e74cb99c8c5a990af1eefa6277d9", size = 150622, upload-time = "2026-07-07T14:33:50.711Z" }, + { url = "https://files.pythonhosted.org/packages/e8/ef/6953a77c7cf2c2ff9998e6f575ab3e380119f100223381565a4f94c1f836/charset_normalizer-3.4.9-cp313-cp313-win_amd64.whl", hash = "sha256:fe2c7201c642b7c308f1675355ad7ff7b66acfe3541625efe5a3ad38f29d6115", size = 161947, upload-time = "2026-07-07T14:33:52.197Z" }, + { url = "https://files.pythonhosted.org/packages/6e/fb/d560d1d1555debbfe7849d9cac6145c1b537709d79576bf22557ed803b82/charset_normalizer-3.4.9-cp313-cp313-win_arm64.whl", hash = "sha256:611057cc5d5c0afc743ba8be6bd828c17e0aaa8643f9d0a9b9bb7dea80eb8012", size = 152594, upload-time = "2026-07-07T14:33:53.486Z" }, + { url = "https://files.pythonhosted.org/packages/7e/8d/496817fa0944239ecae662dd57ea765cfeaec6a735f9f025d4b7b72e7143/charset_normalizer-3.4.9-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:0327fcd59a935777d83410750c50600ee9571af2846f71ce40f25b13da1ef380", size = 317253, upload-time = "2026-07-07T14:33:54.994Z" }, + { url = "https://files.pythonhosted.org/packages/2b/f9/ef4a69ea338ad3c0deceea0f5f7d2380ae8b52132b06d652cb0d2cd86706/charset_normalizer-3.4.9-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a79d9f4d8001473a30c163556b3c3bfebec837495a412dde78b51672f6134f9", size = 215898, upload-time = "2026-07-07T14:33:56.334Z" }, + { url = "https://files.pythonhosted.org/packages/8c/e7/5ddfd76fc061eb52de219658a4aa431cbacadf0a0219c8854f00da50d289/charset_normalizer-3.4.9-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:33bdcc2a32c0a0e861f60841a512c8acc658c87c2ac59d89e3a46dacf7d866e4", size = 236718, upload-time = "2026-07-07T14:33:57.9Z" }, + { url = "https://files.pythonhosted.org/packages/49/ba/768fa3f36048d81c477a0ce61f813bc1454d80917ccfe550abd9f44f5e24/charset_normalizer-3.4.9-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f840ed6d8ecba8255df8c42b87fadeda98ddfc6eeec05e2dc66e26d46dd6f58a", size = 232519, upload-time = "2026-07-07T14:33:59.811Z" }, + { url = "https://files.pythonhosted.org/packages/f4/c4/b3e049d2aa3766180c78507110543d9d50894cc97f57de543f1be521dcdc/charset_normalizer-3.4.9-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c25fe15c70c59eb7c5ce8c06a1f3fa1da0ecc5ea1e7a5922c40fd2fa9b0d5046", size = 223143, upload-time = "2026-07-07T14:34:01.517Z" }, + { url = "https://files.pythonhosted.org/packages/19/79/55c32d06d76ae4feafe053f061f3e3ab70bcf19f4007797ce8c3efda7830/charset_normalizer-3.4.9-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:f7fb7d750cfa0a070d2c24e831fd3481019a60dd317ea2b39acbcebc08b6ed81", size = 206742, upload-time = "2026-07-07T14:34:03.04Z" }, + { url = "https://files.pythonhosted.org/packages/10/e0/47c079dd82d217c807479cd59ffd30af56307ea31c108b75758970459ad3/charset_normalizer-3.4.9-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4d1c96a7a18b9690a4d46df09e3e3382406ae3213727cd1019ebade1c4a81917", size = 219191, upload-time = "2026-07-07T14:34:04.657Z" }, + { url = "https://files.pythonhosted.org/packages/42/ab/b9bc2e77d6b44a7e46ef62ec5cac1c9a6ba7b9135a5d560f002696ec9995/charset_normalizer-3.4.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a4cfde78a9f2880208d16a93b795726a3017d5977e08d1e162a7a31322479c41", size = 218328, upload-time = "2026-07-07T14:34:06.115Z" }, + { url = "https://files.pythonhosted.org/packages/f1/78/c9c71d599f5aa2d42bcdd35cbbd46d7f535351a57e40ff7d8e5a7e219401/charset_normalizer-3.4.9-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:d4d6fcde76f94f5cb9e43e9e9a61f16dacefd228cbbf6f1a09bd9b219a92f1a1", size = 207406, upload-time = "2026-07-07T14:34:07.554Z" }, + { url = "https://files.pythonhosted.org/packages/f6/39/c914445c321a845097ce4f6ac7de9a18228a77b766272125a1ce00d851eb/charset_normalizer-3.4.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:898f0e9068ca27d37f8e83a5b962821df851532e6c4a7d615c1c033f9da6eedf", size = 225157, upload-time = "2026-07-07T14:34:09.061Z" }, + { url = "https://files.pythonhosted.org/packages/9b/f2/c0d4b8508565a36bc5c624e88ed297f5b0b1095011034d7f5b83a69908b5/charset_normalizer-3.4.9-cp314-cp314-win32.whl", hash = "sha256:c1c948747b03be832dceed96ca815cef7360de9aa19d37c730f8e3f6101aca48", size = 151095, upload-time = "2026-07-07T14:34:10.901Z" }, + { url = "https://files.pythonhosted.org/packages/49/fd/a1d26144398c67486422a72bf5812cda22cb4ccfcd95a290fb41ceb4b8e2/charset_normalizer-3.4.9-cp314-cp314-win_amd64.whl", hash = "sha256:16b65ea0f2465b6fb52aa22de5eca612aa964ddfec00a912e26f4656cbef890b", size = 162796, upload-time = "2026-07-07T14:34:12.47Z" }, + { url = "https://files.pythonhosted.org/packages/20/95/d75e82f8ce9fd323ebf059c16c9aadefb22a1ecde13b7840b35835e4886c/charset_normalizer-3.4.9-cp314-cp314-win_arm64.whl", hash = "sha256:40a126142a56b2dfc0aacbad1de8310cbf60da7656db0e6b16eebd48e3e93519", size = 153334, upload-time = "2026-07-07T14:34:14.044Z" }, + { url = "https://files.pythonhosted.org/packages/00/5e/17398df3a139985ba9d11ed072531986f408c8fca952835ef1ab1820c02b/charset_normalizer-3.4.9-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:609b3ba8fcc0fb5ab7af00719d0fb6ad0cb518e48e7712d12fd68f1327951198", size = 338848, upload-time = "2026-07-07T14:34:15.688Z" }, + { url = "https://files.pythonhosted.org/packages/cd/91/7253a32e86b7e1d1239b1b36ba6dd0f021a21107ab33054b53119cc083b9/charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:51447e9aa2684679af07ca5021c3db526e0284347ebf4ffcec1154c3350cfe32", size = 223022, upload-time = "2026-07-07T14:34:17.248Z" }, + { url = "https://files.pythonhosted.org/packages/cb/32/2e64bd2be10e89c61e57ebe6a93fd98ae88eb7ebe414b5121f22c96c69eb/charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cc1b0fff8ead343dae06305f954eb8468ba0ec1a97881f42489d198e4ce3c632", size = 241590, upload-time = "2026-07-07T14:34:18.813Z" }, + { url = "https://files.pythonhosted.org/packages/3d/ef/d96ec496cfea0c21db43b0ad03891308b02388d054cc902cf0e5a1ad6a88/charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fa36ec09ef71d158186bc79e359ff5fdd6e7996fe8ab638f00d6b93139ba4fcf", size = 239584, upload-time = "2026-07-07T14:34:20.52Z" }, + { url = "https://files.pythonhosted.org/packages/d4/ce/9af95f7876194bd7a14e3dfe4a4de2e0bff02666a3910d72beafd06cc297/charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:df115d4d83168fdf2cae48ef1ff6d1cb4c466364e30861b37121de0f3bf1b990", size = 230224, upload-time = "2026-07-07T14:34:22.189Z" }, + { url = "https://files.pythonhosted.org/packages/52/94/af74dde74a3996bd959c350709bfe50e297823d70a8c1cbd54b838880863/charset_normalizer-3.4.9-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:f86c6358749bd4fda175388691e3ba8c46e24c5347d0afd20f9b7edfc9faf07d", size = 212667, upload-time = "2026-07-07T14:34:23.857Z" }, + { url = "https://files.pythonhosted.org/packages/ee/f0/f1c4fe746c395922961b5916ed1d7d6e7d4c84851d19ed43cc89980ec953/charset_normalizer-3.4.9-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:32286a2c8d167e897177b673176c1e3e00d4057caf5d2b64eef9a3666b03018e", size = 227179, upload-time = "2026-07-07T14:34:25.586Z" }, + { url = "https://files.pythonhosted.org/packages/e4/56/6c745619ac397e8871e2bcd3cea1eec86b877488f33888b3aef5c3ed506e/charset_normalizer-3.4.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:83aed2c10721ddd90f68140685391b50811a880af20654c59af6b6c66c40513c", size = 225372, upload-time = "2026-07-07T14:34:27.212Z" }, + { url = "https://files.pythonhosted.org/packages/78/ad/98aae8630ac71f16711968e38a5acfecce41b778bf2f0312851020f565a8/charset_normalizer-3.4.9-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:cd6c3d4b783c556fa00bf540854e42f135e2f256abd29669fcd0da0f2dec79c2", size = 215222, upload-time = "2026-07-07T14:34:28.774Z" }, + { url = "https://files.pythonhosted.org/packages/f7/40/9593d54209765207a7f11073c06494c1721e4ca4a0a426c597679bf7f91e/charset_normalizer-3.4.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ee2f2a527e3c1a6e6411eb4209642e138b544a2d72fe5d0d76daf77b24063534", size = 231958, upload-time = "2026-07-07T14:34:30.345Z" }, + { url = "https://files.pythonhosted.org/packages/b1/27/693ee5e8a18191eb38647360c51cd505013e2bd3b366aa43fd5344c21e3c/charset_normalizer-3.4.9-cp314-cp314t-win32.whl", hash = "sha256:0d861473f743244d349b50f850d10eb87aeb22bbdcc8e64f79273c94af5a8226", size = 155580, upload-time = "2026-07-07T14:34:31.884Z" }, + { url = "https://files.pythonhosted.org/packages/80/3f/bd97d3d9c613013d07cb7733d299385b41df37f0471310f5a73dc359f0b8/charset_normalizer-3.4.9-cp314-cp314t-win_amd64.whl", hash = "sha256:9b8e0f3107e2200b76f6054de99016eac3ee6762713587b36baaa7e4bd2ae177", size = 167620, upload-time = "2026-07-07T14:34:33.438Z" }, + { url = "https://files.pythonhosted.org/packages/3d/c6/eee9dca4439b1061f76373f06ea855678cc4a64c1c3c90b50e479edbb8eb/charset_normalizer-3.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:19ac87f93086ce37b86e098888555c4b4bc48102279bae3350098c0ed664b501", size = 158037, upload-time = "2026-07-07T14:34:35.018Z" }, + { url = "https://files.pythonhosted.org/packages/98/2b/f97f1c193fb855c345d678f5077d6926034db0722df74c8f057020e05a25/charset_normalizer-3.4.9-py3-none-any.whl", hash = "sha256:68e5f26a1ad57ded6d1cfb85331d1c1a195314756471d97758c48498bb4dcdf5", size = 64538, upload-time = "2026-07-07T14:34:56.993Z" }, ] [[package]] name = "click" -version = "8.3.3" +version = "8.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/bb/63/f9e1ea081ce35720d8b92acde70daaedace594dc93b693c869e0d5910718/click-8.3.3.tar.gz", hash = "sha256:398329ad4837b2ff7cbe1dd166a4c0f8900c3ca3a218de04466f38f6497f18a2", size = 328061, upload-time = "2026-04-22T15:11:27.506Z" } +sdist = { url = "https://files.pythonhosted.org/packages/76/d4/81420972a676e8ffea40450d8c8c92943e7218a78fe9b64359836cc9876b/click-8.4.2.tar.gz", hash = "sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6", size = 338000, upload-time = "2026-06-24T17:45:15.148Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl", hash = "sha256:a2bf429bb3033c89fa4936ffb35d5cb471e3719e1f3c8a7c3fff0b8314305613", size = 110502, upload-time = "2026-04-22T15:11:25.044Z" }, + { url = "https://files.pythonhosted.org/packages/fb/e2/79c688af8b210d232694e31e59da9f6ec747bae31c3f5946e4e9b98860d5/click-8.4.2-py3-none-any.whl", hash = "sha256:e6f9f66136c816745b9d65817da91d61d957fb16e02e4dcd0552553c5a197b76", size = 119243, upload-time = "2026-06-24T17:45:13.73Z" }, ] [[package]] @@ -502,101 +617,86 @@ wheels = [ [[package]] name = "coverage" -version = "7.13.5" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9d/e0/70553e3000e345daff267cec284ce4cbf3fc141b6da229ac52775b5428f1/coverage-7.13.5.tar.gz", hash = "sha256:c81f6515c4c40141f83f502b07bbfa5c240ba25bbe73da7b33f1e5b6120ff179", size = 915967, upload-time = "2026-03-17T10:33:18.341Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4b/37/d24c8f8220ff07b839b2c043ea4903a33b0f455abe673ae3c03bbdb7f212/coverage-7.13.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:66a80c616f80181f4d643b0f9e709d97bcea413ecd9631e1dedc7401c8e6695d", size = 219381, upload-time = "2026-03-17T10:30:14.68Z" }, - { url = "https://files.pythonhosted.org/packages/35/8b/cd129b0ca4afe886a6ce9d183c44d8301acbd4ef248622e7c49a23145605/coverage-7.13.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:145ede53ccbafb297c1c9287f788d1bc3efd6c900da23bf6931b09eafc931587", size = 219880, upload-time = "2026-03-17T10:30:16.231Z" }, - { url = "https://files.pythonhosted.org/packages/55/2f/e0e5b237bffdb5d6c530ce87cc1d413a5b7d7dfd60fb067ad6d254c35c76/coverage-7.13.5-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0672854dc733c342fa3e957e0605256d2bf5934feeac328da9e0b5449634a642", size = 250303, upload-time = "2026-03-17T10:30:17.748Z" }, - { url = "https://files.pythonhosted.org/packages/92/be/b1afb692be85b947f3401375851484496134c5554e67e822c35f28bf2fbc/coverage-7.13.5-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ec10e2a42b41c923c2209b846126c6582db5e43a33157e9870ba9fb70dc7854b", size = 252218, upload-time = "2026-03-17T10:30:19.804Z" }, - { url = "https://files.pythonhosted.org/packages/da/69/2f47bb6fa1b8d1e3e5d0c4be8ccb4313c63d742476a619418f85740d597b/coverage-7.13.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be3d4bbad9d4b037791794ddeedd7d64a56f5933a2c1373e18e9e568b9141686", size = 254326, upload-time = "2026-03-17T10:30:21.321Z" }, - { url = "https://files.pythonhosted.org/packages/d5/d0/79db81da58965bd29dabc8f4ad2a2af70611a57cba9d1ec006f072f30a54/coverage-7.13.5-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4d2afbc5cc54d286bfb54541aa50b64cdb07a718227168c87b9e2fb8f25e1743", size = 256267, upload-time = "2026-03-17T10:30:23.094Z" }, - { url = "https://files.pythonhosted.org/packages/e5/32/d0d7cc8168f91ddab44c0ce4806b969df5f5fdfdbb568eaca2dbc2a04936/coverage-7.13.5-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3ad050321264c49c2fa67bb599100456fc51d004b82534f379d16445da40fb75", size = 250430, upload-time = "2026-03-17T10:30:25.311Z" }, - { url = "https://files.pythonhosted.org/packages/4d/06/a055311d891ddbe231cd69fdd20ea4be6e3603ffebddf8704b8ca8e10a3c/coverage-7.13.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7300c8a6d13335b29bb76d7651c66af6bd8658517c43499f110ddc6717bfc209", size = 252017, upload-time = "2026-03-17T10:30:27.284Z" }, - { url = "https://files.pythonhosted.org/packages/d6/f6/d0fd2d21e29a657b5f77a2fe7082e1568158340dceb941954f776dce1b7b/coverage-7.13.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:eb07647a5738b89baab047f14edd18ded523de60f3b30e75c2acc826f79c839a", size = 250080, upload-time = "2026-03-17T10:30:29.481Z" }, - { url = "https://files.pythonhosted.org/packages/4e/ab/0d7fb2efc2e9a5eb7ddcc6e722f834a69b454b7e6e5888c3a8567ecffb31/coverage-7.13.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:9adb6688e3b53adffefd4a52d72cbd8b02602bfb8f74dcd862337182fd4d1a4e", size = 253843, upload-time = "2026-03-17T10:30:31.301Z" }, - { url = "https://files.pythonhosted.org/packages/ba/6f/7467b917bbf5408610178f62a49c0ed4377bb16c1657f689cc61470da8ce/coverage-7.13.5-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7c8d4bc913dd70b93488d6c496c77f3aff5ea99a07e36a18f865bca55adef8bd", size = 249802, upload-time = "2026-03-17T10:30:33.358Z" }, - { url = "https://files.pythonhosted.org/packages/75/2c/1172fb689df92135f5bfbbd69fc83017a76d24ea2e2f3a1154007e2fb9f8/coverage-7.13.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0e3c426ffc4cd952f54ee9ffbdd10345709ecc78a3ecfd796a57236bfad0b9b8", size = 250707, upload-time = "2026-03-17T10:30:35.2Z" }, - { url = "https://files.pythonhosted.org/packages/67/21/9ac389377380a07884e3b48ba7a620fcd9dbfaf1d40565facdc6b36ec9ef/coverage-7.13.5-cp311-cp311-win32.whl", hash = "sha256:259b69bb83ad9894c4b25be2528139eecba9a82646ebdda2d9db1ba28424a6bf", size = 221880, upload-time = "2026-03-17T10:30:36.775Z" }, - { url = "https://files.pythonhosted.org/packages/af/7f/4cd8a92531253f9d7c1bbecd9fa1b472907fb54446ca768c59b531248dc5/coverage-7.13.5-cp311-cp311-win_amd64.whl", hash = "sha256:258354455f4e86e3e9d0d17571d522e13b4e1e19bf0f8596bcf9476d61e7d8a9", size = 222816, upload-time = "2026-03-17T10:30:38.891Z" }, - { url = "https://files.pythonhosted.org/packages/12/a6/1d3f6155fb0010ca68eba7fe48ca6c9da7385058b77a95848710ecf189b1/coverage-7.13.5-cp311-cp311-win_arm64.whl", hash = "sha256:bff95879c33ec8da99fc9b6fe345ddb5be6414b41d6d1ad1c8f188d26f36e028", size = 221483, upload-time = "2026-03-17T10:30:40.463Z" }, - { url = "https://files.pythonhosted.org/packages/a0/c3/a396306ba7db865bf96fc1fb3b7fd29bcbf3d829df642e77b13555163cd6/coverage-7.13.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:460cf0114c5016fa841214ff5564aa4864f11948da9440bc97e21ad1f4ba1e01", size = 219554, upload-time = "2026-03-17T10:30:42.208Z" }, - { url = "https://files.pythonhosted.org/packages/a6/16/a68a19e5384e93f811dccc51034b1fd0b865841c390e3c931dcc4699e035/coverage-7.13.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0e223ce4b4ed47f065bfb123687686512e37629be25cc63728557ae7db261422", size = 219908, upload-time = "2026-03-17T10:30:43.906Z" }, - { url = "https://files.pythonhosted.org/packages/29/72/20b917c6793af3a5ceb7fb9c50033f3ec7865f2911a1416b34a7cfa0813b/coverage-7.13.5-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6e3370441f4513c6252bf042b9c36d22491142385049243253c7e48398a15a9f", size = 251419, upload-time = "2026-03-17T10:30:45.545Z" }, - { url = "https://files.pythonhosted.org/packages/8c/49/cd14b789536ac6a4778c453c6a2338bc0a2fb60c5a5a41b4008328b9acc1/coverage-7.13.5-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:03ccc709a17a1de074fb1d11f217342fb0d2b1582ed544f554fc9fc3f07e95f5", size = 254159, upload-time = "2026-03-17T10:30:47.204Z" }, - { url = "https://files.pythonhosted.org/packages/9d/00/7b0edcfe64e2ed4c0340dac14a52ad0f4c9bd0b8b5e531af7d55b703db7c/coverage-7.13.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3f4818d065964db3c1c66dc0fbdac5ac692ecbc875555e13374fdbe7eedb4376", size = 255270, upload-time = "2026-03-17T10:30:48.812Z" }, - { url = "https://files.pythonhosted.org/packages/93/89/7ffc4ba0f5d0a55c1e84ea7cee39c9fc06af7b170513d83fbf3bbefce280/coverage-7.13.5-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:012d5319e66e9d5a218834642d6c35d265515a62f01157a45bcc036ecf947256", size = 257538, upload-time = "2026-03-17T10:30:50.77Z" }, - { url = "https://files.pythonhosted.org/packages/81/bd/73ddf85f93f7e6fa83e77ccecb6162d9415c79007b4bc124008a4995e4a7/coverage-7.13.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8dd02af98971bdb956363e4827d34425cb3df19ee550ef92855b0acb9c7ce51c", size = 251821, upload-time = "2026-03-17T10:30:52.5Z" }, - { url = "https://files.pythonhosted.org/packages/a0/81/278aff4e8dec4926a0bcb9486320752811f543a3ce5b602cc7a29978d073/coverage-7.13.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f08fd75c50a760c7eb068ae823777268daaf16a80b918fa58eea888f8e3919f5", size = 253191, upload-time = "2026-03-17T10:30:54.543Z" }, - { url = "https://files.pythonhosted.org/packages/70/ee/fe1621488e2e0a58d7e94c4800f0d96f79671553488d401a612bebae324b/coverage-7.13.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:843ea8643cf967d1ac7e8ecd4bb00c99135adf4816c0c0593fdcc47b597fcf09", size = 251337, upload-time = "2026-03-17T10:30:56.663Z" }, - { url = "https://files.pythonhosted.org/packages/37/a6/f79fb37aa104b562207cc23cb5711ab6793608e246cae1e93f26b2236ed9/coverage-7.13.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:9d44d7aa963820b1b971dbecd90bfe5fe8f81cff79787eb6cca15750bd2f79b9", size = 255404, upload-time = "2026-03-17T10:30:58.427Z" }, - { url = "https://files.pythonhosted.org/packages/75/f0/ed15262a58ec81ce457ceb717b7f78752a1713556b19081b76e90896e8d4/coverage-7.13.5-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:7132bed4bd7b836200c591410ae7d97bf7ae8be6fc87d160b2bd881df929e7bf", size = 250903, upload-time = "2026-03-17T10:31:00.093Z" }, - { url = "https://files.pythonhosted.org/packages/0f/e9/9129958f20e7e9d4d56d51d42ccf708d15cac355ff4ac6e736e97a9393d2/coverage-7.13.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a698e363641b98843c517817db75373c83254781426e94ada3197cabbc2c919c", size = 252780, upload-time = "2026-03-17T10:31:01.916Z" }, - { url = "https://files.pythonhosted.org/packages/a4/d7/0ad9b15812d81272db94379fe4c6df8fd17781cc7671fdfa30c76ba5ff7b/coverage-7.13.5-cp312-cp312-win32.whl", hash = "sha256:bdba0a6b8812e8c7df002d908a9a2ea3c36e92611b5708633c50869e6d922fdf", size = 222093, upload-time = "2026-03-17T10:31:03.642Z" }, - { url = "https://files.pythonhosted.org/packages/29/3d/821a9a5799fac2556bcf0bd37a70d1d11fa9e49784b6d22e92e8b2f85f18/coverage-7.13.5-cp312-cp312-win_amd64.whl", hash = "sha256:d2c87e0c473a10bffe991502eac389220533024c8082ec1ce849f4218dded810", size = 222900, upload-time = "2026-03-17T10:31:05.651Z" }, - { url = "https://files.pythonhosted.org/packages/d4/fa/2238c2ad08e35cf4f020ea721f717e09ec3152aea75d191a7faf3ef009a8/coverage-7.13.5-cp312-cp312-win_arm64.whl", hash = "sha256:bf69236a9a81bdca3bff53796237aab096cdbf8d78a66ad61e992d9dac7eb2de", size = 221515, upload-time = "2026-03-17T10:31:07.293Z" }, - { url = "https://files.pythonhosted.org/packages/74/8c/74fedc9663dcf168b0a059d4ea756ecae4da77a489048f94b5f512a8d0b3/coverage-7.13.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ec4af212df513e399cf11610cc27063f1586419e814755ab362e50a85ea69c1", size = 219576, upload-time = "2026-03-17T10:31:09.045Z" }, - { url = "https://files.pythonhosted.org/packages/0c/c9/44fb661c55062f0818a6ffd2685c67aa30816200d5f2817543717d4b92eb/coverage-7.13.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:941617e518602e2d64942c88ec8499f7fbd49d3f6c4327d3a71d43a1973032f3", size = 219942, upload-time = "2026-03-17T10:31:10.708Z" }, - { url = "https://files.pythonhosted.org/packages/5f/13/93419671cee82b780bab7ea96b67c8ef448f5f295f36bf5031154ec9a790/coverage-7.13.5-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:da305e9937617ee95c2e39d8ff9f040e0487cbf1ac174f777ed5eddd7a7c1f26", size = 250935, upload-time = "2026-03-17T10:31:12.392Z" }, - { url = "https://files.pythonhosted.org/packages/ac/68/1666e3a4462f8202d836920114fa7a5ee9275d1fa45366d336c551a162dd/coverage-7.13.5-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:78e696e1cc714e57e8b25760b33a8b1026b7048d270140d25dafe1b0a1ee05a3", size = 253541, upload-time = "2026-03-17T10:31:14.247Z" }, - { url = "https://files.pythonhosted.org/packages/4e/5e/3ee3b835647be646dcf3c65a7c6c18f87c27326a858f72ab22c12730773d/coverage-7.13.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:02ca0eed225b2ff301c474aeeeae27d26e2537942aa0f87491d3e147e784a82b", size = 254780, upload-time = "2026-03-17T10:31:16.193Z" }, - { url = "https://files.pythonhosted.org/packages/44/b3/cb5bd1a04cfcc49ede6cd8409d80bee17661167686741e041abc7ee1b9a9/coverage-7.13.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:04690832cbea4e4663d9149e05dba142546ca05cb1848816760e7f58285c970a", size = 256912, upload-time = "2026-03-17T10:31:17.89Z" }, - { url = "https://files.pythonhosted.org/packages/1b/66/c1dceb7b9714473800b075f5c8a84f4588f887a90eb8645282031676e242/coverage-7.13.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0590e44dd2745c696a778f7bab6aa95256de2cbc8b8cff4f7db8ff09813d6969", size = 251165, upload-time = "2026-03-17T10:31:19.605Z" }, - { url = "https://files.pythonhosted.org/packages/b7/62/5502b73b97aa2e53ea22a39cf8649ff44827bef76d90bf638777daa27a9d/coverage-7.13.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d7cfad2d6d81dd298ab6b89fe72c3b7b05ec7544bdda3b707ddaecff8d25c161", size = 252908, upload-time = "2026-03-17T10:31:21.312Z" }, - { url = "https://files.pythonhosted.org/packages/7d/37/7792c2d69854397ca77a55c4646e5897c467928b0e27f2d235d83b5d08c6/coverage-7.13.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e092b9499de38ae0fbfbc603a74660eb6ff3e869e507b50d85a13b6db9863e15", size = 250873, upload-time = "2026-03-17T10:31:23.565Z" }, - { url = "https://files.pythonhosted.org/packages/a3/23/bc866fb6163be52a8a9e5d708ba0d3b1283c12158cefca0a8bbb6e247a43/coverage-7.13.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:48c39bc4a04d983a54a705a6389512883d4a3b9862991b3617d547940e9f52b1", size = 255030, upload-time = "2026-03-17T10:31:25.58Z" }, - { url = "https://files.pythonhosted.org/packages/7d/8b/ef67e1c222ef49860701d346b8bbb70881bef283bd5f6cbba68a39a086c7/coverage-7.13.5-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2d3807015f138ffea1ed9afeeb8624fd781703f2858b62a8dd8da5a0994c57b6", size = 250694, upload-time = "2026-03-17T10:31:27.316Z" }, - { url = "https://files.pythonhosted.org/packages/46/0d/866d1f74f0acddbb906db212e096dee77a8e2158ca5e6bb44729f9d93298/coverage-7.13.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ee2aa19e03161671ec964004fb74b2257805d9710bf14a5c704558b9d8dbaf17", size = 252469, upload-time = "2026-03-17T10:31:29.472Z" }, - { url = "https://files.pythonhosted.org/packages/7a/f5/be742fec31118f02ce42b21c6af187ad6a344fed546b56ca60caacc6a9a0/coverage-7.13.5-cp313-cp313-win32.whl", hash = "sha256:ce1998c0483007608c8382f4ff50164bfc5bd07a2246dd272aa4043b75e61e85", size = 222112, upload-time = "2026-03-17T10:31:31.526Z" }, - { url = "https://files.pythonhosted.org/packages/66/40/7732d648ab9d069a46e686043241f01206348e2bbf128daea85be4d6414b/coverage-7.13.5-cp313-cp313-win_amd64.whl", hash = "sha256:631efb83f01569670a5e866ceb80fe483e7c159fac6f167e6571522636104a0b", size = 222923, upload-time = "2026-03-17T10:31:33.633Z" }, - { url = "https://files.pythonhosted.org/packages/48/af/fea819c12a095781f6ccd504890aaddaf88b8fab263c4940e82c7b770124/coverage-7.13.5-cp313-cp313-win_arm64.whl", hash = "sha256:f4cd16206ad171cbc2470dbea9103cf9a7607d5fe8c242fdf1edf36174020664", size = 221540, upload-time = "2026-03-17T10:31:35.445Z" }, - { url = "https://files.pythonhosted.org/packages/23/d2/17879af479df7fbbd44bd528a31692a48f6b25055d16482fdf5cdb633805/coverage-7.13.5-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0428cbef5783ad91fe240f673cc1f76b25e74bbfe1a13115e4aa30d3f538162d", size = 220262, upload-time = "2026-03-17T10:31:37.184Z" }, - { url = "https://files.pythonhosted.org/packages/5b/4c/d20e554f988c8f91d6a02c5118f9abbbf73a8768a3048cb4962230d5743f/coverage-7.13.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e0b216a19534b2427cc201a26c25da4a48633f29a487c61258643e89d28200c0", size = 220617, upload-time = "2026-03-17T10:31:39.245Z" }, - { url = "https://files.pythonhosted.org/packages/29/9c/f9f5277b95184f764b24e7231e166dfdb5780a46d408a2ac665969416d61/coverage-7.13.5-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:972a9cd27894afe4bc2b1480107054e062df08e671df7c2f18c205e805ccd806", size = 261912, upload-time = "2026-03-17T10:31:41.324Z" }, - { url = "https://files.pythonhosted.org/packages/d5/f6/7f1ab39393eeb50cfe4747ae8ef0e4fc564b989225aa1152e13a180d74f8/coverage-7.13.5-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4b59148601efcd2bac8c4dbf1f0ad6391693ccf7a74b8205781751637076aee3", size = 263987, upload-time = "2026-03-17T10:31:43.724Z" }, - { url = "https://files.pythonhosted.org/packages/a0/d7/62c084fb489ed9c6fbdf57e006752e7c516ea46fd690e5ed8b8617c7d52e/coverage-7.13.5-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:505d7083c8b0c87a8fa8c07370c285847c1f77739b22e299ad75a6af6c32c5c9", size = 266416, upload-time = "2026-03-17T10:31:45.769Z" }, - { url = "https://files.pythonhosted.org/packages/a9/f6/df63d8660e1a0bff6125947afda112a0502736f470d62ca68b288ea762d8/coverage-7.13.5-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:60365289c3741e4db327e7baff2a4aaacf22f788e80fa4683393891b70a89fbd", size = 267558, upload-time = "2026-03-17T10:31:48.293Z" }, - { url = "https://files.pythonhosted.org/packages/5b/02/353ca81d36779bd108f6d384425f7139ac3c58c750dcfaafe5d0bee6436b/coverage-7.13.5-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1b88c69c8ef5d4b6fe7dea66d6636056a0f6a7527c440e890cf9259011f5e606", size = 261163, upload-time = "2026-03-17T10:31:50.125Z" }, - { url = "https://files.pythonhosted.org/packages/2c/16/2e79106d5749bcaf3aee6d309123548e3276517cd7851faa8da213bc61bf/coverage-7.13.5-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5b13955d31d1633cf9376908089b7cebe7d15ddad7aeaabcbe969a595a97e95e", size = 263981, upload-time = "2026-03-17T10:31:51.961Z" }, - { url = "https://files.pythonhosted.org/packages/29/c7/c29e0c59ffa6942030ae6f50b88ae49988e7e8da06de7ecdbf49c6d4feae/coverage-7.13.5-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:f70c9ab2595c56f81a89620e22899eea8b212a4041bd728ac6f4a28bf5d3ddd0", size = 261604, upload-time = "2026-03-17T10:31:53.872Z" }, - { url = "https://files.pythonhosted.org/packages/40/48/097cdc3db342f34006a308ab41c3a7c11c3f0d84750d340f45d88a782e00/coverage-7.13.5-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:084b84a8c63e8d6fc7e3931b316a9bcafca1458d753c539db82d31ed20091a87", size = 265321, upload-time = "2026-03-17T10:31:55.997Z" }, - { url = "https://files.pythonhosted.org/packages/bb/1f/4994af354689e14fd03a75f8ec85a9a68d94e0188bbdab3fc1516b55e512/coverage-7.13.5-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:ad14385487393e386e2ea988b09d62dd42c397662ac2dabc3832d71253eee479", size = 260502, upload-time = "2026-03-17T10:31:58.308Z" }, - { url = "https://files.pythonhosted.org/packages/22/c6/9bb9ef55903e628033560885f5c31aa227e46878118b63ab15dc7ba87797/coverage-7.13.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:7f2c47b36fe7709a6e83bfadf4eefb90bd25fbe4014d715224c4316f808e59a2", size = 262688, upload-time = "2026-03-17T10:32:00.141Z" }, - { url = "https://files.pythonhosted.org/packages/14/4f/f5df9007e50b15e53e01edea486814783a7f019893733d9e4d6caad75557/coverage-7.13.5-cp313-cp313t-win32.whl", hash = "sha256:67e9bc5449801fad0e5dff329499fb090ba4c5800b86805c80617b4e29809b2a", size = 222788, upload-time = "2026-03-17T10:32:02.246Z" }, - { url = "https://files.pythonhosted.org/packages/e1/98/aa7fccaa97d0f3192bec013c4e6fd6d294a6ed44b640e6bb61f479e00ed5/coverage-7.13.5-cp313-cp313t-win_amd64.whl", hash = "sha256:da86cdcf10d2519e10cabb8ac2de03da1bcb6e4853790b7fbd48523332e3a819", size = 223851, upload-time = "2026-03-17T10:32:04.416Z" }, - { url = "https://files.pythonhosted.org/packages/3d/8b/e5c469f7352651e5f013198e9e21f97510b23de957dd06a84071683b4b60/coverage-7.13.5-cp313-cp313t-win_arm64.whl", hash = "sha256:0ecf12ecb326fe2c339d93fc131816f3a7367d223db37817208905c89bded911", size = 222104, upload-time = "2026-03-17T10:32:06.65Z" }, - { url = "https://files.pythonhosted.org/packages/8e/77/39703f0d1d4b478bfd30191d3c14f53caf596fac00efb3f8f6ee23646439/coverage-7.13.5-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fbabfaceaeb587e16f7008f7795cd80d20ec548dc7f94fbb0d4ec2e038ce563f", size = 219621, upload-time = "2026-03-17T10:32:08.589Z" }, - { url = "https://files.pythonhosted.org/packages/e2/3e/51dff36d99ae14639a133d9b164d63e628532e2974d8b1edb99dd1ebc733/coverage-7.13.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9bb2a28101a443669a423b665939381084412b81c3f8c0fcfbac57f4e30b5b8e", size = 219953, upload-time = "2026-03-17T10:32:10.507Z" }, - { url = "https://files.pythonhosted.org/packages/6a/6c/1f1917b01eb647c2f2adc9962bd66c79eb978951cab61bdc1acab3290c07/coverage-7.13.5-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bd3a2fbc1c6cccb3c5106140d87cc6a8715110373ef42b63cf5aea29df8c217a", size = 250992, upload-time = "2026-03-17T10:32:12.41Z" }, - { url = "https://files.pythonhosted.org/packages/22/e5/06b1f88f42a5a99df42ce61208bdec3bddb3d261412874280a19796fc09c/coverage-7.13.5-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6c36ddb64ed9d7e496028d1d00dfec3e428e0aabf4006583bb1839958d280510", size = 253503, upload-time = "2026-03-17T10:32:14.449Z" }, - { url = "https://files.pythonhosted.org/packages/80/28/2a148a51e5907e504fa7b85490277734e6771d8844ebcc48764a15e28155/coverage-7.13.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:380e8e9084d8eb38db3a9176a1a4f3c0082c3806fa0dc882d1d87abc3c789247", size = 254852, upload-time = "2026-03-17T10:32:16.56Z" }, - { url = "https://files.pythonhosted.org/packages/61/77/50e8d3d85cc0b7ebe09f30f151d670e302c7ff4a1bf6243f71dd8b0981fa/coverage-7.13.5-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e808af52a0513762df4d945ea164a24b37f2f518cbe97e03deaa0ee66139b4d6", size = 257161, upload-time = "2026-03-17T10:32:19.004Z" }, - { url = "https://files.pythonhosted.org/packages/3b/c4/b5fd1d4b7bf8d0e75d997afd3925c59ba629fc8616f1b3aae7605132e256/coverage-7.13.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e301d30dd7e95ae068671d746ba8c34e945a82682e62918e41b2679acd2051a0", size = 251021, upload-time = "2026-03-17T10:32:21.344Z" }, - { url = "https://files.pythonhosted.org/packages/f8/66/6ea21f910e92d69ef0b1c3346ea5922a51bad4446c9126db2ae96ee24c4c/coverage-7.13.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:800bc829053c80d240a687ceeb927a94fd108bbdc68dfbe505d0d75ab578a882", size = 252858, upload-time = "2026-03-17T10:32:23.506Z" }, - { url = "https://files.pythonhosted.org/packages/9e/ea/879c83cb5d61aa2a35fb80e72715e92672daef8191b84911a643f533840c/coverage-7.13.5-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:0b67af5492adb31940ee418a5a655c28e48165da5afab8c7fa6fd72a142f8740", size = 250823, upload-time = "2026-03-17T10:32:25.516Z" }, - { url = "https://files.pythonhosted.org/packages/8a/fb/616d95d3adb88b9803b275580bdeee8bd1b69a886d057652521f83d7322f/coverage-7.13.5-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c9136ff29c3a91e25b1d1552b5308e53a1e0653a23e53b6366d7c2dcbbaf8a16", size = 255099, upload-time = "2026-03-17T10:32:27.944Z" }, - { url = "https://files.pythonhosted.org/packages/1c/93/25e6917c90ec1c9a56b0b26f6cad6408e5f13bb6b35d484a0d75c9cf000d/coverage-7.13.5-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:cff784eef7f0b8f6cb28804fbddcfa99f89efe4cc35fb5627e3ac58f91ed3ac0", size = 250638, upload-time = "2026-03-17T10:32:29.914Z" }, - { url = "https://files.pythonhosted.org/packages/fc/7b/dc1776b0464145a929deed214aef9fb1493f159b59ff3c7eeeedf91eddd0/coverage-7.13.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:68a4953be99b17ac3c23b6efbc8a38330d99680c9458927491d18700ef23ded0", size = 252295, upload-time = "2026-03-17T10:32:31.981Z" }, - { url = "https://files.pythonhosted.org/packages/ea/fb/99cbbc56a26e07762a2740713f3c8f9f3f3106e3a3dd8cc4474954bccd34/coverage-7.13.5-cp314-cp314-win32.whl", hash = "sha256:35a31f2b1578185fbe6aa2e74cea1b1d0bbf4c552774247d9160d29b80ed56cc", size = 222360, upload-time = "2026-03-17T10:32:34.233Z" }, - { url = "https://files.pythonhosted.org/packages/8d/b7/4758d4f73fb536347cc5e4ad63662f9d60ba9118cb6785e9616b2ce5d7fa/coverage-7.13.5-cp314-cp314-win_amd64.whl", hash = "sha256:2aa055ae1857258f9e0045be26a6d62bdb47a72448b62d7b55f4820f361a2633", size = 223174, upload-time = "2026-03-17T10:32:36.369Z" }, - { url = "https://files.pythonhosted.org/packages/2c/f2/24d84e1dfe70f8ac9fdf30d338239860d0d1d5da0bda528959d0ebc9da28/coverage-7.13.5-cp314-cp314-win_arm64.whl", hash = "sha256:1b11eef33edeae9d142f9b4358edb76273b3bfd30bc3df9a4f95d0e49caf94e8", size = 221739, upload-time = "2026-03-17T10:32:38.736Z" }, - { url = "https://files.pythonhosted.org/packages/60/5b/4a168591057b3668c2428bff25dd3ebc21b629d666d90bcdfa0217940e84/coverage-7.13.5-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:10a0c37f0b646eaff7cce1874c31d1f1ccb297688d4c747291f4f4c70741cc8b", size = 220351, upload-time = "2026-03-17T10:32:41.196Z" }, - { url = "https://files.pythonhosted.org/packages/f5/21/1fd5c4dbfe4a58b6b99649125635df46decdfd4a784c3cd6d410d303e370/coverage-7.13.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b5db73ba3c41c7008037fa731ad5459fc3944cb7452fc0aa9f822ad3533c583c", size = 220612, upload-time = "2026-03-17T10:32:43.204Z" }, - { url = "https://files.pythonhosted.org/packages/d6/fe/2a924b3055a5e7e4512655a9d4609781b0d62334fa0140c3e742926834e2/coverage-7.13.5-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:750db93a81e3e5a9831b534be7b1229df848b2e125a604fe6651e48aa070e5f9", size = 261985, upload-time = "2026-03-17T10:32:45.514Z" }, - { url = "https://files.pythonhosted.org/packages/d7/0d/c8928f2bd518c45990fe1a2ab8db42e914ef9b726c975facc4282578c3eb/coverage-7.13.5-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9ddb4f4a5479f2539644be484da179b653273bca1a323947d48ab107b3ed1f29", size = 264107, upload-time = "2026-03-17T10:32:47.971Z" }, - { url = "https://files.pythonhosted.org/packages/ef/ae/4ae35bbd9a0af9d820362751f0766582833c211224b38665c0f8de3d487f/coverage-7.13.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8a7a2049c14f413163e2bdabd37e41179b1d1ccb10ffc6ccc4b7a718429c607", size = 266513, upload-time = "2026-03-17T10:32:50.1Z" }, - { url = "https://files.pythonhosted.org/packages/9c/20/d326174c55af36f74eac6ae781612d9492f060ce8244b570bb9d50d9d609/coverage-7.13.5-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e1c85e0b6c05c592ea6d8768a66a254bfb3874b53774b12d4c89c481eb78cb90", size = 267650, upload-time = "2026-03-17T10:32:52.391Z" }, - { url = "https://files.pythonhosted.org/packages/7a/5e/31484d62cbd0eabd3412e30d74386ece4a0837d4f6c3040a653878bfc019/coverage-7.13.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:777c4d1eff1b67876139d24288aaf1817f6c03d6bae9c5cc8d27b83bcfe38fe3", size = 261089, upload-time = "2026-03-17T10:32:54.544Z" }, - { url = "https://files.pythonhosted.org/packages/e9/d8/49a72d6de146eebb0b7e48cc0f4bc2c0dd858e3d4790ab2b39a2872b62bd/coverage-7.13.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6697e29b93707167687543480a40f0db8f356e86d9f67ddf2e37e2dfd91a9dab", size = 263982, upload-time = "2026-03-17T10:32:56.803Z" }, - { url = "https://files.pythonhosted.org/packages/06/3b/0351f1bd566e6e4dd39e978efe7958bde1d32f879e85589de147654f57bb/coverage-7.13.5-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:8fdf453a942c3e4d99bd80088141c4c6960bb232c409d9c3558e2dbaa3998562", size = 261579, upload-time = "2026-03-17T10:32:59.466Z" }, - { url = "https://files.pythonhosted.org/packages/5d/ce/796a2a2f4017f554d7810f5c573449b35b1e46788424a548d4d19201b222/coverage-7.13.5-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:32ca0c0114c9834a43f045a87dcebd69d108d8ffb666957ea65aa132f50332e2", size = 265316, upload-time = "2026-03-17T10:33:01.847Z" }, - { url = "https://files.pythonhosted.org/packages/3d/16/d5ae91455541d1a78bc90abf495be600588aff8f6db5c8b0dae739fa39c9/coverage-7.13.5-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:8769751c10f339021e2638cd354e13adeac54004d1941119b2c96fe5276d45ea", size = 260427, upload-time = "2026-03-17T10:33:03.945Z" }, - { url = "https://files.pythonhosted.org/packages/48/11/07f413dba62db21fb3fad5d0de013a50e073cc4e2dc4306e770360f6dfc8/coverage-7.13.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cec2d83125531bd153175354055cdb7a09987af08a9430bd173c937c6d0fba2a", size = 262745, upload-time = "2026-03-17T10:33:06.285Z" }, - { url = "https://files.pythonhosted.org/packages/91/15/d792371332eb4663115becf4bad47e047d16234b1aff687b1b18c58d60ae/coverage-7.13.5-cp314-cp314t-win32.whl", hash = "sha256:0cd9ed7a8b181775459296e402ca4fb27db1279740a24e93b3b41942ebe4b215", size = 223146, upload-time = "2026-03-17T10:33:08.756Z" }, - { url = "https://files.pythonhosted.org/packages/db/51/37221f59a111dca5e85be7dbf09696323b5b9f13ff65e0641d535ed06ea8/coverage-7.13.5-cp314-cp314t-win_amd64.whl", hash = "sha256:301e3b7dfefecaca37c9f1aa6f0049b7d4ab8dd933742b607765d757aca77d43", size = 224254, upload-time = "2026-03-17T10:33:11.174Z" }, - { url = "https://files.pythonhosted.org/packages/54/83/6acacc889de8987441aa7d5adfbdbf33d288dad28704a67e574f1df9bcbb/coverage-7.13.5-cp314-cp314t-win_arm64.whl", hash = "sha256:9dacc2ad679b292709e0f5fc1ac74a6d4d5562e424058962c7bb0c658ad25e45", size = 222276, upload-time = "2026-03-17T10:33:13.466Z" }, - { url = "https://files.pythonhosted.org/packages/9e/ee/a4cf96b8ce1e566ed238f0659ac2d3f007ed1d14b181bcb684e19561a69a/coverage-7.13.5-py3-none-any.whl", hash = "sha256:34b02417cf070e173989b3db962f7ed56d2f644307b2cf9d5a0f258e13084a61", size = 211346, upload-time = "2026-03-17T10:33:15.691Z" }, +version = "7.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/8b/adeb62ea8951f13c4c7fef2e7a85e1a06b499c8d8237ea589d496029e53f/coverage-7.15.0.tar.gz", hash = "sha256:9ac3fe7a1435986463eaa8ee253ae2f2a268709ba4ae5c7dd1f52a05391ad78f", size = 925362, upload-time = "2026-07-02T13:10:50.535Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ae/23/82e910835ef4b8391047025e1d53aa48d66029f444eb8b25373c849bf503/coverage-7.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:003fff99412ea848c0aaebcc78ed2b6ce7d8a1227ed17e68470672770b78a02a", size = 220662, upload-time = "2026-07-02T13:08:39.205Z" }, + { url = "https://files.pythonhosted.org/packages/6d/0d/c7b213dde2f1579de5231062b386d8413f79c11667eb58c39319b25991da/coverage-7.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5cbd804bf2784ce7b45114516050f346ecd50f960c4bb630a7ee9e1d78fa2118", size = 221168, upload-time = "2026-07-02T13:08:40.471Z" }, + { url = "https://files.pythonhosted.org/packages/33/77/d000aeedfac085088337b3c7becdad328474b1f8a9e4c9368a0c99605d68/coverage-7.15.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8773e15c23305b58882a4611fb9b2755977eae0dc2e515366a1b6c98866cc4c2", size = 251587, upload-time = "2026-07-02T13:08:42.033Z" }, + { url = "https://files.pythonhosted.org/packages/cc/e0/86787c56b9df17afd370d5e293515dd4d9a107a561d13054873eefad8ecc/coverage-7.15.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f50e40081494c1dc4239ebb202014cbcc3306ea96fb6302a34c8cc0967fc5ae8", size = 253497, upload-time = "2026-07-02T13:08:43.387Z" }, + { url = "https://files.pythonhosted.org/packages/3f/02/181bc917359299c07dead6270f94e411151c8b60cec905c33499da69afe6/coverage-7.15.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:daf96f37f5fc3a7b6c6da862eb4aee61c426bd63da236ed4a73ef0e503b4bca5", size = 255607, upload-time = "2026-07-02T13:08:44.897Z" }, + { url = "https://files.pythonhosted.org/packages/b9/35/ca5e7427699913da6788c4f910e73ab16c5f4b59ec5d3a999dce2a45112f/coverage-7.15.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:51aa20f6ae2788fd197747766edf4cd8234fd9423309b934257fa6b21a592723", size = 257563, upload-time = "2026-07-02T13:08:46.334Z" }, + { url = "https://files.pythonhosted.org/packages/0b/4d/b8220bacc2fc3c4e9078e27c32e99fb411479a4718a72bdd00036a9891c8/coverage-7.15.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:03d1f922757662eb7af586e77834792274cff776bc7b1d1a0b66a49ea9d84735", size = 251726, upload-time = "2026-07-02T13:08:47.941Z" }, + { url = "https://files.pythonhosted.org/packages/c4/e4/2e145da1991d72189b9c3cf7eca05c716ee7080d099aaea6757cfc7df008/coverage-7.15.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a6d6acc9a7666245e6133dd15144ca038a85a9cd5026bb06d6bbae9e77440dc9", size = 253301, upload-time = "2026-07-02T13:08:49.5Z" }, + { url = "https://files.pythonhosted.org/packages/72/28/d2c841d698bf762e481f08bd4839d370246b6d9b61dab085a7b20b201a08/coverage-7.15.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1ac2c4c27c7df851dc9a017c2d7de00b69147e84ba3d96f37a530b0b6fb51035", size = 251361, upload-time = "2026-07-02T13:08:51.304Z" }, + { url = "https://files.pythonhosted.org/packages/9d/ed/55d9ffde994fba3897c0c783f77a7d053b0c18787f6892ed5b0aed73f469/coverage-7.15.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b761a1d504fd4bd1f20f418753964dca9f5862a511fc854dac58296b3b223671", size = 255129, upload-time = "2026-07-02T13:08:52.661Z" }, + { url = "https://files.pythonhosted.org/packages/1d/c0/ecbf33b8c460ea2718aeb813e2df8140d0370e5f67261c31524ceb0a2a8d/coverage-7.15.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:e43b045e11c16e897895758ae90e4a90cf99e93d58549e2f90c0e2272e155695", size = 251081, upload-time = "2026-07-02T13:08:54.188Z" }, + { url = "https://files.pythonhosted.org/packages/a9/de/fb87b4261f54448dd2b9504ef19a58be42cef0d9520595fbfe1219b15234/coverage-7.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:589b54513e901739f4b4582c705ce96b80c96f57641b1464607e2367a270e540", size = 251988, upload-time = "2026-07-02T13:08:55.726Z" }, + { url = "https://files.pythonhosted.org/packages/df/27/3494d5f291b9a4cb868f73c11221a8bd2d5bd761a8f9acea61ff57128dd1/coverage-7.15.0-cp311-cp311-win32.whl", hash = "sha256:106781b8482749162d0b47056937ba0933508e5d9447f65a5e7d5c422f0d6bb4", size = 222754, upload-time = "2026-07-02T13:08:57.091Z" }, + { url = "https://files.pythonhosted.org/packages/2a/ee/cd4847ebc9be6a9c0123d763645a6f1f3be6b8c58c962706368b79cbac07/coverage-7.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:821e92b3631d762a339695824cadbbc73020354eba2a23a551a99ad34938fbe6", size = 223225, upload-time = "2026-07-02T13:08:58.594Z" }, + { url = "https://files.pythonhosted.org/packages/57/37/5011581aa7f2be498b97dcc7c9902192442a42f4f9a748aeadb3d6506b42/coverage-7.15.0-cp311-cp311-win_arm64.whl", hash = "sha256:309990eb5fb8014b9f67cb211f7fd41876ec8a88a88d3ae76de0ed1d611e3640", size = 222774, upload-time = "2026-07-02T13:09:00.074Z" }, + { url = "https://files.pythonhosted.org/packages/2a/74/fd4c0901137c4f8d81a76ada99e43c65163b4c94a02ece107a4ec0c6b615/coverage-7.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b75ee5e8cb7575636ac598719b4307ac529ec8fcd79608a35c3cd4d4dada812d", size = 220838, upload-time = "2026-07-02T13:09:02.084Z" }, + { url = "https://files.pythonhosted.org/packages/0f/2e/2347583467bd7f0402635101a916961915cc68fce652cd0db5f173ea04fc/coverage-7.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffb31267816b93b075302248cc1737506081b4f163df4401e9df1a6424aafabe", size = 221197, upload-time = "2026-07-02T13:09:03.617Z" }, + { url = "https://files.pythonhosted.org/packages/f0/17/99fa688541ae1d6e84543a0e544f83de0c944815b63e9e7b1ed411d15036/coverage-7.15.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e4d0bb73455bf97ab243a8f12c37c686ccf1c13bb614b7b85f1d062f06f42b2c", size = 252705, upload-time = "2026-07-02T13:09:05.059Z" }, + { url = "https://files.pythonhosted.org/packages/fb/02/6a95a5cd83b74839017ef9cf48d2d8c9ae60af919e17a3f336e6f9f1b7bd/coverage-7.15.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:20d9ccc4ebd0edc434d86dfd2a1dd2a8efa6b6b3073d0485a394fee86459ebb4", size = 255441, upload-time = "2026-07-02T13:09:06.559Z" }, + { url = "https://files.pythonhosted.org/packages/67/f2/406f6c57d600f68185942422c4c00f1a3255d60aee6e5fd961425cd9987e/coverage-7.15.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:20c8a976c365c8cb12f0cbd099508772ea41fb5fa80657a8506df0e11bd278c5", size = 256556, upload-time = "2026-07-02T13:09:08.197Z" }, + { url = "https://files.pythonhosted.org/packages/74/8e/d3fa48489c15ecdec1ba48fd61f68798555dddd2f6716f9ad42adeb1a2a9/coverage-7.15.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f948fd5ba1b9cbca91f0ae08b4c1ce2b139509149a435e2585d056d57d70bf01", size = 258815, upload-time = "2026-07-02T13:09:09.691Z" }, + { url = "https://files.pythonhosted.org/packages/47/2e/2d40ddd110462c6a2769677cf7f1c119a52b45f568978fc6c98e4cc0dd0f/coverage-7.15.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f58185f06edf6ad68ec9fb155d63ef650c82f3fbd7e1770e2867751fb13158f4", size = 253117, upload-time = "2026-07-02T13:09:11.212Z" }, + { url = "https://files.pythonhosted.org/packages/51/c0/310782f0d7c3cb2b5ac05ba8d205fe91f24a36f6bf3256098f1782181c38/coverage-7.15.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:02adc79a920c73c647c5d117f55747df7f2de94571884758ce8bc58e04f0a796", size = 254475, upload-time = "2026-07-02T13:09:13.029Z" }, + { url = "https://files.pythonhosted.org/packages/86/f7/702da6c275f8ae6ade423d2877243122932c9b27f5403003b9ef8c927d12/coverage-7.15.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6eb7c300fbed667fd6e3588eba71c1904cdb06110ca6fdf908c26bdd88b8e382", size = 252619, upload-time = "2026-07-02T13:09:14.699Z" }, + { url = "https://files.pythonhosted.org/packages/fb/84/c5b15a7e5ecba4e56218d772d99fe80a63e63f8d11f12783723a6005ab45/coverage-7.15.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b5fb23fa2de9dce1f5c36c09066d8fcda16cd96e8e26686caa2d7cb9b567d65c", size = 256689, upload-time = "2026-07-02T13:09:16.103Z" }, + { url = "https://files.pythonhosted.org/packages/95/2f/c8b07559b57701230c61b23a953858c052890c12ef568d81780c6c46e92e/coverage-7.15.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:cec79341dbe6281484024979976d0c7f22beae08b4a254655decd25d42cbe766", size = 252189, upload-time = "2026-07-02T13:09:17.828Z" }, + { url = "https://files.pythonhosted.org/packages/6b/80/6d2f049dd3fd3dbfd60b62ba6b2162a04009e2c002ce70b24cf3878dec7a/coverage-7.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6c664c5444b1d970b1b2a450e21fb19ee5c9cfdf151ded2dda37260031cca0da", size = 254059, upload-time = "2026-07-02T13:09:19.304Z" }, + { url = "https://files.pythonhosted.org/packages/ce/92/b0287a2c42031d25c628f815f89a3cd9f8268ee78bb1252c9356cda1c689/coverage-7.15.0-cp312-cp312-win32.whl", hash = "sha256:5f764a3fa339bde6b3aa97657f5a6a3a9451e4a5b4ea98a2892c773a43525f77", size = 222893, upload-time = "2026-07-02T13:09:20.812Z" }, + { url = "https://files.pythonhosted.org/packages/a9/69/e34c481915fecb499b3146975061dac528752e37706edc1804f32c822469/coverage-7.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:52f9a4d2c4c56c8848bc2f524916698354b0211488b38c49ad9ae54f6cafbff6", size = 223429, upload-time = "2026-07-02T13:09:22.315Z" }, + { url = "https://files.pythonhosted.org/packages/fe/98/6e878f0b571d32684ef3f38d7c03db241ca5b82a5da8a5391596a8f209c4/coverage-7.15.0-cp312-cp312-win_arm64.whl", hash = "sha256:31e5c3e70c85307ea35a12964e2e40f56ca2ee4b1c8c721ccf4609d17071080b", size = 222810, upload-time = "2026-07-02T13:09:23.812Z" }, + { url = "https://files.pythonhosted.org/packages/76/04/145a3748098bcc86b631a85408d2c3dc5c104e0bd86d605468239b25b6c4/coverage-7.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5be4caf3b28836f078abe700f8944dac4a65d78f16d6c600c89cb624e5535782", size = 220863, upload-time = "2026-07-02T13:09:25.371Z" }, + { url = "https://files.pythonhosted.org/packages/a4/5c/4ed55708fed2c64b63c9bc5715daef670872202101938869b7fe5d5fbb8f/coverage-7.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dd58ad1404704303ca8d4f4b8a1095e7cbc7040ef17a66df1e6619aa10176430", size = 221230, upload-time = "2026-07-02T13:09:26.897Z" }, + { url = "https://files.pythonhosted.org/packages/7b/19/3a80b97d3b2a5c77a01ae359c6bed20c13738fe3d9380f08616d4fec0281/coverage-7.15.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bbcbb317c2e5ded5b21104af81c29f391be2af98d065693ffbe8d23949b948e5", size = 252227, upload-time = "2026-07-02T13:09:28.543Z" }, + { url = "https://files.pythonhosted.org/packages/a1/fa/b70062750686bd7da454da27927622f48bbac6990ac7a4c4a4653e7b0036/coverage-7.15.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:27f31ecb458da3f859aab3f15ada871eb7a7768807d88df4a9f186bb17737970", size = 254823, upload-time = "2026-07-02T13:09:30.177Z" }, + { url = "https://files.pythonhosted.org/packages/a9/09/dad6a75a2e561b9dc5086a8c5257a7591d584246f67e23e70d2995b89ab6/coverage-7.15.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13fb759be317fdc62e0f56bffdf61cfcb45c7761ad6b71e3e583e71a67ae753c", size = 256059, upload-time = "2026-07-02T13:09:31.979Z" }, + { url = "https://files.pythonhosted.org/packages/e6/e7/b5d2941fa9564573d44b693a871ff3156f0c42cbefe977a09fa7fdc59971/coverage-7.15.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d5cf007add5ab4bb8fa9f4c77e3732127c9e6cad501d7db43355fbfafca0be84", size = 258190, upload-time = "2026-07-02T13:09:34.035Z" }, + { url = "https://files.pythonhosted.org/packages/7c/1d/8e895bcde3c57ccd46d896dda5f2b3d5df761a1b0c6c9d450d175dedc632/coverage-7.15.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cc78d9843bd576fbe2118248258d485e968dc535f95ed504a7b0867ba9b51389", size = 252456, upload-time = "2026-07-02T13:09:35.765Z" }, + { url = "https://files.pythonhosted.org/packages/14/4c/f6997da343ddeb959be82c3b05322793f92c071ad45f7cb8a96336e2dd5f/coverage-7.15.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a263060f1de0b4b74b4e089c2a70b8003b3781c733329a9c8fd54995328f9950", size = 254192, upload-time = "2026-07-02T13:09:37.445Z" }, + { url = "https://files.pythonhosted.org/packages/17/27/a0bc09d032267b9da89d95a2d874cfbef2a5aebbf0e87cf7aba221d79a99/coverage-7.15.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c48decf16e0dfd5b049c7d5e82200c23c08126719142998d4f172444e3d0529e", size = 252153, upload-time = "2026-07-02T13:09:39.422Z" }, + { url = "https://files.pythonhosted.org/packages/54/c0/77fc233d9fba07b244c40948c53fe27308b8f21732fb3417f87fbd6fd992/coverage-7.15.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:08fb028000ed0aaa0a4cbdfbb98be7cb42f370db973fbbb469733505ab20e13e", size = 256310, upload-time = "2026-07-02T13:09:41.006Z" }, + { url = "https://files.pythonhosted.org/packages/d5/24/601cecfb5825becacb8d45219a018a3b55b9dbaec624efdb0ea249d08be2/coverage-7.15.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:fb7dc0c3b7d8a1077abea0b8546ebc5e26d6ef6ecefc2f0f5ad2b8a53bdad837", size = 251974, upload-time = "2026-07-02T13:09:42.733Z" }, + { url = "https://files.pythonhosted.org/packages/47/1e/6f45e5a5b3d5484318d368702af6716b5ab8913b0428bec981a562fcf296/coverage-7.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6cb3602054ccbe9f0d8c2dc04bbeba90d5719236e2cd06e042ddd6d3fc7b6e37", size = 253745, upload-time = "2026-07-02T13:09:44.376Z" }, + { url = "https://files.pythonhosted.org/packages/8e/db/4df027a77bd11d0e527f44c53557c76e54ad027413d0304252ea3a78d67e/coverage-7.15.0-cp313-cp313-win32.whl", hash = "sha256:0bf781da64326b677be344df505171435b6f58716108606621d5d27d964fff8b", size = 222902, upload-time = "2026-07-02T13:09:46.122Z" }, + { url = "https://files.pythonhosted.org/packages/a0/10/0355894d34e231f2c5449e71287e81a50793a325df2e2b027b7bcd9dfd19/coverage-7.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:2c57a275078ee3fa185f83e400f765bc764a549de66d99b47881645cbd4ea629", size = 223444, upload-time = "2026-07-02T13:09:47.687Z" }, + { url = "https://files.pythonhosted.org/packages/06/ef/bb725f263befaaff851203ab338e68af15e195d7f7b5f323162532d9b6a8/coverage-7.15.0-cp313-cp313-win_arm64.whl", hash = "sha256:3812c61afc6685c7999b39320779ab8f43b7a3081fdb0def39976e56fbdb9a21", size = 222839, upload-time = "2026-07-02T13:09:49.717Z" }, + { url = "https://files.pythonhosted.org/packages/4f/9c/1e3ca54f72a3185ece06c58d871099898c48f0ed6430d17b6ab75f0d180a/coverage-7.15.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:41cb79af843222e11da87127ad0ecbfa878abadd0f770a4a99391a27d3887324", size = 220906, upload-time = "2026-07-02T13:09:51.339Z" }, + { url = "https://files.pythonhosted.org/packages/09/37/f718613d83b274880382f6b67e78f3802549ae39b0b3e65ae5b5974df56e/coverage-7.15.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:7d2008989ef8fe54188d3f3bfa2e3099b025af11e90a6a1b9e7dc433d04263d8", size = 221239, upload-time = "2026-07-02T13:09:53.138Z" }, + { url = "https://files.pythonhosted.org/packages/a7/ce/22bae91e0b75445f68d365c7643ed0aa4880bbf77450ee74ca65bdae53a7/coverage-7.15.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:769e8ece11a596315ebf5aa7ec383aeeed016c091d2bf6363ffb996d41529092", size = 252286, upload-time = "2026-07-02T13:09:54.996Z" }, + { url = "https://files.pythonhosted.org/packages/dd/1e/bec5e32aa508615d9d7a2790effb25fb4dc28606e995816afe400b25ece3/coverage-7.15.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:65a6b6164ee5c39e2f3803f314292d6c61a607ba7fee253d1e03c42dc3903502", size = 254789, upload-time = "2026-07-02T13:09:56.678Z" }, + { url = "https://files.pythonhosted.org/packages/17/29/0e865435b4354e4a7c03b1b7920046d31d0a273d55decefea27e011cb9bf/coverage-7.15.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:75128817f95a5c45bb01d65fd2d8b9cb54bbe03d81608fb70e3e14b437ad56c2", size = 256135, upload-time = "2026-07-02T13:09:58.343Z" }, + { url = "https://files.pythonhosted.org/packages/84/ff/33a870b58a13325d62fc0a6c8f01fa0ff667cef60c7498e2382a147dfa18/coverage-7.15.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9887bb428fe2d4cd4bee89bac1a6c9932f484afd5b36fbd4ff6ea5f825bb1f5e", size = 258449, upload-time = "2026-07-02T13:10:00.057Z" }, + { url = "https://files.pythonhosted.org/packages/18/7b/6fffe596bf3ddba8462758d02c5dad730fd91055a6634aa2e4226229181a/coverage-7.15.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0bfc0be1f702042207a93a00523b1065ee1fe951e96edf311581c0bbc2e34888", size = 252313, upload-time = "2026-07-02T13:10:01.946Z" }, + { url = "https://files.pythonhosted.org/packages/58/1b/11468dd6c1676ab831a70cb9a8d4e198e8607fa0b7220ab918b73fe9bfbd/coverage-7.15.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f64627d55def5a43282d70e08396672692f77e4da610a5bb8bb4060b432b6859", size = 254142, upload-time = "2026-07-02T13:10:04.065Z" }, + { url = "https://files.pythonhosted.org/packages/79/41/29328e21d16b1b95092c30dd700e08cf915bd3734f836df8f3bdb0e8fa9f/coverage-7.15.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:2c6f0fa473003905c6d5bac328ee4eba9fbea654f15bc24b8a3274b23363fa99", size = 252108, upload-time = "2026-07-02T13:10:06.11Z" }, + { url = "https://files.pythonhosted.org/packages/9b/de/05ccfb990439655b35afbfd8e0d13fe66677565a7d4eb38c3f5ef2635e1c/coverage-7.15.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2bcf9afaf064172c6ec3c58a325a9957ad1178c05dd934e25f253321776e0676", size = 256385, upload-time = "2026-07-02T13:10:08.141Z" }, + { url = "https://files.pythonhosted.org/packages/51/0e/486828a3d2695ea7a2609f17ff572f6b01905e608379440a11da4b8dffbe/coverage-7.15.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:baf06bc987115d6fb938d403f7eab684a057766c490367999a2b71a6883110c6", size = 251923, upload-time = "2026-07-02T13:10:10.179Z" }, + { url = "https://files.pythonhosted.org/packages/18/c7/03582b6715f078e5e558354c87616d945b9894cda2dace8e4009b17035e4/coverage-7.15.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f0405f2ff97b1c4c0e782cb32e02f32369bcf2e6b618b591d67e1ea754575dfe", size = 253580, upload-time = "2026-07-02T13:10:12.052Z" }, + { url = "https://files.pythonhosted.org/packages/db/dc/9e578bbaf2ecb4959a81b7e7601ad8cca772cba2892e8d144cb749b4a71a/coverage-7.15.0-cp314-cp314-win32.whl", hash = "sha256:ab282853ed5fbd64bbb162f19cb8fcb7087187508a6374b4f9c34ec1577c4e8f", size = 223107, upload-time = "2026-07-02T13:10:13.994Z" }, + { url = "https://files.pythonhosted.org/packages/ae/3e/c8c3b75d8dbe0e35f7b0cc3ff5e949fc59500f70b21d0398813f66740664/coverage-7.15.0-cp314-cp314-win_amd64.whl", hash = "sha256:3bb3040e9f4bbe26fcb0cd7cc85ac63e630d3f3a9c74f027abf4caa27e706663", size = 223597, upload-time = "2026-07-02T13:10:15.906Z" }, + { url = "https://files.pythonhosted.org/packages/cd/bc/3cbc9fb036eb388519bccd521f783499c39b64256013fbc362782f196fe1/coverage-7.15.0-cp314-cp314-win_arm64.whl", hash = "sha256:346771144d34f7fa84ec28386f78e0f31653f33cf35e19d253d5b35f9e8201da", size = 223020, upload-time = "2026-07-02T13:10:17.844Z" }, + { url = "https://files.pythonhosted.org/packages/28/00/199c4a8d656dff63102577a056c0fce2ff6a79e40adac092fc986c49cbf1/coverage-7.15.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d34a010905fb6401324ba016b5da03d574967f7b21ce48ea41e66f0f1f95f641", size = 221638, upload-time = "2026-07-02T13:10:19.703Z" }, + { url = "https://files.pythonhosted.org/packages/ba/8e/9d0092c96a3d3a26951ecc7020826aa57bcb1b119ca81acbba996884ab13/coverage-7.15.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:bb25d825d885ca8036795dacfc3924d33091fc76d71ebc99420c6b79e77d96fa", size = 221903, upload-time = "2026-07-02T13:10:21.514Z" }, + { url = "https://files.pythonhosted.org/packages/6d/b4/c0ca3028f42c9a08e51feb4561ef1192e5de99797cd1db5b04590c215bda/coverage-7.15.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:94c9686bfe8a9a6810297aecbd99beaa3445f9e8dc2f80b1382cca0d86b64461", size = 263267, upload-time = "2026-07-02T13:10:23.261Z" }, + { url = "https://files.pythonhosted.org/packages/5f/aa/a375e3846e5d3c013dc600b2a3231089055c73d77f5393dd2192a8d64da6/coverage-7.15.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9bd671c25f9d85f09d7ec481d0e43d5139f486c06a37139847a7ce569788af72", size = 265390, upload-time = "2026-07-02T13:10:25.152Z" }, + { url = "https://files.pythonhosted.org/packages/92/e1/5783cdabb797305e1c9e4809fea496d31834c51fa772514f73dc148bcfc9/coverage-7.15.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:110cbdf8d2e216577312cf06ccf85539c0e5a5420ef747e4a4719b5e483c88cd", size = 267811, upload-time = "2026-07-02T13:10:27.249Z" }, + { url = "https://files.pythonhosted.org/packages/85/31/96d8bbf58b8e9193bc8389574a91a0db48355ee98feb66aa6bf8d1b32eea/coverage-7.15.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2c5d4619214f1d9993e7b00a8600d14614b7e9d84e89507460b126aa5e6559e5", size = 268928, upload-time = "2026-07-02T13:10:29.242Z" }, + { url = "https://files.pythonhosted.org/packages/5e/7a/5294567e811a1cb7eda93140c628fa050d66189da28da320f93d1d815c73/coverage-7.15.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:781a704516e2d8346fbbd5be6c6f3412dd824785146528b3a01816f26c081007", size = 262378, upload-time = "2026-07-02T13:10:31.107Z" }, + { url = "https://files.pythonhosted.org/packages/69/3f/3f48538421f899f28946f90a3d272136a4686e1abf461cc9249a783ee0f3/coverage-7.15.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bd4a1b44bcb65ee29e947ac92bbee04956df3a6bfc6143641bb6cae7ede00fc9", size = 265263, upload-time = "2026-07-02T13:10:32.942Z" }, + { url = "https://files.pythonhosted.org/packages/ce/d3/092df15efcab8a9c1467ee960eb8019bbad3f9300d115d89ea6195f369ff/coverage-7.15.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0e4950c9d6d3e39c64c991814ff315e2d0b9cb8152363594212c9e55208c0a8f", size = 262866, upload-time = "2026-07-02T13:10:35.104Z" }, + { url = "https://files.pythonhosted.org/packages/e5/ab/0254d2b88665efb2c57ad368cc77ab5de3435bd8d5add4729c1b0e79431e/coverage-7.15.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:fe9c87ff42e5472d80d21704972e1f96e104a0a599d77c5e35db5a3c562e2571", size = 266599, upload-time = "2026-07-02T13:10:37.05Z" }, + { url = "https://files.pythonhosted.org/packages/a8/79/1cfa4023e489ce6fbc7be4a5d442dbc375edb4f4fda39a352cedb53263c2/coverage-7.15.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f00d5ae1dd2fe13fb8186e3e7d37bcbd8b25c0d764ff7d1b32cef9be058510a8", size = 261714, upload-time = "2026-07-02T13:10:38.966Z" }, + { url = "https://files.pythonhosted.org/packages/b7/eb/fee5c8665656be63f497418d410484637c438172568688e8ac92e06574e7/coverage-7.15.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:363ab38cc78b615f11c9cac3cf1d7eef950c18b9fdedfb9066f59461dcf84d68", size = 264025, upload-time = "2026-07-02T13:10:40.789Z" }, + { url = "https://files.pythonhosted.org/packages/ab/99/63005db722f91edc81abc16302f9cc2f6228c1679e46e15be9ae144b14d0/coverage-7.15.0-cp314-cp314t-win32.whl", hash = "sha256:54fd9c53a5fafff509195f1b6a3f9be615d8e8362a3629ff1de23d270c03c86b", size = 223413, upload-time = "2026-07-02T13:10:42.597Z" }, + { url = "https://files.pythonhosted.org/packages/c1/e8/2bc6181c4fb06f1a6b981eb85330cc57bfad7e3f710fc9c9d350013ba228/coverage-7.15.0-cp314-cp314t-win_amd64.whl", hash = "sha256:87b47553097ba185ed964866078e7e63adea9f5f51b5f39691c34f30afd21080", size = 224245, upload-time = "2026-07-02T13:10:44.47Z" }, + { url = "https://files.pythonhosted.org/packages/79/b8/4d959bf9cc45d0cfed2f4d35cafcab978cdb6ea02eb5100009cd740632a3/coverage-7.15.0-cp314-cp314t-win_arm64.whl", hash = "sha256:aeefb2dd178fe7eee79f0ad25d75855cb35ee9ed472db2c5ea06f5b4fd00cec5", size = 223558, upload-time = "2026-07-02T13:10:46.368Z" }, + { url = "https://files.pythonhosted.org/packages/52/30/21b2ad45959cd50e909e02ebac1e30b4ceb7162e91c11d4c570223a458b7/coverage-7.15.0-py3-none-any.whl", hash = "sha256:56da6a4cbe8f7e9e80bd072ca9cefe67d7106a440a7ec06519ec6507ac94ad19", size = 212632, upload-time = "2026-07-02T13:10:48.641Z" }, ] [package.optional-dependencies] @@ -606,61 +706,58 @@ toml = [ [[package]] name = "cryptography" -version = "48.0.0" +version = "49.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9f/a9/db8f313fdcd85d767d4973515e1db101f9c71f95fced83233de224673757/cryptography-48.0.0.tar.gz", hash = "sha256:5c3932f4436d1cccb036cb0eaef46e6e2db91035166f1ad6505c3c9d5a635920", size = 832984, upload-time = "2026-05-04T22:59:38.133Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/df/3d/01f6dd9190170a5a241e0e98c2d04be3664a9e6f5b9b872cde63aff1c3dd/cryptography-48.0.0-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:0c558d2cdffd8f4bbb30fc7134c74d2ca9a476f830bb053074498fbc86f41ed6", size = 8001587, upload-time = "2026-05-04T22:57:36.803Z" }, - { url = "https://files.pythonhosted.org/packages/b2/6e/e90527eef33f309beb811cf7c982c3aeffcce8e3edb178baa4ca3ae4a6fa/cryptography-48.0.0-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f5333311663ea94f75dd408665686aaf426563556bb5283554a3539177e03b8c", size = 4690433, upload-time = "2026-05-04T22:57:40.373Z" }, - { url = "https://files.pythonhosted.org/packages/90/04/673510ed51ddff56575f306cf1617d80411ee76831ccd3097599140efdfe/cryptography-48.0.0-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7995ef305d7165c3f11ae07f2517e5a4f1d5c18da1376a0a9ed496336b69e5f3", size = 4710620, upload-time = "2026-05-04T22:57:42.935Z" }, - { url = "https://files.pythonhosted.org/packages/14/d5/e9c4ef932c8d800490c34d8bd589d64a31d5890e27ec9e9ad532be893294/cryptography-48.0.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:40ba1f85eaa6959837b1d51c9767e230e14612eea4ef110ee8854ada22da1bf5", size = 4696283, upload-time = "2026-05-04T22:57:45.294Z" }, - { url = "https://files.pythonhosted.org/packages/0c/29/174b9dfb60b12d59ecfc6cfa04bc88c21b42a54f01b8aae09bb6e51e4c7f/cryptography-48.0.0-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:369a6348999f94bbd53435c894377b20ab95f25a9065c283570e70150d8abc3c", size = 5296573, upload-time = "2026-05-04T22:57:47.933Z" }, - { url = "https://files.pythonhosted.org/packages/95/38/0d29a6fd7d0d1373f0c0c88a04ba20e359b257753ac497564cd660fc1d55/cryptography-48.0.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a0e692c683f4df67815a2d258b324e66f4738bd7a96a218c826dce4f4bd05d8f", size = 4743677, upload-time = "2026-05-04T22:57:50.067Z" }, - { url = "https://files.pythonhosted.org/packages/30/be/eef653013d5c63b6a490529e0316f9ac14a37602965d4903efed1399f32b/cryptography-48.0.0-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:18349bbc56f4743c8b12dc32e2bccb2cf83ee8b69a3bba74ef8ae857e26b3d25", size = 4330808, upload-time = "2026-05-04T22:57:52.301Z" }, - { url = "https://files.pythonhosted.org/packages/84/9e/500463e87abb7a0a0f9f256ec21123ecde0a7b5541a15e840ea54551fd81/cryptography-48.0.0-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:7e8eac43dfca5c4cccc6dad9a80504436fca53bb9bc3100a2386d730fbe6b602", size = 4695941, upload-time = "2026-05-04T22:57:54.603Z" }, - { url = "https://files.pythonhosted.org/packages/e3/dc/7303087450c2ec9e7fbb750e17c2abfbc658f23cbd0e54009509b7cc4091/cryptography-48.0.0-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:9ccdac7d40688ecb5a3b4a604b8a88c8002e3442d6c60aead1db2a89a041560c", size = 5252579, upload-time = "2026-05-04T22:57:57.207Z" }, - { url = "https://files.pythonhosted.org/packages/d0/c0/7101d3b7215edcdc90c45da544961fd8ed2d6448f77577460fa75a8443f7/cryptography-48.0.0-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:bd72e68b06bb1e96913f97dd4901119bc17f39d4586a5adf2d3e47bc2b9d58b5", size = 4743326, upload-time = "2026-05-04T22:57:59.535Z" }, - { url = "https://files.pythonhosted.org/packages/ac/d8/5b833bad13016f562ab9d063d68199a4bd121d18458e439515601d3357ec/cryptography-48.0.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:59baa2cb386c4f0b9905bd6eb4c2a79a69a128408fd31d32ca4d7102d4156321", size = 4826672, upload-time = "2026-05-04T22:58:01.996Z" }, - { url = "https://files.pythonhosted.org/packages/98/e1/7074eb8bf3c135558c73fc2bcf0f5633f912e6fb87e868a55c454080ef09/cryptography-48.0.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:9249e3cd978541d665967ac2cb2787fd6a62bddf1e75b3e347a594d7dacf4f74", size = 4972574, upload-time = "2026-05-04T22:58:03.968Z" }, - { url = "https://files.pythonhosted.org/packages/04/70/e5a1b41d325f797f39427aa44ef8baf0be500065ab6d8e10369d850d4a4f/cryptography-48.0.0-cp311-abi3-win32.whl", hash = "sha256:9c459db21422be75e2809370b829a87eb37f74cd785fc4aa9ea1e5f43b47cda4", size = 3294868, upload-time = "2026-05-04T22:58:06.467Z" }, - { url = "https://files.pythonhosted.org/packages/f4/ac/8ac51b4a5fc5932eb7ee5c517ba7dc8cd834f0048962b6b352f00f41ebf9/cryptography-48.0.0-cp311-abi3-win_amd64.whl", hash = "sha256:5b012212e08b8dd5edc78ef54da83dd9892fd9105323b3993eff6bea65dc21d7", size = 3817107, upload-time = "2026-05-04T22:58:08.845Z" }, - { url = "https://files.pythonhosted.org/packages/6b/84/70e3feea9feea87fd7cbe77efb2712ae1e3e6edf10749dc6e95f4e60e455/cryptography-48.0.0-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:3cb07a3ed6431663cd321ea8a000a1314c74211f823e4177fefa2255e057d1ec", size = 7986556, upload-time = "2026-05-04T22:58:11.172Z" }, - { url = "https://files.pythonhosted.org/packages/89/6e/18e07a618bb5442ba10cf4df16e99c071365528aa570dfcb8c02e25a303b/cryptography-48.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8c7378637d7d88016fa6791c159f698b3d3eed28ebf844ac36b9dc04a14dae18", size = 4684776, upload-time = "2026-05-04T22:58:13.712Z" }, - { url = "https://files.pythonhosted.org/packages/be/6a/4ea3b4c6c6759794d5ee2103c304a5076dc4b19ae1f9fe47dba439e159e9/cryptography-48.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cc90c0b39b2e3c65ef52c804b72e3c58f8a04ab2a1871272798e5f9572c17d20", size = 4698121, upload-time = "2026-05-04T22:58:16.448Z" }, - { url = "https://files.pythonhosted.org/packages/2f/59/6ff6ad6cae03bb887da2a5860b2c9805f8dac969ef01ce563336c49bd1d1/cryptography-48.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:76341972e1eff8b4bea859f09c0d3e64b96ce931b084f9b9b7db8ef364c30eff", size = 4690042, upload-time = "2026-05-04T22:58:18.544Z" }, - { url = "https://files.pythonhosted.org/packages/ca/b4/fc334ed8cfd705aca282fe4d8f5ae64a8e0f74932e9feecb344610cf6e4d/cryptography-48.0.0-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:55b7718303bf06a5753dcdccf2f3945cf18ad7bffde41b61226e4db31ab89a9c", size = 5282526, upload-time = "2026-05-04T22:58:20.75Z" }, - { url = "https://files.pythonhosted.org/packages/11/08/9f8c5386cc4cd90d8255c7cdd0f5baf459a08502a09de30dc51f553d38dc/cryptography-48.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:a64697c641c7b1b2178e573cbc31c7c6684cd56883a478d75143dbb7118036db", size = 4733116, upload-time = "2026-05-04T22:58:23.627Z" }, - { url = "https://files.pythonhosted.org/packages/b8/77/99307d7574045699f8805aa500fa0fb83422d115b5400a064ddd306d7750/cryptography-48.0.0-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:561215ea3879cb1cbbf272867e2efda62476f240fb58c64de6b393ae19246741", size = 4316030, upload-time = "2026-05-04T22:58:25.581Z" }, - { url = "https://files.pythonhosted.org/packages/fd/36/a608b98337af3cb2aff4818e406649d30572b7031918b04c87d979495348/cryptography-48.0.0-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:ad64688338ed4bc1a6618076ba75fd7194a5f1797ac60b47afe926285adb3166", size = 4689640, upload-time = "2026-05-04T22:58:27.747Z" }, - { url = "https://files.pythonhosted.org/packages/dd/a6/825010a291b4438aecc1f568bc428189fc1175515223632477c07dc0a6df/cryptography-48.0.0-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:906cbf0670286c6e0044156bc7d4af9cbb0ef6db9f73e52c3ec56ba6bdde5336", size = 5237657, upload-time = "2026-05-04T22:58:29.848Z" }, - { url = "https://files.pythonhosted.org/packages/b9/09/4e76a09b4caa29aad535ddc806f5d4c5d01885bd978bd984fbc6ca032cae/cryptography-48.0.0-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:ea8990436d914540a40ab24b6a77c0969695ed52f4a4874c5137ccf7045a7057", size = 4732362, upload-time = "2026-05-04T22:58:32.009Z" }, - { url = "https://files.pythonhosted.org/packages/18/78/444fa04a77d0cb95f417dda20d450e13c56ba8e5220fc892a1658f44f882/cryptography-48.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c18684a7f0cc9a3cb60328f496b8e3372def7c5d2df39ac267878b05565aaaae", size = 4819580, upload-time = "2026-05-04T22:58:34.254Z" }, - { url = "https://files.pythonhosted.org/packages/38/85/ea67067c70a1fd4be2c63d35eeed82658023021affccc7b17705f8527dd2/cryptography-48.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9be5aafa5736574f8f15f262adc81b2a9869e2cfe9014d52a44633905b40d52c", size = 4963283, upload-time = "2026-05-04T22:58:36.376Z" }, - { url = "https://files.pythonhosted.org/packages/75/54/cc6d0f3deac3e81c7f847e8a189a12b6cdd65059b43dad25d4316abd849a/cryptography-48.0.0-cp314-cp314t-win32.whl", hash = "sha256:c17dfe85494deaeddc5ce251aebd1d60bbe6afc8b62071bb0b469431a000124f", size = 3270954, upload-time = "2026-05-04T22:58:38.791Z" }, - { url = "https://files.pythonhosted.org/packages/49/67/cc947e288c0758a4e5473d1dcb743037ab7785541265a969240b8885441a/cryptography-48.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27241b1dc9962e056062a8eef1991d02c3a24569c95975bd2322a8a52c6e5e12", size = 3797313, upload-time = "2026-05-04T22:58:40.746Z" }, - { url = "https://files.pythonhosted.org/packages/f2/63/61d4a4e1c6b6bab6ce1e213cd36a24c415d90e76d78c5eb8577c5541d2e8/cryptography-48.0.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:58d00498e8933e4a194f3076aee1b4a97dfec1a6da444535755822fe5d8b0b86", size = 7983482, upload-time = "2026-05-04T22:58:43.769Z" }, - { url = "https://files.pythonhosted.org/packages/d5/ac/f5b5995b87770c693e2596559ffafe195b4033a57f14a82268a2842953f3/cryptography-48.0.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:614d0949f4790582d2cc25553abd09dd723025f0c0e7c67376a1d77196743d6e", size = 4683266, upload-time = "2026-05-04T22:58:46.064Z" }, - { url = "https://files.pythonhosted.org/packages/ec/c6/8b14f67e18338fbc4adb76f66c001f5c3610b3e2d1837f268f47a347dbbb/cryptography-48.0.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7ce4bfae76319a532a2dc68f82cc32f5676ee792a983187dac07183690e5c66f", size = 4696228, upload-time = "2026-05-04T22:58:48.22Z" }, - { url = "https://files.pythonhosted.org/packages/ea/73/f808fbae9514bd91b47875b003f13e284c8c6bdfd904b7944e803937eec1/cryptography-48.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:2eb992bbd4661238c5a397594c83f5b4dc2bc5b848c365c8f991b6780efcc5c7", size = 4689097, upload-time = "2026-05-04T22:58:50.9Z" }, - { url = "https://files.pythonhosted.org/packages/93/01/d86632d7d28db8ae83221995752eeb6639ffb374c2d22955648cf8d52797/cryptography-48.0.0-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:22a5cb272895dce158b2cacdfdc3debd299019659f42947dbdac6f32d68fe832", size = 5283582, upload-time = "2026-05-04T22:58:53.017Z" }, - { url = "https://files.pythonhosted.org/packages/02/e1/50edc7a50334807cc4791fc4a0ce7468b4a1416d9138eab358bfc9a3d70b/cryptography-48.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2b4d59804e8408e2fea7d1fbaf218e5ec984325221db76e6a241a9abd6cdd95c", size = 4730479, upload-time = "2026-05-04T22:58:55.611Z" }, - { url = "https://files.pythonhosted.org/packages/6f/af/99a582b1b1641ff5911ac559beb45097cf79efd4ead4657f578ef1af2d47/cryptography-48.0.0-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:984a20b0f62a26f48a3396c72e4bc34c66e356d356bf370053066b3b6d54634a", size = 4326481, upload-time = "2026-05-04T22:58:57.607Z" }, - { url = "https://files.pythonhosted.org/packages/90/ee/89aa26a06ef0a7d7611788ffd571a7c50e368cc6a4d5eef8b4884e866edb/cryptography-48.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:5a5ed8fde7a1d09376ca0b40e68cd59c69fe23b1f9768bd5824f54681626032a", size = 4688713, upload-time = "2026-05-04T22:59:00.077Z" }, - { url = "https://files.pythonhosted.org/packages/70/ba/bcb1b0bb7a33d4c7c0c4d4c7874b4a62ae4f56113a5f4baefa362dfb1f0f/cryptography-48.0.0-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:8cd666227ef7af430aa5914a9910e0ddd703e75f039cef0825cd0da71b6b711a", size = 5238165, upload-time = "2026-05-04T22:59:02.317Z" }, - { url = "https://files.pythonhosted.org/packages/c9/70/ca4003b1ce5ca3dc3186ada51908c8a9b9ff7d5cab83cc0d43ee14ec144f/cryptography-48.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:9071196d81abc88b3516ac8cdfad32e2b66dd4a5393a8e68a961e9161ddc6239", size = 4729947, upload-time = "2026-05-04T22:59:05.255Z" }, - { url = "https://files.pythonhosted.org/packages/44/a0/4ec7cf774207905aef1a8d11c3750d5a1db805eb380ee4e16df317870128/cryptography-48.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1e2d54c8be6152856a36f0882ab231e70f8ec7f14e93cf87db8a2ed056bf160c", size = 4822059, upload-time = "2026-05-04T22:59:07.802Z" }, - { url = "https://files.pythonhosted.org/packages/1e/75/a2e55f99c16fcac7b5d6c1eb19ad8e00799854d6be5ca845f9259eae1681/cryptography-48.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a5da777e32ffed6f85a7b2b3f7c5cbc88c146bfcd0a1d7baf5fcc6c52ee35dd4", size = 4960575, upload-time = "2026-05-04T22:59:09.851Z" }, - { url = "https://files.pythonhosted.org/packages/b8/23/6e6f32143ab5d8b36ca848a502c4bcd477ae75b9e1677e3530d669062578/cryptography-48.0.0-cp39-abi3-win32.whl", hash = "sha256:77a2ccbbe917f6710e05ba9adaa25fb5075620bf3ea6fb751997875aff4ae4bd", size = 3279117, upload-time = "2026-05-04T22:59:12.019Z" }, - { url = "https://files.pythonhosted.org/packages/9d/9a/0fea98a70cf1749d41d738836f6349d97945f7c89433a259a6c2642eefeb/cryptography-48.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:16cd65b9330583e4619939b3a3843eec1e6e789744bb01e7c7e2e62e33c239c8", size = 3792100, upload-time = "2026-05-04T22:59:14.884Z" }, - { url = "https://files.pythonhosted.org/packages/be/d2/024b5e06be9d44cb021fb0e1a03d34d63989cf56a0fe62f3dfbab695b9b4/cryptography-48.0.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:84cf79f0dc8b36ac5da873481716e87aef31fcfa0444f9e1d8b4b2cece142855", size = 3950391, upload-time = "2026-05-04T22:59:17.415Z" }, - { url = "https://files.pythonhosted.org/packages/bc/17/3861e17c56fa0fd37491a14a8673fdb77c57fc5693cafe745ea8b06dba75/cryptography-48.0.0-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:fdfef35d751d510fcef5252703621574364fec16418c4a1e5e1055248401054b", size = 4637126, upload-time = "2026-05-04T22:59:20.197Z" }, - { url = "https://files.pythonhosted.org/packages/f0/0a/7e226dbff530f21480727eb764973a7bff2b912f8e15cd4f129e71b56d1d/cryptography-48.0.0-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:0890f502ddf7d9c6426129c3f49f5c0a39278ed7cd6322c8755ffca6ee675a13", size = 4667270, upload-time = "2026-05-04T22:59:22.647Z" }, - { url = "https://files.pythonhosted.org/packages/3b/f2/5a72274ca9f1b2a8b44a662ee0bf1b435909deb473d6f97bcd035bcdbc71/cryptography-48.0.0-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:ecde28a596bead48b0cfd2a1b4416c3d43074c2d785e3a398d7ec1fc4d0f7fbb", size = 4636797, upload-time = "2026-05-04T22:59:24.912Z" }, - { url = "https://files.pythonhosted.org/packages/b4/e1/48cedb2fe63626e91ded1edad159e2a4fb8b6906c4425eb7749673077ce7/cryptography-48.0.0-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:4defde8685ae324a9eb9d818717e93b4638ef67070ac9bc15b8ca85f63048355", size = 4666800, upload-time = "2026-05-04T22:59:27.474Z" }, - { url = "https://files.pythonhosted.org/packages/a2/ca/7e8365deec19afb2b2c7be7c1c0aa8f99633b54e90c570999acda93260fc/cryptography-48.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:db63bf618e5dea46c07de12e900fe1cdd2541e6dc9dbae772a70b7d4d4765f6a", size = 3739536, upload-time = "2026-05-04T22:59:29.61Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/1f/99/d1c90d6041656cc6ee229dc99cd67fd0cd5aec3c5f7d72fffc27cc750054/cryptography-49.0.0.tar.gz", hash = "sha256:f89660a348f4f78a92366240a61404e337586ef7f5909a2fef59ca88ef505493", size = 854345, upload-time = "2026-06-12T20:02:30.512Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/22/adf66990e63584a68dfb50c24f48a125c07b1699899381c8151e63ed458c/cryptography-49.0.0-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:966fe0e9c67490071f14c0d2b1cb2dfb3023c5ce39457343931415f08382f2db", size = 4032100, upload-time = "2026-06-12T20:02:32.143Z" }, + { url = "https://files.pythonhosted.org/packages/09/41/3797cfaf69cae04a13ee78ebd83f0678d9c02b4779d21ce24445326f1a69/cryptography-49.0.0-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:36d1709f992593689b45bda411498d62c6e365f2ca00b84657d4dadd24de16db", size = 4692978, upload-time = "2026-06-12T20:01:21.305Z" }, + { url = "https://files.pythonhosted.org/packages/e6/8b/43011f7ebe515a8aa20d61f290a326cd890c2e738e16e59eaff8d9c3a412/cryptography-49.0.0-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0e959b578856a3924bc0cbb710fc12c387b9412a951389f3ca61704a9e25f325", size = 4716422, upload-time = "2026-06-12T20:01:48.566Z" }, + { url = "https://files.pythonhosted.org/packages/4a/91/01ce7303a4579e6d3a6abef01bd322848e9ea7a219adcabc5048b9033571/cryptography-49.0.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:53ecee2e23f7169b6117e99fc8a944e5e50f79e69758a83b52a00cb98ab2b2d2", size = 4700503, upload-time = "2026-06-12T20:02:47.091Z" }, + { url = "https://files.pythonhosted.org/packages/62/99/a2c95cf8293f07491e9e27c20cc4dcd18176d944e674679adeb1d0173fd6/cryptography-49.0.0-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:2eda353d8a27bcbcaa4cbed18994a74ab4d19a2ca897db188ea269ab9b71419b", size = 5309779, upload-time = "2026-06-12T20:02:08.987Z" }, + { url = "https://files.pythonhosted.org/packages/20/2c/0622f20ff02b2ef32558733443805dc82fd4c275be01b2d19d14676f3a1b/cryptography-49.0.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2afe9051da7ae7bd5905da5a949280c7d2bb75682e188f650a9d0f2756b834c6", size = 4749683, upload-time = "2026-06-12T20:02:03.335Z" }, + { url = "https://files.pythonhosted.org/packages/a3/5b/c5246635d5fd3b64e0d45ae10e99fd32fe9676a79915ccfe5a61ba9af1a5/cryptography-49.0.0-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:0b82e28ee398a386f0807bba7884d30f25218855690f45115831bcce5d90822c", size = 4337874, upload-time = "2026-06-12T20:02:54.323Z" }, + { url = "https://files.pythonhosted.org/packages/6d/88/05563c7fe2e914e87d1a536d06fe83e66b4e1d95cb593e05aea375531da8/cryptography-49.0.0-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:ccac2bfebc306b862133e3bb71f3f6ee8bb525240089b2d952e4144b3a6d5da7", size = 4700283, upload-time = "2026-06-12T20:01:34.822Z" }, + { url = "https://files.pythonhosted.org/packages/c4/b6/d7696e4e890d6ae1469935164c9e5215c557671cb78d6e3f458ccceaa632/cryptography-49.0.0-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:d0527ce944105f257f605a827d6ebead966c752038b6e8656abb9c5edee6fc68", size = 5265844, upload-time = "2026-06-12T20:01:24.09Z" }, + { url = "https://files.pythonhosted.org/packages/a9/3c/f3ad17eecc1a57b0ba236dc01f90e783c51f4a2f35f64777cc4f47a184b2/cryptography-49.0.0-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:cbc77da8c523d5abd028635ba850a6966fcee2c82e2bf65a41d1d8afe0f98be9", size = 4749290, upload-time = "2026-06-12T20:01:30.848Z" }, + { url = "https://files.pythonhosted.org/packages/4f/01/339573cf1023163a400b0b5d16f6d507de413b9f60be6fd1b77feeaf6737/cryptography-49.0.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b87e65d263b3e5d3bb92a57e2a6638e2f31110fa7aa890c7b2dbba42248d0a3f", size = 4834612, upload-time = "2026-06-12T20:01:29.246Z" }, + { url = "https://files.pythonhosted.org/packages/71/fd/577302e213a1be9468f92d1afef66fcf1ef83d516819d9992ca547f592bd/cryptography-49.0.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:66ec79c3904820572d7e987abdf304281f141d37ad9a489b8e97066e7b9b6459", size = 4980804, upload-time = "2026-06-12T20:01:42.853Z" }, + { url = "https://files.pythonhosted.org/packages/1f/09/f42b1d190c5ba75f72062a387f8030d1d75f6ab035788f1d9c4b01de6525/cryptography-49.0.0-cp311-abi3-win_amd64.whl", hash = "sha256:e5dfc1e64de5677cec922ffa8da89c546d0415bf6efdf081842e5d44c84e1f0e", size = 3810026, upload-time = "2026-06-12T20:02:39.262Z" }, + { url = "https://files.pythonhosted.org/packages/ec/9e/db72b3ae7fc9cfad53e630e56c6ae83b9b6ff0bf3718ffb8012d20b3aabf/cryptography-49.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:73a205dce83953d131a4aa1e0fd917a2fd1c5b1eef251e9d7152efefcbf5caf7", size = 4013892, upload-time = "2026-06-12T20:02:10.735Z" }, + { url = "https://files.pythonhosted.org/packages/86/12/c48a424f38db03027be9f7ed5c7dc5de9933dbee992865f98b13727a009d/cryptography-49.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:196ecd6a36e4e9aa10270393bb98d8df88fccee0bf1e5128b91ae4eb4375896d", size = 4678835, upload-time = "2026-06-12T20:02:48.743Z" }, + { url = "https://files.pythonhosted.org/packages/68/28/8a3ad4653662c93fc44dc4e5d8fd374c25c42e07b34bbfbadf49cf57a5a8/cryptography-49.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7abcee80084cda3f7691f3eb1ce480d8df49cec637b429aa35986c1de71738aa", size = 4697239, upload-time = "2026-06-12T20:02:56.03Z" }, + { url = "https://files.pythonhosted.org/packages/a8/b2/2193fc74f81aee4f9b62733133b73b5176718932ed8f2e4b03fa040480a6/cryptography-49.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:4ae387c9cb68ea569ca17e490d66d8142b81c3cc814bf179974b7d146e490bbb", size = 4685593, upload-time = "2026-06-12T20:02:50.666Z" }, + { url = "https://files.pythonhosted.org/packages/47/f1/1d3eaa243bfc5de4a187b22aa8c048b3e4980bfbe830ac46e6bac2e66947/cryptography-49.0.0-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:f37d847238971164fdbc68ade6f6574aecc9c0af714190e2083429ff68f4ce9d", size = 5289961, upload-time = "2026-06-12T20:01:46.468Z" }, + { url = "https://files.pythonhosted.org/packages/58/39/2d51306721330c486495853eda1c567880ff036de15a14c4b74f399934af/cryptography-49.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:c2bc30226390d60ea19d9f82b19db005fe0452154a23c1c410c12ea801e43561", size = 4731145, upload-time = "2026-06-12T20:02:16.832Z" }, + { url = "https://files.pythonhosted.org/packages/17/50/983e838c7fd0d87fd8c969bcdd328edaf5f756e38df5281637424c155873/cryptography-49.0.0-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:07cab27cc7b7e0fd28e5e26bb9eeedde5c135c868b46de4a27845abe94af6122", size = 4321719, upload-time = "2026-06-12T20:02:52.611Z" }, + { url = "https://files.pythonhosted.org/packages/a7/f5/8f571d7e27c55bce9f76f026143bcb1e040a4233149ecca0bea5fa5dd5f7/cryptography-49.0.0-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:b20133d204d2bb56ba047642199603876c872026ca53e79c35b83772ab2cc505", size = 4685209, upload-time = "2026-06-12T20:02:07.282Z" }, + { url = "https://files.pythonhosted.org/packages/e7/84/0e27016a6fc5a0886f797018b26aa42f40c09a82332bff77822a451deaaa/cryptography-49.0.0-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:b970c6da94d5bb18629db453d14f2a1300f6bf59b61e9b82377931ef95504866", size = 5246285, upload-time = "2026-06-12T20:01:32.439Z" }, + { url = "https://files.pythonhosted.org/packages/11/2d/5e1fb307cb5931881516b464c98774b3f2c36b5d4bb9a2830253cf553cad/cryptography-49.0.0-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:d8ecde755e2e91bf773fc94e8c9d730cd7f2007004cb492263a794ec3899a1c8", size = 4730441, upload-time = "2026-06-12T20:02:01.469Z" }, + { url = "https://files.pythonhosted.org/packages/e4/c0/bff5a02ee731d207d6a1ed51732549d8c53d2bc8da1d10ec6f2844201d68/cryptography-49.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e3fb64c420688e5319ae25113a354015abbd8dffbfbc41781a1ea66fc7622ac3", size = 4815869, upload-time = "2026-06-12T20:01:36.574Z" }, + { url = "https://files.pythonhosted.org/packages/b9/26/814681d14248d95d73d5c3eea0c39a94eb8302df966f670a2c60de90974b/cryptography-49.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:32703d93296f5c1f4b53349ad3a250c2cae0fdecd3a3dd5d47e616d8d616af27", size = 4960948, upload-time = "2026-06-12T20:02:18.688Z" }, + { url = "https://files.pythonhosted.org/packages/4c/fe/93ecac273d3738939d023612ad12cca9a3740a5345d69fda04134c43fd96/cryptography-49.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:33cd0565932807baddb67b96dbee92f2c374b5c89dee09fd74079aeb8c8dba61", size = 3799153, upload-time = "2026-06-12T20:01:39.059Z" }, + { url = "https://files.pythonhosted.org/packages/19/2a/5bb823f5bedcf80718cea7fbc95ec5515cca3769633c4b01a32be7f30e7c/cryptography-49.0.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ec5e529fb80935c94fe7b729f9972b50e351a0e6b50aa294fd5cabb109fcc29a", size = 4025947, upload-time = "2026-06-12T20:01:25.745Z" }, + { url = "https://files.pythonhosted.org/packages/3d/df/40577043ca124e17012f408ddddaeb213b856336ac82ddb3bc915f39e29f/cryptography-49.0.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f78ff2c9ed8dc2d036b0f4d640e22522213d047c1b14e61205a7e55c80a494d4", size = 4692429, upload-time = "2026-06-12T20:01:53.628Z" }, + { url = "https://files.pythonhosted.org/packages/2c/99/2d13299eb3dd27b02dcfaafcc91d6b5cb3329f7cbd6d8f51921acd566c1a/cryptography-49.0.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:35b151772baff2c74cba7fa290ceaff4c3b11c0c881eb93eb5dbc05a7cfbba18", size = 4700968, upload-time = "2026-06-12T20:02:45.383Z" }, + { url = "https://files.pythonhosted.org/packages/a5/4d/9c0cd02f95e2602dd5e563da149ee0830abef3537be8b34dc56281ebe27a/cryptography-49.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:0f21641cf4b30fca7aee061ced0ec7ad7b073518088b7c9969a297c0ae796c69", size = 4697758, upload-time = "2026-06-12T20:01:41.13Z" }, + { url = "https://files.pythonhosted.org/packages/24/01/186c825898477d77e2324d5360fefe622ff1d8d1963ec0554e2cada8ec77/cryptography-49.0.0-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:9e82dcc8e56052715fb18b2429e3bca4823b1629136a2084fc45a9a5cecb9b64", size = 5298863, upload-time = "2026-06-12T20:02:24.579Z" }, + { url = "https://files.pythonhosted.org/packages/b8/7b/62cbbab75d0659865bf0273790031544a0b16c8072d258f9428dcd8190dc/cryptography-49.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6f2debedf9ca60cf1d5bd466475638af5130f89965605cd818484d19987d3a21", size = 4735983, upload-time = "2026-06-12T20:01:50.14Z" }, + { url = "https://files.pythonhosted.org/packages/6c/72/3e798c064bc39e471008075d0f9bc9daf77a80879c092e4a8e170c585ed4/cryptography-49.0.0-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:8c25ceb16df5b9435f3f6a9829204985b0e0cbee3b48aacd432c7d2c850b44d9", size = 4334173, upload-time = "2026-06-12T20:01:44.743Z" }, + { url = "https://files.pythonhosted.org/packages/f0/ee/6fca21d1ac73e06f8bef71940abfd4d2f6472b4bca284d770f32bd4086f6/cryptography-49.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:28d8b15e6275f12c8a207dc309dfa957903c927d08d0cc937ee3f63f200693cc", size = 4697298, upload-time = "2026-06-12T20:02:20.918Z" }, + { url = "https://files.pythonhosted.org/packages/67/d0/a5fcd3515f0bae49a7b6d0413cc1bdccdcc1fc0047037a0d480642cdc5d6/cryptography-49.0.0-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:6fc361c34fb6aac015ce19435876635e5c6d21db31998b0920f675f131e043b8", size = 5254338, upload-time = "2026-06-12T20:02:22.737Z" }, + { url = "https://files.pythonhosted.org/packages/a0/84/84fe36f19caf857d61cb7fc9c63035a47ffabd84ea12d1d393148efa3615/cryptography-49.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:2400ef9c9e2299a25614eb1dea3db54a69b1349efd043bfac9c67630d136df36", size = 4735650, upload-time = "2026-06-12T20:02:41.389Z" }, + { url = "https://files.pythonhosted.org/packages/6c/a0/db537264e234f7273a73ec020873d6d6b39dfd8a53db78b550ca8320440e/cryptography-49.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:67e1d20ad9ef3a563c59ef22e7a8a0b8210bd26604369ea4a30a7c66aefe504e", size = 4834820, upload-time = "2026-06-12T20:01:51.847Z" }, + { url = "https://files.pythonhosted.org/packages/93/77/8df9eb486495979bccecd1062e2eaf435250e84437040295b57d09048b0b/cryptography-49.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:42b0684e0e40cf26122427802486f6d93aea593612603a94fbf260c7eb1e9c1b", size = 4967968, upload-time = "2026-06-12T20:02:12.524Z" }, + { url = "https://files.pythonhosted.org/packages/c2/e6/f60198ea8d9dfa15fff9ed4ca02ce362f6eadd9ba757dcc50634c4257b63/cryptography-49.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:026ac7423e6fa66872d3bf889be5974507da3944f866f704fa200eadacd00001", size = 3785547, upload-time = "2026-06-12T20:02:26.847Z" }, + { url = "https://files.pythonhosted.org/packages/63/d3/4a83af35d65e3fad632c926fad684c193ea4398569ccb0bbbc7fe8f5dc9a/cryptography-49.0.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:fc1e275c2f1d97b1a6450b8b0ea3ebfa6e087a611c2b26cb2404d48588abab7b", size = 3993685, upload-time = "2026-06-12T20:02:14.883Z" }, + { url = "https://files.pythonhosted.org/packages/d6/a7/f9dac0ab7f80368c56993a7bf638ef9935f825c91902798481fac0898138/cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c83782480a4a9da4d0feb51950131ba32e12e70813848b3343f6e18c28a66838", size = 4676239, upload-time = "2026-06-12T20:02:28.793Z" }, + { url = "https://files.pythonhosted.org/packages/d7/70/2ba3769dd0ae167e2f33dfa9592d45db6ff9a61d62ca1a5b3d1bdd09068f/cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b39efa323140595abd3ecca8529d321ae50f55f3aa3ba9cc81ea56a6011953d5", size = 4715584, upload-time = "2026-06-12T20:01:27.495Z" }, + { url = "https://files.pythonhosted.org/packages/94/64/2923570ac1c0bd3a737aa366ac3abbbbde273042308b8cde95e2364a6e6a/cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:b47db11c2c3525083296069b98ac5221907455e989ae0c2e3008bde851921615", size = 4675885, upload-time = "2026-06-12T20:01:55.49Z" }, + { url = "https://files.pythonhosted.org/packages/ab/f8/614dc7e051418cfe53d55173c1e24c6b0085e89996fe90508c2fdf769aef/cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:084ef1af862eb07ec46d25f68689f2102a9fc0e05ce7b80f14f5fe51e4eef0f6", size = 4715449, upload-time = "2026-06-12T20:02:05.469Z" }, + { url = "https://files.pythonhosted.org/packages/aa/50/a9caea39ad19c431c1a3f8a31114df65b260cdfe67786b6c7e7c040c4c44/cryptography-49.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:be9fcb48a55f023493482827d4f459bd263cc20efde64f204b97c123201850c6", size = 3783731, upload-time = "2026-06-12T20:02:43.319Z" }, ] [[package]] @@ -682,11 +779,11 @@ wheels = [ [[package]] name = "distlib" -version = "0.4.0" +version = "0.4.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d", size = 614605, upload-time = "2025-07-17T16:52:00.465Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/02/bd72be9134d25ed783ecbbc38a539ffaefbf90c78418c7fb7229600dbac7/distlib-0.4.3.tar.gz", hash = "sha256:f152097224a0ae24be5a0f6bae1b9359af82133bce63f98a95f86cae1aede9ed", size = 615141, upload-time = "2026-06-12T08:04:52.847Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047, upload-time = "2025-07-17T16:51:58.613Z" }, + { url = "https://files.pythonhosted.org/packages/02/08/9c41fb51ab5b43eb21674aff13df270e8ba6c4b29c8624e328dc7a9482af/distlib-0.4.3-py2.py3-none-any.whl", hash = "sha256:4b0ce306c966eb73bc3a7b6abad017c556dadd92c44701562cd528ac7fde4d5b", size = 470628, upload-time = "2026-06-12T08:04:50.506Z" }, ] [[package]] @@ -698,6 +795,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" }, ] +[[package]] +name = "dnspython" +version = "2.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/8b/57666417c0f90f08bcafa776861060426765fdb422eb10212086fb811d26/dnspython-2.8.0.tar.gz", hash = "sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f", size = 368251, upload-time = "2025-09-07T18:58:00.022Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af", size = 331094, upload-time = "2025-09-07T18:57:58.071Z" }, +] + [[package]] name = "docstring-parser" version = "0.18.0" @@ -707,13 +813,75 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a7/5f/ed01f9a3cdffbd5a008556fc7b2a08ddb1cc6ace7effa7340604b1d16699/docstring_parser-0.18.0-py3-none-any.whl", hash = "sha256:b3fcbed555c47d8479be0796ef7e19c2670d428d72e96da63f3a40122860374b", size = 22484, upload-time = "2026-04-14T04:09:18.638Z" }, ] +[[package]] +name = "email-validator" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "dnspython" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f5/22/900cb125c76b7aaa450ce02fd727f452243f2e91a61af068b40adba60ea9/email_validator-2.3.0.tar.gz", hash = "sha256:9fc05c37f2f6cf439ff414f8fc46d917929974a82244c20eb10231ba60c54426", size = 51238, upload-time = "2025-08-26T13:09:06.831Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/15/545e2b6cf2e3be84bc1ed85613edd75b8aea69807a71c26f4ca6a9258e82/email_validator-2.3.0-py3-none-any.whl", hash = "sha256:80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4", size = 35604, upload-time = "2025-08-26T13:09:05.858Z" }, +] + +[[package]] +name = "exceptiongroup" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, +] + +[[package]] +name = "executing" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/28/c14e053b6762b1044f34a13aab6859bbf40456d37d23aa286ac24cfd9a5d/executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4", size = 1129488, upload-time = "2025-09-01T09:48:10.866Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" }, +] + +[[package]] +name = "fastmcp-slim" +version = "3.4.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "platformdirs" }, + { name = "pydantic", extra = ["email"] }, + { name = "pydantic-settings" }, + { name = "python-dotenv" }, + { name = "rich" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/89/fa/500f6362016c34fba01c6412bbfd53435dc75900abd1266d88e111e2e9c2/fastmcp_slim-3.4.3.tar.gz", hash = "sha256:e3e12ac1e87c5195fa59a1c3cd2d31b487a463c269089fb4020b7571cbb57b29", size = 588086, upload-time = "2026-07-05T23:27:33.884Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4e/4f/66765dfe4fe65b45e134e54ca46118d93189fb10cd8ecb635cf504b68552/fastmcp_slim-3.4.3-py3-none-any.whl", hash = "sha256:21ad50465494edb141eed76b177dc788e00e705a5df09b53a31efebeb4432a95", size = 761455, upload-time = "2026-07-05T23:27:32.547Z" }, +] + +[package.optional-dependencies] +client = [ + { name = "authlib" }, + { name = "exceptiongroup" }, + { name = "httpx" }, + { name = "mcp" }, + { name = "opentelemetry-api" }, + { name = "py-key-value-aio", extra = ["filetree", "keyring", "memory"] }, + { name = "starlette" }, +] + [[package]] name = "filelock" -version = "3.29.0" +version = "3.29.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b5/fe/997687a931ab51049acce6fa1f23e8f01216374ea81374ddee763c493db5/filelock-3.29.0.tar.gz", hash = "sha256:69974355e960702e789734cb4871f884ea6fe50bd8404051a3530bc07809cf90", size = 57571, upload-time = "2026-04-19T15:39:10.068Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e0/c8/35bdf04fb30755e2ed758f877edf3eb4a243c2463d3a258cc28b18b7a6e2/filelock-3.29.6.tar.gz", hash = "sha256:895c532ef3f4ef04972b9446a8c4e2931a5c399ff3c4be4c9369f2639b80f793", size = 70301, upload-time = "2026-07-06T23:08:08.577Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl", hash = "sha256:96f5f6344709aa1572bbf631c640e4ebeeb519e08da902c39a001882f30ac258", size = 39812, upload-time = "2026-04-19T15:39:08.752Z" }, + { url = "https://files.pythonhosted.org/packages/bb/49/7467c2946ccd9617f7da38187071bdc45bb9a95df51f4d63d6622432ce4e/filelock-3.29.6-py3-none-any.whl", hash = "sha256:14d5f5597d2e0c4dbd774cfb6d8132da1db44da83732aab679d54f7dcf97ab65", size = 45478, upload-time = "2026-07-06T23:08:07.197Z" }, ] [[package]] @@ -752,15 +920,15 @@ wheels = [ [[package]] name = "google-auth" -version = "2.52.0" +version = "2.55.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, { name = "pyasn1-modules" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d4/f8/80d2493cbedece1c623dc3e3cb1883300871af0dcdae254409522985ac23/google_auth-2.52.0.tar.gz", hash = "sha256:01f30e1a9e3638698d89464f5e603ce29d18e1c0e63ec31ac570aba4e164aaf5", size = 335027, upload-time = "2026-05-07T19:45:24.033Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a3/6f/f3f4ac177c67bbee8fe8e88f2ab4f36af88c44a096e165c5217accf6e5d3/google_auth-2.55.1.tar.gz", hash = "sha256:fb2d9b730f2c9b8d326ec8d7222f21aef2ead15bf0513793d6442485d87af0a1", size = 349527, upload-time = "2026-06-25T23:39:27.182Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ee/fc/2cdc74252746f547f81ff3f02d4d4234a3f411b5de5b61af97e633a060b9/google_auth-2.52.0-py3-none-any.whl", hash = "sha256:aee92803ba0ff93a70a3b8a35c7b4797837751cd6380b63ff38372b98f3ed627", size = 245614, upload-time = "2026-05-07T19:45:21.914Z" }, + { url = "https://files.pythonhosted.org/packages/e8/1d/f6d3ca1ad0725f2e08a1c6915640748a52de2e66596160a4d53b010cccf0/google_auth-2.55.1-py3-none-any.whl", hash = "sha256:eada68dfd52b3b81191827601e2a0c3fa12540c818534b630ddc5355769c3995", size = 252349, upload-time = "2026-06-25T23:38:52.946Z" }, ] [package.optional-dependencies] @@ -770,7 +938,7 @@ requests = [ [[package]] name = "google-genai" -version = "1.75.0" +version = "2.10.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -784,18 +952,30 @@ dependencies = [ { name = "typing-extensions" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9d/59/3ed61240ef20b3ae6ed54e82c6f8b6d1f194947bc6679679dd6cdb037594/google_genai-1.75.0.tar.gz", hash = "sha256:56bac3991b311c93f980c0a2abcd287b672146905df1fbd71c92ed633d5a07cf", size = 539039, upload-time = "2026-05-04T22:48:54.857Z" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/fe/b796087493c3c55371aa58b9f264841ace5bfdf8c668cafa7afa33c44bec/google_genai-2.10.0.tar.gz", hash = "sha256:77912cd558cd7dfd5b75c25fd1c609e78d7954dde583331104022a46ea90f9ee", size = 600039, upload-time = "2026-06-24T01:33:18.157Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2d/b6/552d40e96da22921eb1fead7c14b00b5b5473a20e45959488660fab35ee2/google_genai-1.75.0-py3-none-any.whl", hash = "sha256:8dc4c096e7d6288c3087f6893f582fe52468932464781edb8193bd92b9fefb2c", size = 793726, upload-time = "2026-05-04T22:48:53.033Z" }, + { url = "https://files.pythonhosted.org/packages/e0/39/00bcfd94de255d24249401efff4f48d77bf6066b46447e519fa193c0c299/google_genai-2.10.0-py3-none-any.whl", hash = "sha256:d5350311567ae660c24cbc1752aee4b3d660f89c0106d2dcd2a69978c35afe1e", size = 957974, upload-time = "2026-06-24T01:33:16.296Z" }, +] + +[[package]] +name = "googleapis-common-protos" +version = "1.75.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b5/c8/f439cffde755cffa462bfbb156278fa6f9d09119719af9814b858fd4f81f/googleapis_common_protos-1.75.0.tar.gz", hash = "sha256:53a062ff3c32552fbd62c11fe23768b78e4ddf0494d5e5fd97d3f4689c75fbbd", size = 151035, upload-time = "2026-05-07T08:04:49.423Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/c8/e2645aa8ed02fd4c7a2f59d68783b65b1f3cbdfe39a6308e156509d1fee8/googleapis_common_protos-1.75.0-py3-none-any.whl", hash = "sha256:961ed60399c457ceb0ee8f285a84c870aabc9c6a832b9d37bb281b5bebde43ed", size = 300631, upload-time = "2026-05-07T08:03:30.345Z" }, ] [[package]] name = "griffelib" -version = "2.0.2" +version = "2.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9d/82/74f4a3310cdabfbb10da554c3a672847f1ed33c6f61dd472681ce7f1fe67/griffelib-2.0.2.tar.gz", hash = "sha256:3cf20b3bc470e83763ffbf236e0076b1211bac1bc67de13daf494640f2de707e", size = 166461, upload-time = "2026-03-27T11:34:51.091Z" } +sdist = { url = "https://files.pythonhosted.org/packages/33/e4/8d187ea29c2e30b3a09505c567513077d6117861bde1fbd997a167f262ec/griffelib-2.1.0.tar.gz", hash = "sha256:762a186d2c6fd6794d4ea20d428d597ffb857cb56b66421651cbba15bdd5e813", size = 216234, upload-time = "2026-06-19T12:05:42.278Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl", hash = "sha256:925c857658fb1ba40c0772c37acbc2ab650bd794d9c1b9726922e36ea4117ea1", size = 142357, upload-time = "2026-03-27T11:34:46.275Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d3/5268aeabf2ad82658c4e2ff3a060648d0f02f3926cb53247c0e4d0dab49e/griffelib-2.1.0-py3-none-any.whl", hash = "sha256:cc7b3d2d2865ad0b909fcc38086e3f554b5ea7acbaa7bbb7ecaa3f5dfb7d9f00", size = 142560, upload-time = "2026-06-19T12:05:38.742Z" }, ] [[package]] @@ -822,15 +1002,15 @@ wheels = [ [[package]] name = "httpcore2" -version = "2.3.0" +version = "2.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "h11" }, { name = "truststore" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e6/34/18f1c596e677962f040284246f393b10a1f8ce440b3a7e69c637d0f1c7ad/httpcore2-2.3.0.tar.gz", hash = "sha256:07327e251560960eea8e969d92d4c6a325feb13cca39e25340731336c3baf924", size = 64300, upload-time = "2026-06-01T13:15:02.998Z" } +sdist = { url = "https://files.pythonhosted.org/packages/47/06/5c12df521b5322fb1114a83d46911b2fbcb8855ddb3a635f11c01a214af5/httpcore2-2.5.0.tar.gz", hash = "sha256:88aa170137c17328d5ac44234f9fd10706466d5fb347f3edac4d39b91137b09d", size = 64808, upload-time = "2026-06-25T14:16:56.472Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c2/dd/3357218c69360d1cecc196c230c9a1d5c9afd5dba362056e23e60a5e64e5/httpcore2-2.3.0-py3-none-any.whl", hash = "sha256:477e9e334f74e5240dcac002e890580f36a57d40ff0fb14cc9655731d23b8415", size = 80024, upload-time = "2026-06-01T13:15:00.001Z" }, + { url = "https://files.pythonhosted.org/packages/c9/a1/7564199d1a8728fe737b0a72e5b3f8d92dfe085a74ddf7cdd83bce5f206d/httpcore2-2.5.0-py3-none-any.whl", hash = "sha256:5ce35188de461d31e8d000bfb8ef8bf22c6c16587a211e5571deaa5e9bdf842a", size = 80330, upload-time = "2026-06-25T14:16:53.634Z" }, ] [[package]] @@ -848,19 +1028,29 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, ] +[[package]] +name = "httpx-sse" +version = "0.4.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/4c/751061ffa58615a32c31b2d82e8482be8dd4a89154f003147acee90f2be9/httpx_sse-0.4.3.tar.gz", hash = "sha256:9b1ed0127459a66014aec3c56bebd93da3c1bc8bb6618c8082039a44889a755d", size = 15943, upload-time = "2025-10-10T21:48:22.271Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/fd/6668e5aec43ab844de6fc74927e155a3b37bf40d7c3790e49fc0406b6578/httpx_sse-0.4.3-py3-none-any.whl", hash = "sha256:0ac1c9fe3c0afad2e0ebb25a934a59f4c7823b60792691f779fad2c5568830fc", size = 8960, upload-time = "2025-10-10T21:48:21.158Z" }, +] + [[package]] name = "httpx2" -version = "2.3.0" +version = "2.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "httpcore2" }, { name = "idna" }, { name = "truststore" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9f/9a/cca0b9145f13d8ae34b885ae28d403a1469a433abc78e0f94f4ce94e650b/httpx2-2.3.0.tar.gz", hash = "sha256:227e7c41d95a76d4077a52640564132777215fc3394e07b66a3116c33d668fa9", size = 81115, upload-time = "2026-06-01T13:15:04.324Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/e2/b5dedc0cf35aa65de5f541ccd30d2bc1fd7f1d43c9ab09f8ed9a7342317b/httpx2-2.5.0.tar.gz", hash = "sha256:e2df9cb4611021527ff8a675b1c320b610a2ec397acc8d6fe6e91df2d9b33c29", size = 83121, upload-time = "2026-06-25T14:16:57.491Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/87/ce/ae2911859847f9ba1d6b23027e53481cbeb50b93234f355a968d300ca2cb/httpx2-2.3.0-py3-none-any.whl", hash = "sha256:6f393663bdf6dbe7fe90118e3eb5b2bd024a675cae0390ac08cec9198812d8b7", size = 74538, upload-time = "2026-06-01T13:15:01.566Z" }, + { url = "https://files.pythonhosted.org/packages/31/22/859d8252dad9bc9adee34b52e62cde621ece07b042ccb2ab4da1be46695f/httpx2-2.5.0-py3-none-any.whl", hash = "sha256:3d2d4d9cf4b61f1a1f46a95947cfdb47e80cb56a2f91c6256ac8f58e4891df41", size = 76652, upload-time = "2026-06-25T14:16:55.23Z" }, ] [[package]] @@ -874,23 +1064,23 @@ wheels = [ [[package]] name = "idna" -version = "3.13" +version = "3.18" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ce/cc/762dfb036166873f0059f3b7de4565e1b5bc3d6f28a414c13da27e442f99/idna-3.13.tar.gz", hash = "sha256:585ea8fe5d69b9181ec1afba340451fba6ba764af97026f92a91d4eef164a242", size = 194210, upload-time = "2026-04-22T16:42:42.314Z" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/63/9496c57188a2ee585e0f1db071d75089a11e98aa86eb99d9d7618fc1edce/idna-3.18.tar.gz", hash = "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848", size = 196711, upload-time = "2026-06-02T14:34:07.794Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5d/13/ad7d7ca3808a898b4612b6fe93cde56b53f3034dcde235acb1f0e1df24c6/idna-3.13-py3-none-any.whl", hash = "sha256:892ea0cde124a99ce773decba204c5552b69c3c67ffd5f232eb7696135bc8bb3", size = 68629, upload-time = "2026-04-22T16:42:40.909Z" }, + { url = "https://files.pythonhosted.org/packages/1e/5e/d4e9f1a599fb8e573b7b87160658329fbf28d19eac2718f51fc3def3aa5a/idna-3.18-py3-none-any.whl", hash = "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2", size = 65455, upload-time = "2026-06-02T14:34:06.319Z" }, ] [[package]] name = "importlib-metadata" -version = "8.7.1" +version = "9.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "zipp" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f3/49/3b30cad09e7771a4982d9975a8cbf64f00d4a1ececb53297f1d9a7be1b10/importlib_metadata-8.7.1.tar.gz", hash = "sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb", size = 57107, upload-time = "2025-12-21T10:00:19.278Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a9/01/15bb152d77b21318514a96f43af312635eb2500c96b55398d020c93d86ea/importlib_metadata-9.0.0.tar.gz", hash = "sha256:a4f57ab599e6a2e3016d7595cfd72eb4661a5106e787a95bcc90c7105b831efc", size = 56405, upload-time = "2026-03-20T06:42:56.999Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151", size = 27865, upload-time = "2025-12-21T10:00:18.329Z" }, + { url = "https://files.pythonhosted.org/packages/38/3d/2d244233ac4f76e38533cfcb2991c9eb4c7bf688ae0a036d30725b8faafe/importlib_metadata-9.0.0-py3-none-any.whl", hash = "sha256:2d21d1cc5a017bd0559e36150c21c830ab1dc304dedd1b7ea85d20f45ef3edd7", size = 27789, upload-time = "2026-03-20T06:42:55.665Z" }, ] [[package]] @@ -902,6 +1092,51 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, ] +[[package]] +name = "jaraco-classes" +version = "3.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "more-itertools" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/c0/ed4a27bc5571b99e3cff68f8a9fa5b56ff7df1c2251cc715a652ddd26402/jaraco.classes-3.4.0.tar.gz", hash = "sha256:47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd", size = 11780, upload-time = "2024-03-31T07:27:36.643Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/66/b15ce62552d84bbfcec9a4873ab79d993a1dd4edb922cbfccae192bd5b5f/jaraco.classes-3.4.0-py3-none-any.whl", hash = "sha256:f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790", size = 6777, upload-time = "2024-03-31T07:27:34.792Z" }, +] + +[[package]] +name = "jaraco-context" +version = "6.1.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "backports-tarfile", marker = "python_full_version < '3.12'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/af/50/4763cd07e722bb6285316d390a164bc7e479db9d90daa769f22578f698b4/jaraco_context-6.1.2.tar.gz", hash = "sha256:f1a6c9d391e661cc5b8d39861ff077a7dc24dc23833ccee564b234b81c82dfe3", size = 16801, upload-time = "2026-03-20T22:13:33.922Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f2/58/bc8954bda5fcda97bd7c19be11b85f91973d67a706ed4a3aec33e7de22db/jaraco_context-6.1.2-py3-none-any.whl", hash = "sha256:bf8150b79a2d5d91ae48629d8b427a8f7ba0e1097dd6202a9059f29a36379535", size = 7871, upload-time = "2026-03-20T22:13:32.808Z" }, +] + +[[package]] +name = "jaraco-functools" +version = "4.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "more-itertools" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/36/cf/ea4ef2920830dea3f5ab2ea4da6fb67724e6dca80ee2553788c3607243d0/jaraco_functools-4.5.0.tar.gz", hash = "sha256:3bb5665ea4a020cf78a7040e89154c77edadb3ca74f366479669c5999aa70b03", size = 20272, upload-time = "2026-05-15T21:34:10.025Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/9a/982e48afcffcd727a9144506720ffd4224b6b7e355c98641866f38b7c043/jaraco_functools-4.5.0-py3-none-any.whl", hash = "sha256:79ce39246eddbde4b3a03b77ea5f0f7878dc669b166a66cf3fa8e266aa3fa2f4", size = 10594, upload-time = "2026-05-15T21:34:08.595Z" }, +] + +[[package]] +name = "jeepney" +version = "0.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7b/6f/357efd7602486741aa73ffc0617fb310a29b588ed0fd69c2399acbb85b0c/jeepney-0.9.0.tar.gz", hash = "sha256:cf0e9e845622b81e4a28df94c40345400256ec608d0e55bb8a3feaa9163f5732", size = 106758, upload-time = "2025-02-27T18:51:01.684Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b2/a3/e137168c9c44d18eff0376253da9f1e9234d0239e0ee230d2fee6cea8e55/jeepney-0.9.0-py3-none-any.whl", hash = "sha256:97e5714520c16fc0a45695e5365a2e11b81ea79bba796e26f9f1d178cb182683", size = 49010, upload-time = "2025-02-27T18:51:00.104Z" }, +] + [[package]] name = "jinja2" version = "3.1.6" @@ -916,92 +1151,100 @@ wheels = [ [[package]] name = "jiter" -version = "0.14.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6e/c1/0cddc6eb17d4c53a99840953f95dd3accdc5cfc7a337b0e9b26476276be9/jiter-0.14.0.tar.gz", hash = "sha256:e8a39e66dac7153cf3f964a12aad515afa8d74938ec5cc0018adcdae5367c79e", size = 165725, upload-time = "2026-04-10T14:28:42.01Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8a/1f/198ae537fccb7080a0ed655eb56abf64a92f79489dfbf79f40fa34225bcd/jiter-0.14.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:7e791e247b8044512e070bd1f3633dc08350d32776d2d6e7473309d0edf256a2", size = 316896, upload-time = "2026-04-10T14:26:01.986Z" }, - { url = "https://files.pythonhosted.org/packages/cf/34/da67cff3fce964a36d03c3e365fb0f8726ade2a6cfd4d3c70107e216ead6/jiter-0.14.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:71527ce13fd5a0c4e40ad37331f8c547177dbb2dd0a93e5278b6a5eecf748804", size = 321085, upload-time = "2026-04-10T14:26:03.364Z" }, - { url = "https://files.pythonhosted.org/packages/ed/36/4c72e67180d4e71a4f5dcf7886d0840e83c49ab11788172177a77570326e/jiter-0.14.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02c4a7ab56f746014874f2c525584c0daca1dec37f66fd707ecef3b7e5c2228c", size = 347393, upload-time = "2026-04-10T14:26:05.314Z" }, - { url = "https://files.pythonhosted.org/packages/bc/db/9b39e09ceafa9878235c0fc29e3e3f9b12a4c6a98ea3085b998cadf3accc/jiter-0.14.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:376e9dafff914253bb9d46cdc5f7965607fbe7feb0a491c34e35f92b2770702e", size = 372937, upload-time = "2026-04-10T14:26:06.884Z" }, - { url = "https://files.pythonhosted.org/packages/b0/96/0dcba1d7a82c1b720774b48ef239376addbaf30df24c34742ac4a57b67b2/jiter-0.14.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:23ad2a7a9da1935575c820428dd8d2490ce4d23189691ce33da1fc0a58e14e1c", size = 463646, upload-time = "2026-04-10T14:26:08.345Z" }, - { url = "https://files.pythonhosted.org/packages/f1/e3/f61b71543e746e6b8b805e7755814fc242715c16f1dba58e1cbccb8032c2/jiter-0.14.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:54b3ddf5786bc7732d293bba3411ac637ecfa200a39983166d1df86a59a43c9f", size = 380225, upload-time = "2026-04-10T14:26:10.161Z" }, - { url = "https://files.pythonhosted.org/packages/ad/5e/0ddeb7096aca099114abe36c4921016e8d251e6f35f5890240b31f1f60ae/jiter-0.14.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c001d5a646c2a50dc055dd526dad5d5245969e8234d2b1131d0451e81f3a373", size = 358682, upload-time = "2026-04-10T14:26:11.574Z" }, - { url = "https://files.pythonhosted.org/packages/e9/d1/fe0c46cd7fda9cad8f1ff9ad217dc61f1e4280b21052ec6dfe88c1446ef2/jiter-0.14.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:834bb5bdabca2e91592a03d373838a8d0a1b8bbde7077ae6913fd2fc51812d00", size = 359973, upload-time = "2026-04-10T14:26:13.316Z" }, - { url = "https://files.pythonhosted.org/packages/ac/21/f5317f91729b501019184771c80d60abd89907009e7bfa6c7e348c5bdd44/jiter-0.14.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4e9178be60e229b1b2b0710f61b9e24d1f4f8556985a83ff4c4f95920eea7314", size = 397568, upload-time = "2026-04-10T14:26:15.212Z" }, - { url = "https://files.pythonhosted.org/packages/e9/05/79d8f33fb2bf168db0df5c9cd16fe440a8ada57e929d3677b22712c2568f/jiter-0.14.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a7e4ccff04ec03614e62c613e976a3a5860dc9714ce8266f44328bdc8b1cab2c", size = 522535, upload-time = "2026-04-10T14:26:16.956Z" }, - { url = "https://files.pythonhosted.org/packages/5c/00/d1e3ff3d2a465e67f08507d74bafb2dcd29eba91dc939820e39e8dea38b8/jiter-0.14.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:69539d936fb5d55caf6ecd33e2e884de083ff0ea28579780d56c4403094bb8d9", size = 556709, upload-time = "2026-04-10T14:26:18.5Z" }, - { url = "https://files.pythonhosted.org/packages/60/5b/bbb2189f62ace8d95e869aa4c84c9946616f301e2d02895a6f20dcc3bba3/jiter-0.14.0-cp311-cp311-win32.whl", hash = "sha256:4927d09b3e572787cc5e0a5318601448e1ab9391bcef95677f5840c2d00eaa6d", size = 208660, upload-time = "2026-04-10T14:26:20.511Z" }, - { url = "https://files.pythonhosted.org/packages/b8/86/c500b53dcbf08575f5963e536ebd757a1f7c568272ba5d180b212c9a87fb/jiter-0.14.0-cp311-cp311-win_amd64.whl", hash = "sha256:42d6ed359ac49eb922fdd565f209c57340aa06d589c84c8413e42a0f9ae1b842", size = 204659, upload-time = "2026-04-10T14:26:22.152Z" }, - { url = "https://files.pythonhosted.org/packages/75/4a/a676249049d42cb29bef82233e4fe0524d414cbe3606c7a4b311193c2f77/jiter-0.14.0-cp311-cp311-win_arm64.whl", hash = "sha256:6dd689f5f4a5a33747b28686e051095beb214fe28cfda5e9fe58a295a788f593", size = 194772, upload-time = "2026-04-10T14:26:23.458Z" }, - { url = "https://files.pythonhosted.org/packages/5a/68/7390a418f10897da93b158f2d5a8bd0bcd73a0f9ec3bb36917085bb759ef/jiter-0.14.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:2fb2ce3a7bc331256dfb14cefc34832366bb28a9aca81deaf43bbf2a5659e607", size = 316295, upload-time = "2026-04-10T14:26:24.887Z" }, - { url = "https://files.pythonhosted.org/packages/60/a0/5854ac00ff63551c52c6c89534ec6aba4b93474e7924d64e860b1c94165b/jiter-0.14.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5252a7ca23785cef5d02d4ece6077a1b556a410c591b379f82091c3001e14844", size = 315898, upload-time = "2026-04-10T14:26:26.601Z" }, - { url = "https://files.pythonhosted.org/packages/41/a1/4f44832650a16b18e8391f1bf1d6ca4909bc738351826bcc198bba4357f4/jiter-0.14.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c409578cbd77c338975670ada777add4efd53379667edf0aceea730cabede6fb", size = 343730, upload-time = "2026-04-10T14:26:28.326Z" }, - { url = "https://files.pythonhosted.org/packages/48/64/a329e9d469f86307203594b1707e11ae51c3348d03bfd514a5f997870012/jiter-0.14.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7ede4331a1899d604463369c730dbb961ffdc5312bc7f16c41c2896415b1304a", size = 370102, upload-time = "2026-04-10T14:26:30.089Z" }, - { url = "https://files.pythonhosted.org/packages/94/c1/5e3dfc59635aa4d4c7bd20a820ac1d09b8ed851568356802cf1c08edb3cf/jiter-0.14.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:92cd8b6025981a041f5310430310b55b25ca593972c16407af8837d3d7d2ca01", size = 461335, upload-time = "2026-04-10T14:26:31.911Z" }, - { url = "https://files.pythonhosted.org/packages/e3/1b/dd157009dbc058f7b00108f545ccb72a2d56461395c4fc7b9cfdccb00af4/jiter-0.14.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:351bf6eda4e3a7ceb876377840c702e9a3e4ecc4624dbfb2d6463c67ae52637d", size = 378536, upload-time = "2026-04-10T14:26:33.595Z" }, - { url = "https://files.pythonhosted.org/packages/91/78/256013667b7c10b8834f8e6e54cd3e562d4c6e34227a1596addccc05e38c/jiter-0.14.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1dcfbeb93d9ecd9ca128bbf8910120367777973fa193fb9a39c31237d8df165", size = 353859, upload-time = "2026-04-10T14:26:35.098Z" }, - { url = "https://files.pythonhosted.org/packages/de/d9/137d65ade9093a409fe80955ce60b12bb753722c986467aeda47faf450ad/jiter-0.14.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:ae039aaef8de3f8157ecc1fdd4d85043ac4f57538c245a0afaecb8321ec951c3", size = 357626, upload-time = "2026-04-10T14:26:36.685Z" }, - { url = "https://files.pythonhosted.org/packages/2e/48/76750835b87029342727c1a268bea8878ab988caf81ee4e7b880900eeb5a/jiter-0.14.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7d9d51eb96c82a9652933bd769fe6de66877d6eb2b2440e281f2938c51b5643e", size = 393172, upload-time = "2026-04-10T14:26:38.097Z" }, - { url = "https://files.pythonhosted.org/packages/a6/60/456c4e81d5c8045279aefe60e9e483be08793828800a4e64add8fdde7f2a/jiter-0.14.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d824ca4148b705970bf4e120924a212fdfca9859a73e42bd7889a63a4ea6bb98", size = 520300, upload-time = "2026-04-10T14:26:39.532Z" }, - { url = "https://files.pythonhosted.org/packages/a8/9f/2020e0984c235f678dced38fe4eec3058cf528e6af36ebf969b410305941/jiter-0.14.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ff3a6465b3a0f54b1a430f45c3c0ba7d61ceb45cbc3e33f9e1a7f638d690baf3", size = 553059, upload-time = "2026-04-10T14:26:40.991Z" }, - { url = "https://files.pythonhosted.org/packages/ef/32/e2d298e1a22a4bbe6062136d1c7192db7dba003a6975e51d9a9eecabc4c2/jiter-0.14.0-cp312-cp312-win32.whl", hash = "sha256:5dec7c0a3e98d2a3f8a2e67382d0d7c3ac60c69103a4b271da889b4e8bb1e129", size = 206030, upload-time = "2026-04-10T14:26:42.517Z" }, - { url = "https://files.pythonhosted.org/packages/36/ac/96369141b3d8a4a8e4590e983085efe1c436f35c0cda940dd76d942e3e40/jiter-0.14.0-cp312-cp312-win_amd64.whl", hash = "sha256:fc7e37b4b8bc7e80a63ad6cfa5fc11fab27dbfea4cc4ae644b1ab3f273dc348f", size = 201603, upload-time = "2026-04-10T14:26:44.328Z" }, - { url = "https://files.pythonhosted.org/packages/01/c3/75d847f264647017d7e3052bbcc8b1e24b95fa139c320c5f5066fa7a0bdd/jiter-0.14.0-cp312-cp312-win_arm64.whl", hash = "sha256:ee4a72f12847ef29b072aee9ad5474041ab2924106bdca9fcf5d7d965853e057", size = 191525, upload-time = "2026-04-10T14:26:46Z" }, - { url = "https://files.pythonhosted.org/packages/97/2a/09f70020898507a89279659a1afe3364d57fc1b2c89949081975d135f6f5/jiter-0.14.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:af72f204cf4d44258e5b4c1745130ac45ddab0e71a06333b01de660ab4187a94", size = 315502, upload-time = "2026-04-10T14:26:47.697Z" }, - { url = "https://files.pythonhosted.org/packages/d6/be/080c96a45cd74f9fce5db4fd68510b88087fb37ffe2541ff73c12db92535/jiter-0.14.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4b77da71f6e819be5fbcec11a453fde5b1d0267ef6ed487e2a392fd8e14e4e3a", size = 314870, upload-time = "2026-04-10T14:26:49.149Z" }, - { url = "https://files.pythonhosted.org/packages/7d/5e/2d0fee155826a968a832cc32438de5e2a193292c8721ca70d0b53e58245b/jiter-0.14.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f4ea612fe8b84b8b04e51d0e78029ecf3466348e25973f953de6e6a59aa4c1", size = 343406, upload-time = "2026-04-10T14:26:50.762Z" }, - { url = "https://files.pythonhosted.org/packages/70/af/bf9ee0d3a4f8dc0d679fc1337f874fe60cdbf841ebbb304b374e1c9aaceb/jiter-0.14.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:62fe2451f8fcc0240261e6a4df18ecbcd58327857e61e625b2393ea3b468aac9", size = 369415, upload-time = "2026-04-10T14:26:52.188Z" }, - { url = "https://files.pythonhosted.org/packages/0f/83/8e8561eadba31f4d3948a5b712fb0447ec71c3560b57a855449e7b8ddc98/jiter-0.14.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6112f26f5afc75bcb475787d29da3aa92f9d09c7858f632f4be6ffe607be82e9", size = 461456, upload-time = "2026-04-10T14:26:53.611Z" }, - { url = "https://files.pythonhosted.org/packages/f6/c9/c5299e826a5fe6108d172b344033f61c69b1bb979dd8d9ddd4278a160971/jiter-0.14.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:215a6cb8fb7dc702aa35d475cc00ddc7f970e5c0b1417fb4b4ac5d82fa2a29db", size = 378488, upload-time = "2026-04-10T14:26:55.211Z" }, - { url = "https://files.pythonhosted.org/packages/5d/37/c16d9d15c0a471b8644b1abe3c82668092a707d9bedcf076f24ff2e380cd/jiter-0.14.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4ab96a30fb3cb2c7e0cd33f7616c8860da5f5674438988a54ac717caccdbaa", size = 353242, upload-time = "2026-04-10T14:26:56.705Z" }, - { url = "https://files.pythonhosted.org/packages/58/ea/8050cb0dc654e728e1bfacbc0c640772f2181af5dedd13ae70145743a439/jiter-0.14.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:3a99c1387b1f2928f799a9de899193484d66206a50e98233b6b088a7f0c1edb2", size = 356823, upload-time = "2026-04-10T14:26:58.281Z" }, - { url = "https://files.pythonhosted.org/packages/b0/3b/cf71506d270e5f84d97326bf220e47aed9b95e9a4a060758fb07772170ab/jiter-0.14.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ab18d11074485438695f8d34a1b6da61db9754248f96d51341956607a8f39985", size = 392564, upload-time = "2026-04-10T14:27:00.018Z" }, - { url = "https://files.pythonhosted.org/packages/b0/cc/8c6c74a3efb5bd671bfd14f51e8a73375464ca914b1551bc3b40e26ac2c9/jiter-0.14.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:801028dcfc26ac0895e4964cbc0fd62c73be9fd4a7d7b1aaf6e5790033a719b7", size = 520322, upload-time = "2026-04-10T14:27:01.664Z" }, - { url = "https://files.pythonhosted.org/packages/41/24/68d7b883ec959884ddf00d019b2e0e82ba81b167e1253684fa90519ce33c/jiter-0.14.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ad425b087aafb4a1c7e1e98a279200743b9aaf30c3e0ba723aec93f061bd9bc8", size = 552619, upload-time = "2026-04-10T14:27:03.316Z" }, - { url = "https://files.pythonhosted.org/packages/b6/89/b1a0985223bbf3150ff9e8f46f98fc9360c1de94f48abe271bbe1b465682/jiter-0.14.0-cp313-cp313-win32.whl", hash = "sha256:882bcb9b334318e233950b8be366fe5f92c86b66a7e449e76975dfd6d776a01f", size = 205699, upload-time = "2026-04-10T14:27:04.662Z" }, - { url = "https://files.pythonhosted.org/packages/4c/19/3f339a5a7f14a11730e67f6be34f9d5105751d547b615ef593fa122a5ded/jiter-0.14.0-cp313-cp313-win_amd64.whl", hash = "sha256:9b8c571a5dba09b98bd3462b5a53f27209a5cbbe85670391692ede71974e979f", size = 201323, upload-time = "2026-04-10T14:27:06.139Z" }, - { url = "https://files.pythonhosted.org/packages/50/56/752dd89c84be0e022a8ea3720bcfa0a8431db79a962578544812ce061739/jiter-0.14.0-cp313-cp313-win_arm64.whl", hash = "sha256:34f19dcc35cb1abe7c369b3756babf8c7f04595c0807a848df8f26ef8298ef92", size = 191099, upload-time = "2026-04-10T14:27:07.564Z" }, - { url = "https://files.pythonhosted.org/packages/91/28/292916f354f25a1fe8cf2c918d1415c699a4a659ae00be0430e1c5d9ffea/jiter-0.14.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e89bcd7d426a75bb4952c696b267075790d854a07aad4c9894551a82c5b574ab", size = 320880, upload-time = "2026-04-10T14:27:09.326Z" }, - { url = "https://files.pythonhosted.org/packages/ad/c7/b002a7d8b8957ac3d469bd59c18ef4b1595a5216ae0de639a287b9816023/jiter-0.14.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b25beaa0d4447ea8c7ae0c18c688905d34840d7d0b937f2f7bdd52162c98a40", size = 346563, upload-time = "2026-04-10T14:27:11.287Z" }, - { url = "https://files.pythonhosted.org/packages/f9/3b/f8d07580d8706021d255a6356b8fab13ee4c869412995550ce6ed4ddf97d/jiter-0.14.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:651a8758dd413c51e3b7f6557cdc6921faf70b14106f45f969f091f5cda990ea", size = 357928, upload-time = "2026-04-10T14:27:12.729Z" }, - { url = "https://files.pythonhosted.org/packages/47/5b/ac1a974da29e35507230383110ffec59998b290a8732585d04e19a9eb5ba/jiter-0.14.0-cp313-cp313t-win_amd64.whl", hash = "sha256:e1a7eead856a5038a8d291f1447176ab0b525c77a279a058121b5fccee257f6f", size = 203519, upload-time = "2026-04-10T14:27:14.125Z" }, - { url = "https://files.pythonhosted.org/packages/96/6d/9fc8433d667d2454271378a79747d8c76c10b51b482b454e6190e511f244/jiter-0.14.0-cp313-cp313t-win_arm64.whl", hash = "sha256:2e692633a12cda97e352fdcd1c4acc971b1c28707e1e33aeef782b0cbf051975", size = 190113, upload-time = "2026-04-10T14:27:16.638Z" }, - { url = "https://files.pythonhosted.org/packages/4f/1e/354ed92461b165bd581f9ef5150971a572c873ec3b68a916d5aa91da3cc2/jiter-0.14.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:6f396837fc7577871ca8c12edaf239ed9ccef3bbe39904ae9b8b63ce0a48b140", size = 315277, upload-time = "2026-04-10T14:27:18.109Z" }, - { url = "https://files.pythonhosted.org/packages/a6/95/8c7c7028aa8636ac21b7a55faef3e34215e6ed0cbf5ae58258427f621aa3/jiter-0.14.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a4d50ea3d8ba4176f79754333bd35f1bbcd28e91adc13eb9b7ca91bc52a6cef9", size = 315923, upload-time = "2026-04-10T14:27:19.603Z" }, - { url = "https://files.pythonhosted.org/packages/47/40/e2a852a44c4a089f2681a16611b7ce113224a80fd8504c46d78491b47220/jiter-0.14.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce17f8a050447d1b4153bda4fb7d26e6a9e74eb4f4a41913f30934c5075bf615", size = 344943, upload-time = "2026-04-10T14:27:21.262Z" }, - { url = "https://files.pythonhosted.org/packages/fc/1f/670f92adee1e9895eac41e8a4d623b6da68c4d46249d8b556b60b63f949e/jiter-0.14.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f4f1c4b125e1652aefbc2e2c1617b60a160ab789d180e3d423c41439e5f32850", size = 369725, upload-time = "2026-04-10T14:27:22.766Z" }, - { url = "https://files.pythonhosted.org/packages/01/2f/541c9ba567d05de1c4874a0f8f8c5e3fd78e2b874266623da9a775cf46e0/jiter-0.14.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be808176a6a3a14321d18c603f2d40741858a7c4fc982f83232842689fe86dd9", size = 461210, upload-time = "2026-04-10T14:27:24.315Z" }, - { url = "https://files.pythonhosted.org/packages/ce/a9/c31cbec09627e0d5de7aeaec7690dba03e090caa808fefd8133137cf45bc/jiter-0.14.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:26679d58ba816f88c3849306dd58cb863a90a1cf352cdd4ef67e30ccf8a77994", size = 380002, upload-time = "2026-04-10T14:27:26.155Z" }, - { url = "https://files.pythonhosted.org/packages/50/02/3c05c1666c41904a2f607475a73e7a4763d1cbde2d18229c4f85b22dc253/jiter-0.14.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80381f5a19af8fa9aef743f080e34f6b25ebd89656475f8cf0470ec6157052aa", size = 354678, upload-time = "2026-04-10T14:27:27.701Z" }, - { url = "https://files.pythonhosted.org/packages/7d/97/e15b33545c2b13518f560d695f974b9891b311641bdcf178d63177e8801e/jiter-0.14.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:004df5fdb8ecbd6d99f3227df18ba1a259254c4359736a2e6f036c944e02d7c5", size = 358920, upload-time = "2026-04-10T14:27:29.256Z" }, - { url = "https://files.pythonhosted.org/packages/ad/d2/8b1461def6b96ba44530df20d07ef7a1c7da22f3f9bf1727e2d611077bf1/jiter-0.14.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cff5708f7ed0fa098f2b53446c6fa74c48469118e5cd7497b4f1cd569ab06928", size = 394512, upload-time = "2026-04-10T14:27:31.344Z" }, - { url = "https://files.pythonhosted.org/packages/e3/88/837566dd6ed6e452e8d3205355afd484ce44b2533edfa4ed73a298ea893e/jiter-0.14.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:2492e5f06c36a976d25c7cc347a60e26d5470178d44cde1b9b75e60b4e519f28", size = 521120, upload-time = "2026-04-10T14:27:33.299Z" }, - { url = "https://files.pythonhosted.org/packages/89/6b/b00b45c4d1b4c031777fe161d620b755b5b02cdade1e316dcb46e4471d63/jiter-0.14.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:7609cfbe3a03d37bfdbf5052012d5a879e72b83168a363deae7b3a26564d57de", size = 553668, upload-time = "2026-04-10T14:27:34.868Z" }, - { url = "https://files.pythonhosted.org/packages/ad/d8/6fe5b42011d19397433d345716eac16728ac241862a2aac9c91923c7509a/jiter-0.14.0-cp314-cp314-win32.whl", hash = "sha256:7282342d32e357543565286b6450378c3cd402eea333fc1ebe146f1fabb306fc", size = 207001, upload-time = "2026-04-10T14:27:36.455Z" }, - { url = "https://files.pythonhosted.org/packages/e5/43/5c2e08da1efad5e410f0eaaabeadd954812612c33fbbd8fd5328b489139d/jiter-0.14.0-cp314-cp314-win_amd64.whl", hash = "sha256:bd77945f38866a448e73b0b7637366afa814d4617790ecd88a18ca74377e6c02", size = 202187, upload-time = "2026-04-10T14:27:38Z" }, - { url = "https://files.pythonhosted.org/packages/aa/1f/6e39ac0b4cdfa23e606af5b245df5f9adaa76f35e0c5096790da430ca506/jiter-0.14.0-cp314-cp314-win_arm64.whl", hash = "sha256:f2d4c61da0821ee42e0cdf5489da60a6d074306313a377c2b35af464955a3611", size = 192257, upload-time = "2026-04-10T14:27:39.504Z" }, - { url = "https://files.pythonhosted.org/packages/05/57/7dbc0ffbbb5176a27e3518716608aa464aee2e2887dc938f0b900a120449/jiter-0.14.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1bf7ff85517dd2f20a5750081d2b75083c1b269cf75afc7511bdf1f9548beb3b", size = 323441, upload-time = "2026-04-10T14:27:41.039Z" }, - { url = "https://files.pythonhosted.org/packages/83/6e/7b3314398d8983f06b557aa21b670511ec72d3b79a68ee5e4d9bff972286/jiter-0.14.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8ef8791c3e78d6c6b157c6d360fbb5c715bebb8113bc6a9303c5caff012754a", size = 348109, upload-time = "2026-04-10T14:27:42.552Z" }, - { url = "https://files.pythonhosted.org/packages/ae/4f/8dc674bcd7db6dba566de73c08c763c337058baff1dbeb34567045b27cdc/jiter-0.14.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e74663b8b10da1fe0f4e4703fd7980d24ad17174b6bb35d8498d6e3ebce2ae6a", size = 368328, upload-time = "2026-04-10T14:27:44.574Z" }, - { url = "https://files.pythonhosted.org/packages/3b/5f/188e09a1f20906f98bbdec44ed820e19f4e8eb8aff88b9d1a5a497587ff3/jiter-0.14.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1aca29ba52913f78362ec9c2da62f22cdc4c3083313403f90c15460979b84d9b", size = 463301, upload-time = "2026-04-10T14:27:46.717Z" }, - { url = "https://files.pythonhosted.org/packages/ac/f0/19046ef965ed8f349e8554775bb12ff4352f443fbe12b95d31f575891256/jiter-0.14.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8b39b7d87a952b79949af5fef44d2544e58c21a28da7f1bae3ef166455c61746", size = 378891, upload-time = "2026-04-10T14:27:48.32Z" }, - { url = "https://files.pythonhosted.org/packages/c4/c3/da43bd8431ee175695777ee78cf0e93eacbb47393ff493f18c45231b427d/jiter-0.14.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78d918a68b26e9fab068c2b5453577ef04943ab2807b9a6275df2a812599a310", size = 360749, upload-time = "2026-04-10T14:27:49.88Z" }, - { url = "https://files.pythonhosted.org/packages/72/26/e054771be889707c6161dbdec9c23d33a9ec70945395d70f07cfea1e9a6f/jiter-0.14.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:b08997c35aee1201c1a5361466a8fb9162d03ae7bf6568df70b6c859f1e654a4", size = 358526, upload-time = "2026-04-10T14:27:51.504Z" }, - { url = "https://files.pythonhosted.org/packages/c3/0f/7bea65ea2a6d91f2bf989ff11a18136644392bf2b0497a1fa50934c30a9c/jiter-0.14.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:260bf7ca20704d58d41f669e5e9fe7fe2fa72901a6b324e79056f5d52e9c9be2", size = 393926, upload-time = "2026-04-10T14:27:53.368Z" }, - { url = "https://files.pythonhosted.org/packages/3c/a1/b1ff7d70deef61ac0b7c6c2f12d2ace950cdeecb4fdc94500a0926802857/jiter-0.14.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:37826e3df29e60f30a382f9294348d0238ef127f4b5d7f5f8da78b5b9e050560", size = 521052, upload-time = "2026-04-10T14:27:55.058Z" }, - { url = "https://files.pythonhosted.org/packages/0b/7b/3b0649983cbaf15eda26a414b5b1982e910c67bd6f7b1b490f3cfc76896a/jiter-0.14.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:645be49c46f2900937ba0eaf871ad5183c96858c0af74b6becc7f4e367e36e06", size = 553716, upload-time = "2026-04-10T14:27:57.269Z" }, - { url = "https://files.pythonhosted.org/packages/97/f8/33d78c83bd93ae0c0af05293a6660f88a1977caef39a6d72a84afab94ce0/jiter-0.14.0-cp314-cp314t-win32.whl", hash = "sha256:2f7877ed45118de283786178eceaf877110abacd04fde31efff3940ae9672674", size = 207957, upload-time = "2026-04-10T14:27:59.285Z" }, - { url = "https://files.pythonhosted.org/packages/d6/ac/2b760516c03e2227826d1f7025d89bf6bf6357a28fe75c2a2800873c50bf/jiter-0.14.0-cp314-cp314t-win_amd64.whl", hash = "sha256:14c0cb10337c49f5eafe8e7364daca5e29a020ea03580b8f8e6c597fed4e1588", size = 204690, upload-time = "2026-04-10T14:28:00.962Z" }, - { url = "https://files.pythonhosted.org/packages/dc/2e/a44c20c58aeed0355f2d326969a181696aeb551a25195f47563908a815be/jiter-0.14.0-cp314-cp314t-win_arm64.whl", hash = "sha256:5419d4aa2024961da9fe12a9cfe7484996735dca99e8e090b5c88595ef1951ff", size = 191338, upload-time = "2026-04-10T14:28:02.853Z" }, - { url = "https://files.pythonhosted.org/packages/32/a1/ef34ca2cab2962598591636a1804b93645821201cc0095d4a93a9a329c9d/jiter-0.14.0-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:a25ffa2dbbdf8721855612f6dca15c108224b12d0c4024d0ac3d7902132b4211", size = 311366, upload-time = "2026-04-10T14:28:27.943Z" }, - { url = "https://files.pythonhosted.org/packages/60/bb/520576a532a6b8a6f42747afed289c8448c879a34d7802fe2c832d4fd38f/jiter-0.14.0-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:0ac9cbaa86c10996b92bd12c91659b60f939f8e28fcfa6bc11a0e90a774ce95b", size = 309873, upload-time = "2026-04-10T14:28:29.688Z" }, - { url = "https://files.pythonhosted.org/packages/b2/7c/c16db114ea1f2f532f198aa8dc39585026af45af362c69a0492f31bc4821/jiter-0.14.0-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:844e73b6c56b505e9e169234ea3bdea2ea43f769f847f47ac559ba1d2361ebea", size = 344816, upload-time = "2026-04-10T14:28:31.348Z" }, - { url = "https://files.pythonhosted.org/packages/99/8f/15e7741ff19e9bcd4d753f7ff22f988fd54592f134ca13701c13ea8c20e0/jiter-0.14.0-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e52c076f187405fc21523c746c04399c9af8ece566077ed147b2126f2bcba577", size = 351445, upload-time = "2026-04-10T14:28:33.093Z" }, - { url = "https://files.pythonhosted.org/packages/21/42/9042c3f3019de4adcb8c16591c325ec7255beea9fcd33a42a43f3b0b1000/jiter-0.14.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:fbd9e482663ca9d005d051330e4d2d8150bb208a209409c10f7e7dfdf7c49da9", size = 308810, upload-time = "2026-04-10T14:28:34.673Z" }, - { url = "https://files.pythonhosted.org/packages/60/cf/a7e19b308bd86bb04776803b1f01a5f9a287a4c55205f4708827ee487fbf/jiter-0.14.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:33a20d838b91ef376b3a56896d5b04e725c7df5bc4864cc6569cf046a8d73b6d", size = 308443, upload-time = "2026-04-10T14:28:36.658Z" }, - { url = "https://files.pythonhosted.org/packages/ca/44/e26ede3f0caeff93f222559cb0cc4ca68579f07d009d7b6010c5b586f9b1/jiter-0.14.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:432c4db5255d86a259efde91e55cb4c8d18c0521d844c9e2e7efcce3899fb016", size = 343039, upload-time = "2026-04-10T14:28:38.356Z" }, - { url = "https://files.pythonhosted.org/packages/da/e9/1f9ada30cef7b05e74bb06f52127e7a724976c225f46adb65c37b1dadfb6/jiter-0.14.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67f00d94b281174144d6532a04b66a12cb866cbdc47c3af3bfe2973677f9861a", size = 349613, upload-time = "2026-04-10T14:28:40.066Z" }, +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1d/1f/10936e16d8860c70698a1aa939a46aa0224813b782bce4e000e637da0b2d/jiter-0.16.0.tar.gz", hash = "sha256:7b24c3492c5f4f84a37946ad9cf504910cf6a782d6a4e0689b6673c5894b4a1c", size = 176431, upload-time = "2026-06-29T13:05:13.657Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4e/3f/fae6cc967d120ec89e31c5418a51176d8278b3087fbb384a9176754f353c/jiter-0.16.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:67fddeda1688f0cce2d2ae83ccf8a80f79936f2d2997d6cc2261f82fdb54a4d3", size = 309289, upload-time = "2026-06-29T13:02:52.301Z" }, + { url = "https://files.pythonhosted.org/packages/c8/e3/97c6c3562c077f6247d6e6ce5c82562500b6316c0d928e97e106b7a1321a/jiter-0.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c90c0f63df322be920eda6ce622e3083d8906ba267f8220fe7873213b8b4430e", size = 315181, upload-time = "2026-06-29T13:02:53.964Z" }, + { url = "https://files.pythonhosted.org/packages/7b/89/d8d073f8aa2667e46c6c0873f86fe4a512bba4293cc730f626a076211a62/jiter-0.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64c0203212098470032aabcde9356fc168f377aade3e43def61dfe17e92f2037", size = 340939, upload-time = "2026-06-29T13:02:55.412Z" }, + { url = "https://files.pythonhosted.org/packages/87/c9/db4fda3ed73fb864139305e935e5b8b38a5a24692a5a9dd356c22f1b9c8d/jiter-0.16.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:12288303c9844e61e1651d02a9a6f6633e47d39f897d6991d1427161ce6b746e", size = 364932, upload-time = "2026-06-29T13:02:57.28Z" }, + { url = "https://files.pythonhosted.org/packages/a2/74/52b5e86241057f52ddd7c9a580f90effb51f9d06239f6fc612279b91a838/jiter-0.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cf109d010b4b05a105afb3d43be36a21322d345ad3111e13d15f680afef0e5b", size = 461132, upload-time = "2026-06-29T13:02:58.994Z" }, + { url = "https://files.pythonhosted.org/packages/a9/87/544a700f7447c1f31c5d7833821a4daa5683165c2d5a094fbf5b5800c3dc/jiter-0.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:62c1b7fe1f77925acf5af68b6140b8810fa87dfd4dc0a9c8568ec2fa2a10429c", size = 374857, upload-time = "2026-06-29T13:03:00.455Z" }, + { url = "https://files.pythonhosted.org/packages/40/cd/0fcc3f7d39183674d5bfa9ec640faaeb506c60be7c8f94625dfba366e37c/jiter-0.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8597d23c87f59294f83bcb6229b9ed1fccee13dbba967b46930d2f1759466fee", size = 347053, upload-time = "2026-06-29T13:03:02.045Z" }, + { url = "https://files.pythonhosted.org/packages/5c/ae/c7e64e7932ad597fa395b61440b249ada6366716e25c6e08dd2afbd021e6/jiter-0.16.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:3126a5dbad56401989ac769aca0cb56005bfb3e2366eea0ca99d1a91c3c1ee03", size = 356153, upload-time = "2026-06-29T13:03:03.706Z" }, + { url = "https://files.pythonhosted.org/packages/d4/1c/1c719044f14da814e1a060191ab19b96f3e99207bc5b4bfc6d6be34b3f80/jiter-0.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c4b4717bdb35ae456f831a6b08d01880fff399887a6bbc526a583a406e484eea", size = 393956, upload-time = "2026-06-29T13:03:05.165Z" }, + { url = "https://files.pythonhosted.org/packages/3b/dc/7b2f303a2847207e265503853a2d964a55354cffd62a5f2936c155486798/jiter-0.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:adff21bc78edfe086c15eb495b900306076de378dc2337c132401fc39bd79c91", size = 521081, upload-time = "2026-06-29T13:03:06.886Z" }, + { url = "https://files.pythonhosted.org/packages/c2/5f/501cf6e1e09caeb420195179ffc6f62aca603f1220ec53fd80d0d70b3e56/jiter-0.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dab907db06fc593645e73109acf4581ba5b548897d28b9348dc41ddc8343b2d3", size = 552085, upload-time = "2026-06-29T13:03:08.339Z" }, + { url = "https://files.pythonhosted.org/packages/79/54/aa5be86520113b79455c3877f3d1f07a348098df4083ba3688e9537e52dd/jiter-0.16.0-cp311-cp311-win32.whl", hash = "sha256:560b2cf3fb03240cd34f27409a238547488708f05b7c3924f571a60422251ec7", size = 206755, upload-time = "2026-06-29T13:03:09.653Z" }, + { url = "https://files.pythonhosted.org/packages/64/ec/2feb893eb330bd69b413866f4d5daada33c3962f1c6f270c91ca2d87fdf9/jiter-0.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:e431cfc9caf44c1d5459ff77d4e64cbf85fddb6a35dad836a15c6a9ec23087c1", size = 199155, upload-time = "2026-06-29T13:03:10.979Z" }, + { url = "https://files.pythonhosted.org/packages/b9/9c/ca040d94415048a3666fc237774df8151c96f8d2b661cbe3b184acc95876/jiter-0.16.0-cp311-cp311-win_arm64.whl", hash = "sha256:2a8e9e39cf083016137aa5cadafe3188adc2ba6ba1fbf1e5d18889ad3e9ad056", size = 194403, upload-time = "2026-06-29T13:03:12.341Z" }, + { url = "https://files.pythonhosted.org/packages/83/2b/52ace16ed031354f0539749a49e4bf33797d82bea5137910835fa4b09793/jiter-0.16.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:67c3bc1760f8c99d805dcab4e644027142a53b1d5d861f18780ebdbd5d40b72a", size = 306943, upload-time = "2026-06-29T13:03:14.035Z" }, + { url = "https://files.pythonhosted.org/packages/94/2e/34957c2c1b661c252ba9bcc60ae0bddc27e0f7202c6073326a13c5390eec/jiter-0.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5af7780e4a26bd7d0d989592bf9ef12ebf806b74ab709223ecca37c749872ea9", size = 307779, upload-time = "2026-06-29T13:03:15.418Z" }, + { url = "https://files.pythonhosted.org/packages/88/6c/59bd309cab4460c54cf1079f3eb7fe7af6a4c895c5c957a53378693bad2b/jiter-0.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5bf78d0e05e45cfdd66558893938d59afe3d1b1a824a202039b20e607d25a72", size = 335826, upload-time = "2026-06-29T13:03:17.11Z" }, + { url = "https://files.pythonhosted.org/packages/3b/8c/f5ef7b65f0df47afa16596969defb281ebb86e96df346d62be6fd853d620/jiter-0.16.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f4444a83f946605990c98f625cdd3d2725bfb818158760c5748c653170a20e0e", size = 362573, upload-time = "2026-06-29T13:03:18.781Z" }, + { url = "https://files.pythonhosted.org/packages/2b/0b/ace4354da061ee38844a0c27dc2c21eecd27aea119e8da324bea987522d0/jiter-0.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3a23f0e4f957e1be65752d2dfac9a5a06b1917af8dc85deb639c3b9d02e31290", size = 457979, upload-time = "2026-06-29T13:03:20.293Z" }, + { url = "https://files.pythonhosted.org/packages/55/40/c0253d3772eb9dcd8e6606ee9b2d53ec8e5b814589c47f140aa585f21eaa/jiter-0.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c22a488f7b9218e245a0025a9ba6b100e2e54700831cf4cf16833a27fba3ad01", size = 372302, upload-time = "2026-06-29T13:03:21.739Z" }, + { url = "https://files.pythonhosted.org/packages/a8/d2/4839422241aa12860ce597b20068727094ba0bc480723c74924ca5bad483/jiter-0.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46add52f4ad47a08bfb1219f3e673da972191489a33016edefdb5ea55bfa8c48", size = 343805, upload-time = "2026-06-29T13:03:23.384Z" }, + { url = "https://files.pythonhosted.org/packages/e2/59/e196888a05befdda7dbe299b722d56f2f6eec65402bc34c0a3306d595feb/jiter-0.16.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:9c8a956fd72c2cf1e730d01ea080341f13aa0a97a4a33b51abebe725b7ae9ca9", size = 351107, upload-time = "2026-06-29T13:03:24.815Z" }, + { url = "https://files.pythonhosted.org/packages/ec/74/4cd9e0fca65232136400354b630fbfcd2de634e22ccbb96567725981b548/jiter-0.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:561926e0573ffe4a32498420a76d64b16c513e1ab413b9d28158a8764ac701e5", size = 388441, upload-time = "2026-06-29T13:03:26.266Z" }, + { url = "https://files.pythonhosted.org/packages/d9/8c/554691e48bc711299c0a293dd8a6179e24b2d66a54dc295421fcf64569c0/jiter-0.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:44d019fa8cdaf89bf29c71b39e3712143fdd0ac76725c6ef954f9957a5ea8730", size = 516354, upload-time = "2026-06-29T13:03:28.02Z" }, + { url = "https://files.pythonhosted.org/packages/a4/cb/01e9d69dc2cc6759d4f91e230b34489c4fdb2518992650633f9e20bece89/jiter-0.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0df91907609837f33341b8e6fe73b95991fdaa57caf1a0fbd343dffe826f386f", size = 547880, upload-time = "2026-06-29T13:03:29.534Z" }, + { url = "https://files.pythonhosted.org/packages/79/70/2953195f1c6ad00f49fa67e13df7e60acb3dd4f387101bc15abccddd905e/jiter-0.16.0-cp312-cp312-win32.whl", hash = "sha256:51d7b836acb0108d7c77df1742332cac2a1fa04a74d6dacec46e7091f0e91274", size = 203473, upload-time = "2026-06-29T13:03:31.025Z" }, + { url = "https://files.pythonhosted.org/packages/2d/05/2909a8b10699a4d560f8c502b6b2c5f3991b682b1922c1eedda242b225bd/jiter-0.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:1878349266f8ee36ecb1375cc5ba2f115f35fd9f0a1a4119e725e379126647f7", size = 196905, upload-time = "2026-06-29T13:03:32.472Z" }, + { url = "https://files.pythonhosted.org/packages/e9/a9/6b82bb1c8d7790d602489b967b982a909e5d092875a6c2ade96444c8dfc5/jiter-0.16.0-cp312-cp312-win_arm64.whl", hash = "sha256:2ed5738ae4af18271a51a528b8811b0cbfa4a1858de9d83359e4169855d6a331", size = 190618, upload-time = "2026-06-29T13:03:34.672Z" }, + { url = "https://files.pythonhosted.org/packages/91/c0/555fc60473d30d66894ba825e63615e3be7524fac23858356afa7a38906c/jiter-0.16.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:41977aa5654023948c2dae2a81cbf9c43343954bef1cd59a154dd15a4d84c195", size = 306203, upload-time = "2026-06-29T13:03:36.243Z" }, + { url = "https://files.pythonhosted.org/packages/d0/2b/c3eaf16f5d7c9bad66ea32f40a95bd169b29a91217fcc7f081375157e99c/jiter-0.16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d28bb3c26762358dadf3e5bf0bccd29ae987d65e6988d2e6f49829c76b003c09", size = 306489, upload-time = "2026-06-29T13:03:37.846Z" }, + { url = "https://files.pythonhosted.org/packages/96/3f/02fdfc6705cad96127d883af5c34e4867f554f29ec7705ec1a46156400a9/jiter-0.16.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0542a7189c26920778658fc8fcf2af8bae05bae9924577f71804acef37996536", size = 335453, upload-time = "2026-06-29T13:03:39.221Z" }, + { url = "https://files.pythonhosted.org/packages/b2/a6/e4bda5920d4b0d7c5dfb7174ce4a6b2e4d3e11c9162c452ef0eab4cdbdbd/jiter-0.16.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8fb8de1e23a0cb2a7f53c335049c7b72b6db41aa6227cdcc0972a1de5cb39450", size = 361625, upload-time = "2026-06-29T13:03:40.597Z" }, + { url = "https://files.pythonhosted.org/packages/b7/97/4e6b59b2c6e55cbb3e183595f81ad65dcfb21c915fee5e19e335df21bc55/jiter-0.16.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b72d0b2990ca754a9102779ac98d8597b7cb31678958562214a007f909eab78e", size = 456958, upload-time = "2026-06-29T13:03:42.074Z" }, + { url = "https://files.pythonhosted.org/packages/15/e0/97e9557686d2f94f4b93786eccb7eed28e9228ad132ea8237f44727314a7/jiter-0.16.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5f91b1c27fc22a57993d5a5cb8a627cb8ed4b10502716fac1ffbfe1d19d84e8", size = 372017, upload-time = "2026-06-29T13:03:43.658Z" }, + { url = "https://files.pythonhosted.org/packages/0f/94/db768b6938e0df35c86beeba3dfbbb025c9ee5c19e1aa271f2396e50864d/jiter-0.16.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c682bea068a90b764577bdb78a60a4c1d1606daf9cd4c893832a37c7cc9d9026", size = 343320, upload-time = "2026-06-29T13:03:45.226Z" }, + { url = "https://files.pythonhosted.org/packages/c1/d6/5a59d938244a30735fe62d9433fd325f9021ea29d89780ea4596ea93bc89/jiter-0.16.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:8d031aabecc4f1b6276adfb42e3aabb77c89d468bf616600e8d3a11328929053", size = 350520, upload-time = "2026-06-29T13:03:46.671Z" }, + { url = "https://files.pythonhosted.org/packages/67/f8/c4a857f49c9af125f6bbcac7e3eee7f7978ed89682833062e2dbf62576b1/jiter-0.16.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:eab2cd170150e70153de16896a1774e3a1dca80154c56b54d7a812c479a7165e", size = 387550, upload-time = "2026-06-29T13:03:48.361Z" }, + { url = "https://files.pythonhosted.org/packages/8b/d6/5fbc2f7d6b67b754caa61a993a2e626e815dec47ffc2f9e35f01adfebec7/jiter-0.16.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:6edb63a46e65a82c26800a868e49b2cac30dd5a4218b88d74bc2c848c8ad60bb", size = 515424, upload-time = "2026-06-29T13:03:49.881Z" }, + { url = "https://files.pythonhosted.org/packages/ed/54/284f0164b64a5fed915fea6ba7e9ba9b3d8d37c67d59cf2e3bb99d45cdfe/jiter-0.16.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:659039cc50b5addcc35fcc87ae2c1833b7c0a8e5326ef631a75e4478447bcf84", size = 546981, upload-time = "2026-06-29T13:03:51.363Z" }, + { url = "https://files.pythonhosted.org/packages/13/c5/2a467585a576594384e1d2c43e1224deaafc085f24e243529cf98beef8e1/jiter-0.16.0-cp313-cp313-win32.whl", hash = "sha256:c9c53be232c2e206ef9cdbad81a48bfa74c3d3f08bcf8124630a8a748aad993e", size = 202853, upload-time = "2026-06-29T13:03:53.015Z" }, + { url = "https://files.pythonhosted.org/packages/88/6a/de61d04b9eec69c71719968d2f716532a3bc121170c44a39e14979c6be81/jiter-0.16.0-cp313-cp313-win_amd64.whl", hash = "sha256:baad945ed47f163ad833314f8e3288c396118934f94e7bbb9e243ce4b341a4fd", size = 196160, upload-time = "2026-06-29T13:03:54.447Z" }, + { url = "https://files.pythonhosted.org/packages/19/4b/b390ed59bafb3f31d008d1218578f10327714484b334439947f7e5b11e7f/jiter-0.16.0-cp313-cp313-win_arm64.whl", hash = "sha256:3c1fd2dbe1b0af19e987f03fe66c5f5bd105a2229c1aff4ab14890b24f41d21a", size = 189862, upload-time = "2026-06-29T13:03:55.754Z" }, + { url = "https://files.pythonhosted.org/packages/a7/89/bc4f1b57d5da938fd344a466396541e586d161320d70bffd929aaafcd8f4/jiter-0.16.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:b2c61484666ad42726029af0c00ef4541f0f3b5cdc550221f56c2343208018ee", size = 308239, upload-time = "2026-06-29T13:03:57.205Z" }, + { url = "https://files.pythonhosted.org/packages/65/7a/c415453e5213001bf3b411ff65dec3d303b0e76a4a2cfea9768cd4960994/jiter-0.16.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:63efadc657488f45db1c676d81e704cac2abf3fdb892def1faea61db053127e2", size = 308928, upload-time = "2026-06-29T13:03:58.643Z" }, + { url = "https://files.pythonhosted.org/packages/11/fc/1f4fb7ebf9a724c7741994f4aae18fba1e2f3133df14521a79194952c34a/jiter-0.16.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf0d73f50e7b6935677854f6e8e31d499ca7064dd24734f703e060f5b237d883", size = 336998, upload-time = "2026-06-29T13:04:00.071Z" }, + { url = "https://files.pythonhosted.org/packages/a0/8d/72cadaac05ccfa7cc3a0a2232862e6c72443ca40cf300ba8b57f9f18b69b/jiter-0.16.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bf3ea07d9bc8e7d03a9fbc051295462e6dbc295b894fd72457c3136e3e43d898", size = 362112, upload-time = "2026-06-29T13:04:01.52Z" }, + { url = "https://files.pythonhosted.org/packages/58/4a/c4b0d5f651fda90a24ffce9f8d56cde462a2e09d31ae3de3c68cef34c04e/jiter-0.16.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:26798522707abb47d767db536e4148ceac1b14446bf028ee85e579a2e043cfe5", size = 459807, upload-time = "2026-06-29T13:04:03.214Z" }, + { url = "https://files.pythonhosted.org/packages/80/58/ef77879ea9aa56b50824edc5a445e226422c7a8d211f3fd2a56bcb9493cf/jiter-0.16.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bc837c1b9631be10abfe0191537fe8009838204cec7e44827401ace390ddb567", size = 373181, upload-time = "2026-06-29T13:04:04.629Z" }, + { url = "https://files.pythonhosted.org/packages/49/2e/ffbc3f254e4d8a66da3062c624a7df4b7c2b2cf9e1fe43cf394b3e104041/jiter-0.16.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49060fd70737fad59d33ba9dcc0d83247dc9e77187de26053a19c16c9f32bd69", size = 344927, upload-time = "2026-06-29T13:04:06.067Z" }, + { url = "https://files.pythonhosted.org/packages/9a/f6/0be5dc6d64a89f80aa8fec984f94dedb2973e251edcae55841d60786d578/jiter-0.16.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:adbb8edeadd431bc4477879d5d371ece7cb1334486584e0f252656dd7ffada29", size = 352754, upload-time = "2026-06-29T13:04:07.477Z" }, + { url = "https://files.pythonhosted.org/packages/da/6e/7d31243b3b91cd261dd19e9d3557fc3251a80883d3d8049c86174e7ab7af/jiter-0.16.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:31aaee5b80f672c1dc21272bcfb9cbdcfc1ea04ff50f00ed5af500b80c44fa93", size = 390553, upload-time = "2026-06-29T13:04:08.92Z" }, + { url = "https://files.pythonhosted.org/packages/25/33/51ae371fde3c88897520f62b4d5f8b27ad7103e2bb10812ff52195609853/jiter-0.16.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:6722bcef4ffc86c835574b1b2fac6b33b9fb4a889c781e67950e891591f3c55a", size = 516900, upload-time = "2026-06-29T13:04:10.407Z" }, + { url = "https://files.pythonhosted.org/packages/a0/45/6449b3d123ea439ba79507c657288f461d55049e7bcbdc2cf8eb8210f491/jiter-0.16.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:5ab4f50ff971b611d656554ea10b75f80097392c827bc32923c6eeb6386c8b00", size = 548754, upload-time = "2026-06-29T13:04:12.046Z" }, + { url = "https://files.pythonhosted.org/packages/9b/e7/fd2fb11ae3e2649333da3aa170d04d7b3000bbdc3b270f6513382fdf4e04/jiter-0.16.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:710cc51d4ebdcd3c1f70b232c1db1ea1344a075770422bbd4bede5708335acbe", size = 122381, upload-time = "2026-06-29T13:04:13.413Z" }, + { url = "https://files.pythonhosted.org/packages/26/80/f0b147a62c315a164ed2168908286ca302310824c218d3aae52b06c0c9a9/jiter-0.16.0-cp314-cp314-win32.whl", hash = "sha256:57b37fc887a32d44798e4d8ebfa7c9683ff3da1d5bf38f08d1bb3573ccb39106", size = 204578, upload-time = "2026-06-29T13:04:14.813Z" }, + { url = "https://files.pythonhosted.org/packages/5e/e6/4758a14304b4523a6f5adb2419340086aa3593bd4327c2b25b5948a90548/jiter-0.16.0-cp314-cp314-win_amd64.whl", hash = "sha256:cbd18dd5e2df96b580487b5745adf57ef64ad89ba2d9662fc3c19386acce7db8", size = 198154, upload-time = "2026-06-29T13:04:16.272Z" }, + { url = "https://files.pythonhosted.org/packages/26/be/41fa54a2e7ea41d6c99f1dc5b1f0fd4cb474680304b5d268dd518e81da3a/jiter-0.16.0-cp314-cp314-win_arm64.whl", hash = "sha256:a32d2027a9fa67f109ff245a3252ece3ccc32cc56703e1deab6cc846a59e0585", size = 191458, upload-time = "2026-06-29T13:04:17.707Z" }, + { url = "https://files.pythonhosted.org/packages/81/6b/59127338b86d9fe4d99418f5a15118bea778103ee0fe9d9dd7e0af174e95/jiter-0.16.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2577196f4474ef3fc4779a088a23b0897bbf86f9ea3679c372d45b8383b43207", size = 316739, upload-time = "2026-06-29T13:04:19.663Z" }, + { url = "https://files.pythonhosted.org/packages/2d/95/49461034d5388196d3dabf98748935f017b7785d8f3f5349f834bcc4ed0d/jiter-0.16.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:616e89e008a93c01104161c75b4988e58716b01d62307ebfe161e52a56d2a818", size = 340911, upload-time = "2026-06-29T13:04:21.257Z" }, + { url = "https://files.pythonhosted.org/packages/cd/97/a4369f2fb82cb3dda13b98622f31249b2e014b223fe64ee534413ad72294/jiter-0.16.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0e2e9efbe042210df657bade597f66d6d75723e3d8f45a12ea6d8167ff8bbce3", size = 361747, upload-time = "2026-06-29T13:04:22.677Z" }, + { url = "https://files.pythonhosted.org/packages/28/51/49b6ed456261646e1906016a6760367a28aacd3c24805e4e5fe64116c1db/jiter-0.16.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f4d9e473a5ce7d27fef8b848df4dc16e283893d3f53b4a585e72c9595f3c284", size = 460225, upload-time = "2026-06-29T13:04:24.441Z" }, + { url = "https://files.pythonhosted.org/packages/33/b5/5689aff4f66c5b60be63106e591dbfcba2190df97d2c9c7cf052361ddb98/jiter-0.16.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d30a4a1c87713060c8d1cc59a7b6c8fb6b8ef0a6900368014c76c87922a2929", size = 373169, upload-time = "2026-06-29T13:04:25.884Z" }, + { url = "https://files.pythonhosted.org/packages/a2/96/3ae1b85ee0d6d6cab254fb7f8da018272b932bbf2d69b07e98aa2a96c746/jiter-0.16.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bae96332410f866e5900d809298b1ed82735932986c672495f9701daacd80620", size = 350332, upload-time = "2026-06-29T13:04:27.302Z" }, + { url = "https://files.pythonhosted.org/packages/15/32/c99d7bafd78986556c95bf60ce84c6cc98786eac56066c12d7f828bb6747/jiter-0.16.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:da3d7ec75dc83bb18bca888b5edfae0656a26849056c59e05a7728badd17e7af", size = 353377, upload-time = "2026-06-29T13:04:28.731Z" }, + { url = "https://files.pythonhosted.org/packages/0e/4b/f99a8e571287c3dec766bcc18528bbe8e8fb5365522ab5e6d64c93e87066/jiter-0.16.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ee6162b77d49a9939229df666dfa8af3e656b6701b54c4c84966d740e189264e", size = 387746, upload-time = "2026-06-29T13:04:30.319Z" }, + { url = "https://files.pythonhosted.org/packages/75/69/c78a5b3f71040e34eb5917df26fb7ae9a2174cad1ccbf277512507c53a6e/jiter-0.16.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:63ffdbdae7d4499f4cda14eadc12ddcabef0fc0c081191bdc2247489cb698077", size = 517292, upload-time = "2026-06-29T13:04:31.709Z" }, + { url = "https://files.pythonhosted.org/packages/c2/f7/095b38eda4c70d03651c403f29a5590f16d12ddc5d544aac9f9cddf72277/jiter-0.16.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:a111256a7193bea0759267b10385e5870949c239ed7b6ddbaaf57573edb38734", size = 549259, upload-time = "2026-06-29T13:04:33.721Z" }, + { url = "https://files.pythonhosted.org/packages/2e/c5/6a0207d90e5f656d95af98ebd0934f382d37674416f215aeda2ff8063e51/jiter-0.16.0-cp314-cp314t-win32.whl", hash = "sha256:de5ba8763e56b793561f43bed197c9ea55776daa5e9a6b91eed68a909bc9cdbf", size = 206523, upload-time = "2026-06-29T13:04:35.068Z" }, + { url = "https://files.pythonhosted.org/packages/a5/31/c757d5f30a8980fd945ce7b98be10be9e4ff59c7c42f5fd86804c2e87db8/jiter-0.16.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b8a3f9a6008048fe9def7bf465180564a6e458047d2ce499149cfbe73c3ae9db", size = 200366, upload-time = "2026-06-29T13:04:36.61Z" }, + { url = "https://files.pythonhosted.org/packages/7c/a2/d88de6d313d734a544a7901353ad5db67cb38dcfcd91713b7979dafc345d/jiter-0.16.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0fa25b09b13075c46f5bc174f2690525a925a4fc2f7c82969a2bbabff22386ce", size = 190516, upload-time = "2026-06-29T13:04:38.004Z" }, + { url = "https://files.pythonhosted.org/packages/06/d3/8e278946d43eeca2585b4dd0834a887cd71136329b837f3a16ed86a8b4b0/jiter-0.16.0-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:850ccb1d7eedb4200f4014b1c0e8a577de114fc3cd88faad646dcc9bc4bb12ad", size = 304518, upload-time = "2026-06-29T13:05:00.172Z" }, + { url = "https://files.pythonhosted.org/packages/72/43/28d4ef495028bf0506a413d4db3f4eb3e7288a382e0f065f306a17bbeb5e/jiter-0.16.0-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:e34e97bda77eb63242a410243c071e28ac7e0d8c0948c5ee658498690a4b2f2f", size = 310207, upload-time = "2026-06-29T13:05:02.123Z" }, + { url = "https://files.pythonhosted.org/packages/e0/ca/c366b1012da1d640de975d9683acd44e4d150d9068845d0ca2610435253f/jiter-0.16.0-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7dc85ea77d4abbae8bad0d3538678aedee75bceec4e2f6c8dfb1c74772e5aa5", size = 342771, upload-time = "2026-06-29T13:05:03.55Z" }, + { url = "https://files.pythonhosted.org/packages/16/52/50cc4056fc1ae02e7154704e7ecc89df0afb8300222cfe8a52d3f67e4730/jiter-0.16.0-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17ca7fae79f6d99cd9a042b75f917eaada7b895cfc7dd2ee3a16089dcaec7a85", size = 346468, upload-time = "2026-06-29T13:05:05.452Z" }, + { url = "https://files.pythonhosted.org/packages/98/ab/664fd8c4be028b2bedd3d2ff08769c4ede23d0dbc87a77c62384a0515b5d/jiter-0.16.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:f17d61a28b4b3e0e3e2ba98490c70501403b4d196f78732439160e7fd3678127", size = 303106, upload-time = "2026-06-29T13:05:07.118Z" }, + { url = "https://files.pythonhosted.org/packages/1a/07/421f1d5b65493a76e16027b848aba6a7d28073ae75944fa4289cc914d39f/jiter-0.16.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:96e38eea538c8ddf853a35727c7be0741c76c13f04148ac5c116222f50ece3b3", size = 304658, upload-time = "2026-06-29T13:05:08.708Z" }, + { url = "https://files.pythonhosted.org/packages/0a/db/bba1155f01a01c3c37a89425d571da751bbedf5c54247b831a04cb971798/jiter-0.16.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d284fb8d94d5855d60c44fefcab4bf966f1da6fada73992b01f6f0c9bc0c6702", size = 339719, upload-time = "2026-06-29T13:05:10.41Z" }, + { url = "https://files.pythonhosted.org/packages/78/f7/18a1afcd64f35314b68c1f23afcd9994d0bc13e65cc77517afff4e83986d/jiter-0.16.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64d613743df53199b1aa256a7d328340da6d7078aac7705a7db9d7a791e9cfd2", size = 343885, upload-time = "2026-06-29T13:05:12.087Z" }, +] + +[[package]] +name = "joserfc" +version = "1.7.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cryptography" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f1/26/abe1ad855eb334b5ebc9c6495d4798e12bee70e5e8e815d54570710b8312/joserfc-1.7.2.tar.gz", hash = "sha256:537ffb8888b2df039cb5b6d017d7cff6f09d521ce65d89cc9b8ab752b1cff947", size = 233183, upload-time = "2026-06-29T09:03:10.868Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/80/d1b30336582cced4dce0dae776508a6011723e32f907bc7a702c0b25890a/joserfc-1.7.2-py3-none-any.whl", hash = "sha256:ddd818c0ca9b4f17bbc2d72cb3966e6ded7502be089316c62c3cc64ae86132b5", size = 70426, upload-time = "2026-06-29T09:03:09.393Z" }, ] [[package]] @@ -1025,6 +1268,51 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl", hash = "sha256:8ff8b95779d071ba472cf5bc913028df06031797532f08a7d5b602d8b2a488ca", size = 7659, upload-time = "2026-03-23T22:32:31.568Z" }, ] +[[package]] +name = "jsonschema" +version = "4.26.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b3/fc/e067678238fa451312d4c62bf6e6cf5ec56375422aee02f9cb5f909b3047/jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326", size = 366583, upload-time = "2026-01-07T13:41:07.246Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce", size = 90630, upload-time = "2026-01-07T13:41:05.306Z" }, +] + +[[package]] +name = "jsonschema-specifications" +version = "2025.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" }, +] + +[[package]] +name = "keyring" +version = "25.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "importlib-metadata", marker = "python_full_version < '3.12'" }, + { name = "jaraco-classes" }, + { name = "jaraco-context" }, + { name = "jaraco-functools" }, + { name = "jeepney", marker = "sys_platform == 'linux'" }, + { name = "pywin32-ctypes", marker = "sys_platform == 'win32'" }, + { name = "secretstorage", marker = "sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/43/4b/674af6ef2f97d56f0ab5153bf0bfa28ccb6c3ed4d1babf4305449668807b/keyring-25.7.0.tar.gz", hash = "sha256:fe01bd85eb3f8fb3dd0405defdeac9a5b4f6f0439edbb3149577f244a2e8245b", size = 63516, upload-time = "2025-11-16T16:26:09.482Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/db/e655086b7f3a705df045bf0933bdd9c2f79bb3c97bfef1384598bb79a217/keyring-25.7.0-py3-none-any.whl", hash = "sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f", size = 39160, upload-time = "2025-11-16T16:26:08.402Z" }, +] + [[package]] name = "langchain" version = "1.3.11" @@ -1102,7 +1390,7 @@ wheels = [ [[package]] name = "langchain-google-genai" -version = "4.2.6" +version = "4.2.7" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "filetype" }, @@ -1110,23 +1398,23 @@ dependencies = [ { name = "langchain-core" }, { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4c/08/68e4f90b273d1d8dc3a7a948e6535e60baac726adbb2a8341dcf17662f54/langchain_google_genai-4.2.6.tar.gz", hash = "sha256:653dc331e691ddd79784d9ff6a4082749e0f873394c6dc782c414eb4409850eb", size = 280074, upload-time = "2026-06-26T06:18:58.807Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1d/0c/bc60dabc362ca7c6ffe8c4bcc2f724c7e566b43eb230cee51419f88f784c/langchain_google_genai-4.2.7.tar.gz", hash = "sha256:03b1463ffe4d42435f43c7870467f2215f684bb46400d2543435d10157c80ac7", size = 281605, upload-time = "2026-07-06T13:51:58.724Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/85/3c/9a6b43bced0238f95640555e14423fe4a8268e3f4f536f67e26e79e633d4/langchain_google_genai-4.2.6-py3-none-any.whl", hash = "sha256:c40db0c2d033a5fb6db8e2cc3fb6d49c5678b89b337a64da095fb73ec9f72021", size = 70457, upload-time = "2026-06-26T06:18:57.781Z" }, + { url = "https://files.pythonhosted.org/packages/b2/f9/d73d1e712591723aaddb7a7b1e94978cd2320c29acfe0d26b6169a2f26f0/langchain_google_genai-4.2.7-py3-none-any.whl", hash = "sha256:0d9c388d0e6c629718fca6abb19c6fdca728a9a7873d0324c1ec821288b5b571", size = 70702, upload-time = "2026-07-06T13:51:57.499Z" }, ] [[package]] name = "langchain-openai" -version = "1.2.1" +version = "1.3.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, { name = "openai" }, { name = "tiktoken" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9a/0e/d8e16c28aa67106d285e63b8ffc04c5af68341e345ce24a0751dbf2e167e/langchain_openai-1.2.1.tar.gz", hash = "sha256:ee4480b787706361b7125fad46930589a624df87aa158c6986ef1fad10d10675", size = 1146092, upload-time = "2026-04-24T19:46:43.328Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/f3/b38e052f943a75ba0e6762c0a50b6f1d6bcd52a9ce63386d8803c2ff506e/langchain_openai-1.3.3.tar.gz", hash = "sha256:143769bf943820b80db769e47ca8fd0aac08ed18714519333b044c4431e9aa67", size = 3256559, upload-time = "2026-06-22T22:54:05.445Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/dc/55/2865b18ee3a3dd11160b8c4b2cf37e75bf2a4a8d1d38868ffffc7b7cc180/langchain_openai-1.2.1-py3-none-any.whl", hash = "sha256:a80732185030d4f453dda6c25feef46f645f665423fdffe38ae3edf1ac3c6c4d", size = 98626, upload-time = "2026-04-24T19:46:41.971Z" }, + { url = "https://files.pythonhosted.org/packages/2f/4b/7520114de1ce36bb17cbc98d0fcda048a9f755bedaeb73b92137aeaaf1db/langchain_openai-1.3.3-py3-none-any.whl", hash = "sha256:e469659862c8aabba4f6653df973206e7be54f98cf2275c86be7f06b7abe20d7", size = 120437, upload-time = "2026-06-22T22:54:03.8Z" }, ] [[package]] @@ -1143,7 +1431,7 @@ wheels = [ [[package]] name = "langgraph" -version = "1.2.7" +version = "1.2.8" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, @@ -1153,9 +1441,9 @@ dependencies = [ { name = "pydantic" }, { name = "xxhash" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/bf/11/c3961537ac7577125aabba68effc33ecc3dc0962e2d287d734dbd61caad7/langgraph-1.2.7.tar.gz", hash = "sha256:dcdf5b441bf8c7c7c154e603b302c9dbfbfd2d11e1b7ae7d93a5aba979dc87bd", size = 721385, upload-time = "2026-06-30T01:24:12.528Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b6/ad/583fda4c69501390b989770a465ccd0bdab1c1612eba582c012002ddf9b6/langgraph-1.2.8.tar.gz", hash = "sha256:f79d3575f45b404899358976e4fac0294eb75f8df1bfe8cd11286be7539c4548", size = 722464, upload-time = "2026-07-06T20:40:19.487Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/16/5d/19de0c674cf2d8bc95b25cdb4c13ba3f4fbe0f35bf2224ef19cc46bbb4cd/langgraph-1.2.7-py3-none-any.whl", hash = "sha256:249349a5d6a32cb0aa2304a8fb6529bd0cf56db8780d21db9e086e5383668f89", size = 246930, upload-time = "2026-06-30T01:24:11.15Z" }, + { url = "https://files.pythonhosted.org/packages/36/49/b958a9963606807e5a20cc75fced14aa77c5cbcc470d5bf8ae13277cd298/langgraph-1.2.8-py3-none-any.whl", hash = "sha256:aa8de1d4df44162353d117589ae0bf6930ca009b62d2d6e26cc32580794c5be6", size = 246983, upload-time = "2026-07-06T20:40:18.242Z" }, ] [[package]] @@ -1202,7 +1490,7 @@ wheels = [ [[package]] name = "langsmith" -version = "0.9.7" +version = "0.9.8" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -1220,18 +1508,41 @@ dependencies = [ { name = "xxhash" }, { name = "zstandard" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d4/8b/a56b97a3b8a94f850fe2ec42351d4c508cc6bd7ca96644906c311e32ec5b/langsmith-0.9.7.tar.gz", hash = "sha256:40f8a66a466a7abd991a9df1b50de0a9d30c48ee0d3da46ce00516b68e41c9d7", size = 4711142, upload-time = "2026-07-02T20:11:09.619Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0c/68/8d8471233ee0cd82c2af946d76f80a01aeb8bb04160c392c1229fddf5d3d/langsmith-0.9.8.tar.gz", hash = "sha256:8c3d6a6d5246a3ea6d439b726d59edefba31dfb251de9eedb256119bbea4439e", size = 4710812, upload-time = "2026-07-06T19:06:10.866Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4a/67/a85caaa99117bbc988a0df7faa39e7f68344361854638d86bcce0ffe3619/langsmith-0.9.8-py3-none-any.whl", hash = "sha256:098da9fc6c184284f17913cb813a41e28c5ab1508e90bd50db40c28166681017", size = 671148, upload-time = "2026-07-06T19:06:08.911Z" }, +] + +[[package]] +name = "logfire" +version = "4.37.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "executing" }, + { name = "opentelemetry-exporter-otlp-proto-http" }, + { name = "opentelemetry-instrumentation" }, + { name = "opentelemetry-sdk" }, + { name = "protobuf" }, + { name = "rich" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c2/f2/34b8ebbd6bbd82c71055d6b881b24d8ada79a0e6692d3dd8cca5e86fadb3/logfire-4.37.0.tar.gz", hash = "sha256:7ee0cb64b59c356a41a1701fb84597037f8db1fa15df7a3715ef363e5a1de06a", size = 1212176, upload-time = "2026-06-12T20:47:06.904Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/54/95/0abb8647123c9ebbb31162bcdba3183f5f3d3bb2f752ef3d777ab715e88c/langsmith-0.9.7-py3-none-any.whl", hash = "sha256:a5ff9179b77eb0c3a0129294d30924eab13e51e2720f374372dbbc014c892911", size = 671052, upload-time = "2026-07-02T20:11:07.702Z" }, + { url = "https://files.pythonhosted.org/packages/7a/08/1805d2f26955671115aae555d78cc4c72a6fe733f332d44d69756bc1737b/logfire-4.37.0-py3-none-any.whl", hash = "sha256:a20823e6dbb3204614a3ea5e79c91df42405c5112393ec9d8e34ef45b60d315f", size = 378930, upload-time = "2026-06-12T20:47:03.674Z" }, +] + +[package.optional-dependencies] +httpx = [ + { name = "opentelemetry-instrumentation-httpx" }, ] [[package]] name = "logfire-api" -version = "4.32.1" +version = "4.37.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/58/1b/0c74ad85f977743ba4c589e46e0cb138d6a6e69487830f4e86ebbdb145a3/logfire_api-4.32.1.tar.gz", hash = "sha256:5e8714b2bb5fb5d1f4a4a833941e4ca711b75d2c1f98e76c5ad680fe6991af6a", size = 78788, upload-time = "2026-04-15T14:11:58.788Z" } +sdist = { url = "https://files.pythonhosted.org/packages/03/04/471b916249fe7e22056818ca734af46418cd3ff9b9b920c1829c3627b4d2/logfire_api-4.37.0.tar.gz", hash = "sha256:0f62debd6ed593d51307277bd6d5636b57bda07935b5604b96db10fe64441af4", size = 88906, upload-time = "2026-06-12T20:47:08.163Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0c/ab/d5adeab6253c7ecd5904fc5ef3265859f218610caf4e1e55efe9aff6ac49/logfire_api-4.32.1-py3-none-any.whl", hash = "sha256:4b4c27cf6e27e8e26ef4b22a77f2a2988dd1d07e2d24ee70673ef34b234fb8a5", size = 124394, upload-time = "2026-04-15T14:11:56.157Z" }, + { url = "https://files.pythonhosted.org/packages/10/2f/23e5b8fa22f75f73965c72e5c29e6fb8715263457394601e254fe26fbe31/logfire_api-4.37.0-py3-none-any.whl", hash = "sha256:1d756f8ba23aa56d438e0ba2c0f529a00fcac975b8785c561b058267f9465088", size = 138710, upload-time = "2026-06-12T20:47:05.526Z" }, ] [[package]] @@ -1243,6 +1554,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl", hash = "sha256:e91464b71ae3ee7afd3017d9f358ef0baf158fd9a298db92f1d4761133824c36", size = 108180, upload-time = "2026-02-09T14:57:25.787Z" }, ] +[[package]] +name = "markdown-it-py" +version = "4.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" }, +] + [[package]] name = "markupsafe" version = "3.0.3" @@ -1317,6 +1640,40 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, ] +[[package]] +name = "mcp" +version = "1.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "httpx" }, + { name = "httpx-sse" }, + { name = "jsonschema" }, + { name = "pydantic" }, + { name = "pydantic-settings" }, + { name = "pyjwt", extra = ["crypto"] }, + { name = "python-multipart" }, + { name = "pywin32", marker = "sys_platform == 'win32'" }, + { name = "sse-starlette" }, + { name = "starlette" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, + { name = "uvicorn", marker = "sys_platform != 'emscripten'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6e/77/9450b8f251a13affb6281997d0523c4615f8a8b35d0b21ff30db3a5aac9d/mcp-1.28.1.tar.gz", hash = "sha256:d51e36a5f5644faea4f85ea649bfffa6bc6c26770d42798ad6a3de3d2ba69683", size = 638501, upload-time = "2026-06-26T12:57:29.093Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e2/5e/d118fce19f87a2e7d8101c35c8ae0ec289098a4df0ff244cec23e415aca0/mcp-1.28.1-py3-none-any.whl", hash = "sha256:2726bca5e7193f61c5dde8b12500a6de2d9acf6d1a1c0be9e8c2e706437991df", size = 222620, upload-time = "2026-06-26T12:57:27.218Z" }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, +] + [[package]] name = "mergedeep" version = "1.3.4" @@ -1433,16 +1790,25 @@ python = [ [[package]] name = "mkdocstrings-python" -version = "2.0.3" +version = "2.0.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "griffelib" }, { name = "mkdocs-autorefs" }, { name = "mkdocstrings" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/29/33/c225eaf898634bdda489a6766fc35d1683c640bffe0e0acd10646b13536d/mkdocstrings_python-2.0.3.tar.gz", hash = "sha256:c518632751cc869439b31c9d3177678ad2bfa5c21b79b863956ad68fc92c13b8", size = 199083, upload-time = "2026-02-20T10:38:36.368Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b1/b6/e858701499d57eee8b3fd8e78168083956c6683ddbe727b46758b19e1119/mkdocstrings_python-2.0.5.tar.gz", hash = "sha256:3a4d92556ad39637e88af94a5374213af9a8e3040c3824ceaed04b486c017594", size = 199578, upload-time = "2026-06-19T10:41:08.868Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl", hash = "sha256:0b83513478bdfd803ff05aa43e9b1fca9dd22bcd9471f09ca6257f009bc5ee12", size = 104779, upload-time = "2026-02-20T10:38:34.517Z" }, + { url = "https://files.pythonhosted.org/packages/d1/fc/10ab7e80650a9c9e8f4f1105f8c8e73567f88ed0c06ada589ab81d38687c/mkdocstrings_python-2.0.5-py3-none-any.whl", hash = "sha256:30c837bbff016549f659fcba6539ac351303f0fd7e713c89a040611072236e9d", size = 104951, upload-time = "2026-06-19T10:41:07.378Z" }, +] + +[[package]] +name = "more-itertools" +version = "11.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/de/1d/f4da6f02cdffe04d6362210b807146a26044c88d839208aec273bb0d9184/more_itertools-11.1.0.tar.gz", hash = "sha256:48e8f4d9e7e5878571ecf6f2b4e57634f93cd474cc8cfbd2376f2d11b396e30d", size = 145772, upload-time = "2026-05-22T14:14:29.909Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e8/3d/1087453384dbde46a8c7f9356eead2c58be8a7bf156bca40243377c85715/more_itertools-11.1.0-py3-none-any.whl", hash = "sha256:4b65538ae22f6fed0ce4874efd317463a7489796a0939fa66824dd542125a192", size = 72226, upload-time = "2026-05-22T14:14:28.824Z" }, ] [[package]] @@ -1456,23 +1822,23 @@ wheels = [ [[package]] name = "nodejs-wheel-binaries" -version = "24.15.0" +version = "24.16.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/3f/70/a1e4f4d5986768ab90cc860b1cc3660fd2ded74ca175a900a5c29f839c7d/nodejs_wheel_binaries-24.15.0.tar.gz", hash = "sha256:b43f5c4f6e5768d8845b2ae4682eb703a19bf7aadc84187e2d903ed3a611c859", size = 8057, upload-time = "2026-04-19T15:48:16.899Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a3/22/2a5beb4e21417c73233d9f65cf6f3e96e891b80d2f550a8f630ebc6b88c6/nodejs_wheel_binaries-24.16.0.tar.gz", hash = "sha256:c973cb69dc5fd16e6f6dc6e579e2c3d5534e2a1f57619dddf5ba070efa7dde37", size = 8056, upload-time = "2026-05-30T16:52:09.807Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/85/66/54051d14853d6ab4fb85f8be9b042b530be653357fb9a19557498bc91ab7/nodejs_wheel_binaries-24.15.0-py2.py3-none-macosx_13_0_arm64.whl", hash = "sha256:a6232fa8b754220941f52388c8ead923f7c1c7fdf0ea0d98f657523bd9a81ef4", size = 55173485, upload-time = "2026-04-19T15:47:34.561Z" }, - { url = "https://files.pythonhosted.org/packages/ad/5f/66acada164da5ca10a0824db021aa7394ae18396c550cd9280e839a43126/nodejs_wheel_binaries-24.15.0-py2.py3-none-macosx_13_0_x86_64.whl", hash = "sha256:001a6b62c69d9109c1738163cca00608dd2722e8663af59300054ea02610972d", size = 55348100, upload-time = "2026-04-19T15:47:40.521Z" }, - { url = "https://files.pythonhosted.org/packages/0d/2d/0cbd5ff40c9bb030ca1735d8f8793bd74f08a4cbd49100a1d19313ea57ab/nodejs_wheel_binaries-24.15.0-py2.py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:0fbc48765e60ed0ff30d43898dbf5cadbadf2e5f1e7f204afc2b01493b7ebce6", size = 59668206, upload-time = "2026-04-19T15:47:46.848Z" }, - { url = "https://files.pythonhosted.org/packages/da/d5/91ac63951ec75927a486b83b8cafe650e360fa70ac01dc94adfb32b93b97/nodejs_wheel_binaries-24.15.0-py2.py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:20ee0536809795da8a4942fc1ab4cbdebbcaaf29383eab67ba8874268fb00008", size = 60206736, upload-time = "2026-04-19T15:47:52.668Z" }, - { url = "https://files.pythonhosted.org/packages/db/72/dc22776974d928869c0c30d23ee98ed7df254243c2df68f09f5963e8e8b8/nodejs_wheel_binaries-24.15.0-py2.py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:1fade6c214285e72472ca40a631e98ff36559671cd5eefc8bf009471d67f04b4", size = 61720456, upload-time = "2026-04-19T15:47:58.325Z" }, - { url = "https://files.pythonhosted.org/packages/01/0a/34461b9050cb45ee371dccdefc622aef6351506ea2691b08fc761ca67150/nodejs_wheel_binaries-24.15.0-py2.py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3984cb8d87766567aee67a49743227ab40ede6f47734ec990ff90e50b74e7740", size = 62326172, upload-time = "2026-04-19T15:48:04.094Z" }, - { url = "https://files.pythonhosted.org/packages/c9/17/09252bf35672dba926649d59dfe51443a0f6955ad13784e91131d5ec82a2/nodejs_wheel_binaries-24.15.0-py2.py3-none-win_amd64.whl", hash = "sha256:a437601956b532dcb3082046e6978e622733f90edc0932cbb9adb3bb97a16501", size = 41543461, upload-time = "2026-04-19T15:48:09.332Z" }, - { url = "https://files.pythonhosted.org/packages/0a/7e/b649777d148e1e0c2ce349156603cdb12f7ed99921b95d93717393650193/nodejs_wheel_binaries-24.15.0-py2.py3-none-win_arm64.whl", hash = "sha256:bdf4a431e08321a32efc604111c6f23941f87055d796a537e8c4110daecad23f", size = 39233248, upload-time = "2026-04-19T15:48:13.326Z" }, + { url = "https://files.pythonhosted.org/packages/83/d1/68b43b53cd0fa83ae6fd406705023ca988d9e0ca41c724d82e66fbeb2ef6/nodejs_wheel_binaries-24.16.0-py2.py3-none-macosx_13_0_arm64.whl", hash = "sha256:d9f8f677dcf30e37ac244f07869726abe043f01eb0f45722b1df31cc2af7093c", size = 55666374, upload-time = "2026-05-30T16:51:39.588Z" }, + { url = "https://files.pythonhosted.org/packages/e9/b2/40a989159599080da485de966c4c2d207e852ac7aa7864702626d96c8bf5/nodejs_wheel_binaries-24.16.0-py2.py3-none-macosx_13_0_x86_64.whl", hash = "sha256:3d0370fe7120ce9697a4f60d40480d2bd8808d9f30131458d5afc0040d4e5a51", size = 55838487, upload-time = "2026-05-30T16:51:43.383Z" }, + { url = "https://files.pythonhosted.org/packages/d7/a7/cd42174fb5ff6faff7fa8d326a18914d8f232098ab5de055b57c16fa13ca/nodejs_wheel_binaries-24.16.0-py2.py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:85dc92bbb79c851569c5925dcc2a4c915a034efab375f99e4e7e6bbe9cca8342", size = 60179540, upload-time = "2026-05-30T16:51:47.036Z" }, + { url = "https://files.pythonhosted.org/packages/2b/95/c8a1f9ae140aa28df8744d984d01d4b3af7cdd6555af12127f40ceb45a7d/nodejs_wheel_binaries-24.16.0-py2.py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:2f3036292811514ba847b3708492644764f88a833ac425c5f55007014308ddfd", size = 60716262, upload-time = "2026-05-30T16:51:50.711Z" }, + { url = "https://files.pythonhosted.org/packages/64/c9/7c35b3737f59e36d0249c265397b7bff570519b95301d6e16ea361e904ad/nodejs_wheel_binaries-24.16.0-py2.py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:db8a8a76ebd2b28ecbfc9ad464baa3707241b9e050a30e2efdf6f60c0f886502", size = 62230592, upload-time = "2026-05-30T16:51:55Z" }, + { url = "https://files.pythonhosted.org/packages/04/96/d931255cf9d11a84d6b54d882dba7434646467d568ccf070ea3418638df3/nodejs_wheel_binaries-24.16.0-py2.py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:f1a3d8f7b4491cbbd023ba3fc4e901fcca2d9fb80d57f24ba3890de8b1dbac03", size = 62841759, upload-time = "2026-05-30T16:51:59.407Z" }, + { url = "https://files.pythonhosted.org/packages/a2/7b/8b7a3f41bc255411be30b6d7d288aab8ffd9ea2055db8555ced3548007b9/nodejs_wheel_binaries-24.16.0-py2.py3-none-win_amd64.whl", hash = "sha256:bb136be9944f0662dcf1120f45193a6b75b13fac378971a95cc42c9f879a81aa", size = 42027734, upload-time = "2026-05-30T16:52:03.348Z" }, + { url = "https://files.pythonhosted.org/packages/17/66/1ed71f1f529b8ca727d42c7ceb9db0bef145ce4a13dfc86fb50aa44f3be6/nodejs_wheel_binaries-24.16.0-py2.py3-none-win_arm64.whl", hash = "sha256:8308940b5edd0a50dc5267ea36ba21c9f668e83fe0d9f293937174d3a7e31c36", size = 39714528, upload-time = "2026-05-30T16:52:06.421Z" }, ] [[package]] name = "openai" -version = "2.36.0" +version = "2.44.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -1484,22 +1850,130 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f4/a1/4d5e84cf51720fc1526cc49e10ac1961abcccb55b0efb3d970db1e9a2728/openai-2.36.0.tar.gz", hash = "sha256:139dea0edd2f1b30c33d46ae1a6929e03906254140318e4608e98fe8c566f2e7", size = 753003, upload-time = "2026-05-07T17:33:17.075Z" } +sdist = { url = "https://files.pythonhosted.org/packages/49/f5/7c7cb955305cb41f7f3c5fd7e0e38bf6bbf2658468863d4b7b868a5cb8df/openai-2.44.0.tar.gz", hash = "sha256:68a5a5ffad82b8ff7d451c437529fb64f7c3b8123aaf0c021966a882d9e3947d", size = 988753, upload-time = "2026-06-24T20:56:02.293Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9d/1c/5d43735b2553baae2a5e899dcbcd0670a86930d993184d72ca909bf11c9b/openai-2.36.0-py3-none-any.whl", hash = "sha256:143f6194b548dbc2c921af1f1b03b9f14c85fed8a75b5b516f5bcc11a2a50c63", size = 1302361, upload-time = "2026-05-07T17:33:15.063Z" }, + { url = "https://files.pythonhosted.org/packages/ae/f4/561ed79fd94876160018a5e75254cfcb9b0e62d4dded9dcb20072e86d623/openai-2.44.0-py3-none-any.whl", hash = "sha256:0a2a3ab2e29aeda368700f662ff9ba0f9df17ba4c54577a64e08b8115a3cc0ad", size = 1366216, upload-time = "2026-06-24T20:55:58.882Z" }, ] [[package]] name = "opentelemetry-api" -version = "1.41.1" +version = "1.42.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "importlib-metadata" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fa/fc/b7564cbef36601aef0d6c9bc01f7badb64be8e862c2e1c3c5c3b43b53e4f/opentelemetry_api-1.41.1.tar.gz", hash = "sha256:0ad1814d73b875f84494387dae86ce0b12c68556331ce6ce8fe789197c949621", size = 71416, upload-time = "2026-04-24T13:15:38.262Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b4/1c/125e1c936c0873796771b7f04f6c93b9f1bf5d424cea90fda94a99f61da8/opentelemetry_api-1.42.1.tar.gz", hash = "sha256:56c63bea9f77b62856be8c47600474acad853b2924b99b1687c4cb6297166716", size = 72296, upload-time = "2026-05-21T16:32:49.335Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/29/59/3e7118ed140f76b0982ba4321bdaed1997a0473f9720de2d10788a577033/opentelemetry_api-1.41.1-py3-none-any.whl", hash = "sha256:a22df900e75c76dc08440710e51f52f1aa6b451b429298896023e60db5b3139f", size = 69007, upload-time = "2026-04-24T13:15:15.662Z" }, + { url = "https://files.pythonhosted.org/packages/a3/ca/9520cc1f3dfbbd03ac5903bbf55833e257bc64b1cf30fa8b0d6df374d821/opentelemetry_api-1.42.1-py3-none-any.whl", hash = "sha256:51a69edacadbc03a8950ace1c4c21099cacc538820ac2c9e36277e78cebba714", size = 61311, upload-time = "2026-05-21T16:32:28.822Z" }, +] + +[[package]] +name = "opentelemetry-exporter-otlp-proto-common" +version = "1.42.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-proto" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0e/9c/216acfeaedadf2e1937f4373929b20f73197c5c4a2546d4f584b7fa63813/opentelemetry_exporter_otlp_proto_common-1.42.1.tar.gz", hash = "sha256:04f1f01fb597c4249dfcd7f8b861c902c2102369d376d9d346ff38de4469a2ee", size = 21433, upload-time = "2026-05-21T16:32:55.526Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d6/43/2375e7612e1121a4518c17603b6e0b03ad94f565aafad53f464dc5be2bf6/opentelemetry_exporter_otlp_proto_common-1.42.1-py3-none-any.whl", hash = "sha256:f48d395ab815b444da118868977e9798ea354c25737d5cf39578ae894011c140", size = 17327, upload-time = "2026-05-21T16:32:33.387Z" }, +] + +[[package]] +name = "opentelemetry-exporter-otlp-proto-http" +version = "1.42.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "googleapis-common-protos" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-exporter-otlp-proto-common" }, + { name = "opentelemetry-proto" }, + { name = "opentelemetry-sdk" }, + { name = "requests" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/77/32/826bfa1d80ecea24f47808de03cd4a0d13c17ecc07712f45123f0f61e4ac/opentelemetry_exporter_otlp_proto_http-1.42.1.tar.gz", hash = "sha256:bf142a21035d7571ac3a09cb2e5639f49886f243972883cfe777ed3bf02b734d", size = 25406, upload-time = "2026-05-21T16:32:56.807Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d3/96/82cb223a1502f0787d4bbff12907f5f8d870a50731febcd5818d93ef9555/opentelemetry_exporter_otlp_proto_http-1.42.1-py3-none-any.whl", hash = "sha256:00a16da1b312a1d6c7233d600d557c91df71125af73020f3b9a7765bd699d59d", size = 21793, upload-time = "2026-05-21T16:32:35.277Z" }, +] + +[[package]] +name = "opentelemetry-instrumentation" +version = "0.63b1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "packaging" }, + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/da/6d/4de72d97ff54db1ed270c7a59c9b904b917c0ac7af429c086c388b824ddb/opentelemetry_instrumentation-0.63b1.tar.gz", hash = "sha256:32368d6ae52c8de20aa790a6ad86b10a76f09956092337ae37d675773990e541", size = 41081, upload-time = "2026-05-21T16:36:14.206Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/35/a1/9314e621c143e4d82a5bf7a43c2ff7a745d31023506336857607c8c543cc/opentelemetry_instrumentation-0.63b1-py3-none-any.whl", hash = "sha256:f1986716d52cc316ea5f60189098726a9071d8ecc0eee96c9ed110be08bade9c", size = 35577, upload-time = "2026-05-21T16:34:56.818Z" }, +] + +[[package]] +name = "opentelemetry-instrumentation-httpx" +version = "0.63b1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-instrumentation" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "opentelemetry-util-http" }, + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/02/27/c2b4335bca030e893acbe5ff2b4f434868773bf94508be7e6bf5af981b24/opentelemetry_instrumentation_httpx-0.63b1.tar.gz", hash = "sha256:f41ec82f25c3abcdada621052db3e5fd648e3b43d55eec4b9c0c5d3ecb7b4ff4", size = 23557, upload-time = "2026-05-21T16:36:34.583Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ba/b8/f536780996195c3b9f2354998554671e05a7a262df8c043f63fe9e5a6f0b/opentelemetry_instrumentation_httpx-0.63b1-py3-none-any.whl", hash = "sha256:14df6e99d81be9a8cd238f6639b6fa52404c4d3ce219058fcb5dc8c0f2211f86", size = 16336, upload-time = "2026-05-21T16:35:32.221Z" }, +] + +[[package]] +name = "opentelemetry-proto" +version = "1.42.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b4/55/63eac3e1089b768ba014091fdd2ae8a9a440c821ef5e2b786909c94c8836/opentelemetry_proto-1.42.1.tar.gz", hash = "sha256:c6a51e6b4f05ae63565f3a113217f3d2bfaec68f78c02d7a6c85f9010d1cfca6", size = 45839, upload-time = "2026-05-21T16:33:03.937Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/9d/171c02c84a76940b7e601805b3bb536985aded9168fbcc9ba52f0a730fa2/opentelemetry_proto-1.42.1-py3-none-any.whl", hash = "sha256:dedb74cba2886c59c7789b227a7a670613025a07489040050aedff6e5c0fb43c", size = 71782, upload-time = "2026-05-21T16:32:44.867Z" }, +] + +[[package]] +name = "opentelemetry-sdk" +version = "1.42.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/40/f7/b390bd9bfd703bf98a68fea1f27786c6872331fd617164a54b8a59bdc008/opentelemetry_sdk-1.42.1.tar.gz", hash = "sha256:8c834e8f8c9ba4171d4ec843d0cb8a67e4c7394d3f9e9297e582cbd9456ddbf7", size = 239262, upload-time = "2026-05-21T16:33:04.641Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8f/6b/4287766cfbde577ae2272e8884abac325aeaac0d64f41c61d5b8cc595105/opentelemetry_sdk-1.42.1-py3-none-any.whl", hash = "sha256:083cd4bbfaa5aa7b5a9e552430d9951219967cfb27aa61feb13a77aba1fc839d", size = 170907, upload-time = "2026-05-21T16:32:45.894Z" }, +] + +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.63b1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/93/99/4d7dd6df64795951413ce6e815f8cf1eb191daf7196ae86574589643d5f3/opentelemetry_semantic_conventions-0.63b1.tar.gz", hash = "sha256:3daf963611334b365e98a57438183eb012d3bfb40b2d931a9af613476b8701a9", size = 148340, upload-time = "2026-05-21T16:33:05.455Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/7a/7fe66f5f3682b1dd47d88cc4e11f1c6c0966b737de2d16671146e23c39a5/opentelemetry_semantic_conventions-0.63b1-py3-none-any.whl", hash = "sha256:dfe5ef4dee82586b746f522b818ceb298d00b3d59f660042bd79404bff8d0682", size = 203713, upload-time = "2026-05-21T16:32:47.016Z" }, +] + +[[package]] +name = "opentelemetry-util-http" +version = "0.63b1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6c/d8/7bf5e4cec0578ac3c28c18eb7b88f34279139cbc8c568d6aa02b9c5ae53e/opentelemetry_util_http-0.63b1.tar.gz", hash = "sha256:ba1268f00922ee522dba2ae38458060f99486e7385a8056985901ca9685adfff", size = 11102, upload-time = "2026-05-21T16:36:56.675Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/f1/34e047e8f6a3c67e5220acf1af7b9f62868c25d77791bca74457bd2180a6/opentelemetry_util_http-0.63b1-py3-none-any.whl", hash = "sha256:6284194028c59cd439f8acfe388145069a6127f11dc077e1344a2094adacc3f8", size = 8205, upload-time = "2026-05-21T16:36:09.736Z" }, ] [[package]] @@ -1647,11 +2121,11 @@ wheels = [ [[package]] name = "platformdirs" -version = "4.9.6" +version = "4.10.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9f/4a/0883b8e3802965322523f0b200ecf33d31f10991d0401162f4b23c698b42/platformdirs-4.9.6.tar.gz", hash = "sha256:3bfa75b0ad0db84096ae777218481852c0ebc6c727b3168c1b9e0118e458cf0a", size = 29400, upload-time = "2026-04-09T00:04:10.812Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/47/e4501f49c178ae1d9f4a75073fda4204f52647993f075a9db4d14930e0c5/platformdirs-4.10.0.tar.gz", hash = "sha256:31e761a6a0ca04faf7353ea759bdba55652be214725111e5aac52dfa29d4bef7", size = 31224, upload-time = "2026-05-28T03:32:53.587Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/75/a6/a0a304dc33b49145b21f4808d763822111e67d1c3a32b524a1baf947b6e1/platformdirs-4.9.6-py3-none-any.whl", hash = "sha256:e61adb1d5e5cb3441b4b7710bea7e4c12250ca49439228cc1021c00dcfac0917", size = 21348, upload-time = "2026-04-09T00:04:09.463Z" }, + { url = "https://files.pythonhosted.org/packages/81/e6/cd9575ac904136b3cbf7aa7ee819ef86eedb7274e46f230e94ea4342e729/platformdirs-4.10.0-py3-none-any.whl", hash = "sha256:fb516cdb12eb0d857d0cd85a7c57cea4d060bee4578d6cf5a14dfdf8cbf8784a", size = 22743, upload-time = "2026-05-28T03:32:52.175Z" }, ] [[package]] @@ -1679,6 +2153,58 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl", hash = "sha256:e2cf246f7299edcabcf15f9b0571fdce06058527f0a06535068a86d38089f29b", size = 226472, upload-time = "2026-04-21T20:31:40.092Z" }, ] +[[package]] +name = "prompt-toolkit" +version = "3.0.52" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wcwidth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", size = 434198, upload-time = "2025-08-27T15:24:02.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" }, +] + +[[package]] +name = "protobuf" +version = "6.33.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/66/70/e908e9c5e52ef7c3a6c7902c9dfbb34c7e29c25d2f81ade3856445fd5c94/protobuf-6.33.6.tar.gz", hash = "sha256:a6768d25248312c297558af96a9f9c929e8c4cee0659cb07e780731095f38135", size = 444531, upload-time = "2026-03-18T19:05:00.988Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fc/9f/2f509339e89cfa6f6a4c4ff50438db9ca488dec341f7e454adad60150b00/protobuf-6.33.6-cp310-abi3-win32.whl", hash = "sha256:7d29d9b65f8afef196f8334e80d6bc1d5d4adedb449971fefd3723824e6e77d3", size = 425739, upload-time = "2026-03-18T19:04:48.373Z" }, + { url = "https://files.pythonhosted.org/packages/76/5d/683efcd4798e0030c1bab27374fd13a89f7c2515fb1f3123efdfaa5eab57/protobuf-6.33.6-cp310-abi3-win_amd64.whl", hash = "sha256:0cd27b587afca21b7cfa59a74dcbd48a50f0a6400cfb59391340ad729d91d326", size = 437089, upload-time = "2026-03-18T19:04:50.381Z" }, + { url = "https://files.pythonhosted.org/packages/5c/01/a3c3ed5cd186f39e7880f8303cc51385a198a81469d53d0fdecf1f64d929/protobuf-6.33.6-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:9720e6961b251bde64edfdab7d500725a2af5280f3f4c87e57c0208376aa8c3a", size = 427737, upload-time = "2026-03-18T19:04:51.866Z" }, + { url = "https://files.pythonhosted.org/packages/ee/90/b3c01fdec7d2f627b3a6884243ba328c1217ed2d978def5c12dc50d328a3/protobuf-6.33.6-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:e2afbae9b8e1825e3529f88d514754e094278bb95eadc0e199751cdd9a2e82a2", size = 324610, upload-time = "2026-03-18T19:04:53.096Z" }, + { url = "https://files.pythonhosted.org/packages/9b/ca/25afc144934014700c52e05103c2421997482d561f3101ff352e1292fb81/protobuf-6.33.6-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:c96c37eec15086b79762ed265d59ab204dabc53056e3443e702d2681f4b39ce3", size = 339381, upload-time = "2026-03-18T19:04:54.616Z" }, + { url = "https://files.pythonhosted.org/packages/16/92/d1e32e3e0d894fe00b15ce28ad4944ab692713f2e7f0a99787405e43533a/protobuf-6.33.6-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:e9db7e292e0ab79dd108d7f1a94fe31601ce1ee3f7b79e0692043423020b0593", size = 323436, upload-time = "2026-03-18T19:04:55.768Z" }, + { url = "https://files.pythonhosted.org/packages/c4/72/02445137af02769918a93807b2b7890047c32bfb9f90371cbc12688819eb/protobuf-6.33.6-py3-none-any.whl", hash = "sha256:77179e006c476e69bf8e8ce866640091ec42e1beb80b213c3900006ecfba6901", size = 170656, upload-time = "2026-03-18T19:04:59.826Z" }, +] + +[[package]] +name = "py-key-value-aio" +version = "0.4.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "beartype" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fb/e2/d689d922894a7ecde73b6daeaf9b13dab5aae06fe6aaaf7514722644d382/py_key_value_aio-0.4.5.tar.gz", hash = "sha256:c6563a2c6abe5da5e20f4f9e875c2a9b425a2244a54fadbf46cf140a9eea45d7", size = 107547, upload-time = "2026-05-27T16:37:08.107Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f6/95/b8ba862968712caa12a19666175334fa979e1f198b896a430adb3bacfe87/py_key_value_aio-0.4.5-py3-none-any.whl", hash = "sha256:ab862adbcb8c72547d1c57821f22cbbb71ab86509039c96f36e914e0336c8dd7", size = 170005, upload-time = "2026-05-27T16:37:06.629Z" }, +] + +[package.optional-dependencies] +filetree = [ + { name = "aiofile" }, + { name = "anyio" }, +] +keyring = [ + { name = "keyring" }, +] +memory = [ + { name = "cachetools" }, +] + [[package]] name = "pyasn1" version = "0.6.3" @@ -1724,6 +2250,11 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba", size = 472262, upload-time = "2026-05-06T13:43:02.641Z" }, ] +[package.optional-dependencies] +email = [ + { name = "email-validator" }, +] + [[package]] name = "pydantic-acp" source = { editable = "packages/adapters/pydantic-acp" } @@ -1751,6 +2282,18 @@ requires-dist = [ ] provides-extras = ["harness"] +[[package]] +name = "pydantic-ai" +version = "2.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic-ai-slim", extra = ["anthropic", "cli", "evals", "google", "logfire", "mcp", "openai", "retries", "web"] }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0c/fb/402ba0a0121f67ac8f4ae90fbc53352380bc29c9fbc7323b7e59ae80b8ee/pydantic_ai-2.4.0.tar.gz", hash = "sha256:817c06491513e08f6674ced75a83be3b7a87d66b123e0aa4bb8fe5778d6a6f18", size = 18383, upload-time = "2026-07-03T01:37:08.369Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/0a/2297d804e0f00ab99ecf94a87407fb15120ba3ecd7b52fd079afcfda3325/pydantic_ai-2.4.0-py3-none-any.whl", hash = "sha256:8822777ec5d8874f526f3dcd2aacd654b9e3dfe11858183f1471e14f564a31f3", size = 7716, upload-time = "2026-07-03T01:37:00.37Z" }, +] + [[package]] name = "pydantic-ai-harness" version = "0.5.0" @@ -1787,6 +2330,42 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/72/67/425f06d496465c9b4d4c1f394507200cf24c1ef27972ebb4cd39e30821b9/pydantic_ai_slim-2.4.0-py3-none-any.whl", hash = "sha256:8f2a6d8ebcab484c9c809f466709af33aa26fe23e44dda85b8396347e77b39a9", size = 930798, upload-time = "2026-07-03T01:37:02.937Z" }, ] +[package.optional-dependencies] +anthropic = [ + { name = "anthropic" }, +] +cli = [ + { name = "argcomplete" }, + { name = "prompt-toolkit" }, + { name = "pyperclip" }, + { name = "pyyaml" }, + { name = "rich" }, +] +evals = [ + { name = "pydantic-evals" }, +] +google = [ + { name = "google-genai" }, +] +logfire = [ + { name = "logfire", extra = ["httpx"] }, +] +mcp = [ + { name = "fastmcp-slim", extra = ["client"] }, +] +openai = [ + { name = "openai" }, + { name = "tiktoken" }, +] +retries = [ + { name = "tenacity" }, +] +web = [ + { name = "httpx" }, + { name = "starlette" }, + { name = "uvicorn" }, +] + [[package]] name = "pydantic-core" version = "2.46.4" @@ -1889,6 +2468,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4b/2d/69abac8f838090bbecd5df894befb2c2619e7996a98ddb949db9f3b93225/pydantic_core-2.46.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:d51026d73fcfd93610abc7b27789c26b313920fcfb20e27462d74a7f8b06e983", size = 2193071, upload-time = "2026-05-06T13:38:08.682Z" }, ] +[[package]] +name = "pydantic-evals" +version = "2.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "logfire-api" }, + { name = "pydantic" }, + { name = "pydantic-ai-slim" }, + { name = "pyyaml" }, + { name = "rich" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/03/30/b563a1f535f57d815823cbadde90ca6d9288cff86c0771461da68a8bad80/pydantic_evals-2.4.0.tar.gz", hash = "sha256:7e8a608ce3eaa136f86e188132c5498fbc1ef97787dd2fd9e67f637c16680a32", size = 84683, upload-time = "2026-07-03T01:37:11.488Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/7a/4de5bfb1369948cc7158022d0a0b4ff9a287134234de0ad4ae00d873ee95/pydantic_evals-2.4.0-py3-none-any.whl", hash = "sha256:1a3da3058a70962bb2b85cbd6a4c0a7e1f85028f1933a64f16a371855ca99189", size = 99989, upload-time = "2026-07-03T01:37:04.724Z" }, +] + [[package]] name = "pydantic-graph" version = "2.4.0" @@ -1963,6 +2559,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b6/0e/c395b22ddc32c746d7e2d271dd18bb585289576bb67483435e25643b7ecd/pydantic_monty-0.0.18-cp314-cp314-win_amd64.whl", hash = "sha256:83b6e2b73b0fa60c5641ecb6e8b588840023163ca6ab8b3e5da7ad088390ee7c", size = 9467375, upload-time = "2026-05-29T08:29:54.227Z" }, ] +[[package]] +name = "pydantic-settings" +version = "2.14.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, + { name = "python-dotenv" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5c/b5/8f48e906c3e0205276e8bd8cb7512217a87b2685304d64be27cad5b3019f/pydantic_settings-2.14.2.tar.gz", hash = "sha256:c19dd64b19097f1de80184f0cc7b0272a13ae6e170cbf240a3e27e381ed14a5f", size = 237700, upload-time = "2026-06-19T13:44:56.324Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/c1/6e422f34e569cf8e18df68d1939c81c099d2b61e4f7d9621c8a77560799c/pydantic_settings-2.14.2-py3-none-any.whl", hash = "sha256:a20c97b37910b6550d5ea50fbcc2d4187defe58cd57070b73863d069419c9440", size = 61715, upload-time = "2026-06-19T13:44:55.02Z" }, +] + [[package]] name = "pygments" version = "2.20.0" @@ -1972,22 +2582,45 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, ] +[[package]] +name = "pyjwt" +version = "2.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/81/58d0ac84e1ef3a3843791d6954d94c0b33d526c75eeb1efbce9d0a4c4077/pyjwt-2.13.0.tar.gz", hash = "sha256:41571c89ca91598c79e8ef18a2d07367d4810fbbd6f637794879baf1b7703423", size = 107515, upload-time = "2026-05-21T19:54:36.618Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a3/5e/ecf12fdb62546d64385c158514e9b2b671f7832108ef2ecd2020ce0af2d1/pyjwt-2.13.0-py3-none-any.whl", hash = "sha256:66adcc2aff09b3f1bbd95fc1e1577df8ac8723c978552fd43304c8a290ac5728", size = 31274, upload-time = "2026-05-21T19:54:35.362Z" }, +] + +[package.optional-dependencies] +crypto = [ + { name = "cryptography" }, +] + [[package]] name = "pymdown-extensions" -version = "10.21.2" +version = "11.0.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markdown" }, { name = "pyyaml" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/df/08/f1c908c581fd11913da4711ea7ba32c0eee40b0190000996bb863b0c9349/pymdown_extensions-10.21.2.tar.gz", hash = "sha256:c3f55a5b8a1d0edf6699e35dcbea71d978d34ff3fa79f3d807b8a5b3fa90fbdc", size = 853922, upload-time = "2026-03-29T15:01:55.233Z" } +sdist = { url = "https://files.pythonhosted.org/packages/21/a9/5f0c535ba3b08fe09270c16808e053a968868242ecbd5676d4e3a488bf28/pymdown_extensions-11.0.1.tar.gz", hash = "sha256:dd2905ae6fc5b75582fafb139a1266ffc754705efa902aa50067fa7ff4f94ec0", size = 857113, upload-time = "2026-07-02T17:59:22.955Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-py3-none-any.whl", hash = "sha256:5c0fd2a2bea14eb39af8ff284f1066d898ab2187d81b889b75d46d4348c01638", size = 268901, upload-time = "2026-03-29T15:01:53.244Z" }, + { url = "https://files.pythonhosted.org/packages/d6/54/da572c98c0b77626a91b5d3b89f0231d8bff5125c225420908632f8b342d/pymdown_extensions-11.0.1-py3-none-any.whl", hash = "sha256:db3943a62bab7e03af1364f0c4083e64b91fb097675a4b6cceccfbe9a77e5eb2", size = 269455, upload-time = "2026-07-02T17:59:21.271Z" }, +] + +[[package]] +name = "pyperclip" +version = "1.11.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/52/d87eba7cb129b81563019d1679026e7a112ef76855d6159d24754dbd2a51/pyperclip-1.11.0.tar.gz", hash = "sha256:244035963e4428530d9e3a6101a1ef97209c6825edab1567beac148ccc1db1b6", size = 12185, upload-time = "2025-09-26T14:40:37.245Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/df/80/fc9d01d5ed37ba4c42ca2b55b4339ae6e200b456be3a1aaddf4a9fa99b8c/pyperclip-1.11.0-py3-none-any.whl", hash = "sha256:299403e9ff44581cb9ba2ffeed69c7aa96a008622ad0c46cb575ca75b5b84273", size = 11063, upload-time = "2025-09-26T14:40:36.069Z" }, ] [[package]] name = "pytest" -version = "9.0.3" +version = "9.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -1996,22 +2629,22 @@ dependencies = [ { name = "pluggy" }, { name = "pygments" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c", size = 1572165, upload-time = "2026-04-07T17:16:18.027Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9", size = 375249, upload-time = "2026-04-07T17:16:16.13Z" }, + { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" }, ] [[package]] name = "pytest-asyncio" -version = "1.3.0" +version = "1.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/90/2c/8af215c0f776415f3590cac4f9086ccefd6fd463befeae41cd4d3f193e5a/pytest_asyncio-1.3.0.tar.gz", hash = "sha256:d7f52f36d231b80ee124cd216ffb19369aa168fc10095013c6b014a34d3ee9e5", size = 50087, upload-time = "2025-11-10T16:07:47.256Z" } +sdist = { url = "https://files.pythonhosted.org/packages/43/7c/d36d04db312ecf4298932ef77e6e4a9e8ad017906e24e34f0b0c361a2473/pytest_asyncio-1.4.0.tar.gz", hash = "sha256:c6c0d2259945122819f171a32ecea2c349ead889ee28176caaf492143424be42", size = 58514, upload-time = "2026-05-26T09:56:04.083Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/35/f8b19922b6a25bc0880171a2f1a003eaeb93657475193ab516fd87cac9da/pytest_asyncio-1.3.0-py3-none-any.whl", hash = "sha256:611e26147c7f77640e6d0a92a38ed17c3e9848063698d5c93d5aa7aa11cebff5", size = 15075, upload-time = "2025-11-10T16:07:45.537Z" }, + { url = "https://files.pythonhosted.org/packages/03/e2/08a497ef684b88559c9cc5f4ad53a37e7b99e727094a86d6ea32536d5d3c/pytest_asyncio-1.4.0-py3-none-any.whl", hash = "sha256:933ca923a23075a87fb7070c0ec272a6848489824d887c85c812670932835aa1", size = 16930, upload-time = "2026-05-26T09:56:02.576Z" }, ] [[package]] @@ -2042,15 +2675,15 @@ wheels = [ [[package]] name = "python-discovery" -version = "1.3.0" +version = "1.4.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "filelock" }, { name = "platformdirs" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ae/e0/cc5a8653e9a24f6cf84768f05064aa8ed5a83dcefd5e2a043db14a1c5f44/python_discovery-1.3.0.tar.gz", hash = "sha256:d098f1e86be5d45fe4d14bf1029294aabbd332f4321179dec85e76cddce834b0", size = 63925, upload-time = "2026-05-05T14:38:39.769Z" } +sdist = { url = "https://files.pythonhosted.org/packages/66/26/8b004cc36f430345136f6f00fa1aa9ed596c8ed1e8504625fa79522ff39c/python_discovery-1.4.3.tar.gz", hash = "sha256:ad57d7045a862460d4a235986c33f13ed707d3aeb9153fa47eb7dfd0d4673289", size = 70438, upload-time = "2026-07-03T13:21:51.621Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-py3-none-any.whl", hash = "sha256:441d9ced3dfce36e113beb35ca302c71c7ef06f3c0f9c227a0b9bb3bd49b9e9f", size = 33124, upload-time = "2026-05-05T14:38:38.539Z" }, + { url = "https://files.pythonhosted.org/packages/28/78/9b77ecb4644d1bbea94d29abf78f21c47eca6eb79e9745b702ec0bed2e19/python_discovery-1.4.3-py3-none-any.whl", hash = "sha256:b6e1e4a7d9e3f6948c39746ffe8218225162d738ba39d05ab1d2f6c1cac4878c", size = 33885, upload-time = "2026-07-03T13:21:50.174Z" }, ] [[package]] @@ -2062,6 +2695,46 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, ] +[[package]] +name = "python-multipart" +version = "0.0.32" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5b/42/55c32bb9b12693c092ad250a0e82edb5b31ddeda6eb772de5f308b3804ad/python_multipart-0.0.32.tar.gz", hash = "sha256:be54b7f3fa167bb83e4fcd936b887b708f4e57fe75911c02aebf53efaf8d938e", size = 46881, upload-time = "2026-06-04T16:18:58.647Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/04/e8135ebd1ad02c56ec633277529b2602ff99ff634be76cdba5744cf554fd/python_multipart-0.0.32-py3-none-any.whl", hash = "sha256:ff6d3f776f16878c894e52e107296ffc890e913c611b1a4ec6c44e2821fe2e23", size = 30042, upload-time = "2026-06-04T16:18:57.319Z" }, +] + +[[package]] +name = "pywin32" +version = "312" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1f/f5/10a6e845a00fc5e7afd0a988b744f403d4d57162a28d160a093c4d9322f0/pywin32-312-cp311-cp311-win32.whl", hash = "sha256:17948aeadbdb091f0ced6ef0841620794e68327b94ee415571c1203594b7215c", size = 6362659, upload-time = "2026-06-04T07:49:21.349Z" }, + { url = "https://files.pythonhosted.org/packages/35/c4/dcd2d62b5944b6d5db53413a5899016ccd57ffcb7278f3f81655d25d2027/pywin32-312-cp311-cp311-win_amd64.whl", hash = "sha256:d11417d84412f859b722fad0841b3614459ed0047f7542d8362e77884f6b6e8a", size = 6928825, upload-time = "2026-06-04T07:49:23.934Z" }, + { url = "https://files.pythonhosted.org/packages/b7/56/3cbb433fe4501cdba2eb9040f56a4e1a8243faa4186b25295564d1a7a79d/pywin32-312-cp311-cp311-win_arm64.whl", hash = "sha256:b2200a054ca6d6625c4842fc56a4976a4b47f96b73dbe5538c3f813a80359f47", size = 6721875, upload-time = "2026-06-04T07:49:26.416Z" }, + { url = "https://files.pythonhosted.org/packages/83/ff/32aa7d2ed0ab12b323aaa64f9b75e6ad4f8fd09f9ccfc28c79414d46838d/pywin32-312-cp312-cp312-win32.whl", hash = "sha256:dab4f65ac9c4e48400a2a0530c46c3c579cd5905ecd11b80692373915269208b", size = 6371877, upload-time = "2026-06-04T07:49:28.836Z" }, + { url = "https://files.pythonhosted.org/packages/03/d9/77040d3b43df3f3be32ea289433d660d2727f5ba327bc73be835127d9d60/pywin32-312-cp312-cp312-win_amd64.whl", hash = "sha256:b457f6d628a47e8a7346ce22acb7e1a46a4a78b52e1d17e1af56871bd19a93bc", size = 6914841, upload-time = "2026-06-04T07:49:31.85Z" }, + { url = "https://files.pythonhosted.org/packages/e3/cc/7b1ec671775756020a0ee7f4feeaf3c568f0ab86bd3900088cf986937a92/pywin32-312-cp312-cp312-win_arm64.whl", hash = "sha256:6017c58e12f6809fbb0555b75df144c2922a9ffd18e4b9b5afa863b6c1a9d950", size = 6727901, upload-time = "2026-06-04T07:49:34.244Z" }, + { url = "https://files.pythonhosted.org/packages/2d/41/12fbfd7f36ed2146d8bc9de96c2741296bf0d490b98508496cff322e274c/pywin32-312-cp313-cp313-win32.whl", hash = "sha256:7a27df850933d16a8eabfbaeb73d52b273e2da667f80d70b01a89d1f6828d02c", size = 6370184, upload-time = "2026-06-04T07:49:36.253Z" }, + { url = "https://files.pythonhosted.org/packages/ba/db/36a78e3403099d31d9746d13fdcde5accc43c1155f375a34d15983a479a7/pywin32-312-cp313-cp313-win_amd64.whl", hash = "sha256:c53e878d15a1c44788082bfe712a905433473aa38f86375b7cf8b45e3acbaaf9", size = 6914298, upload-time = "2026-06-04T07:49:38.876Z" }, + { url = "https://files.pythonhosted.org/packages/84/37/c1697194092b76de9ed47ca124323f02c57ffc8a45c06f88a3d5acaf01eb/pywin32-312-cp313-cp313-win_arm64.whl", hash = "sha256:59aba5d5940842075343a5ddc6b11f1cdf0d1567fe745290359dfbcc7c2eb831", size = 6727640, upload-time = "2026-06-04T07:49:41.083Z" }, + { url = "https://files.pythonhosted.org/packages/fc/2b/1f3cded5822fd49c02f40544cbb5f58c7cfd6b1694869fd476cb6170ee97/pywin32-312-cp314-cp314-win32.whl", hash = "sha256:a77a90fbb6881238d2ca9c6fd797b25817f3768fe78d214a90137ff055a75f5b", size = 6468928, upload-time = "2026-06-04T07:49:43.188Z" }, + { url = "https://files.pythonhosted.org/packages/21/82/3bf86d2e2808902013132e1ce905a7da0da53790f3836c64bf44d55e24f3/pywin32-312-cp314-cp314-win_amd64.whl", hash = "sha256:a4dd3a848290ef724347b19f301045831d8e802fa4464f491b98b1e0a081432e", size = 7024157, upload-time = "2026-06-04T07:49:45.34Z" }, + { url = "https://files.pythonhosted.org/packages/a4/0e/73f6d6800b4f27655abd9e9f6aaeaefcddb2b946e4674efa2bab184a7f7b/pywin32-312-cp314-cp314-win_arm64.whl", hash = "sha256:9fce94568364e0155e6dfb781ac5d95903be8baf28670632beab1b523f300daa", size = 6839598, upload-time = "2026-06-04T07:49:47.613Z" }, + { url = "https://files.pythonhosted.org/packages/eb/61/caa39686032d2ebdd04ff0ab5cbe163126c0066d98e00c9018646e42393b/pywin32-312-cp315-cp315-win32.whl", hash = "sha256:5c1fbe4a937a73ae9297384a3da38518cbc694c68ad8a809b2e19acd350f03ed", size = 6471159, upload-time = "2026-06-04T07:49:50.035Z" }, + { url = "https://files.pythonhosted.org/packages/0f/cd/7e1de64a4a6f69c04214169657ccab0d93a670ea50e35eb8f489d7378249/pywin32-312-cp315-cp315-win_amd64.whl", hash = "sha256:c2f03a0f73f804a13c2735b99392b0cd426bb4f2c4d0178e5ac966a0f21618d5", size = 7025293, upload-time = "2026-06-04T07:49:54.857Z" }, + { url = "https://files.pythonhosted.org/packages/23/ed/4532e9388e65fa16b46776ef47ad631a64eda1631884488af707666350ed/pywin32-312-cp315-cp315-win_arm64.whl", hash = "sha256:a8597d28f267b39074aef51fa593530082b39cbe5a074226096857b1fed2dfb9", size = 6840337, upload-time = "2026-06-04T07:49:57.531Z" }, +] + +[[package]] +name = "pywin32-ctypes" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/85/9f/01a1a99704853cb63f253eea009390c88e7131c67e66a0a02099a8c917cb/pywin32-ctypes-0.2.3.tar.gz", hash = "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755", size = 29471, upload-time = "2024-08-14T10:15:34.626Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8", size = 30756, upload-time = "2024-08-14T10:15:33.187Z" }, +] + [[package]] name = "pyyaml" version = "6.0.3" @@ -2129,113 +2802,127 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl", hash = "sha256:17109e1a528561e32f026364712fee1264bc2ea6715120891174ed1b980d2e04", size = 4722, upload-time = "2025-05-13T15:23:59.629Z" }, ] +[[package]] +name = "referencing" +version = "0.37.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "rpds-py" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766, upload-time = "2025-10-13T15:30:47.625Z" }, +] + [[package]] name = "regex" -version = "2026.4.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cb/0e/3a246dbf05666918bd3664d9d787f84a9108f6f43cc953a077e4a7dfdb7e/regex-2026.4.4.tar.gz", hash = "sha256:e08270659717f6973523ce3afbafa53515c4dc5dcad637dc215b6fd50f689423", size = 416000, upload-time = "2026-04-03T20:56:28.155Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e0/7a/617356cbecdb452812a5d42f720d6d5096b360d4a4c1073af700ea140ad2/regex-2026.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b4c36a85b00fadb85db9d9e90144af0a980e1a3d2ef9cd0f8a5bef88054657c6", size = 489415, upload-time = "2026-04-03T20:53:11.645Z" }, - { url = "https://files.pythonhosted.org/packages/20/e6/bf057227144d02e3ba758b66649e87531d744dda5f3254f48660f18ae9d8/regex-2026.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dcb5453ecf9cd58b562967badd1edbf092b0588a3af9e32ee3d05c985077ce87", size = 291205, upload-time = "2026-04-03T20:53:13.289Z" }, - { url = "https://files.pythonhosted.org/packages/eb/3b/637181b787dd1a820ba1c712cee2b4144cd84a32dc776ca067b12b2d70c8/regex-2026.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6aa809ed4dc3706cc38594d67e641601bd2f36d5555b2780ff074edfcb136cf8", size = 289225, upload-time = "2026-04-03T20:53:16.002Z" }, - { url = "https://files.pythonhosted.org/packages/05/21/bac05d806ed02cd4b39d9c8e5b5f9a2998c94c3a351b7792e80671fa5315/regex-2026.4.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:33424f5188a7db12958246a54f59a435b6cb62c5cf9c8d71f7cc49475a5fdada", size = 792434, upload-time = "2026-04-03T20:53:17.414Z" }, - { url = "https://files.pythonhosted.org/packages/d9/17/c65d1d8ae90b772d5758eb4014e1e011bb2db353fc4455432e6cc9100df7/regex-2026.4.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7d346fccdde28abba117cc9edc696b9518c3307fbfcb689e549d9b5979018c6d", size = 861730, upload-time = "2026-04-03T20:53:18.903Z" }, - { url = "https://files.pythonhosted.org/packages/ad/64/933321aa082a2c6ee2785f22776143ba89840189c20d3b6b1d12b6aae16b/regex-2026.4.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:415a994b536440f5011aa77e50a4274d15da3245e876e5c7f19da349caaedd87", size = 906495, upload-time = "2026-04-03T20:53:20.561Z" }, - { url = "https://files.pythonhosted.org/packages/01/ea/4c8d306e9c36ac22417336b1e02e7b358152c34dc379673f2d331143725f/regex-2026.4.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:21e5eb86179b4c67b5759d452ea7c48eb135cd93308e7a260aa489ed2eb423a4", size = 799810, upload-time = "2026-04-03T20:53:22.961Z" }, - { url = "https://files.pythonhosted.org/packages/29/ce/7605048f00e1379eba89d610c7d644d8f695dc9b26d3b6ecfa3132b872ff/regex-2026.4.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:312ec9dd1ae7d96abd8c5a36a552b2139931914407d26fba723f9e53c8186f86", size = 774242, upload-time = "2026-04-03T20:53:25.015Z" }, - { url = "https://files.pythonhosted.org/packages/e9/77/283e0d5023fde22cd9e86190d6d9beb21590a452b195ffe00274de470691/regex-2026.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a0d2b28aa1354c7cd7f71b7658c4326f7facac106edd7f40eda984424229fd59", size = 781257, upload-time = "2026-04-03T20:53:26.918Z" }, - { url = "https://files.pythonhosted.org/packages/8b/fb/7f3b772be101373c8626ed34c5d727dcbb8abd42a7b1219bc25fd9a3cc04/regex-2026.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:349d7310eddff40429a099c08d995c6d4a4bfaf3ff40bd3b5e5cb5a5a3c7d453", size = 854490, upload-time = "2026-04-03T20:53:29.065Z" }, - { url = "https://files.pythonhosted.org/packages/85/30/56547b80f34f4dd2986e1cdd63b1712932f63b6c4ce2f79c50a6cd79d1c2/regex-2026.4.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:e7ab63e9fe45a9ec3417509e18116b367e89c9ceb6219222a3396fa30b147f80", size = 763544, upload-time = "2026-04-03T20:53:30.917Z" }, - { url = "https://files.pythonhosted.org/packages/ac/2f/ce060fdfea8eff34a8997603532e44cdb7d1f35e3bc253612a8707a90538/regex-2026.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fe896e07a5a2462308297e515c0054e9ec2dd18dfdc9427b19900b37dfe6f40b", size = 844442, upload-time = "2026-04-03T20:53:32.463Z" }, - { url = "https://files.pythonhosted.org/packages/e5/44/810cb113096a1dacbe82789fbfab2823f79d19b7f1271acecb7009ba9b88/regex-2026.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:eb59c65069498dbae3c0ef07bbe224e1eaa079825a437fb47a479f0af11f774f", size = 789162, upload-time = "2026-04-03T20:53:34.039Z" }, - { url = "https://files.pythonhosted.org/packages/20/96/9647dd7f2ecf6d9ce1fb04dfdb66910d094e10d8fe53e9c15096d8aa0bd2/regex-2026.4.4-cp311-cp311-win32.whl", hash = "sha256:2a5d273181b560ef8397c8825f2b9d57013de744da9e8257b8467e5da8599351", size = 266227, upload-time = "2026-04-03T20:53:35.601Z" }, - { url = "https://files.pythonhosted.org/packages/33/80/74e13262460530c3097ff343a17de9a34d040a5dc4de9cf3a8241faab51c/regex-2026.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:9542ccc1e689e752594309444081582f7be2fdb2df75acafea8a075108566735", size = 278399, upload-time = "2026-04-03T20:53:37.021Z" }, - { url = "https://files.pythonhosted.org/packages/1c/3c/39f19f47f19dcefa3403f09d13562ca1c0fd07ab54db2bc03148f3f6b46a/regex-2026.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:b5f9fb784824a042be3455b53d0b112655686fdb7a91f88f095f3fee1e2a2a54", size = 270473, upload-time = "2026-04-03T20:53:38.633Z" }, - { url = "https://files.pythonhosted.org/packages/e5/28/b972a4d3df61e1d7bcf1b59fdb3cddef22f88b6be43f161bb41ebc0e4081/regex-2026.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:c07ab8794fa929e58d97a0e1796b8b76f70943fa39df225ac9964615cf1f9d52", size = 490434, upload-time = "2026-04-03T20:53:40.219Z" }, - { url = "https://files.pythonhosted.org/packages/84/20/30041446cf6dc3e0eab344fc62770e84c23b6b68a3b657821f9f80cb69b4/regex-2026.4.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2c785939dc023a1ce4ec09599c032cc9933d258a998d16ca6f2b596c010940eb", size = 292061, upload-time = "2026-04-03T20:53:41.862Z" }, - { url = "https://files.pythonhosted.org/packages/62/c8/3baa06d75c98c46d4cc4262b71fd2edb9062b5665e868bca57859dadf93a/regex-2026.4.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b1ce5c81c9114f1ce2f9288a51a8fd3aeea33a0cc440c415bf02da323aa0a76", size = 289628, upload-time = "2026-04-03T20:53:43.701Z" }, - { url = "https://files.pythonhosted.org/packages/31/87/3accf55634caad8c0acab23f5135ef7d4a21c39f28c55c816ae012931408/regex-2026.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:760ef21c17d8e6a4fe8cf406a97cf2806a4df93416ccc82fc98d25b1c20425be", size = 796651, upload-time = "2026-04-03T20:53:45.379Z" }, - { url = "https://files.pythonhosted.org/packages/f6/0c/aaa2c83f34efedbf06f61cb1942c25f6cf1ee3b200f832c4d05f28306c2e/regex-2026.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7088fcdcb604a4417c208e2169715800d28838fefd7455fbe40416231d1d47c1", size = 865916, upload-time = "2026-04-03T20:53:47.064Z" }, - { url = "https://files.pythonhosted.org/packages/d9/f6/8c6924c865124643e8f37823eca845dc27ac509b2ee58123685e71cd0279/regex-2026.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:07edca1ba687998968f7db5bc355288d0c6505caa7374f013d27356d93976d13", size = 912287, upload-time = "2026-04-03T20:53:49.422Z" }, - { url = "https://files.pythonhosted.org/packages/11/0e/a9f6f81013e0deaf559b25711623864970fe6a098314e374ccb1540a4152/regex-2026.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:993f657a7c1c6ec51b5e0ba97c9817d06b84ea5fa8d82e43b9405de0defdc2b9", size = 801126, upload-time = "2026-04-03T20:53:51.096Z" }, - { url = "https://files.pythonhosted.org/packages/71/61/3a0cc8af2dc0c8deb48e644dd2521f173f7e6513c6e195aad9aa8dd77ac5/regex-2026.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2b69102a743e7569ebee67e634a69c4cb7e59d6fa2e1aa7d3bdbf3f61435f62d", size = 776788, upload-time = "2026-04-03T20:53:52.889Z" }, - { url = "https://files.pythonhosted.org/packages/64/0b/8bb9cbf21ef7dee58e49b0fdb066a7aded146c823202e16494a36777594f/regex-2026.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dac006c8b6dda72d86ea3d1333d45147de79a3a3f26f10c1cf9287ca4ca0ac3", size = 785184, upload-time = "2026-04-03T20:53:55.627Z" }, - { url = "https://files.pythonhosted.org/packages/99/c2/d3e80e8137b25ee06c92627de4e4d98b94830e02b3e6f81f3d2e3f504cf5/regex-2026.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:50a766ee2010d504554bfb5f578ed2e066898aa26411d57e6296230627cdefa0", size = 859913, upload-time = "2026-04-03T20:53:57.249Z" }, - { url = "https://files.pythonhosted.org/packages/bc/e6/9d5d876157d969c804622456ef250017ac7a8f83e0e14f903b9e6df5ce95/regex-2026.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:9e2f5217648f68e3028c823df58663587c1507a5ba8419f4fdfc8a461be76043", size = 765732, upload-time = "2026-04-03T20:53:59.428Z" }, - { url = "https://files.pythonhosted.org/packages/82/80/b568935b4421388561c8ed42aff77247285d3ae3bb2a6ca22af63bae805e/regex-2026.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:39d8de85a08e32632974151ba59c6e9140646dcc36c80423962b1c5c0a92e244", size = 852152, upload-time = "2026-04-03T20:54:01.505Z" }, - { url = "https://files.pythonhosted.org/packages/39/29/f0f81217e21cd998245da047405366385d5c6072048038a3d33b37a79dc0/regex-2026.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:55d9304e0e7178dfb1e106c33edf834097ddf4a890e2f676f6c5118f84390f73", size = 789076, upload-time = "2026-04-03T20:54:03.323Z" }, - { url = "https://files.pythonhosted.org/packages/49/1d/1d957a61976ab9d4e767dd4f9d04b66cc0c41c5e36cf40e2d43688b5ae6f/regex-2026.4.4-cp312-cp312-win32.whl", hash = "sha256:04bb679bc0bde8a7bfb71e991493d47314e7b98380b083df2447cda4b6edb60f", size = 266700, upload-time = "2026-04-03T20:54:05.639Z" }, - { url = "https://files.pythonhosted.org/packages/c5/5c/bf575d396aeb58ea13b06ef2adf624f65b70fafef6950a80fc3da9cae3bc/regex-2026.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:db0ac18435a40a2543dbb3d21e161a6c78e33e8159bd2e009343d224bb03bb1b", size = 277768, upload-time = "2026-04-03T20:54:07.312Z" }, - { url = "https://files.pythonhosted.org/packages/c9/27/049df16ec6a6828ccd72add3c7f54b4df029669bea8e9817df6fff58be90/regex-2026.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:4ce255cc05c1947a12989c6db801c96461947adb7a59990f1360b5983fab4983", size = 270568, upload-time = "2026-04-03T20:54:09.484Z" }, - { url = "https://files.pythonhosted.org/packages/9d/83/c4373bc5f31f2cf4b66f9b7c31005bd87fe66f0dce17701f7db4ee79ee29/regex-2026.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:62f5519042c101762509b1d717b45a69c0139d60414b3c604b81328c01bd1943", size = 490273, upload-time = "2026-04-03T20:54:11.202Z" }, - { url = "https://files.pythonhosted.org/packages/46/f8/fe62afbcc3cf4ad4ac9adeaafd98aa747869ae12d3e8e2ac293d0593c435/regex-2026.4.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3790ba9fb5dd76715a7afe34dbe603ba03f8820764b1dc929dd08106214ed031", size = 291954, upload-time = "2026-04-03T20:54:13.412Z" }, - { url = "https://files.pythonhosted.org/packages/5a/92/4712b9fe6a33d232eeb1c189484b80c6c4b8422b90e766e1195d6e758207/regex-2026.4.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8fae3c6e795d7678963f2170152b0d892cf6aee9ee8afc8c45e6be38d5107fe7", size = 289487, upload-time = "2026-04-03T20:54:15.824Z" }, - { url = "https://files.pythonhosted.org/packages/88/2c/f83b93f85e01168f1070f045a42d4c937b69fdb8dd7ae82d307253f7e36e/regex-2026.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:298c3ec2d53225b3bf91142eb9691025bab610e0c0c51592dde149db679b3d17", size = 796646, upload-time = "2026-04-03T20:54:18.229Z" }, - { url = "https://files.pythonhosted.org/packages/df/55/61a2e17bf0c4dc57e11caf8dd11771280d8aaa361785f9e3bc40d653f4a7/regex-2026.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e9638791082eaf5b3ac112c587518ee78e083a11c4b28012d8fe2a0f536dfb17", size = 865904, upload-time = "2026-04-03T20:54:20.019Z" }, - { url = "https://files.pythonhosted.org/packages/45/32/1ac8ed1b5a346b5993a3d256abe0a0f03b0b73c8cc88d928537368ac65b6/regex-2026.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ae3e764bd4c5ff55035dc82a8d49acceb42a5298edf6eb2fc4d328ee5dd7afae", size = 912304, upload-time = "2026-04-03T20:54:22.403Z" }, - { url = "https://files.pythonhosted.org/packages/26/47/2ee5c613ab546f0eddebf9905d23e07beb933416b1246c2d8791d01979b4/regex-2026.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ffa81f81b80047ba89a3c69ae6a0f78d06f4a42ce5126b0eb2a0a10ad44e0b2e", size = 801126, upload-time = "2026-04-03T20:54:24.308Z" }, - { url = "https://files.pythonhosted.org/packages/75/cd/41dacd129ca9fd20bd7d02f83e0fad83e034ac8a084ec369c90f55ef37e2/regex-2026.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f56ebf9d70305307a707911b88469213630aba821e77de7d603f9d2f0730687d", size = 776772, upload-time = "2026-04-03T20:54:26.319Z" }, - { url = "https://files.pythonhosted.org/packages/89/6d/5af0b588174cb5f46041fa7dd64d3fd5cd2fe51f18766703d1edc387f324/regex-2026.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:773d1dfd652bbffb09336abf890bfd64785c7463716bf766d0eb3bc19c8b7f27", size = 785228, upload-time = "2026-04-03T20:54:28.387Z" }, - { url = "https://files.pythonhosted.org/packages/b7/3b/f5a72b7045bd59575fc33bf1345f156fcfd5a8484aea6ad84b12c5a82114/regex-2026.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d51d20befd5275d092cdffba57ded05f3c436317ee56466c8928ac32d960edaf", size = 860032, upload-time = "2026-04-03T20:54:30.641Z" }, - { url = "https://files.pythonhosted.org/packages/39/a4/72a317003d6fcd7a573584a85f59f525dfe8f67e355ca74eb6b53d66a5e2/regex-2026.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:0a51cdb3c1e9161154f976cb2bef9894bc063ac82f31b733087ffb8e880137d0", size = 765714, upload-time = "2026-04-03T20:54:32.789Z" }, - { url = "https://files.pythonhosted.org/packages/25/1e/5672e16f34dbbcb2560cc7e6a2fbb26dfa8b270711e730101da4423d3973/regex-2026.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ae5266a82596114e41fb5302140e9630204c1b5f325c770bec654b95dd54b0aa", size = 852078, upload-time = "2026-04-03T20:54:34.546Z" }, - { url = "https://files.pythonhosted.org/packages/f7/0d/c813f0af7c6cc7ed7b9558bac2e5120b60ad0fa48f813e4d4bd55446f214/regex-2026.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c882cd92ec68585e9c1cf36c447ec846c0d94edd706fe59e0c198e65822fd23b", size = 789181, upload-time = "2026-04-03T20:54:36.642Z" }, - { url = "https://files.pythonhosted.org/packages/ea/6d/a344608d1adbd2a95090ddd906cec09a11be0e6517e878d02a5123e0917f/regex-2026.4.4-cp313-cp313-win32.whl", hash = "sha256:05568c4fbf3cb4fa9e28e3af198c40d3237cf6041608a9022285fe567ec3ad62", size = 266690, upload-time = "2026-04-03T20:54:38.343Z" }, - { url = "https://files.pythonhosted.org/packages/31/07/54049f89b46235ca6f45cd6c88668a7050e77d4a15555e47dd40fde75263/regex-2026.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:3384df51ed52db0bea967e21458ab0a414f67cdddfd94401688274e55147bb81", size = 277733, upload-time = "2026-04-03T20:54:40.11Z" }, - { url = "https://files.pythonhosted.org/packages/0e/21/61366a8e20f4d43fb597708cac7f0e2baadb491ecc9549b4980b2be27d16/regex-2026.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:acd38177bd2c8e69a411d6521760806042e244d0ef94e2dd03ecdaa8a3c99427", size = 270565, upload-time = "2026-04-03T20:54:41.883Z" }, - { url = "https://files.pythonhosted.org/packages/f1/1e/3a2b9672433bef02f5d39aa1143ca2c08f311c1d041c464a42be9ae648dc/regex-2026.4.4-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:f94a11a9d05afcfcfa640e096319720a19cc0c9f7768e1a61fceee6a3afc6c7c", size = 494126, upload-time = "2026-04-03T20:54:43.602Z" }, - { url = "https://files.pythonhosted.org/packages/4e/4b/c132a4f4fe18ad3340d89fcb56235132b69559136036b845be3c073142ed/regex-2026.4.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:36bcb9d6d1307ab629edc553775baada2aefa5c50ccc0215fbfd2afcfff43141", size = 293882, upload-time = "2026-04-03T20:54:45.41Z" }, - { url = "https://files.pythonhosted.org/packages/f4/5f/eaa38092ce7a023656280f2341dbbd4ad5f05d780a70abba7bb4f4bea54c/regex-2026.4.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:261c015b3e2ed0919157046d768774ecde57f03d8fa4ba78d29793447f70e717", size = 292334, upload-time = "2026-04-03T20:54:47.051Z" }, - { url = "https://files.pythonhosted.org/packages/5f/f6/dd38146af1392dac33db7074ab331cec23cced3759167735c42c5460a243/regex-2026.4.4-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c228cf65b4a54583763645dcd73819b3b381ca8b4bb1b349dee1c135f4112c07", size = 811691, upload-time = "2026-04-03T20:54:49.074Z" }, - { url = "https://files.pythonhosted.org/packages/7a/f0/dc54c2e69f5eeec50601054998ec3690d5344277e782bd717e49867c1d29/regex-2026.4.4-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dd2630faeb6876fb0c287f664d93ddce4d50cd46c6e88e60378c05c9047e08ca", size = 871227, upload-time = "2026-04-03T20:54:51.035Z" }, - { url = "https://files.pythonhosted.org/packages/a1/af/cb16bd5dc61621e27df919a4449bbb7e5a1034c34d307e0a706e9cc0f3e3/regex-2026.4.4-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6a50ab11b7779b849472337191f3a043e27e17f71555f98d0092fa6d73364520", size = 917435, upload-time = "2026-04-03T20:54:52.994Z" }, - { url = "https://files.pythonhosted.org/packages/5c/71/8b260897f22996b666edd9402861668f45a2ca259f665ac029e6104a2d7d/regex-2026.4.4-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0734f63afe785138549fbe822a8cfeaccd1bae814c5057cc0ed5b9f2de4fc883", size = 816358, upload-time = "2026-04-03T20:54:54.884Z" }, - { url = "https://files.pythonhosted.org/packages/1c/60/775f7f72a510ef238254906c2f3d737fc80b16ca85f07d20e318d2eea894/regex-2026.4.4-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c4ee50606cb1967db7e523224e05f32089101945f859928e65657a2cbb3d278b", size = 785549, upload-time = "2026-04-03T20:54:57.01Z" }, - { url = "https://files.pythonhosted.org/packages/58/42/34d289b3627c03cf381e44da534a0021664188fa49ba41513da0b4ec6776/regex-2026.4.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6c1818f37be3ca02dcb76d63f2c7aaba4b0dc171b579796c6fbe00148dfec6b1", size = 801364, upload-time = "2026-04-03T20:54:58.981Z" }, - { url = "https://files.pythonhosted.org/packages/fc/20/f6ecf319b382a8f1ab529e898b222c3f30600fcede7834733c26279e7465/regex-2026.4.4-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:f5bfc2741d150d0be3e4a0401a5c22b06e60acb9aa4daa46d9e79a6dcd0f135b", size = 866221, upload-time = "2026-04-03T20:55:00.88Z" }, - { url = "https://files.pythonhosted.org/packages/92/6a/9f16d3609d549bd96d7a0b2aee1625d7512ba6a03efc01652149ef88e74d/regex-2026.4.4-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:504ffa8a03609a087cad81277a629b6ce884b51a24bd388a7980ad61748618ff", size = 772530, upload-time = "2026-04-03T20:55:03.213Z" }, - { url = "https://files.pythonhosted.org/packages/fa/f6/aa9768bc96a4c361ac96419fbaf2dcdc33970bb813df3ba9b09d5d7b6d96/regex-2026.4.4-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:70aadc6ff12e4b444586e57fc30771f86253f9f0045b29016b9605b4be5f7dfb", size = 856989, upload-time = "2026-04-03T20:55:05.087Z" }, - { url = "https://files.pythonhosted.org/packages/4d/b4/c671db3556be2473ae3e4bb7a297c518d281452871501221251ea4ecba57/regex-2026.4.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f4f83781191007b6ef43b03debc35435f10cad9b96e16d147efe84a1d48bdde4", size = 803241, upload-time = "2026-04-03T20:55:07.162Z" }, - { url = "https://files.pythonhosted.org/packages/2a/5c/83e3b1d89fa4f6e5a1bc97b4abd4a9a97b3c1ac7854164f694f5f0ba98a0/regex-2026.4.4-cp313-cp313t-win32.whl", hash = "sha256:e014a797de43d1847df957c0a2a8e861d1c17547ee08467d1db2c370b7568baa", size = 269921, upload-time = "2026-04-03T20:55:09.62Z" }, - { url = "https://files.pythonhosted.org/packages/28/07/077c387121f42cdb4d92b1301133c0d93b5709d096d1669ab847dda9fe2e/regex-2026.4.4-cp313-cp313t-win_amd64.whl", hash = "sha256:b15b88b0d52b179712632832c1d6e58e5774f93717849a41096880442da41ab0", size = 281240, upload-time = "2026-04-03T20:55:11.521Z" }, - { url = "https://files.pythonhosted.org/packages/9d/22/ead4a4abc7c59a4d882662aa292ca02c8b617f30b6e163bc1728879e9353/regex-2026.4.4-cp313-cp313t-win_arm64.whl", hash = "sha256:586b89cdadf7d67bf86ae3342a4dcd2b8d70a832d90c18a0ae955105caf34dbe", size = 272440, upload-time = "2026-04-03T20:55:13.365Z" }, - { url = "https://files.pythonhosted.org/packages/f0/f5/ed97c2dc47b5fbd4b73c0d7d75f9ebc8eca139f2bbef476bba35f28c0a77/regex-2026.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:2da82d643fa698e5e5210e54af90181603d5853cf469f5eedf9bfc8f59b4b8c7", size = 490343, upload-time = "2026-04-03T20:55:15.241Z" }, - { url = "https://files.pythonhosted.org/packages/80/e9/de4828a7385ec166d673a5790ad06ac48cdaa98bc0960108dd4b9cc1aef7/regex-2026.4.4-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:54a1189ad9d9357760557c91103d5e421f0a2dabe68a5cdf9103d0dcf4e00752", size = 291909, upload-time = "2026-04-03T20:55:17.558Z" }, - { url = "https://files.pythonhosted.org/packages/b4/d6/5cfbfc97f3201a4d24b596a77957e092030dcc4205894bc035cedcfce62f/regex-2026.4.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:76d67d5afb1fe402d10a6403bae668d000441e2ab115191a804287d53b772951", size = 289692, upload-time = "2026-04-03T20:55:20.561Z" }, - { url = "https://files.pythonhosted.org/packages/8e/ac/f2212d9fd56fe897e36d0110ba30ba2d247bd6410c5bd98499c7e5a1e1f2/regex-2026.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e7cd3e4ee8d80447a83bbc9ab0c8459781fa77087f856c3e740d7763be0df27f", size = 796979, upload-time = "2026-04-03T20:55:22.56Z" }, - { url = "https://files.pythonhosted.org/packages/c9/e3/a016c12675fbac988a60c7e1c16e67823ff0bc016beb27bd7a001dbdabc6/regex-2026.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2e19e18c568d2866d8b6a6dfad823db86193503f90823a8f66689315ba28fbe8", size = 866744, upload-time = "2026-04-03T20:55:24.646Z" }, - { url = "https://files.pythonhosted.org/packages/af/a4/0b90ca4cf17adc3cb43de80ec71018c37c88ad64987e8d0d481a95ca60b5/regex-2026.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7698a6f38730fd1385d390d1ed07bb13dce39aa616aca6a6d89bea178464b9a4", size = 911613, upload-time = "2026-04-03T20:55:27.033Z" }, - { url = "https://files.pythonhosted.org/packages/8e/3b/2b3dac0b82d41ab43aa87c6ecde63d71189d03fe8854b8ca455a315edac3/regex-2026.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:173a66f3651cdb761018078e2d9487f4cf971232c990035ec0eb1cdc6bf929a9", size = 800551, upload-time = "2026-04-03T20:55:29.532Z" }, - { url = "https://files.pythonhosted.org/packages/25/fe/5365eb7aa0e753c4b5957815c321519ecab033c279c60e1b1ae2367fa810/regex-2026.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fa7922bbb2cc84fa062d37723f199d4c0cd200245ce269c05db82d904db66b83", size = 776911, upload-time = "2026-04-03T20:55:31.526Z" }, - { url = "https://files.pythonhosted.org/packages/aa/b3/7fb0072156bba065e3b778a7bc7b0a6328212be5dd6a86fd207e0c4f2dab/regex-2026.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:59f67cd0a0acaf0e564c20bbd7f767286f23e91e2572c5703bf3e56ea7557edb", size = 785751, upload-time = "2026-04-03T20:55:33.797Z" }, - { url = "https://files.pythonhosted.org/packages/02/1a/9f83677eb699273e56e858f7bd95acdbee376d42f59e8bfca2fd80d79df3/regex-2026.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:475e50f3f73f73614f7cba5524d6de49dee269df00272a1b85e3d19f6d498465", size = 860484, upload-time = "2026-04-03T20:55:35.745Z" }, - { url = "https://files.pythonhosted.org/packages/3b/7a/93937507b61cfcff8b4c5857f1b452852b09f741daa9acae15c971d8554e/regex-2026.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:a1c0c7d67b64d85ac2e1879923bad2f08a08f3004055f2f406ef73c850114bd4", size = 765939, upload-time = "2026-04-03T20:55:37.972Z" }, - { url = "https://files.pythonhosted.org/packages/86/ea/81a7f968a351c6552b1670ead861e2a385be730ee28402233020c67f9e0f/regex-2026.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:1371c2ccbb744d66ee63631cc9ca12aa233d5749972626b68fe1a649dd98e566", size = 851417, upload-time = "2026-04-03T20:55:39.92Z" }, - { url = "https://files.pythonhosted.org/packages/4c/7e/323c18ce4b5b8f44517a36342961a0306e931e499febbd876bb149d900f0/regex-2026.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:59968142787042db793348a3f5b918cf24ced1f23247328530e063f89c128a95", size = 789056, upload-time = "2026-04-03T20:55:42.303Z" }, - { url = "https://files.pythonhosted.org/packages/c0/af/e7510f9b11b1913b0cd44eddb784b2d650b2af6515bfce4cffcc5bfd1d38/regex-2026.4.4-cp314-cp314-win32.whl", hash = "sha256:59efe72d37fd5a91e373e5146f187f921f365f4abc1249a5ab446a60f30dd5f8", size = 272130, upload-time = "2026-04-03T20:55:44.995Z" }, - { url = "https://files.pythonhosted.org/packages/9a/51/57dae534c915e2d3a21490e88836fa2ae79dde3b66255ecc0c0a155d2c10/regex-2026.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:e0aab3ff447845049d676827d2ff714aab4f73f340e155b7de7458cf53baa5a4", size = 280992, upload-time = "2026-04-03T20:55:47.316Z" }, - { url = "https://files.pythonhosted.org/packages/0a/5e/abaf9f4c3792e34edb1434f06717fae2b07888d85cb5cec29f9204931bf8/regex-2026.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:a7a5bb6aa0cf62208bb4fa079b0c756734f8ad0e333b425732e8609bd51ee22f", size = 273563, upload-time = "2026-04-03T20:55:49.273Z" }, - { url = "https://files.pythonhosted.org/packages/ff/06/35da85f9f217b9538b99cbb170738993bcc3b23784322decb77619f11502/regex-2026.4.4-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:97850d0638391bdc7d35dc1c1039974dcb921eaafa8cc935ae4d7f272b1d60b3", size = 494191, upload-time = "2026-04-03T20:55:51.258Z" }, - { url = "https://files.pythonhosted.org/packages/54/5b/1bc35f479eef8285c4baf88d8c002023efdeebb7b44a8735b36195486ae7/regex-2026.4.4-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:ee7337f88f2a580679f7bbfe69dc86c043954f9f9c541012f49abc554a962f2e", size = 293877, upload-time = "2026-04-03T20:55:53.214Z" }, - { url = "https://files.pythonhosted.org/packages/39/5b/f53b9ad17480b3ddd14c90da04bfb55ac6894b129e5dea87bcaf7d00e336/regex-2026.4.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7429f4e6192c11d659900c0648ba8776243bf396ab95558b8c51a345afeddde6", size = 292410, upload-time = "2026-04-03T20:55:55.736Z" }, - { url = "https://files.pythonhosted.org/packages/bb/56/52377f59f60a7c51aa4161eecf0b6032c20b461805aca051250da435ffc9/regex-2026.4.4-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc4f10fbd5dd13dcf4265b4cc07d69ca70280742870c97ae10093e3d66000359", size = 811831, upload-time = "2026-04-03T20:55:57.802Z" }, - { url = "https://files.pythonhosted.org/packages/dd/63/8026310bf066f702a9c361f83a8c9658f3fe4edb349f9c1e5d5273b7c40c/regex-2026.4.4-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a152560af4f9742b96f3827090f866eeec5becd4765c8e0d3473d9d280e76a5a", size = 871199, upload-time = "2026-04-03T20:56:00.333Z" }, - { url = "https://files.pythonhosted.org/packages/20/9f/a514bbb00a466dbb506d43f187a04047f7be1505f10a9a15615ead5080ee/regex-2026.4.4-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:54170b3e95339f415d54651f97df3bff7434a663912f9358237941bbf9143f55", size = 917649, upload-time = "2026-04-03T20:56:02.445Z" }, - { url = "https://files.pythonhosted.org/packages/cb/6b/8399f68dd41a2030218839b9b18360d79b86d22b9fab5ef477c7f23ca67c/regex-2026.4.4-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:07f190d65f5a72dcb9cf7106bfc3d21e7a49dd2879eda2207b683f32165e4d99", size = 816388, upload-time = "2026-04-03T20:56:04.595Z" }, - { url = "https://files.pythonhosted.org/packages/1e/9c/103963f47c24339a483b05edd568594c2be486188f688c0170fd504b2948/regex-2026.4.4-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9a2741ce5a29d3c84b0b94261ba630ab459a1b847a0d6beca7d62d188175c790", size = 785746, upload-time = "2026-04-03T20:56:07.13Z" }, - { url = "https://files.pythonhosted.org/packages/fa/ee/7f6054c0dec0cee3463c304405e4ff42e27cff05bf36fcb34be549ab17bd/regex-2026.4.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:b26c30df3a28fd9793113dac7385a4deb7294a06c0f760dd2b008bd49a9139bc", size = 801483, upload-time = "2026-04-03T20:56:09.365Z" }, - { url = "https://files.pythonhosted.org/packages/30/c2/51d3d941cf6070dc00c3338ecf138615fc3cce0421c3df6abe97a08af61a/regex-2026.4.4-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:421439d1bee44b19f4583ccf42670ca464ffb90e9fdc38d37f39d1ddd1e44f1f", size = 866331, upload-time = "2026-04-03T20:56:12.039Z" }, - { url = "https://files.pythonhosted.org/packages/16/e8/76d50dcc122ac33927d939f350eebcfe3dbcbda96913e03433fc36de5e63/regex-2026.4.4-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:b40379b53ecbc747fd9bdf4a0ea14eb8188ca1bd0f54f78893a39024b28f4863", size = 772673, upload-time = "2026-04-03T20:56:14.558Z" }, - { url = "https://files.pythonhosted.org/packages/a5/6e/5f6bf75e20ea6873d05ba4ec78378c375cbe08cdec571c83fbb01606e563/regex-2026.4.4-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:08c55c13d2eef54f73eeadc33146fb0baaa49e7335eb1aff6ae1324bf0ddbe4a", size = 857146, upload-time = "2026-04-03T20:56:16.663Z" }, - { url = "https://files.pythonhosted.org/packages/0b/33/3c76d9962949e487ebba353a18e89399f292287204ac8f2f4cfc3a51c233/regex-2026.4.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9776b85f510062f5a75ef112afe5f494ef1635607bf1cc220c1391e9ac2f5e81", size = 803463, upload-time = "2026-04-03T20:56:18.923Z" }, - { url = "https://files.pythonhosted.org/packages/19/eb/ef32dcd2cb69b69bc0c3e55205bce94a7def48d495358946bc42186dcccc/regex-2026.4.4-cp314-cp314t-win32.whl", hash = "sha256:385edaebde5db5be103577afc8699fea73a0e36a734ba24870be7ffa61119d74", size = 275709, upload-time = "2026-04-03T20:56:20.996Z" }, - { url = "https://files.pythonhosted.org/packages/a0/86/c291bf740945acbf35ed7dbebf8e2eea2f3f78041f6bd7cdab80cb274dc0/regex-2026.4.4-cp314-cp314t-win_amd64.whl", hash = "sha256:5d354b18839328927832e2fa5f7c95b7a3ccc39e7a681529e1685898e6436d45", size = 285622, upload-time = "2026-04-03T20:56:23.641Z" }, - { url = "https://files.pythonhosted.org/packages/d5/e7/ec846d560ae6a597115153c02ca6138a7877a1748b2072d9521c10a93e58/regex-2026.4.4-cp314-cp314t-win_arm64.whl", hash = "sha256:af0384cb01a33600c49505c27c6c57ab0b27bf84a74e28524c92ca897ebdac9d", size = 275773, upload-time = "2026-04-03T20:56:26.07Z" }, +version = "2026.6.28" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/05/e4f219230e11e774a6c9987d2ab0d0c6b8573e13a17e143d0015bee710ef/regex-2026.6.28.tar.gz", hash = "sha256:3cb4b6c5cb3060cc31efdc1fbb27c25fb9b29044afd87e40601a1c4d9db54342", size = 416101, upload-time = "2026-06-28T19:56:55.302Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/72/db/9051b36294bdbabaa9c7db57db0fbcdfbd17f7a106c539bb423d0323faea/regex-2026.6.28-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a71b51dd08b9b62f055fafab3dee8af8bd2ec81b373a44caef18d6c5ca28f43a", size = 489481, upload-time = "2026-06-28T19:53:36.684Z" }, + { url = "https://files.pythonhosted.org/packages/35/3f/24097a3c3ff30f9a639888900faaecabcf5f54a5bc9c851c297e11b349ef/regex-2026.6.28-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9c26a47770d30a0f85c01e261d2a3ebc342c4af6fd666dbd8c1fe4cbf3adf726", size = 291292, upload-time = "2026-06-28T19:53:38.39Z" }, + { url = "https://files.pythonhosted.org/packages/5e/cc/e0d762a189cfb4e8926d16e691720690d139a977b38fdb80230c259332ab/regex-2026.6.28-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e5efbc1af38f97e300d43028e5a92e752d924bcfb7f465d8669d5d5a6e78c233", size = 289232, upload-time = "2026-06-28T19:53:40.181Z" }, + { url = "https://files.pythonhosted.org/packages/4b/c8/ca0ac7f09cc88ca61e0c61c53f7db29334f660ffba5d0b52378e7c44723c/regex-2026.6.28-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f1758df6fdd8c800620a5638958720e8a635e1da49a2f09df2dd63e94a24ec4a", size = 792332, upload-time = "2026-06-28T19:53:41.782Z" }, + { url = "https://files.pythonhosted.org/packages/8e/92/04ae94cbe0dd1f478b2aef6c46f995bb6946d3e338d4b28605478b66a2b7/regex-2026.6.28-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ad73ecf20c1ef5c975639f8bf845a9370fcf7dada7edc1e3b0bca20e2f8202f6", size = 861743, upload-time = "2026-06-28T19:53:43.261Z" }, + { url = "https://files.pythonhosted.org/packages/4c/ec/024d7638c807679ff8a0e6081d01d66c7762339af1cac71e45911587ff9a/regex-2026.6.28-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4d80c798b0eec6ea3d45f8816a1e8886c5664615d347d89e8c075b576a1b5a5d", size = 906481, upload-time = "2026-06-28T19:53:44.948Z" }, + { url = "https://files.pythonhosted.org/packages/cd/fd/93bfe5af45f0be4fa8983945455c0e6924e1aeb879cde227958869c1e71c/regex-2026.6.28-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a361feeaf1b6ba1df060f2ff5c5947092edf537a35ce78e76387ac56d3e0f4a4", size = 799867, upload-time = "2026-06-28T19:53:46.997Z" }, + { url = "https://files.pythonhosted.org/packages/ee/fd/e5d965d41f2398c8ce0f37a4652f03bb297fd009bb796d390134225dda12/regex-2026.6.28-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8b92366d9c8bba9642989534073662abdd9b41faf7603a7ae71597833f3b88f0", size = 773632, upload-time = "2026-06-28T19:53:48.892Z" }, + { url = "https://files.pythonhosted.org/packages/eb/d9/ff39afaec92b9ee2dba0302a4783976005091681069808938c31cf8df3b6/regex-2026.6.28-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:11251768cc23f097dd61b18f67966e70f74da822784d17e12a444eb6b29d4288", size = 781669, upload-time = "2026-06-28T19:53:50.693Z" }, + { url = "https://files.pythonhosted.org/packages/45/4e/e2fd4bb8228e10c24af2d7ff867182372190e498eab9fd29cbe54c403c95/regex-2026.6.28-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ad5c67786145ec28a71a267d9f9d92bdc8d70d65541eea852c253f520a01f918", size = 854497, upload-time = "2026-06-28T19:53:52.323Z" }, + { url = "https://files.pythonhosted.org/packages/72/7c/f0340384a973082979064156d05f3d2cc1dced7371efcd7a1b45726a1a8a/regex-2026.6.28-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:f1da438e739765c3e85175ede05816cbede3caaacb1e0680568bda6119bfdfca", size = 763335, upload-time = "2026-06-28T19:53:54.024Z" }, + { url = "https://files.pythonhosted.org/packages/e1/32/90ce0d0898e205506cc22b9c81cfb16b722e06ca5f50fad51c053c2a727b/regex-2026.6.28-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d98b639046e51c5de64d9f77351532105e99ca271cb6f7640e1f903d6ab63032", size = 844615, upload-time = "2026-06-28T19:53:56.216Z" }, + { url = "https://files.pythonhosted.org/packages/6a/ef/55abb149599dce1ade687170557129524011eeb3d92afe02429cea7754a2/regex-2026.6.28-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e164ace4dbab5c6ad4a4ac7c41a2638fe226d0c770a86f2eb041f594bac6ee7", size = 789193, upload-time = "2026-06-28T19:53:57.791Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ea/cf7f6f6f152e52fdad978b913bf24c14df647eca0f81ef31f3aee0be8982/regex-2026.6.28-cp311-cp311-win32.whl", hash = "sha256:3169a3159e4d99d9ae85ff0ed90ef3b8906cc3152653b6078b842ace6c8f72c3", size = 266731, upload-time = "2026-06-28T19:53:59.938Z" }, + { url = "https://files.pythonhosted.org/packages/c6/cf/a48d8e8d406b22481cad146f48fa0dfca3c5f402b91f26d8e5a0fe4f513d/regex-2026.6.28-cp311-cp311-win_amd64.whl", hash = "sha256:5977295b0a74e8241df8a4b3b27b12412a831f6fa32ee8b755039592cd768c3d", size = 277918, upload-time = "2026-06-28T19:54:01.502Z" }, + { url = "https://files.pythonhosted.org/packages/89/b2/a222392207db7ed86281a732a99f7cf7f2bb35d332799e892b8510be000e/regex-2026.6.28-cp311-cp311-win_arm64.whl", hash = "sha256:f5fbaef40c3e9282ccee4b075f5600a0d858aa0c34147732f1baa69c8188a95d", size = 276876, upload-time = "2026-06-28T19:54:03.411Z" }, + { url = "https://files.pythonhosted.org/packages/da/21/44aa415873032056c43eac21c67285deb2cf66cddb2a964c3cdc8f803efc/regex-2026.6.28-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:81cc5793ad33a10444445e8d29d3c73e752c8fb2e120772d70fcb6d41df40fe1", size = 490480, upload-time = "2026-06-28T19:54:05.392Z" }, + { url = "https://files.pythonhosted.org/packages/8b/5f/30d4116093c2128099f78b6990dfc1698fdbf3ee528f1e1c647378034c79/regex-2026.6.28-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e18225243250a1f7d7e5e5d883f3b96465cd79031acf5c6db902b7025f2125d9", size = 292137, upload-time = "2026-06-28T19:54:07.088Z" }, + { url = "https://files.pythonhosted.org/packages/cb/0e/ca20a0e0de49837e6337603a91ab77556aa27033ac5b975615d98698cfb3/regex-2026.6.28-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ecd1638b1c2db1f2d01c182a4b0d3e2e88b0e99910320a745c1727ee3638ddab", size = 289623, upload-time = "2026-06-28T19:54:08.762Z" }, + { url = "https://files.pythonhosted.org/packages/50/11/c013422a7e2c59946df8ac93e792a4922c98287f2a2181341603c78a5d98/regex-2026.6.28-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4303ebe16b74eeb3fe2715745023266fea92fd44a23f3e7bb2fb48c7a7bbc195", size = 796756, upload-time = "2026-06-28T19:54:10.616Z" }, + { url = "https://files.pythonhosted.org/packages/b0/95/1309645a0e1ee6fb91d954501da57a0b33d50ad2a9acb313702851a7054e/regex-2026.6.28-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56b856b70b96c381d837f609eee442a1bd320cd2159f5c294b679552fb1a7eaf", size = 865465, upload-time = "2026-06-28T19:54:12.742Z" }, + { url = "https://files.pythonhosted.org/packages/20/06/491802db47c6f5e2904ffa2518ad3ac27fe6bbf5a66d73210a95cc080d47/regex-2026.6.28-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f74675ab76ab1d005ffba4dee308e53e89efc22be6e9f9fae5b539a3f81bdff2", size = 912350, upload-time = "2026-06-28T19:54:14.508Z" }, + { url = "https://files.pythonhosted.org/packages/5e/60/3ba57840bcc7e2367090360de0c15a5ba6ad22be89314251105f2e943f43/regex-2026.6.28-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:90581684565a93f7258af1e5d3f41ef20d7d7c61f2a428183a342bcb65485e38", size = 801261, upload-time = "2026-06-28T19:54:16.432Z" }, + { url = "https://files.pythonhosted.org/packages/eb/27/af1eb74e9a78c782b3e450b611a595e44906da8a5107e1227f4a7fd0480b/regex-2026.6.28-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:28f9e6c28f9b90f6f784595a33240a57e181e61b6ee3dc259b25c61e356d1aa3", size = 777072, upload-time = "2026-06-28T19:54:18.128Z" }, + { url = "https://files.pythonhosted.org/packages/20/18/fdd4c883a39e3ed00d669062af1135809bfd3281bf528150849fbd68825b/regex-2026.6.28-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:378a71d861fc7c8806b04ac5b133d53c0e774f92f5d9663a539872d3fa2b0417", size = 785119, upload-time = "2026-06-28T19:54:20.314Z" }, + { url = "https://files.pythonhosted.org/packages/1c/79/0aabe34b8482dcadf64355f70f96e22eba5ec6c1efb33563f89654f4061c/regex-2026.6.28-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4cc199874ecd6267a49b111052250825bfe19b5101b23b2ba80f54efa3e0994e", size = 860118, upload-time = "2026-06-28T19:54:22.368Z" }, + { url = "https://files.pythonhosted.org/packages/a8/2c/c973323306a27c9db7d160e9584eb7e0ece2a96224ccb0d39060558b31f9/regex-2026.6.28-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:b916a10431494ef4b4d62c6c89cab6426af7873125b8cd6c15811bf5fc58eec8", size = 765786, upload-time = "2026-06-28T19:54:24.265Z" }, + { url = "https://files.pythonhosted.org/packages/e3/df/9ca3e378e352242a4cb45573a5e9162c3ee791507702a23966fa559e36b5/regex-2026.6.28-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:2e27727fba075f1e4409416d2f537d4c30fc11f012ea507f7bd74d3e19ecb57a", size = 852120, upload-time = "2026-06-28T19:54:25.972Z" }, + { url = "https://files.pythonhosted.org/packages/a2/3e/3e31e255c4971f53cbce6306b5e3c76cbd3735a54f419bb3b2f194e9f68c/regex-2026.6.28-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:700fc6a7844bb2c4149292ac79d1df8841a00acd4d45cd32c1ebc7bcc1fd0da8", size = 789503, upload-time = "2026-06-28T19:54:27.678Z" }, + { url = "https://files.pythonhosted.org/packages/72/01/d36561c21c3033d7eeb31d51b491916817de7861acefccc5fc9db8a5037c/regex-2026.6.28-cp312-cp312-win32.whl", hash = "sha256:03376d60b6a11aecb88a79fa2be06b40faa01c6693bc31ef69435cd4818b9463", size = 267109, upload-time = "2026-06-28T19:54:29.316Z" }, + { url = "https://files.pythonhosted.org/packages/a0/59/bbbb0591f38b18c65977cd65ce64749eba1c1996c99ac04e900fc30c0dcb/regex-2026.6.28-cp312-cp312-win_amd64.whl", hash = "sha256:fbd2ded482bf99e6651992bbfcde460272724d4bbc49ef3d6b46d9312867ec84", size = 277711, upload-time = "2026-06-28T19:54:31.143Z" }, + { url = "https://files.pythonhosted.org/packages/86/06/be4f6b337d773ae5739a1bc238f97c16926e72017243735853c030f4c628/regex-2026.6.28-cp312-cp312-win_arm64.whl", hash = "sha256:37294d3d7ddb64c7e89184b2894e0f8f0a19c514bc59513d71fe692c3a8d5fc6", size = 277022, upload-time = "2026-06-28T19:54:32.97Z" }, + { url = "https://files.pythonhosted.org/packages/b6/53/d5c1b3cc0b5a0c985563ad6fac93d73ff2b300cb84342d89f044625d6bc7/regex-2026.6.28-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:b295a83426e0e44e9e60fde99789e181bd26788a1890ae7fe2a24c69bb6246ca", size = 490329, upload-time = "2026-06-28T19:54:35.775Z" }, + { url = "https://files.pythonhosted.org/packages/8d/9f/0c3503e819e91ca0e7a901a8e989ebf840ac7c7aea20b1fc7f31b6759f77/regex-2026.6.28-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0c31665c0deb5c111557a1cac8c27bd5629e2f9e7fd5058900a03576c33b601c", size = 292039, upload-time = "2026-06-28T19:54:37.977Z" }, + { url = "https://files.pythonhosted.org/packages/bb/7f/cd004e13fcad23b3794a82307dfd222e6365eb7f598bd3caab148a830bff/regex-2026.6.28-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6bf295f2c59de77d1ea7de053607ae4dc9ceb3d57bbb6c7ec51ef4acc4ccff94", size = 289488, upload-time = "2026-06-28T19:54:39.545Z" }, + { url = "https://files.pythonhosted.org/packages/73/4c/293fb34586fbcdc47eac436069e9c11f71fae5dadfd4889b475d7d2e5f7a/regex-2026.6.28-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:17c077586770f67e05bbffeba07fbee6b2b22244f4d4caf8d94e59d574befe04", size = 796772, upload-time = "2026-06-28T19:54:41.347Z" }, + { url = "https://files.pythonhosted.org/packages/92/fa/c0cd1a90b7d12d9dc155cfc8bdea8df9720988ea5b07e8fa1eccbd0ab2dd/regex-2026.6.28-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0e6cb5a61486f9062397d2e189573b39d38ecfaed698fd9fb6e2756a8ebb8762", size = 865467, upload-time = "2026-06-28T19:54:43.485Z" }, + { url = "https://files.pythonhosted.org/packages/4e/db/0b479973046d005a1eaea299d5d536aeecb9488a16d9cbb8286338102e2d/regex-2026.6.28-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e86e91a2664f44c3a4e363a7d78fb17c27d5046882e30ea5a877f5e89b28d2ba", size = 912345, upload-time = "2026-06-28T19:54:46.091Z" }, + { url = "https://files.pythonhosted.org/packages/5b/5b/d65adfbd02f32212431bca1f06d1e2eb763a20b12978b454bafaf23dacb7/regex-2026.6.28-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4dfd1331c49233998d84fc5f1f4436cf7a435a7655f6cf0f490229bb5c7254e5", size = 801291, upload-time = "2026-06-28T19:54:48.3Z" }, + { url = "https://files.pythonhosted.org/packages/fc/09/2103686defaf9a0a31c1663782359d5b45f42524c64cca681f5481e44a5e/regex-2026.6.28-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cadea12805a1bce0b091c302b814207be26fb60a9c0e7f9ad2f9e21790a429fe", size = 777106, upload-time = "2026-06-28T19:54:50.326Z" }, + { url = "https://files.pythonhosted.org/packages/85/5a/b57593c0aa23ed269ec332fbcf07852abcb6b746e811d9464e0d09b4e25f/regex-2026.6.28-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5f2c1682b67ad5d2376498f2a5a2a8f782fa2e4a06d0465b5e357799806e8a20", size = 785175, upload-time = "2026-06-28T19:54:52.172Z" }, + { url = "https://files.pythonhosted.org/packages/79/59/c36e756ad29bf14d7b6c6d7138952476b21f6160286cedb98ac13481c993/regex-2026.6.28-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:64e142eb55e84868087da1375d7c36ff97d55010951849f515322a91d5fef1b4", size = 860186, upload-time = "2026-06-28T19:54:54.11Z" }, + { url = "https://files.pythonhosted.org/packages/61/66/49808aea0da9649c300139360708fb91b7144be1f962fcebf96755fde948/regex-2026.6.28-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:abb4daabe7be63273787a62dfd6164dadf8f7a63fbec3d2730e5e5e7126d858c", size = 765754, upload-time = "2026-06-28T19:54:56.04Z" }, + { url = "https://files.pythonhosted.org/packages/be/c5/52bbd436cf2200decdf48825fa38363eaaeebb77011ea9928a1ef9e0b9f2/regex-2026.6.28-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ec2b2ad00ab8c16a2798cc8db80c53c4d5b8b3a2441f6cbaef06625f5ca25854", size = 852085, upload-time = "2026-06-28T19:54:57.988Z" }, + { url = "https://files.pythonhosted.org/packages/f9/c3/0390b66e3019497143fe768b3ba567b64d8b24f3812d09506deb86f4a0f0/regex-2026.6.28-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bfc9677982c914d9085b8e1c3b3ae6e88f139fb56531c2416d6c8f338093c22b", size = 789600, upload-time = "2026-06-28T19:54:59.977Z" }, + { url = "https://files.pythonhosted.org/packages/88/fd/ab5b03653a244975069fed93d73f4f5f7484c03a84cedb238292510d7182/regex-2026.6.28-cp313-cp313-win32.whl", hash = "sha256:bf54bc693fc4e0530e666ba5ec4bcba14dbe8f66b7cfc15c27317d1a6e40b9a5", size = 267088, upload-time = "2026-06-28T19:55:02.159Z" }, + { url = "https://files.pythonhosted.org/packages/68/55/21022f7d3143210ae8d4ff905c45306237b657375cc0b97883f49db3d423/regex-2026.6.28-cp313-cp313-win_amd64.whl", hash = "sha256:e128feaf65bf3d9eb91bec92322a8f7e4835e9c798f3e9ea4b69f4def85620e3", size = 277680, upload-time = "2026-06-28T19:55:04.185Z" }, + { url = "https://files.pythonhosted.org/packages/b6/99/7f664804f1aef924542b0b233996b78b3e4d0a52d9951358aac99f129f51/regex-2026.6.28-cp313-cp313-win_arm64.whl", hash = "sha256:695873e0ea8d3815ea9e92e2c68faf039cc450e2c0a62a31afe2049eb11be767", size = 277017, upload-time = "2026-06-28T19:55:06.29Z" }, + { url = "https://files.pythonhosted.org/packages/cb/e1/9eb83518e159d719fd681c4932dc2aaff855ce72451e1d05d69466f25a96/regex-2026.6.28-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:189dbf9fc4252d9f1352bf4bd1bef885edb6cc4b7341df202a65f821aaa3891c", size = 494195, upload-time = "2026-06-28T19:55:08.292Z" }, + { url = "https://files.pythonhosted.org/packages/fd/e2/e259c5f2f7be269d0e2fb54275c1fa6a13fb47019f389c3f3ae457447825/regex-2026.6.28-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:9277a4c6503390aa39cb4483b87ec0384faee0850a23b5cea33d008b5d8d83f1", size = 293976, upload-time = "2026-06-28T19:55:10.014Z" }, + { url = "https://files.pythonhosted.org/packages/8d/4e/9bdf444014d22b045d0c82ca114fac7e07a597b5b5331b7c4ce6328426e2/regex-2026.6.28-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:17eddca4e8ea9af0b5739314776cdf0172a49731ab61f2e1ea66e066ddd46c97", size = 292340, upload-time = "2026-06-28T19:55:11.88Z" }, + { url = "https://files.pythonhosted.org/packages/fd/3a/f49b11e59cbfe187ace0053a460bd72a0169b8cd52e7db9421a074ce7a43/regex-2026.6.28-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e4466b8641e00c697aab5a73150150d2b2ea96b131c595691f42031abafd9f4d", size = 811704, upload-time = "2026-06-28T19:55:13.612Z" }, + { url = "https://files.pythonhosted.org/packages/2f/fb/ad04c39e149bf8b6cf357df5fff78341733ec366780a00c803a36735818c/regex-2026.6.28-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9cfcd4b0bdcf768c498415c170d1ed2a25a99bf0b65fa253bbd02f68ceba6475", size = 871157, upload-time = "2026-06-28T19:55:15.797Z" }, + { url = "https://files.pythonhosted.org/packages/7f/64/0e5ba31c11eb8ef7aac19a690c1211fc9aa9990caf09565785ebb0081b9a/regex-2026.6.28-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:80c7adf1ef647f6b1e8aa2ca280e517174cd08bdf7a2e412cdfb68bd6a0917cb", size = 917287, upload-time = "2026-06-28T19:55:18.692Z" }, + { url = "https://files.pythonhosted.org/packages/11/75/6b78df2b858c2fcbbc4858fdc3f2975cf2703be374b2842db7d2c32591a7/regex-2026.6.28-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a043f5770e82283a22aed4cefef1a4e0f9dd8fd7184cb6ce0ad2e579e2134a9e", size = 816333, upload-time = "2026-06-28T19:55:20.973Z" }, + { url = "https://files.pythonhosted.org/packages/b4/01/ecfe665a3694d5eda9f3ec686c856438ada0943947b6005e90556a1e2cdf/regex-2026.6.28-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3bd630a8dba06b55254ea5ee862194edab52ec783100d2ef1cd15a9c512fee27", size = 785518, upload-time = "2026-06-28T19:55:23.003Z" }, + { url = "https://files.pythonhosted.org/packages/b4/0a/88f9cd88ff1e82881605c4ffd62d77ee67d051232cfe6f8e9a64b86cf0e8/regex-2026.6.28-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b77207e3cee13086f1906a6a2a12b41244c577e8ad9370d4b35ae1d548d354f3", size = 801371, upload-time = "2026-06-28T19:55:24.888Z" }, + { url = "https://files.pythonhosted.org/packages/a8/97/601483732f93275482ceb9fed57813dfed7c47d3a019db6ec4a3bb6e23e0/regex-2026.6.28-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:6de82c268e5d101ee9e3ffd869924aa9a371e3a21e752cf4fa17b6ce50d219f7", size = 866517, upload-time = "2026-06-28T19:55:27.232Z" }, + { url = "https://files.pythonhosted.org/packages/81/ed/385c2a0351b994a693453c1d1a6e9af9eb35db3c9460d76b5078acd70c62/regex-2026.6.28-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:b15859e3908544fb99cf47341dcf0bfd089147d258c4c4d8a29e5b087f8085cb", size = 772834, upload-time = "2026-06-28T19:55:29.154Z" }, + { url = "https://files.pythonhosted.org/packages/06/bc/bbf4a5b3b29770d7f307d3c28b5b1bca0105b0cb424be0a4eb1339bc92cf/regex-2026.6.28-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:c91487a917edd48a1ea646fdf60d7936d304f0e686fa7ea8326e47efca51d816", size = 856606, upload-time = "2026-06-28T19:55:32.186Z" }, + { url = "https://files.pythonhosted.org/packages/28/26/51d74fff82f682819979249f8d700267108ba5dc4eb284b0e11b9c85e4b3/regex-2026.6.28-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4ac65f3e3a99fd8f3a4a74e7a6610acd1ce9dfe9b8a03d346a4922380d68aeb", size = 803475, upload-time = "2026-06-28T19:55:34.328Z" }, + { url = "https://files.pythonhosted.org/packages/7c/3e/6be10cefdc813533fe604dbf5d3c77d2638e7ee658b2749ebadc113b6b2e/regex-2026.6.28-cp313-cp313t-win32.whl", hash = "sha256:3f6316f258bc7e6c9c2acbe9954947bbd397a81be3742a637a555f1855d6618d", size = 269126, upload-time = "2026-06-28T19:55:36.565Z" }, + { url = "https://files.pythonhosted.org/packages/3c/3c/32cda905ea1a6eeeb798291c294d8ec66ee0efe0cdba28b061e248b1d396/regex-2026.6.28-cp313-cp313t-win_amd64.whl", hash = "sha256:1484bdd6fba28422df9b5ebb04055b2e1b680e8e4f08490bb21ff0f3cc50d0ab", size = 279961, upload-time = "2026-06-28T19:55:38.456Z" }, + { url = "https://files.pythonhosted.org/packages/ea/b9/69f4e5cd6fbe0bb420cb2dbae441ca118f2495bdda522a74da75aa9829e7/regex-2026.6.28-cp313-cp313t-win_arm64.whl", hash = "sha256:3f15020f0b69cafe57baa067ff65b29acef68ff6b1670a53bef1ca11d708e02d", size = 279266, upload-time = "2026-06-28T19:55:40.62Z" }, + { url = "https://files.pythonhosted.org/packages/3b/fb/fad3b810a5bb1e09b9e5d6913fc6ba88cab738fdf283196827a3c59a4c10/regex-2026.6.28-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:f7c032b0c8a73739ff8ff1aaf30c281fa19c17bf7f1543256c8507390db7807c", size = 490407, upload-time = "2026-06-28T19:55:42.724Z" }, + { url = "https://files.pythonhosted.org/packages/d6/52/b8c79d12276d93e90e707e939b396034c04980caf1235312ef790f8e11fc/regex-2026.6.28-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:f6710f512c57b84f127a23d0f59560a03b64136eff419ae1be5ab557577fe5e3", size = 291988, upload-time = "2026-06-28T19:55:44.549Z" }, + { url = "https://files.pythonhosted.org/packages/23/d2/6a911f18279daa8d7bb8b20d771ddb6ef31fabd35f5921f9d3ba21640e80/regex-2026.6.28-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c0013958f427bd82509a186b9ff206d66cb8d60a81fc797a4c717afd18c5b0ba", size = 289704, upload-time = "2026-06-28T19:55:46.365Z" }, + { url = "https://files.pythonhosted.org/packages/fd/22/ad1955c47c669291a05804d53d7071cc0732dfdf166857be38003cedc2d1/regex-2026.6.28-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94f06cdcd6421f8e194ad312ea608020381250df9b8a57661c1b57e9e5273878", size = 797017, upload-time = "2026-06-28T19:55:48.166Z" }, + { url = "https://files.pythonhosted.org/packages/e5/67/a83159ff8703ab4d0c2cf99e76ebf289b7b4a501623241d09f88f3614f80/regex-2026.6.28-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ec9689392f7494ff4e3f8e7e8522f9158f11023f337eaaf04a64542fc45bbf26", size = 866112, upload-time = "2026-06-28T19:55:51.047Z" }, + { url = "https://files.pythonhosted.org/packages/b9/09/7bff2d6dbbd77421b3274aa51db1c887381cbc5b6eda93598c3e882ea345/regex-2026.6.28-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:aa084684e6d2078bf6139e374d1fc2af5ddc1ac7122759a2db716d68169f6fd0", size = 911554, upload-time = "2026-06-28T19:55:53.707Z" }, + { url = "https://files.pythonhosted.org/packages/29/44/ae59c3826e7ba492e56795cdf74ea2a7b5b7c5ea116afb79ee4956a5dff1/regex-2026.6.28-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:40455e6840dc4e96a6fe50f4cedc957de2752c954d91e789812be55d49be199a", size = 800665, upload-time = "2026-06-28T19:55:55.875Z" }, + { url = "https://files.pythonhosted.org/packages/d6/19/6fd033d2ab00f35d445aaeaf3307c1e721424dcbfd48f6f65c857cb939cf/regex-2026.6.28-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:530b5c223b9ca5dd8370ac502e080aee0e4ded32be987c6564b425fb5523d581", size = 777243, upload-time = "2026-06-28T19:55:57.909Z" }, + { url = "https://files.pythonhosted.org/packages/4e/9d/99730f26df4938049ab1e652ca75e967b4c6739444e18d9707bfdb8af20c/regex-2026.6.28-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e0ed273ecd1a89be84466c1749bfe58609cc2a32b5d5e05006c4625ba96411b", size = 785784, upload-time = "2026-06-28T19:56:00.072Z" }, + { url = "https://files.pythonhosted.org/packages/48/49/105cd57162f5fc5c04cc917a1388a060cf8427e5c14353cd9044660fbf4d/regex-2026.6.28-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:0ab0d5344311fc8e8667078942056c3b9c9b4a4b1cc99f2eb8a5af54554f4acc", size = 860914, upload-time = "2026-06-28T19:56:02.017Z" }, + { url = "https://files.pythonhosted.org/packages/a2/a5/788245a95b69018f58bff2f4fd27d007cacaea088cdb390979743f1b2571/regex-2026.6.28-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:eacb79625323d9f7e7925366b917f492b8356fad58f5dc4fa12ff8c21d8f4ca9", size = 765915, upload-time = "2026-06-28T19:56:05.021Z" }, + { url = "https://files.pythonhosted.org/packages/ca/01/292065a39a004b05e67a337b18213670a7cb919d6856ac2d7df7f1a10dbb/regex-2026.6.28-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:20f4d87702702aa1d572721e146f301660c50eef6fd6cb596e48a22b0ace17db", size = 851404, upload-time = "2026-06-28T19:56:07.251Z" }, + { url = "https://files.pythonhosted.org/packages/98/9e/a93d865db0e13483ae1a01d81e2ce16d4a7fe2f9b9fe4aac4cc08590b136/regex-2026.6.28-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1e693940a3b9e6d6e4dc2a54ecaa74b74934f77af1ef95f518a74261ef7cc1bc", size = 789373, upload-time = "2026-06-28T19:56:09.894Z" }, + { url = "https://files.pythonhosted.org/packages/82/0c/38b1685ad4017d78efbc8fa7dbbf96d8113b53750c8aa2d3609defd46605/regex-2026.6.28-cp314-cp314-win32.whl", hash = "sha256:234a51e20ebc18ab83b2c0600cf28f2e884560a0e00f743878f0b7d8e7c4cf03", size = 272496, upload-time = "2026-06-28T19:56:11.83Z" }, + { url = "https://files.pythonhosted.org/packages/55/50/e19f261ff9ba9b50722a529e09b1743ecf65eb348be99d0fd2cd7fcede1c/regex-2026.6.28-cp314-cp314-win_amd64.whl", hash = "sha256:7b15c437bc4604f03ceb3f8d37eae2f8930e320e1bc556b259848c639d9eec1a", size = 280754, upload-time = "2026-06-28T19:56:13.758Z" }, + { url = "https://files.pythonhosted.org/packages/36/b8/c9e68f3a9e33be73f20990b2c065b144ff2d0aa242608a950d8c4f3b56e8/regex-2026.6.28-cp314-cp314-win_arm64.whl", hash = "sha256:c6e6f790d01380a74ad564f216c533b86504afb61bf66f2b2e11e7f1a3e287a7", size = 280979, upload-time = "2026-06-28T19:56:15.928Z" }, + { url = "https://files.pythonhosted.org/packages/03/e6/21c425a37880c650d007c4171c6a80325446d830d85f5fbf335e7205b1e7/regex-2026.6.28-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:3527a72adcbe9e3600f1553b497d397c1a371d227580d41d96c3c5964109b65c", size = 494282, upload-time = "2026-06-28T19:56:18.049Z" }, + { url = "https://files.pythonhosted.org/packages/07/50/6647a7ccf5ffff995ba955a0b7d766440f4e58ce1666549c8ee998f2b972/regex-2026.6.28-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:a644f6408692812f5ead82519eed680e08d5d546fddbd9f7d9514e3c73899aa5", size = 293977, upload-time = "2026-06-28T19:56:20.145Z" }, + { url = "https://files.pythonhosted.org/packages/8c/dc/a3e141a4eaf125e50f63105570c01fa477c06ac5259dcfa95e9b90760e84/regex-2026.6.28-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8e2fae6bb883648346f84db270dc9aafc29d8e895f62b88a75ccc83b09519820", size = 292432, upload-time = "2026-06-28T19:56:22.345Z" }, + { url = "https://files.pythonhosted.org/packages/35/ee/2ac1a6b9f167f8ff69f5a789938cc103b60cff41b24a6990daced8b88e34/regex-2026.6.28-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:debe623e09cee97ef9404575e936c610aac9bb08358c5099aaef14644a6871f2", size = 811877, upload-time = "2026-06-28T19:56:25.056Z" }, + { url = "https://files.pythonhosted.org/packages/df/7b/9a5505ee92180bcae300b1018b9ff3d3c19962436e66f2505f255e9fde35/regex-2026.6.28-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cc579c91fb4605773483a8d940b136bcc5b854fff44fa14a1572a038f46563f1", size = 871212, upload-time = "2026-06-28T19:56:27.352Z" }, + { url = "https://files.pythonhosted.org/packages/24/4d/d61a702a9f9d1bd29b22cbef1aed6d477baa961232a7eb4d91b7775b0b3e/regex-2026.6.28-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e7c42be203d84ecf7d487ff23f8a61ef0eb0534fa0fc317a2fce8c065d20618f", size = 917507, upload-time = "2026-06-28T19:56:29.762Z" }, + { url = "https://files.pythonhosted.org/packages/d4/60/1308066f5966b65fbb6905b99ba37e9f1cd753dd0ac08485f8257334ee92/regex-2026.6.28-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8184b4e2fdaf9cdfe77e38f15a4d9dc149168c9c29eb0ea17c5481d3bb80546", size = 816389, upload-time = "2026-06-28T19:56:32.043Z" }, + { url = "https://files.pythonhosted.org/packages/bd/5c/57ce2cb8d714ee0b7f11c7ee4cfe2af66df2b90f147feadcb538609a3a02/regex-2026.6.28-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:697f103104f5872d64078d8eeac59979960be8ee76115a2d3f31096312e2a400", size = 785890, upload-time = "2026-06-28T19:56:34.492Z" }, + { url = "https://files.pythonhosted.org/packages/ff/fd/1d5350d3a8a327bff0fccacb911732baf7b5b6f5529c0e3fa602a23e7dad/regex-2026.6.28-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:714d2b1aa29beef0ddfcdc72ad0771c05326551a8bb0680b0ddf74bfaad87387", size = 801451, upload-time = "2026-06-28T19:56:36.749Z" }, + { url = "https://files.pythonhosted.org/packages/f3/79/3c9e4f8a0306e030ad5a43bbbc01625fb28d58a813bc52d42fd1cc63fb2e/regex-2026.6.28-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0f09f62e450cc2f113018cc8412aeea3a120a04e1ca7e801a0d441583f9a3b06", size = 866504, upload-time = "2026-06-28T19:56:38.994Z" }, + { url = "https://files.pythonhosted.org/packages/65/12/f747de475b54f4709efb24dd0fbc8467c64cec91f5db0d047b079646ee78/regex-2026.6.28-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:731ea12d5aeb2577eaef2393d6428b995f76eb35f68a89e03e15a97719d1de19", size = 773047, upload-time = "2026-06-28T19:56:41.061Z" }, + { url = "https://files.pythonhosted.org/packages/58/3c/f02f860e0500c1b2d61a79dec7e214b37fb9656281dcddc92397edf96678/regex-2026.6.28-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:51e952c8783eabd4706d0f63922f219bcfc1bef9b8cb35941c0d1a0396578858", size = 856665, upload-time = "2026-06-28T19:56:43.466Z" }, + { url = "https://files.pythonhosted.org/packages/4d/6c/28b3fa222513484be9dee26b7222bda109056c43ea28aa2314262ca48816/regex-2026.6.28-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:43248fe4c0ab8fbb223588a0795b11268940072c97bba30ea8f9b49d8cdfde34", size = 803573, upload-time = "2026-06-28T19:56:45.791Z" }, + { url = "https://files.pythonhosted.org/packages/fa/f0/8f86cf1a1fd85c5ab0c503c9fe4607ad4ad48978b2d8b435d94465e134c7/regex-2026.6.28-cp314-cp314t-win32.whl", hash = "sha256:fc1eddc25ad23c0f1344ab280d961ac595ead48292d7c779497975942373f493", size = 274515, upload-time = "2026-06-28T19:56:47.948Z" }, + { url = "https://files.pythonhosted.org/packages/0f/de/f8613c03b36786ddef2c930d28f9bcae861fcd541cc9203a870956cf1e83/regex-2026.6.28-cp314-cp314t-win_amd64.whl", hash = "sha256:ede8d8e53b6dde0a50f7eca902f0af76d87ab02a55aba7542da68ae3e5dfe83d", size = 283650, upload-time = "2026-06-28T19:56:50.614Z" }, + { url = "https://files.pythonhosted.org/packages/4d/f3/f5ec86839bbabe33b6dee649b62ff9a445d43de6b0ad780cf6b83c56f61e/regex-2026.6.28-cp314-cp314t-win_arm64.whl", hash = "sha256:4da6f6a72f8700b97a1a765e837fb7d5750bfd9f13acea7bae498f573e3a70a8", size = 283338, upload-time = "2026-06-28T19:56:52.879Z" }, ] [[package]] name = "requests" -version = "2.33.1" +version = "2.34.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, @@ -2243,9 +2930,9 @@ dependencies = [ { name = "idna" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5f/a4/98b9c7c6428a668bf7e42ebb7c79d576a1c3c1e3ae2d47e674b468388871/requests-2.33.1.tar.gz", hash = "sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517", size = 134120, upload-time = "2026-03-30T16:09:15.531Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ac/c3/e2a2b89f2d3e2179abd6d00ebd70bff6273f37fb3e0cc209f48b39d00cbf/requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed", size = 142856, upload-time = "2026-05-14T19:25:27.735Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d7/8e/7540e8a2036f79a125c1d2ebadf69ed7901608859186c856fa0388ef4197/requests-2.33.1-py3-none-any.whl", hash = "sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a", size = 64947, upload-time = "2026-03-30T16:09:13.83Z" }, + { url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", size = 73075, upload-time = "2026-05-14T19:25:26.443Z" }, ] [[package]] @@ -2260,29 +2947,178 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06", size = 54481, upload-time = "2023-05-01T04:11:28.427Z" }, ] +[[package]] +name = "rich" +version = "15.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" }, +] + +[[package]] +name = "rpds-py" +version = "2026.6.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/2a/9618a122aeb2a169a28b03889a2995fe297588964333d4a7d67bdf46e147/rpds_py-2026.6.3.tar.gz", hash = "sha256:1cebd1337c242e4ec2293e541f712b2da849b29f48f0c293684b71c0632625d4", size = 64051, upload-time = "2026-06-30T07:17:53.009Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/1f/a2dca5ffdbf1d475ffc4e80e4d5d720ff3a00f691795910116960ee12511/rpds_py-2026.6.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:7b689145a1485c335569bd056464f3243a29af7ed3871c7be31ad624ba239bc7", size = 342174, upload-time = "2026-06-30T07:14:54.821Z" }, + { url = "https://files.pythonhosted.org/packages/4d/dc/323d08583c0832911768663d1944f0107fcd4088704858d84b5e06d105a0/rpds_py-2026.6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:db08f45aecde626498fb3df07bcf6d2ec040af42e859a4f5040d79c200342911", size = 345513, upload-time = "2026-06-30T07:14:56.515Z" }, + { url = "https://files.pythonhosted.org/packages/0b/2a/e31989834d18d2f26ec1d2774c5b1eb3331df4ea8ada525175294c94b48a/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:acc992ab27b15f852c76755eb2ab7dce86585ddadba6fa5946e58556088845b4", size = 373783, upload-time = "2026-06-30T07:14:57.736Z" }, + { url = "https://files.pythonhosted.org/packages/87/fe/e80107ee3639585c9941c17d6a42cd65325022f656c023191fce78c324c8/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f88d653e7b3b779d71ae7454e20dcc9b6bae903f33c269db9f2be41bda3f261", size = 378316, upload-time = "2026-06-30T07:14:59.077Z" }, + { url = "https://files.pythonhosted.org/packages/22/6f/81e3adf81acfb6fa694de2a6e4e7d8863121e3e0799e0a7725e6cf5679c4/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e52655eaf81e32593abedaa4bfe33170c8cfedf3365ed9be6e11e07f148f0278", size = 499423, upload-time = "2026-06-30T07:15:00.488Z" }, + { url = "https://files.pythonhosted.org/packages/2d/9a/41263969df0ce3d9af2a96d5005a288200af1989aed3354bfceb5fc0b21f/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dfcc8b909769d19db55c7cc9541eb64b9b774b1057ffffb4f1048070475bb9f9", size = 386077, upload-time = "2026-06-30T07:15:01.911Z" }, + { url = "https://files.pythonhosted.org/packages/5e/19/7e98f468bd50346faff5b10e5297374b443bfdddacc8e9fbc65984539597/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c1255b302953c86a486b81d330d5ee1d5bd937691ce271b6be0ef0e299eaab7", size = 371315, upload-time = "2026-06-30T07:15:03.317Z" }, + { url = "https://files.pythonhosted.org/packages/99/3c/2b973b4d371906a134b03decfea7f5d9835a2c6d263454392e15b64b5b18/rpds_py-2026.6.3-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:8d2294a31386bfa251d8c8a39472beee17db67d4f1a6eabea665d35c9a4461c3", size = 383502, upload-time = "2026-06-30T07:15:04.627Z" }, + { url = "https://files.pythonhosted.org/packages/98/2a/12e2799500af0a307bca76b63361c51f9fe479223561489c29eea1f2ee41/rpds_py-2026.6.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f8f23ead891a3b762f35ab3b04623da7056545b48aa60d59957e6789914545da", size = 402673, upload-time = "2026-06-30T07:15:05.856Z" }, + { url = "https://files.pythonhosted.org/packages/2d/e3/21e5872d165fe08be4f229e3d5ee9d90019c0bf0e5538de60dbd54009450/rpds_py-2026.6.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:421aba32367055614287a4292b6a17f1939c9452299f7a0209c117e990b646d4", size = 549964, upload-time = "2026-06-30T07:15:07.159Z" }, + { url = "https://files.pythonhosted.org/packages/1a/d0/5ee0fe36844297de8123bee27bc12078c1a7416ad9f1b8a8ca18d6b0c0ac/rpds_py-2026.6.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1e5822dfc2f0d4ab7e745eaa6d85945069329beeccef965af3f3bb26058fcab6", size = 615446, upload-time = "2026-06-30T07:15:08.531Z" }, + { url = "https://files.pythonhosted.org/packages/b1/80/1ea5873cb683f2fbe5f21b23ea1f6d179ead19f3c5b249b7eb5dca568ef2/rpds_py-2026.6.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:83e35b57523816c8613fd0776b40cd8bb9f596b37ddd2692eb4a6bb5ab2f8c93", size = 576975, upload-time = "2026-06-30T07:15:09.97Z" }, + { url = "https://files.pythonhosted.org/packages/c9/e1/90ef639217a5ddb15b7f4f61b1c33911fd044ad03c311bafdd2bcab85582/rpds_py-2026.6.3-cp311-cp311-win32.whl", hash = "sha256:de3eceba0b683bcbb1ab93da016d0270df1f9ae7be716b40214c5dafac6ea45a", size = 204453, upload-time = "2026-06-30T07:15:11.324Z" }, + { url = "https://files.pythonhosted.org/packages/f2/b7/b7a1695d7af36f521fb11e80d6d3adbd744f73b921859bd3c2a2c0dc706f/rpds_py-2026.6.3-cp311-cp311-win_amd64.whl", hash = "sha256:2c54a076ca4d370980ab57bc0e31df57bbe8d41340436a90ef8b1219a3cbb127", size = 223219, upload-time = "2026-06-30T07:15:12.476Z" }, + { url = "https://files.pythonhosted.org/packages/d7/a2/145afacf796e4506062825941176ad9445c2dcf2b3b6a1f13d3030a15e19/rpds_py-2026.6.3-cp311-cp311-win_arm64.whl", hash = "sha256:168c733a7112e071bb7a66460e667edfcff06c017a3c523f7a8a8e08d0140804", size = 219137, upload-time = "2026-06-30T07:15:13.631Z" }, + { url = "https://files.pythonhosted.org/packages/5c/be/2e8974163072e7bab7df1a5acd54c4498e75e35d6d18b864d3a9d5dadc92/rpds_py-2026.6.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a0811d33247c3d6128a3001d763f2aa056bb3425204335400ac54f89eec3a0d0", size = 343691, upload-time = "2026-06-30T07:15:14.96Z" }, + { url = "https://files.pythonhosted.org/packages/a4/73/319dfa745dd668efe89309141ded489126461fcecd2b8f3a3cda185129b6/rpds_py-2026.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:538949e262e46caa31ac01bdb3c1e8f642622922cacbabbae6a8445d9dc33eaf", size = 338542, upload-time = "2026-06-30T07:15:16.267Z" }, + { url = "https://files.pythonhosted.org/packages/21/63/4239893be1c4d09b709b1a8f6be4188f0870084ff547f46606b8a75f1b03/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55927d532399c2c646100ff7feb48eaa940ad70f42cd68e1328f3ded9f81ca24", size = 368180, upload-time = "2026-06-30T07:15:17.62Z" }, + { url = "https://files.pythonhosted.org/packages/1c/ca/9c5de382225234ceb37b1844ebdb140db12b2a278bb9efe2fcd19f6c82ce/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f56f1695bc5c0871cbc33dc0130fcf503aab0c57dcc5a6700a4f49eba4f2652e", size = 375067, upload-time = "2026-06-30T07:15:18.952Z" }, + { url = "https://files.pythonhosted.org/packages/87/dc/863f69d1bf04ade34b7fe0d59b9fdf6f0135fe2d7cbca74f1d665589559d/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:270b293dae9058fc9fcedab50f13cebf46fb8ed1d1d54e0521a9da5d6b211975", size = 490509, upload-time = "2026-06-30T07:15:20.434Z" }, + { url = "https://files.pythonhosted.org/packages/ce/ef/eac16a12048b45ec7c7fa94f2be3438a5f26bf9cc8580b18a1cfd609b7f6/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:127565fead0a10943b282957bd5447804ff3160ad79f2ad2635e6d249e380680", size = 382754, upload-time = "2026-06-30T07:15:21.831Z" }, + { url = "https://files.pythonhosted.org/packages/04/8f/d2f3f532616be4d06c316ef119683e832bd3d41e112bf3a88f4151c95b17/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecabd69db66de867690f9797f2f8fa27ba501bbc24540cbdbdc649cd15888ba6", size = 366189, upload-time = "2026-06-30T07:15:23.371Z" }, + { url = "https://files.pythonhosted.org/packages/e3/29/41a7b0e98a4b44cd676ab7598419623373eb43b20be68c084935c1a8cf88/rpds_py-2026.6.3-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:58eadac9cd119677b60e1cf8ac4052f35949d71b8a9e5556efccbe82533cf22a", size = 377750, upload-time = "2026-06-30T07:15:24.659Z" }, + { url = "https://files.pythonhosted.org/packages/2e/05/ecda0bec46f9a1565090bcdc941d023f6a25aff85fda28f89f8d19878152/rpds_py-2026.6.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7491ee23305ac3eb59e492b6945881f5cd77a6f731061a3f25b77fd40f9e99a4", size = 395576, upload-time = "2026-06-30T07:15:25.987Z" }, + { url = "https://files.pythonhosted.org/packages/68/a8/6ed52f03ee6cb854ce78785cc9a9a672eb880e83fd7224d471f667d151f1/rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2c99f7e8ccb3dd6e3e4bfeac657a7b208c9bac8075f4b078c02d7404c34107fa", size = 543807, upload-time = "2026-06-30T07:15:27.356Z" }, + { url = "https://files.pythonhosted.org/packages/8f/d6/156c0d3eea27ba09b92562ba2364ba124c0a061b199e17eac637cd25a5e2/rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:62698275682bf121181861295c9181e789030a2d516071f5b8f3c23c170cd0fc", size = 611187, upload-time = "2026-06-30T07:15:28.931Z" }, + { url = "https://files.pythonhosted.org/packages/f1/31/774212ed989c62f7f310220089f9b0a3fb8f40f5443d1727abd5d9f52bc9/rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a214c993455f99a89aaeadc9b21241900037adc9d97203e374d75513c5911822", size = 573030, upload-time = "2026-06-30T07:15:30.553Z" }, + { url = "https://files.pythonhosted.org/packages/c9/50/22f73127a41f1ce4f87fe39aadfb9a126345801c274aa93ae88456249327/rpds_py-2026.6.3-cp312-cp312-win32.whl", hash = "sha256:501f9f04a588d6a09179368c57071301445191767c64e4b52a6aa9871f1ef5ed", size = 202185, upload-time = "2026-06-30T07:15:32.027Z" }, + { url = "https://files.pythonhosted.org/packages/04/3a/f0ee4d4dde9d3b69dedf1b5f74e7a40017046d55052d173e418c6a94f960/rpds_py-2026.6.3-cp312-cp312-win_amd64.whl", hash = "sha256:2c958bf94822e9290a40aaf2a822d4bc5c88099093e3948ad6c571eca9272e5f", size = 220394, upload-time = "2026-06-30T07:15:33.359Z" }, + { url = "https://files.pythonhosted.org/packages/f3/83/3382fe37f809b59f02aac04dbc4e765b480b46ee0227ed516e3bdc4d3dfc/rpds_py-2026.6.3-cp312-cp312-win_arm64.whl", hash = "sha256:22bffe6042b9bcb0822bcd1955ec00e245daf17b4344e4ed8e9551b976b63e96", size = 215753, upload-time = "2026-06-30T07:15:34.778Z" }, + { url = "https://files.pythonhosted.org/packages/a4/9e/b818ee580026ec578138e961027a68820c40afeb1ec8f6819b54fb99e196/rpds_py-2026.6.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:3cfe765c1da0072636ca06628261e0ea05688e160d5c8a03e0217c3854037223", size = 343012, upload-time = "2026-06-30T07:15:36.005Z" }, + { url = "https://files.pythonhosted.org/packages/f3/6b/686d9dc4359a8f163cfbbf89ee0b4e586431de22fe8248edb63a8cf50d49/rpds_py-2026.6.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f4d78253f6996be4901669ad25319f842f740eccf4d58e3c7f3dd39e6dde1d8f", size = 338203, upload-time = "2026-06-30T07:15:37.462Z" }, + { url = "https://files.pythonhosted.org/packages/9e/9b/069aa329940f8207615e091f5eedbbd40e1e15eac68a0790fd05ccdf796c/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54f45a148e28767bf343d33a684693c70e451c6f4c0e9904709a723fafbdfc1f", size = 367984, upload-time = "2026-06-30T07:15:39.008Z" }, + { url = "https://files.pythonhosted.org/packages/14/db/34c203e4becff3703e4d3bc121842c00b8689197f398161203a880052f4e/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:842e7b070435622248c7a2c44ae53fa1440e073cc3023bc919fed570884097a7", size = 374815, upload-time = "2026-06-30T07:15:40.253Z" }, + { url = "https://files.pythonhosted.org/packages/ee/7d/8071067d2cc453d916ad836e828c943f575e8a44612537759002a1e07381/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8020133a74bd81b4572dd8e4be028a6b1ebcd70e6726edc3918008c08bee6ee6", size = 490545, upload-time = "2026-06-30T07:15:41.729Z" }, + { url = "https://files.pythonhosted.org/packages/a3/42/da06c5aa8f0484ff07f270787434204d9f4535e2f8c3b51ed402267e63c3/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cdc7e35386f3847df728fbcb5e887e2d79c19e2fa1eba9e51b6621d23e3243af", size = 382828, upload-time = "2026-06-30T07:15:43.327Z" }, + { url = "https://files.pythonhosted.org/packages/57/d7/fe978efc2ae50abe48eb7464668ea99f53c010c60aeebb7b35ad27f23661/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acac386b453c2516111b50985d60ce46e7fadb5ea71ae7b25f4c946935bf27cf", size = 365678, upload-time = "2026-06-30T07:15:44.992Z" }, + { url = "https://files.pythonhosted.org/packages/69/9d/1d8922e1990b2a6eb532b6ff53d3e73d2b3bbffc84116c75826bee73dfc6/rpds_py-2026.6.3-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:425560c6fa0415f27261727bb20bd097568485e5eb0c121f1949417d1c516885", size = 377811, upload-time = "2026-06-30T07:15:46.523Z" }, + { url = "https://files.pythonhosted.org/packages/b1/3d/198dceafb4fb034a6a47347e1b0735d34e0bd4a50be4e898d408ee66cb14/rpds_py-2026.6.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a550fb4950a06dde3beb4721f5ad4b25bf4513784665b0a8522c792e2bd822a4", size = 395382, upload-time = "2026-06-30T07:15:47.955Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f1/13968e49655d40b6b19d8b9140296bbc6f1d86b3f0f6c346cf9f1adddf4b/rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f4bca01b63096f606e095734dd56e74e175f94cfbf24ff3d63281cec61f7bb7", size = 543832, upload-time = "2026-06-30T07:15:49.33Z" }, + { url = "https://files.pythonhosted.org/packages/ac/ab/289bcb1b90bd3e40a2900c561fa0e2087345ecbb094f0b870f2345142b7c/rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ccffae9a092a00deb7efd545fe5e2c33c33b88e7c054337e9a74c179347d0b7d", size = 611011, upload-time = "2026-06-30T07:15:50.847Z" }, + { url = "https://files.pythonhosted.org/packages/1e/16/5043105e679436ccfbc8e5e0dd2d663ed18a8b8113515fd06a5e5d77c83e/rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1cf01971c4f2c5553b772a542e4aaf191789cd331bc2cd4ff0e6e65ba49e1e97", size = 572431, upload-time = "2026-06-30T07:15:52.394Z" }, + { url = "https://files.pythonhosted.org/packages/85/ed/adab103321c0a6565d5ae1c2998349bc3ee175b82ccc5ae8fc04cc413075/rpds_py-2026.6.3-cp313-cp313-win32.whl", hash = "sha256:8c3d1e9c15b9d51ca0391e13da1a25a0a4df3c58a37c9dc368e0736cf7f69df0", size = 201710, upload-time = "2026-06-30T07:15:53.894Z" }, + { url = "https://files.pythonhosted.org/packages/7b/ed/a03b09668e74e5dabbf2e211f6468e1820c0552f7b0500082da31841bf7b/rpds_py-2026.6.3-cp313-cp313-win_amd64.whl", hash = "sha256:9250a9a0a6fd4648b3f868da8d91a4c52b5811a62df58e753d50ae4454a36f80", size = 219454, upload-time = "2026-06-30T07:15:55.25Z" }, + { url = "https://files.pythonhosted.org/packages/27/17/b8642c12930b71bc2b25831f6708ccf0f75abcd11883932ec9ce54ba3a78/rpds_py-2026.6.3-cp313-cp313-win_arm64.whl", hash = "sha256:900a67df3fd1660b035a4761c4ce73c382ea6b35f90f9863c36c6fd8bf8b09bb", size = 215063, upload-time = "2026-06-30T07:15:56.573Z" }, + { url = "https://files.pythonhosted.org/packages/b6/36/7fbe9dcdaf857fb3f63c2a2284b62492d95f5e8334e947e5fb6e7f68c9be/rpds_py-2026.6.3-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:931908d9fc855d8f74783377822be318edb6dcb19e47169dc038f9a1bf60b06e", size = 344510, upload-time = "2026-06-30T07:15:57.921Z" }, + { url = "https://files.pythonhosted.org/packages/ba/54/f785cc3d3f60839ca57a5af4927a9f347b07b2799c373fc20f7949f87c7e/rpds_py-2026.6.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d7469697dce35be237db177d42e2a2ee26e6dcc5fc052078a6fefabd288c6edd", size = 339495, upload-time = "2026-06-30T07:15:59.238Z" }, + { url = "https://files.pythonhosted.org/packages/63/ef/d4cdaf309e6b095b43597103cf8c0b951d6cca2acce68c474f75ec12e0c7/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcfbcf66006befb9fd2aeaa9e01feaf881b4dc330a02ba07d2322b1c11be7b5d", size = 369454, upload-time = "2026-06-30T07:16:01.021Z" }, + { url = "https://files.pythonhosted.org/packages/96/4a/9559a68b7ee15db09d7981212e8c2e219d2a1d6d4faa0391d813c3496a36/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:847927daf4cffbd4e90e42bc890069897101edd015f956cb8721b3473372edda", size = 374583, upload-time = "2026-06-30T07:16:02.287Z" }, + { url = "https://files.pythonhosted.org/packages/ef/75/8964aa7d2c6e8ac43eba8eb6e6b0fdda1f46d39f2fc3e6aa9f2cb17f485d/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aca6c1ef08a82bfe327cc156da694660f599923e2e6665b6d81c9c2d0ac9ffc8", size = 492919, upload-time = "2026-06-30T07:16:03.723Z" }, + { url = "https://files.pythonhosted.org/packages/8f/97/6908094ac804115e65aedfd90f1b5fee4eebebd3f6c4cfc5419939267565/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ae50181a047c871561212bb97f7932a2d45fb53e947bd9b57ebad85b529cbc53", size = 383725, upload-time = "2026-06-30T07:16:05.305Z" }, + { url = "https://files.pythonhosted.org/packages/d1/9c/0d1fdc2e7aba23e290d603bc494e97bd205bae262ce33c6b32a69768ed5e/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc319e5a1de4b6913aac94bf6a2f9e847371e0a140a43dd4991db1a09bc2d504", size = 367255, upload-time = "2026-06-30T07:16:07.086Z" }, + { url = "https://files.pythonhosted.org/packages/c4/fe/f0209ca4a9ed074bc8acb44dfd0e81c3122e94c9689f5645b7973a866719/rpds_py-2026.6.3-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:e4316bf32babbed84e691e352faf967ce2f0f024174a8643c37c94a1080374fc", size = 379060, upload-time = "2026-06-30T07:16:08.525Z" }, + { url = "https://files.pythonhosted.org/packages/c6/8d/f1cc54c616b9d8897de8738aac148d20afca93f68187475fe194d09a71b9/rpds_py-2026.6.3-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8c6e5a2f750cc71c3e3b11d71661f21d6f9bc6cebc6564b1466417a1ec03ec77", size = 395960, upload-time = "2026-06-30T07:16:09.989Z" }, + { url = "https://files.pythonhosted.org/packages/fb/04/aafff00f73aeca2945f734f1d483c64ab8f472d0864ab02377fd8e89c3b2/rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4470ce197d4090875cf6affbf1f853338387428df97c4fb7b7106317b8214698", size = 545356, upload-time = "2026-06-30T07:16:11.816Z" }, + { url = "https://files.pythonhosted.org/packages/fd/cc/e229663b9e4ddac5a4acbe9085dd80a71af2a5d356b8b39d6bff233f24b0/rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ea964164cc9afa72d4d9b23cc28dafae93693c0a53e0b42acbff15b22c3f9ddd", size = 612319, upload-time = "2026-06-30T07:16:13.586Z" }, + { url = "https://files.pythonhosted.org/packages/e3/7a/8a0e6d3e6cd066af108b71b43122c3fe158dd9eb86acac626593a2582eb1/rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:639c8929aa0afe81be836b04de888460d6bed38b9c54cfc18da8f6bfabf5af5d", size = 573508, upload-time = "2026-06-30T07:16:15.23Z" }, + { url = "https://files.pythonhosted.org/packages/87/03/2a69ab618a789cf6cf85c86bb844c62d090e700ab1a2aa676b3741b6c516/rpds_py-2026.6.3-cp314-cp314-win32.whl", hash = "sha256:882076c00c0a608b131187055ddc5ae29f2e7eaf870d6168980420d58528a5c8", size = 202504, upload-time = "2026-06-30T07:16:16.893Z" }, + { url = "https://files.pythonhosted.org/packages/85/62/a3892ba945f4e24c78f352e5de3c7620d8479f73f211406a97263d13c7d2/rpds_py-2026.6.3-cp314-cp314-win_amd64.whl", hash = "sha256:0be972be84cfcaf46c8c6edf690ca0f154ac17babf1f6a955a51579b34ad2dc5", size = 220380, upload-time = "2026-06-30T07:16:18.108Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e7/c2bd44dc831931815ad11ebb5f430b5a0a4d3caa9de837107876c30c3432/rpds_py-2026.6.3-cp314-cp314-win_arm64.whl", hash = "sha256:2a9c6f195058cb45335e8cc3802745c603d716eb96bc9625950c1aac71c0c703", size = 215976, upload-time = "2026-06-30T07:16:19.654Z" }, + { url = "https://files.pythonhosted.org/packages/79/9c/fff7b74bce9a091ec9a012a03f9ff5f69364eaf9451060dfc4486da2ffdd/rpds_py-2026.6.3-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:f90938e92afda60266da758ee7d363447f7f0138c9559f9e1811629580582d90", size = 346840, upload-time = "2026-06-30T07:16:21.268Z" }, + { url = "https://files.pythonhosted.org/packages/e9/44/77bcb1168b33704908295533d27f10eb811e9e3e193e8993dc99572211d3/rpds_py-2026.6.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ec829541c45bca16e61c7ae50c20501f213605beb75d1aba91a6ee37fbbb56a4", size = 340282, upload-time = "2026-06-30T07:16:22.875Z" }, + { url = "https://files.pythonhosted.org/packages/87/3c/7a9081c7c9e645b39efe19e4ffbeccd80add246327cd9b888aecffd72317/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afd70d95892096cdb26f15a00c45907b17817577aa8d1c76b2dcc2788391f9e9", size = 370403, upload-time = "2026-06-30T07:16:24.415Z" }, + { url = "https://files.pythonhosted.org/packages/f7/69/af47021eb7dad6ff3396cb001c08f0f3c4d06c20253f75be6421a59fe6b7/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:29dfa0533a5d4c94d4dfa1b694fcb56c9c63aad8330ffdd816fd225d0a7a162f", size = 376055, upload-time = "2026-06-30T07:16:26.111Z" }, + { url = "https://files.pythonhosted.org/packages/81/fc/a3bcf517084396a6dd258c592567a3c011ba4557f2fde23dceaf26e74f2e/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:af05d726809bff6b141be124d4c7ce998f9c9c7f30edb1f46c07aa103d540b41", size = 494419, upload-time = "2026-06-30T07:16:27.596Z" }, + { url = "https://files.pythonhosted.org/packages/c9/eb/13d529d1788135425c7bf207f8463458ca5d92e43f3f701365b83e9dffc1/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9826217f048f620d9a712672818bf231442c1b35d96b227a07eabd11b4bb6945", size = 384848, upload-time = "2026-06-30T07:16:29.183Z" }, + { url = "https://files.pythonhosted.org/packages/8e/f4/b7ac49f30013aba8f7b9566b1dd07e81de95e708c1374b7bacc5b9bc5c9c/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:536bceea4fa4acf7e1c61da2b5786304367c816c8895be71b8f537c480b0ea1f", size = 371369, upload-time = "2026-06-30T07:16:30.912Z" }, + { url = "https://files.pythonhosted.org/packages/31/86/6260bafa622f788b07ddec0e52d810305c8b9b0b8c27f58a2ab04bf62b4f/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:bc0011654b91cc4fb2ae701bec0a0ba1e552c0714247fa7af6c59e0ccfa3a4e1", size = 379673, upload-time = "2026-06-30T07:16:32.486Z" }, + { url = "https://files.pythonhosted.org/packages/19/c3/03f1ee79a047b48daeca157c89a18509cde22b6b951d642b9b0af1be660a/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:539d75de9e0d536c84ff18dfeb805398e58227001ce09231a26a08b9aed1ee0e", size = 397500, upload-time = "2026-06-30T07:16:34.471Z" }, + { url = "https://files.pythonhosted.org/packages/f0/95/8ed0cd8c377dca12aea498f119fe639fc474d1461545c39d2b5872eb1c0f/rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:166cf54d9f44fc6ceb53c7860258dde44a81406646de79f8ed3234fca3b6e538", size = 545978, upload-time = "2026-06-30T07:16:36.45Z" }, + { url = "https://files.pythonhosted.org/packages/d3/f2/0eb57f0eaa83f8fc152a7e03de968ab77e1f00732bebc892b190c6eebde7/rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:d34c20167764fbcf927194d532dd7e0c56772f0a5f943fa5ef9e9afbba8fb9db", size = 613350, upload-time = "2026-06-30T07:16:38.213Z" }, + { url = "https://files.pythonhosted.org/packages/5b/de/e0674bdbc3ef7634989b3f854c3f34bc1f587d36e5bfdc5c378d57034619/rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ea7bb13b7c9a29791f87a0387ba7d3ad3a6d783d827e4d3f27b40a0ff44495e2", size = 576486, upload-time = "2026-06-30T07:16:39.797Z" }, + { url = "https://files.pythonhosted.org/packages/f2/f6/21101359743cd136ada781e8210a85769578422ba460672eea0e29739200/rpds_py-2026.6.3-cp314-cp314t-win32.whl", hash = "sha256:6de4744d05bd1aa1be4ed7ea1189e3979196808008113bbbf899a460966b925e", size = 201068, upload-time = "2026-06-30T07:16:41.316Z" }, + { url = "https://files.pythonhosted.org/packages/a6/b2/9574d4d44f7760c2aa32d92a0a4f41698e33f5b204a0bf5c9758f52c79d5/rpds_py-2026.6.3-cp314-cp314t-win_amd64.whl", hash = "sha256:c7b9a2f8f4d8e90af72571d3d495deebdd7e3c75451f5b41719aee166e940fc2", size = 220600, upload-time = "2026-06-30T07:16:43.091Z" }, + { url = "https://files.pythonhosted.org/packages/08/ae/f23a2697e6ee6340a578b0f136be6483657bef0c6f9497b752bb5c0964bb/rpds_py-2026.6.3-cp315-cp315-macosx_10_12_x86_64.whl", hash = "sha256:e059c5dde6452b44424bd1834557556c226b57781dee1227af23518459722b13", size = 344726, upload-time = "2026-06-30T07:16:44.5Z" }, + { url = "https://files.pythonhosted.org/packages/c3/63/e7b3a1a5358dd32c930a1062d8e15b67fd6e8922e81df9e91706d66ee5c8/rpds_py-2026.6.3-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:2f7c26fbc5acd2522b95d4177fe4710ffd8e9b20529e703ffbf8db4d93903f05", size = 339587, upload-time = "2026-06-30T07:16:46.255Z" }, + { url = "https://files.pythonhosted.org/packages/ec/64/10a85681916ca55fffb91b0a211f84e34297c109243484dd6394660a8a7c/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3086b538543802f84c843911242db20447de00d8752dd0efc936dbcf02218ba", size = 369585, upload-time = "2026-06-30T07:16:48.101Z" }, + { url = "https://files.pythonhosted.org/packages/76/c2/baf95c7c38823e12ba34407c5f5767a89e5cf2233895e56f608167ae9493/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8f2e5c5ee828d42cb11760761c0af6507927bec42d0ad5458f97c9203b054617", size = 375479, upload-time = "2026-06-30T07:16:49.93Z" }, + { url = "https://files.pythonhosted.org/packages/6a/94/0aad06c72d65101e11d33528d438cda99a39ce0da99466e156158f2541d3/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed0c1e5d10cdc7135537988c74a0188da68e2f3c30813ba3744ab1e42e0480f9", size = 492418, upload-time = "2026-06-30T07:16:51.641Z" }, + { url = "https://files.pythonhosted.org/packages/b5/17/de3f5a479a1f056535d7489819639d8cd591ea6281d700390b43b1abd745/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c2642a7603ec0b16ed77da4555db3b4b472341904873788327c0b0d7b95f1bb", size = 384123, upload-time = "2026-06-30T07:16:53.622Z" }, + { url = "https://files.pythonhosted.org/packages/46/7d/bf09bd1b145bb2671c03e1e6d1ab8651858d90d8c7dfeadd85a37a934fd8/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e4320744c1ffdd95a603def63344bfab2d33edeab301c5007e7de9f9f5b3885", size = 367351, upload-time = "2026-06-30T07:16:55.241Z" }, + { url = "https://files.pythonhosted.org/packages/a3/ea/1bb734f314b8be319149ddee80b18bd41372bdcfbdf88d28131c0cd37719/rpds_py-2026.6.3-cp315-cp315-manylinux_2_31_riscv64.whl", hash = "sha256:a9f4645593036b81bbdb36b9c8e0ea0d1c3fee968c4d59db0344c14087ef143a", size = 378827, upload-time = "2026-06-30T07:16:56.841Z" }, + { url = "https://files.pythonhosted.org/packages/4b/93/d9611e5b25e26df9a3649813ed66193ace9347a7c7fc4ab7cf70e94851c0/rpds_py-2026.6.3-cp315-cp315-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e55d236be29255554da47abe5c577637db7c24a02b8b46f0ca9524c855801868", size = 395966, upload-time = "2026-06-30T07:16:58.557Z" }, + { url = "https://files.pythonhosted.org/packages/c3/cb/99d77e16e5534ae1d90629bbe419ba6ee170833a6a85e3aa1cc41726fbbc/rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:24e9c5386e16669b674a69c156c8eeefcb578f3b3397b713b08e6d60f3c7b187", size = 545680, upload-time = "2026-06-30T07:17:00.164Z" }, + { url = "https://files.pythonhosted.org/packages/59/15/11a29755f790cef7a2f755e8e14f4f0c33f39489e1893a632a2eee59672b/rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:c60924535c75f1566b6eb75b5c31a48a43fef04fa2d0d201acbad8a9969c6107", size = 611853, upload-time = "2026-06-30T07:17:01.962Z" }, + { url = "https://files.pythonhosted.org/packages/68/86/0c27547e21644da938fb530f7e1a8148dd24d02db07e7a5f2567a17ce710/rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:38a2fea2787428f811719ceb9114cb78964a3138838320c29ac39526c79c16ba", size = 573715, upload-time = "2026-06-30T07:17:03.693Z" }, + { url = "https://files.pythonhosted.org/packages/29/71/4d8fcf700931815594bce892255bbd973b94efaf0fc1932b0590df18d886/rpds_py-2026.6.3-cp315-cp315-win32.whl", hash = "sha256:d483fe17f01ad64b7bf7cc38fcefff1ca9fb83f8c2b2542b68f97ffe0611b369", size = 202864, upload-time = "2026-06-30T07:17:05.746Z" }, + { url = "https://files.pythonhosted.org/packages/eb/62/b577562de0edbb55b2be85ce5fd09c33e386b9b13eee09833af4240fd5c4/rpds_py-2026.6.3-cp315-cp315-win_amd64.whl", hash = "sha256:67e3a721ffc5d8d2210d3671872298c4a84e4b8035cfe42ffd7cde35d772b146", size = 220430, upload-time = "2026-06-30T07:17:07.471Z" }, + { url = "https://files.pythonhosted.org/packages/c8/95/d6d0b2509825141eef60669a5739eec88dbc6a48053d6c92993a5704defe/rpds_py-2026.6.3-cp315-cp315-win_arm64.whl", hash = "sha256:6e84adbcf4bf841aed8116a8264b9f50b4cb3e7bd89b516122e616ac56ca269e", size = 215877, upload-time = "2026-06-30T07:17:09.008Z" }, + { url = "https://files.pythonhosted.org/packages/b7/bf/f3ea278f0afd615c1d0f19cb69043a41526e2bb600c2b536eb192218eb27/rpds_py-2026.6.3-cp315-cp315t-macosx_10_12_x86_64.whl", hash = "sha256:ae6dd8f10bd17aad820876d24caec9efdafd80a318d16c0a48edb5e136902c6b", size = 346933, upload-time = "2026-06-30T07:17:10.762Z" }, + { url = "https://files.pythonhosted.org/packages/9d/29/9907bdf1c5346763cf10b7f6852aad86652168c259def904cbe0082c5864/rpds_py-2026.6.3-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:bdbd97738551fca3917c1bd7188bec1920bb520104f28e7e1007f9ceb17b7690", size = 340274, upload-time = "2026-06-30T07:17:12.266Z" }, + { url = "https://files.pythonhosted.org/packages/6f/2c/8e03767b5778ef25cebf74a7a91a2c3806f8eced4c92cb7406bbe060756d/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b95977e7211527ab0ba576e286d023389fbeeb32a6b7b771665d333c60e5342", size = 370763, upload-time = "2026-06-30T07:17:14.107Z" }, + { url = "https://files.pythonhosted.org/packages/2e/e1/df2a7e1ba2efd796af26194250b8d42c821b46592311595162af9ef0528d/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d15fde0e6fb0d88a60d221204873743e5d9f0b7d29165e62cd86d0413ad74ba6", size = 376467, upload-time = "2026-06-30T07:17:15.76Z" }, + { url = "https://files.pythonhosted.org/packages/6b/de/8a0814d1946af29cb068fb259aa8622f856df1d0bab58429448726b537f5/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a136d453475ac0fcbda502ef1e6504bd28d6d904700915d278deeab0d00fe140", size = 496689, upload-time = "2026-06-30T07:17:17.308Z" }, + { url = "https://files.pythonhosted.org/packages/df/f3/f19e0c852ba13694f5a79f3b719331051573cb5693feacf8a88ffffc3a71/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f826877d462181e5eb1c26a0026b8d0cab05d99844ecb6d8bf3627a2ca0c0442", size = 385340, upload-time = "2026-06-30T07:17:18.928Z" }, + { url = "https://files.pythonhosted.org/packages/e2/ae/7ec3a9d2d4351f99e37bcb06b6b6f954512646bfdbf9742e1de727865daf/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79486287de1730dbaff3dbd124d0ca4d2ef7f9d29bf2544f1f93c09b5bcbbd12", size = 372179, upload-time = "2026-06-30T07:17:20.539Z" }, + { url = "https://files.pythonhosted.org/packages/d3/ac/9cee911dff2aaa9a5a8354f6610bf2e6a616de9197c5fff4f54f82585f1e/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_31_riscv64.whl", hash = "sha256:808345f53cb952433ca2816f1604ff3515608a81784954f38d4452acfe8e61d5", size = 379993, upload-time = "2026-06-30T07:17:22.212Z" }, + { url = "https://files.pythonhosted.org/packages/83/6b/7c2a07ba88d1e9a936612f7a5d067467ed03d971d5a06f7d309dff044a7e/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1967debc37f64f2c4dc90a7f563aec558b471966e12adcac4e1c4240496b6ebf", size = 398909, upload-time = "2026-06-30T07:17:23.66Z" }, + { url = "https://files.pythonhosted.org/packages/97/0b/776ffcb66783637b0031f6d58d6fb55913c8b5abf00aeecd46bf933fb477/rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:f0840b5b17057f7fd918b76183a4b5a0635f43e14eb2ce60dce1d4ee4707ea00", size = 546584, upload-time = "2026-06-30T07:17:25.264Z" }, + { url = "https://files.pythonhosted.org/packages/55/33/ba3bc04d7092bd553c9b2b195624992d2cc4f3de1f380b7b93cbee67bd79/rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:faa679d19a6696fd54259ad321251ad77a13e70e03dd834daa762a44fb6196ef", size = 614357, upload-time = "2026-06-30T07:17:26.888Z" }, + { url = "https://files.pythonhosted.org/packages/8b/71/14edf065f04630b1a8472f7653cad03f6c478bcf95ea0e6aed55451e33ea/rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:23a439f31ccbeff1574e24889128821d1f7917470e830cf6544dced1c662262a", size = 576533, upload-time = "2026-06-30T07:17:28.546Z" }, + { url = "https://files.pythonhosted.org/packages/ba/76/65002b08596c389105720a8c0d22298b8dc25a4baf89b2ce431343c8b1de/rpds_py-2026.6.3-cp315-cp315t-win32.whl", hash = "sha256:913ca42ccad3f8cc6e292b587ae8ae49c8c823e5dce51a736252fc7c7cdfa577", size = 201204, upload-time = "2026-06-30T07:17:30.193Z" }, + { url = "https://files.pythonhosted.org/packages/8c/97/d855d6b3c322d1f27e26f5241c42016b56cf01377ea8ed348285f54652f0/rpds_py-2026.6.3-cp315-cp315t-win_amd64.whl", hash = "sha256:ae3d4fe8c0b9213624fdce7279d70e3b148b682ca20719ebd193a23ebfa47324", size = 220719, upload-time = "2026-06-30T07:17:31.788Z" }, + { url = "https://files.pythonhosted.org/packages/b4/9c/f0d19ac587fd0e4ab6b72cda355e9c5a6166b01ef7e064e437aef8eb9fef/rpds_py-2026.6.3-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:4cf2d36a2357e4d07bb5a4f98801265327b48256867816cfd2ceb001e9754a8f", size = 349791, upload-time = "2026-06-30T07:17:33.315Z" }, + { url = "https://files.pythonhosted.org/packages/38/c7/1d49d204c9fd2ee6c537601dc4c1ba921e03363ca576bfab94a00254ac9a/rpds_py-2026.6.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:30c6dc199b24a5e3e81d50da0f00858c5bbdb2617a750395687f4339c5818171", size = 352842, upload-time = "2026-06-30T07:17:34.897Z" }, + { url = "https://files.pythonhosted.org/packages/ac/e5/c0b5dc93cd0d4c06ce1f438907649514e2ea077bcd911e3154a51e96c38e/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9891e594296ab9dada6551c8e7b387b2721f27a67eecd528412e8906247a7b90", size = 382094, upload-time = "2026-06-30T07:17:36.514Z" }, + { url = "https://files.pythonhosted.org/packages/0d/54/ec0e907b4ca8d541112db352409bd15f871c9b243e0c92c9b5a46ae96f01/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5c2dc92304aa48a4a60443b548bb12f12e119d4b72f314015e67b9e1be97fca", size = 388662, upload-time = "2026-06-30T07:17:38.235Z" }, + { url = "https://files.pythonhosted.org/packages/d3/f4/921c22a4fd0f1c1ac13a3996ffbf0aa67951e2c8ad0d1d9574938a2932e8/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:127e08c0642d880cf32ca47ec2a4a77b901f7e2dd1ad9762adb13955d72ffcc9", size = 504896, upload-time = "2026-06-30T07:17:39.689Z" }, + { url = "https://files.pythonhosted.org/packages/0b/1b/a114b972cefa1ab1cdb3c7bb177cd3844a12826c507c722d3a73516dbbaf/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8bb68f03f395eb793220b45c097bd4d8c32944393da0fad8b999efac0868fc8c", size = 391545, upload-time = "2026-06-30T07:17:41.336Z" }, + { url = "https://files.pythonhosted.org/packages/4e/98/af9b3db77d47fcbe6c8c1f36e2c2147ec70292819e99c325f871584a1c11/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3450b693fde92133e9f51060568a4c31fcca76d5e53bbd611e689ca446517e9", size = 380059, upload-time = "2026-06-30T07:17:42.857Z" }, + { url = "https://files.pythonhosted.org/packages/c9/ba/0efd8668b97c1d26a61566386c636a7a7a09829e474fdf807caa15a2c844/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:5e8d07bddee435a2ff6f1920e18feff28d0bc4533e42f4bf6927fbd073312c41", size = 393235, upload-time = "2026-06-30T07:17:44.637Z" }, + { url = "https://files.pythonhosted.org/packages/62/90/8c139ee9690f73b0829f32647de6f40d826f8f443af6fa72644f96351aac/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3a83ae6c67b7676b9878378547ca8e93ed77a580037bcbcd1d32f739e1e6089c", size = 413008, upload-time = "2026-06-30T07:17:46.225Z" }, + { url = "https://files.pythonhosted.org/packages/9c/97/0043896fdd7828ce09a1d9a8b06433714d0960fc4ff3fc4aa72b666b764e/rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2bfd04c19ddbd6640de0b51894d764bd2758854d5b75bd102d2ef10cb9c293a9", size = 558118, upload-time = "2026-06-30T07:17:47.759Z" }, + { url = "https://files.pythonhosted.org/packages/f6/40/02355f0e134f783a8f9814c4680a1bd311d37671577a5964ea838573ff37/rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:ca6546b66be9dc4738b1b043d5ebd5488c66c578c5ff0fd0e8065313fe3afb76", size = 623138, upload-time = "2026-06-30T07:17:49.355Z" }, + { url = "https://files.pythonhosted.org/packages/10/85/48f0abdcef5cce4e034c7a5b0ceeceba0b01bf0d942824f4bb720afe2dec/rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:8e65860d238379ed982fd9ba690579b5e95af2f4840f99c772816dbe573cb826", size = 586486, upload-time = "2026-06-30T07:17:51.141Z" }, +] + [[package]] name = "ruff" -version = "0.15.12" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/99/43/3291f1cc9106f4c63bdce7a8d0df5047fe8422a75b091c16b5e9355e0b11/ruff-0.15.12.tar.gz", hash = "sha256:ecea26adb26b4232c0c2ca19ccbc0083a68344180bba2a600605538ce51a40a6", size = 4643852, upload-time = "2026-04-24T18:17:14.305Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c3/6e/e78ffb61d4686f3d96ba3df2c801161843746dcbcbb17a1e927d4829312b/ruff-0.15.12-py3-none-linux_armv6l.whl", hash = "sha256:f86f176e188e94d6bdbc09f09bfd9dc729059ad93d0e7390b5a73efe19f8861c", size = 10640713, upload-time = "2026-04-24T18:17:22.841Z" }, - { url = "https://files.pythonhosted.org/packages/ae/08/a317bc231fb9e7b93e4ef3089501e51922ff88d6936ce5cf870c4fe55419/ruff-0.15.12-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:e3bcd123364c3770b8e1b7baaf343cc99a35f197c5c6e8af79015c666c423a6c", size = 11069267, upload-time = "2026-04-24T18:17:30.105Z" }, - { url = "https://files.pythonhosted.org/packages/aa/a4/f828e9718d3dce1f5f11c39c4f65afd32783c8b2aebb2e3d259e492c47bd/ruff-0.15.12-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fe87510d000220aa1ed530d4448a7c696a0cae1213e5ec30e5874287b66557b5", size = 10397182, upload-time = "2026-04-24T18:17:07.177Z" }, - { url = "https://files.pythonhosted.org/packages/71/e0/3310fc6d1b5e1fdea22bf3b1b807c7e187b581021b0d7d4514cccdb5fb71/ruff-0.15.12-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84a1630093121375a3e2a95b4a6dc7b59e2b4ee76216e32d81aae550a832d002", size = 10758012, upload-time = "2026-04-24T18:16:55.759Z" }, - { url = "https://files.pythonhosted.org/packages/11/c1/a606911aee04c324ddaa883ae418f3569792fd3c4a10c50e0dd0a2311e1e/ruff-0.15.12-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fb129f40f114f089ebe0ca56c0d251cf2061b17651d464bb6478dc01e69f11f5", size = 10447479, upload-time = "2026-04-24T18:16:51.677Z" }, - { url = "https://files.pythonhosted.org/packages/9d/68/4201e8444f0894f21ab4aeeaee68aa4f10b51613514a20d80bd628d57e88/ruff-0.15.12-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0c862b172d695db7598426b8af465e7e9ac00a3ea2a3630ee67eb82e366aaa6", size = 11234040, upload-time = "2026-04-24T18:17:16.529Z" }, - { url = "https://files.pythonhosted.org/packages/34/ff/8a6d6cf4ccc23fd67060874e832c18919d1557a0611ebef03fdb01fff11e/ruff-0.15.12-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2849ea9f3484c3aca43a82f484210370319e7170df4dfe4843395ddf6c57bc33", size = 12087377, upload-time = "2026-04-24T18:17:04.944Z" }, - { url = "https://files.pythonhosted.org/packages/85/f6/c669cf73f5152f623d34e69866a46d5e6185816b19fcd5b6dd8a2d299922/ruff-0.15.12-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e77c7e51c07fe396826d5969a5b846d9cd4c402535835fb6e21ce8b28fef847", size = 11367784, upload-time = "2026-04-24T18:17:25.409Z" }, - { url = "https://files.pythonhosted.org/packages/e8/39/c61d193b8a1daaa8977f7dea9e8d8ba866e02ea7b65d32f6861693aa4c12/ruff-0.15.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83b2f4f2f3b1026b5fb449b467d9264bf22067b600f7b6f41fc5958909f449d0", size = 11344088, upload-time = "2026-04-24T18:17:12.258Z" }, - { url = "https://files.pythonhosted.org/packages/c2/8d/49afab3645e31e12c590acb6d3b5b69d7aab5b81926dbaf7461f9441f37a/ruff-0.15.12-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:9ba3b8f1afd7e2e43d8943e55f249e13f9682fde09711644a6e7290eb4f3e339", size = 11271770, upload-time = "2026-04-24T18:17:02.457Z" }, - { url = "https://files.pythonhosted.org/packages/46/06/33f41fe94403e2b755481cdfb9b7ef3e4e0ed031c4581124658d935d52b4/ruff-0.15.12-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e852ba9fdc890655e1d78f2df1499efbe0e54126bd405362154a75e2bde159c5", size = 10719355, upload-time = "2026-04-24T18:17:27.648Z" }, - { url = "https://files.pythonhosted.org/packages/0d/59/18aa4e014debbf559670e4048e39260a85c7fcee84acfd761ac01e7b8d35/ruff-0.15.12-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:dd8aed930da53780d22fc70bdf84452c843cf64f8cb4eb38984319c24c5cd5fd", size = 10462758, upload-time = "2026-04-24T18:17:32.347Z" }, - { url = "https://files.pythonhosted.org/packages/25/e7/cc9f16fd0f3b5fddcbd7ec3d6ae30c8f3fde1047f32a4093a98d633c6570/ruff-0.15.12-py3-none-musllinux_1_2_i686.whl", hash = "sha256:01da3988d225628b709493d7dc67c3b9b12c0210016b08690ef9bd27970b262b", size = 10953498, upload-time = "2026-04-24T18:17:20.674Z" }, - { url = "https://files.pythonhosted.org/packages/72/7a/a9ba7f98c7a575978698f4230c5e8cc54bbc761af34f560818f933dafa0c/ruff-0.15.12-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:9cae0f92bd5700d1213188b31cd3bdd2b315361296d10b96b8e2337d3d11f53e", size = 11447765, upload-time = "2026-04-24T18:17:09.755Z" }, - { url = "https://files.pythonhosted.org/packages/ea/f9/0ae446942c846b8266059ad8a30702a35afae55f5cdc54c5adf8d7afdc27/ruff-0.15.12-py3-none-win32.whl", hash = "sha256:d0185894e038d7043ba8fd6aee7499ece6462dc0ea9f1e260c7451807c714c20", size = 10657277, upload-time = "2026-04-24T18:17:18.591Z" }, - { url = "https://files.pythonhosted.org/packages/33/f1/9614e03e1cdcbf9437570b5400ced8a720b5db22b28d8e0f1bda429f660d/ruff-0.15.12-py3-none-win_amd64.whl", hash = "sha256:c87a162d61ab3adca47c03f7f717c68672edec7d1b5499e652331780fe74950d", size = 11837758, upload-time = "2026-04-24T18:17:00.113Z" }, - { url = "https://files.pythonhosted.org/packages/c0/98/6beb4b351e472e5f4c4613f7c35a5290b8be2497e183825310c4c3a3984b/ruff-0.15.12-py3-none-win_arm64.whl", hash = "sha256:a538f7a82d061cee7be55542aca1d86d1393d55d81d4fcc314370f4340930d4f", size = 11120821, upload-time = "2026-04-24T18:16:57.979Z" }, +version = "0.15.20" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/dc/35b341fc554ba02f217fc10da57d1a75168cfbcf75b0ef2202176d4c4f2d/ruff-0.15.20.tar.gz", hash = "sha256:1416eb04349192646b54de98f146c4f59afe37d0decfc02c3cbbf396f3a28566", size = 4755489, upload-time = "2026-06-25T17:20:37.578Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/d9/2d5014f0253ba541d2061d9fa7193f48e941c8b21bb88a7ff9bbe0bd0596/ruff-0.15.20-py3-none-linux_armv6l.whl", hash = "sha256:00e188c53e499c3c1637f73c91dcf2fb56d576cab76ce1be50a27c4e80e37078", size = 10839665, upload-time = "2026-06-25T17:19:44.702Z" }, + { url = "https://files.pythonhosted.org/packages/c6/d3/ac1798ba64f670698867fcfc591d50e7e421bef137db564858f619a30fcf/ruff-0.15.20-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9ebd1fd9b9c95fc0bd7b2761aebec1f030013d2e193a2901b224af68fe47251b", size = 11208649, upload-time = "2026-06-25T17:19:48.787Z" }, + { url = "https://files.pythonhosted.org/packages/47/47/d3ac899991202095dfcf3d5176be4272642be3cf981a2f1a30f72a2afb95/ruff-0.15.20-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c5b16cdd67ca108185cd36dce98c576350c03b1660a751de725fb049193a0632", size = 10622638, upload-time = "2026-06-25T17:19:51.354Z" }, + { url = "https://files.pythonhosted.org/packages/33/13/4e043fe30aa94d4ff5213a9881fc296d12960f5971b234a5263fdc225312/ruff-0.15.20-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3413bb3c3d2ca6a8208f1f4809cd2dca3c6de6d0b491c0e70847672bde6e6efd", size = 10984227, upload-time = "2026-06-25T17:19:54.044Z" }, + { url = "https://files.pythonhosted.org/packages/76/e6/92e7bf40388bc5800073b96564f56264f7e48bfd1a498f5ced6ae6d5a769/ruff-0.15.20-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd7ec42b3bb3da066488db093308a69c4ac5ee6d2af333a86ba6e2eb2e7dd44b", size = 10622882, upload-time = "2026-06-25T17:19:57.037Z" }, + { url = "https://files.pythonhosted.org/packages/13/7a/43460be3f24495a3aa46d4b16873e2c4941b3b5f0b00cf88c03b7b94b339/ruff-0.15.20-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1a36ad0eb77fba9aabfb69ede54de6f376d04ac18ebea022847046d340a8267", size = 11474808, upload-time = "2026-06-25T17:20:00.357Z" }, + { url = "https://files.pythonhosted.org/packages/27/a0/f37077884873221c6b33b4ab49eb18f9f88e54a16a25a5bca59bef46dd66/ruff-0.15.20-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b6df3b1e4610432f0386dba04d853b5f08cbbc903410c6fcc02f620f05aff53c", size = 12293094, upload-time = "2026-06-25T17:20:03.446Z" }, + { url = "https://files.pythonhosted.org/packages/a6/74/165545b60256a9704c21ac0ec4a0d07933b320812f9584836c9f4aca4292/ruff-0.15.20-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e89f198a1ea6ef0d727c1cf16088bc91a6cb0ab947dedc966715691647186eae", size = 11526176, upload-time = "2026-06-25T17:20:06.301Z" }, + { url = "https://files.pythonhosted.org/packages/86/b1/a976a136d40ade83ce743578399865f57001003a409acadc0ecbb3051082/ruff-0.15.20-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309809086c2acb67624950a3c8133e80f32d0d3e27106c0cd60ff26657c9f24b", size = 11520767, upload-time = "2026-06-25T17:20:09.191Z" }, + { url = "https://files.pythonhosted.org/packages/19/0f/f032696cb01c9b54c0263fa393474d7758f1cdc021a01b04e3cbc2500999/ruff-0.15.20-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:2d2374caa2f2c2f9e2b7da0a50802cfb8b79f55a9b5e49379f564544fbf56487", size = 11500132, upload-time = "2026-06-25T17:20:13.602Z" }, + { url = "https://files.pythonhosted.org/packages/4b/f4/51b1a14bc69e8c224b15dab9cce8e99b425e0455d462caa2b3c9be2b6a8e/ruff-0.15.20-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a1ed17b65293e0c2f22fc387bc13198a5de94bf4429589b0ff6946b0feaf21a3", size = 10943828, upload-time = "2026-06-25T17:20:16.635Z" }, + { url = "https://files.pythonhosted.org/packages/71/4b/fe267640783cd02bf6c5cc290b1df1051be2ec294c678b5c15fe19e52343/ruff-0.15.20-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:f701305e66b38ea6c91882490eb73459796808e4c6362a1b765255e0cdcd4053", size = 10645418, upload-time = "2026-06-25T17:20:19.4Z" }, + { url = "https://files.pythonhosted.org/packages/b0/c0/a65aa4ec2f5e87a1df32dc3ec1fede434fe3dfd5cbcf3b503cafc676ab54/ruff-0.15.20-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5b9c0c367ad8e5d0d5b5b8537864c469a0a0e55417aadfbeca41fa61333be9f4", size = 11211770, upload-time = "2026-06-25T17:20:22.033Z" }, + { url = "https://files.pythonhosted.org/packages/5a/a4/0caa331d954ae2723d729d351c989cb4ca8b6077d5c6c2cb6de75e98c041/ruff-0.15.20-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:01cc00dd58f0df339d0e902219dd53990ea99996a0344e5d9cc8d45d5307e460", size = 11618698, upload-time = "2026-06-25T17:20:25.259Z" }, + { url = "https://files.pythonhosted.org/packages/10/9b/5f14927848d2fd4aa891fd88d883788c5a7baba561c7874732364045708c/ruff-0.15.20-py3-none-win32.whl", hash = "sha256:ed65ef510e43a137207e0f01cfcf998aeddb1aeeda5c9d35023e910284d7cf21", size = 10857322, upload-time = "2026-06-25T17:20:28.612Z" }, + { url = "https://files.pythonhosted.org/packages/fa/f0/fe47c501f9dea92a26d788ff98bb5d92ed4cb4c88792c5c88af6b697dc8e/ruff-0.15.20-py3-none-win_amd64.whl", hash = "sha256:a525c81c70fb0380344dd1d8745d8cc1c890b7fc94a58d5a07bd8eb9557b8415", size = 11993274, upload-time = "2026-06-25T17:20:31.871Z" }, + { url = "https://files.pythonhosted.org/packages/d7/2b/9555445e1201d92b3195f45cdb153a0b68f24e0a4273f6e3d5ab46e212bb/ruff-0.15.20-py3-none-win_arm64.whl", hash = "sha256:2f5b2a6d614e8700388806a14996c40fab2c47b819ef57d790a34878858ed9ca", size = 11343498, upload-time = "2026-06-25T17:20:35.03Z" }, +] + +[[package]] +name = "secretstorage" +version = "3.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cryptography" }, + { name = "jeepney" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1c/03/e834bcd866f2f8a49a85eaff47340affa3bfa391ee9912a952a1faa68c7b/secretstorage-3.5.0.tar.gz", hash = "sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be", size = 19884, upload-time = "2025-11-23T19:02:53.191Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/46/f5af3402b579fd5e11573ce652019a67074317e18c1935cc0b4ba9b35552/secretstorage-3.5.0-py3-none-any.whl", hash = "sha256:0ce65888c0725fcb2c5bc0fdb8e5438eece02c523557ea40ce0703c266248137", size = 15554, upload-time = "2025-11-23T19:02:51.545Z" }, ] [[package]] @@ -2303,6 +3139,32 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, ] +[[package]] +name = "sse-starlette" +version = "3.4.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "starlette" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d2/1b/bc9e3e7a72dcdad7dc7888758f5d00f56f8909ed5cfdff822bd72bb4c520/sse_starlette-3.4.5.tar.gz", hash = "sha256:83072538bc211a2f68b7b0422226c4af3e9b62e106e07034664b832ca019842a", size = 35249, upload-time = "2026-06-20T17:36:58.322Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/75/c88d3f5dafd59c791da1ce27650d30bf5b70cbf1cbf01cd00e5f9e360915/sse_starlette-3.4.5-py3-none-any.whl", hash = "sha256:e71bad53323f65573c3864a6c3bd0c1eb6e5f092b2e48082b0c35927d19ca296", size = 16518, upload-time = "2026-06-20T17:36:56.729Z" }, +] + +[[package]] +name = "starlette" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/e3/7c1dc7381d9f8ab7d854328ebfa884e62cb3f3d8549ddfd37c7814f42afa/starlette-1.3.1.tar.gz", hash = "sha256:05d0213193f2fbaae60e2ecb593b4add4262ad4e46536b54abe36f11a71724e0", size = 2703240, upload-time = "2026-06-12T09:23:11.602Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/bb/2799cc2ede3ed41131f8975621e7213dfc7ef4acbbaadfa440f32500c370/starlette-1.3.1-py3-none-any.whl", hash = "sha256:c7372aae11c3c3f26a42df7bd626cec2f47d03483d261d369516a615a53714c6", size = 73632, upload-time = "2026-06-12T09:23:10.017Z" }, +] + [[package]] name = "tenacity" version = "9.1.4" @@ -2314,56 +3176,56 @@ wheels = [ [[package]] name = "tiktoken" -version = "0.12.0" +version = "0.13.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "regex" }, { name = "requests" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7d/ab/4d017d0f76ec3171d469d80fc03dfbb4e48a4bcaddaa831b31d526f05edc/tiktoken-0.12.0.tar.gz", hash = "sha256:b18ba7ee2b093863978fcb14f74b3707cdc8d4d4d3836853ce7ec60772139931", size = 37806, upload-time = "2025-10-06T20:22:45.419Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/de/46/21ea696b21f1d6d1efec8639c204bdf20fde8bafb351e1355c72c5d7de52/tiktoken-0.12.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6e227c7f96925003487c33b1b32265fad2fbcec2b7cf4817afb76d416f40f6bb", size = 1051565, upload-time = "2025-10-06T20:21:44.566Z" }, - { url = "https://files.pythonhosted.org/packages/c9/d9/35c5d2d9e22bb2a5f74ba48266fb56c63d76ae6f66e02feb628671c0283e/tiktoken-0.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c06cf0fcc24c2cb2adb5e185c7082a82cba29c17575e828518c2f11a01f445aa", size = 995284, upload-time = "2025-10-06T20:21:45.622Z" }, - { url = "https://files.pythonhosted.org/packages/01/84/961106c37b8e49b9fdcf33fe007bb3a8fdcc380c528b20cc7fbba80578b8/tiktoken-0.12.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:f18f249b041851954217e9fd8e5c00b024ab2315ffda5ed77665a05fa91f42dc", size = 1129201, upload-time = "2025-10-06T20:21:47.074Z" }, - { url = "https://files.pythonhosted.org/packages/6a/d0/3d9275198e067f8b65076a68894bb52fd253875f3644f0a321a720277b8a/tiktoken-0.12.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:47a5bc270b8c3db00bb46ece01ef34ad050e364b51d406b6f9730b64ac28eded", size = 1152444, upload-time = "2025-10-06T20:21:48.139Z" }, - { url = "https://files.pythonhosted.org/packages/78/db/a58e09687c1698a7c592e1038e01c206569b86a0377828d51635561f8ebf/tiktoken-0.12.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:508fa71810c0efdcd1b898fda574889ee62852989f7c1667414736bcb2b9a4bd", size = 1195080, upload-time = "2025-10-06T20:21:49.246Z" }, - { url = "https://files.pythonhosted.org/packages/9e/1b/a9e4d2bf91d515c0f74afc526fd773a812232dd6cda33ebea7f531202325/tiktoken-0.12.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a1af81a6c44f008cba48494089dd98cccb8b313f55e961a52f5b222d1e507967", size = 1255240, upload-time = "2025-10-06T20:21:50.274Z" }, - { url = "https://files.pythonhosted.org/packages/9d/15/963819345f1b1fb0809070a79e9dd96938d4ca41297367d471733e79c76c/tiktoken-0.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:3e68e3e593637b53e56f7237be560f7a394451cb8c11079755e80ae64b9e6def", size = 879422, upload-time = "2025-10-06T20:21:51.734Z" }, - { url = "https://files.pythonhosted.org/packages/a4/85/be65d39d6b647c79800fd9d29241d081d4eeb06271f383bb87200d74cf76/tiktoken-0.12.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b97f74aca0d78a1ff21b8cd9e9925714c15a9236d6ceacf5c7327c117e6e21e8", size = 1050728, upload-time = "2025-10-06T20:21:52.756Z" }, - { url = "https://files.pythonhosted.org/packages/4a/42/6573e9129bc55c9bf7300b3a35bef2c6b9117018acca0dc760ac2d93dffe/tiktoken-0.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b90f5ad190a4bb7c3eb30c5fa32e1e182ca1ca79f05e49b448438c3e225a49b", size = 994049, upload-time = "2025-10-06T20:21:53.782Z" }, - { url = "https://files.pythonhosted.org/packages/66/c5/ed88504d2f4a5fd6856990b230b56d85a777feab84e6129af0822f5d0f70/tiktoken-0.12.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:65b26c7a780e2139e73acc193e5c63ac754021f160df919add909c1492c0fb37", size = 1129008, upload-time = "2025-10-06T20:21:54.832Z" }, - { url = "https://files.pythonhosted.org/packages/f4/90/3dae6cc5436137ebd38944d396b5849e167896fc2073da643a49f372dc4f/tiktoken-0.12.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:edde1ec917dfd21c1f2f8046b86348b0f54a2c0547f68149d8600859598769ad", size = 1152665, upload-time = "2025-10-06T20:21:56.129Z" }, - { url = "https://files.pythonhosted.org/packages/a3/fe/26df24ce53ffde419a42f5f53d755b995c9318908288c17ec3f3448313a3/tiktoken-0.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:35a2f8ddd3824608b3d650a000c1ef71f730d0c56486845705a8248da00f9fe5", size = 1194230, upload-time = "2025-10-06T20:21:57.546Z" }, - { url = "https://files.pythonhosted.org/packages/20/cc/b064cae1a0e9fac84b0d2c46b89f4e57051a5f41324e385d10225a984c24/tiktoken-0.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:83d16643edb7fa2c99eff2ab7733508aae1eebb03d5dfc46f5565862810f24e3", size = 1254688, upload-time = "2025-10-06T20:21:58.619Z" }, - { url = "https://files.pythonhosted.org/packages/81/10/b8523105c590c5b8349f2587e2fdfe51a69544bd5a76295fc20f2374f470/tiktoken-0.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ffc5288f34a8bc02e1ea7047b8d041104791d2ddbf42d1e5fa07822cbffe16bd", size = 878694, upload-time = "2025-10-06T20:21:59.876Z" }, - { url = "https://files.pythonhosted.org/packages/00/61/441588ee21e6b5cdf59d6870f86beb9789e532ee9718c251b391b70c68d6/tiktoken-0.12.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:775c2c55de2310cc1bc9a3ad8826761cbdc87770e586fd7b6da7d4589e13dab3", size = 1050802, upload-time = "2025-10-06T20:22:00.96Z" }, - { url = "https://files.pythonhosted.org/packages/1f/05/dcf94486d5c5c8d34496abe271ac76c5b785507c8eae71b3708f1ad9b45a/tiktoken-0.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a01b12f69052fbe4b080a2cfb867c4de12c704b56178edf1d1d7b273561db160", size = 993995, upload-time = "2025-10-06T20:22:02.788Z" }, - { url = "https://files.pythonhosted.org/packages/a0/70/5163fe5359b943f8db9946b62f19be2305de8c3d78a16f629d4165e2f40e/tiktoken-0.12.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:01d99484dc93b129cd0964f9d34eee953f2737301f18b3c7257bf368d7615baa", size = 1128948, upload-time = "2025-10-06T20:22:03.814Z" }, - { url = "https://files.pythonhosted.org/packages/0c/da/c028aa0babf77315e1cef357d4d768800c5f8a6de04d0eac0f377cb619fa/tiktoken-0.12.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:4a1a4fcd021f022bfc81904a911d3df0f6543b9e7627b51411da75ff2fe7a1be", size = 1151986, upload-time = "2025-10-06T20:22:05.173Z" }, - { url = "https://files.pythonhosted.org/packages/a0/5a/886b108b766aa53e295f7216b509be95eb7d60b166049ce2c58416b25f2a/tiktoken-0.12.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:981a81e39812d57031efdc9ec59fa32b2a5a5524d20d4776574c4b4bd2e9014a", size = 1194222, upload-time = "2025-10-06T20:22:06.265Z" }, - { url = "https://files.pythonhosted.org/packages/f4/f8/4db272048397636ac7a078d22773dd2795b1becee7bc4922fe6207288d57/tiktoken-0.12.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9baf52f84a3f42eef3ff4e754a0db79a13a27921b457ca9832cf944c6be4f8f3", size = 1255097, upload-time = "2025-10-06T20:22:07.403Z" }, - { url = "https://files.pythonhosted.org/packages/8e/32/45d02e2e0ea2be3a9ed22afc47d93741247e75018aac967b713b2941f8ea/tiktoken-0.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:b8a0cd0c789a61f31bf44851defbd609e8dd1e2c8589c614cc1060940ef1f697", size = 879117, upload-time = "2025-10-06T20:22:08.418Z" }, - { url = "https://files.pythonhosted.org/packages/ce/76/994fc868f88e016e6d05b0da5ac24582a14c47893f4474c3e9744283f1d5/tiktoken-0.12.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d5f89ea5680066b68bcb797ae85219c72916c922ef0fcdd3480c7d2315ffff16", size = 1050309, upload-time = "2025-10-06T20:22:10.939Z" }, - { url = "https://files.pythonhosted.org/packages/f6/b8/57ef1456504c43a849821920d582a738a461b76a047f352f18c0b26c6516/tiktoken-0.12.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b4e7ed1c6a7a8a60a3230965bdedba8cc58f68926b835e519341413370e0399a", size = 993712, upload-time = "2025-10-06T20:22:12.115Z" }, - { url = "https://files.pythonhosted.org/packages/72/90/13da56f664286ffbae9dbcfadcc625439142675845baa62715e49b87b68b/tiktoken-0.12.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:fc530a28591a2d74bce821d10b418b26a094bf33839e69042a6e86ddb7a7fb27", size = 1128725, upload-time = "2025-10-06T20:22:13.541Z" }, - { url = "https://files.pythonhosted.org/packages/05/df/4f80030d44682235bdaecd7346c90f67ae87ec8f3df4a3442cb53834f7e4/tiktoken-0.12.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:06a9f4f49884139013b138920a4c393aa6556b2f8f536345f11819389c703ebb", size = 1151875, upload-time = "2025-10-06T20:22:14.559Z" }, - { url = "https://files.pythonhosted.org/packages/22/1f/ae535223a8c4ef4c0c1192e3f9b82da660be9eb66b9279e95c99288e9dab/tiktoken-0.12.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:04f0e6a985d95913cabc96a741c5ffec525a2c72e9df086ff17ebe35985c800e", size = 1194451, upload-time = "2025-10-06T20:22:15.545Z" }, - { url = "https://files.pythonhosted.org/packages/78/a7/f8ead382fce0243cb625c4f266e66c27f65ae65ee9e77f59ea1653b6d730/tiktoken-0.12.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0ee8f9ae00c41770b5f9b0bb1235474768884ae157de3beb5439ca0fd70f3e25", size = 1253794, upload-time = "2025-10-06T20:22:16.624Z" }, - { url = "https://files.pythonhosted.org/packages/93/e0/6cc82a562bc6365785a3ff0af27a2a092d57c47d7a81d9e2295d8c36f011/tiktoken-0.12.0-cp313-cp313t-win_amd64.whl", hash = "sha256:dc2dd125a62cb2b3d858484d6c614d136b5b848976794edfb63688d539b8b93f", size = 878777, upload-time = "2025-10-06T20:22:18.036Z" }, - { url = "https://files.pythonhosted.org/packages/72/05/3abc1db5d2c9aadc4d2c76fa5640134e475e58d9fbb82b5c535dc0de9b01/tiktoken-0.12.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:a90388128df3b3abeb2bfd1895b0681412a8d7dc644142519e6f0a97c2111646", size = 1050188, upload-time = "2025-10-06T20:22:19.563Z" }, - { url = "https://files.pythonhosted.org/packages/e3/7b/50c2f060412202d6c95f32b20755c7a6273543b125c0985d6fa9465105af/tiktoken-0.12.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:da900aa0ad52247d8794e307d6446bd3cdea8e192769b56276695d34d2c9aa88", size = 993978, upload-time = "2025-10-06T20:22:20.702Z" }, - { url = "https://files.pythonhosted.org/packages/14/27/bf795595a2b897e271771cd31cb847d479073497344c637966bdf2853da1/tiktoken-0.12.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:285ba9d73ea0d6171e7f9407039a290ca77efcdb026be7769dccc01d2c8d7fff", size = 1129271, upload-time = "2025-10-06T20:22:22.06Z" }, - { url = "https://files.pythonhosted.org/packages/f5/de/9341a6d7a8f1b448573bbf3425fa57669ac58258a667eb48a25dfe916d70/tiktoken-0.12.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:d186a5c60c6a0213f04a7a802264083dea1bbde92a2d4c7069e1a56630aef830", size = 1151216, upload-time = "2025-10-06T20:22:23.085Z" }, - { url = "https://files.pythonhosted.org/packages/75/0d/881866647b8d1be4d67cb24e50d0c26f9f807f994aa1510cb9ba2fe5f612/tiktoken-0.12.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:604831189bd05480f2b885ecd2d1986dc7686f609de48208ebbbddeea071fc0b", size = 1194860, upload-time = "2025-10-06T20:22:24.602Z" }, - { url = "https://files.pythonhosted.org/packages/b3/1e/b651ec3059474dab649b8d5b69f5c65cd8fcd8918568c1935bd4136c9392/tiktoken-0.12.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:8f317e8530bb3a222547b85a58583238c8f74fd7a7408305f9f63246d1a0958b", size = 1254567, upload-time = "2025-10-06T20:22:25.671Z" }, - { url = "https://files.pythonhosted.org/packages/80/57/ce64fd16ac390fafde001268c364d559447ba09b509181b2808622420eec/tiktoken-0.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:399c3dd672a6406719d84442299a490420b458c44d3ae65516302a99675888f3", size = 921067, upload-time = "2025-10-06T20:22:26.753Z" }, - { url = "https://files.pythonhosted.org/packages/ac/a4/72eed53e8976a099539cdd5eb36f241987212c29629d0a52c305173e0a68/tiktoken-0.12.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c2c714c72bc00a38ca969dae79e8266ddec999c7ceccd603cc4f0d04ccd76365", size = 1050473, upload-time = "2025-10-06T20:22:27.775Z" }, - { url = "https://files.pythonhosted.org/packages/e6/d7/0110b8f54c008466b19672c615f2168896b83706a6611ba6e47313dbc6e9/tiktoken-0.12.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:cbb9a3ba275165a2cb0f9a83f5d7025afe6b9d0ab01a22b50f0e74fee2ad253e", size = 993855, upload-time = "2025-10-06T20:22:28.799Z" }, - { url = "https://files.pythonhosted.org/packages/5f/77/4f268c41a3957c418b084dd576ea2fad2e95da0d8e1ab705372892c2ca22/tiktoken-0.12.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:dfdfaa5ffff8993a3af94d1125870b1d27aed7cb97aa7eb8c1cefdbc87dbee63", size = 1129022, upload-time = "2025-10-06T20:22:29.981Z" }, - { url = "https://files.pythonhosted.org/packages/4e/2b/fc46c90fe5028bd094cd6ee25a7db321cb91d45dc87531e2bdbb26b4867a/tiktoken-0.12.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:584c3ad3d0c74f5269906eb8a659c8bfc6144a52895d9261cdaf90a0ae5f4de0", size = 1150736, upload-time = "2025-10-06T20:22:30.996Z" }, - { url = "https://files.pythonhosted.org/packages/28/c0/3c7a39ff68022ddfd7d93f3337ad90389a342f761c4d71de99a3ccc57857/tiktoken-0.12.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:54c891b416a0e36b8e2045b12b33dd66fb34a4fe7965565f1b482da50da3e86a", size = 1194908, upload-time = "2025-10-06T20:22:32.073Z" }, - { url = "https://files.pythonhosted.org/packages/ab/0d/c1ad6f4016a3968c048545f5d9b8ffebf577774b2ede3e2e352553b685fe/tiktoken-0.12.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5edb8743b88d5be814b1a8a8854494719080c28faaa1ccbef02e87354fe71ef0", size = 1253706, upload-time = "2025-10-06T20:22:33.385Z" }, - { url = "https://files.pythonhosted.org/packages/af/df/c7891ef9d2712ad774777271d39fdef63941ffba0a9d59b7ad1fd2765e57/tiktoken-0.12.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f61c0aea5565ac82e2ec50a05e02a6c44734e91b51c10510b084ea1b8e633a71", size = 920667, upload-time = "2025-10-06T20:22:34.444Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/e4/e5/5f3cb2159769d0f4324c0e9e87f9de3c4b1cd45848a96b2eb3566ad5ca77/tiktoken-0.13.0.tar.gz", hash = "sha256:c9435714c3a84c2319499de9a300c0e604449dd0799ff246458b3bb6a7f433c1", size = 38986, upload-time = "2026-05-15T04:51:27.153Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1a/4c/1bc81f4cd53e827c4ee67ca951b5935724716049452d8dfa09b8b82372bb/tiktoken-0.13.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:7bfe1849caa65d1e1d9871817170ec497bbb7984e182012e1bdce72f66608cdb", size = 1036353, upload-time = "2026-05-15T04:50:21.757Z" }, + { url = "https://files.pythonhosted.org/packages/75/91/10b9c7076bc02c246c853201fdbbe300a4b8c5ed7b84c25f7403f4e32655/tiktoken-0.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:91c180fe255bd5a86d8316210d2833a1d4d33d026cd86a67812f4773743c8d26", size = 984644, upload-time = "2026-05-15T04:50:23.256Z" }, + { url = "https://files.pythonhosted.org/packages/4e/e4/fceae98015fab47fcd49b8bd7f46145bcd187a47e0add1e5378ed67ef980/tiktoken-0.13.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:059c8ecf554eb5b41e6e054ba467b871b03277d267dee7244380aca4359747d4", size = 1119261, upload-time = "2026-05-15T04:50:24.348Z" }, + { url = "https://files.pythonhosted.org/packages/f9/39/fe42ad00de01a8c4a49ad8649a2c8a316835a9cad5961b11d21eac0020a5/tiktoken-0.13.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:36217497eaffc158607a3b26f065300db2aefd43b115263f3b9688ce38146173", size = 1138253, upload-time = "2026-05-15T04:50:25.505Z" }, + { url = "https://files.pythonhosted.org/packages/03/c4/ccee1ecccca107e9a16efcecdeeb964c325305038554d466ece65b42338f/tiktoken-0.13.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:303f7d91b4fce3baddbcde05c139091d4caa5026ac7214c1dc7ff7a71ee429ff", size = 1185747, upload-time = "2026-05-15T04:50:27.02Z" }, + { url = "https://files.pythonhosted.org/packages/9d/03/cd0cba295522b91eb55c6b2704f1df895f8226cfe60ab10d4d51d0cc9e69/tiktoken-0.13.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5d48843bee149630eb735a99e1f4a85b47308d21868ea63163f6e87768d3cfed", size = 1241265, upload-time = "2026-05-15T04:50:28.815Z" }, + { url = "https://files.pythonhosted.org/packages/7e/25/a10efd564402d82c2ff50d12057353ace447aa8007deceaa48641f63d35c/tiktoken-0.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:fc1c44cd37b43fc46bae593129164f4f281e82ea116b57a85aa81bda57eafc94", size = 876509, upload-time = "2026-05-15T04:50:30.026Z" }, + { url = "https://files.pythonhosted.org/packages/85/8e/144bde4e01df66b34bb865557c7cd754ed08b036217ebd79c9db5e9048a9/tiktoken-0.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:32ac870a806cfb260a02d0cb70426aef02e038297f8ad50df5040bb5af360791", size = 1034888, upload-time = "2026-05-15T04:50:31.579Z" }, + { url = "https://files.pythonhosted.org/packages/36/18/d4ac9d20956cdebca04841316660ed584c2fecdc2b81722a28bc7ad3b1e4/tiktoken-0.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4d9980f11429ed2d737c463bb1fb78cf330caa026adf002f714aced7849a687b", size = 982970, upload-time = "2026-05-15T04:50:32.961Z" }, + { url = "https://files.pythonhosted.org/packages/74/ed/6bb8d05b9f731f749fee5c6f5ca63e981143c826a5985877330507bd13b7/tiktoken-0.13.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:3f277ebea5edd7b8bf03c6f9431e1d67d517530115572b2dc1d465326e8f88c7", size = 1115741, upload-time = "2026-05-15T04:50:34.475Z" }, + { url = "https://files.pythonhosted.org/packages/34/de/2ca96b07a82d972b74fe4b46de055b79c904e45c7eab699354a0bfa697dc/tiktoken-0.13.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:a116178fa7e1b4065bff05214360373a65cac22f965be7b3f73d00a0dbfe7649", size = 1136523, upload-time = "2026-05-15T04:50:35.782Z" }, + { url = "https://files.pythonhosted.org/packages/ee/dc/9dafec002c2d4424378563cf4cf5c7fb93631d2a55013c8b87554ee4012c/tiktoken-0.13.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2c397ddda233208345b01bd30f2fca79ff730e55731d0108a603f9bc57f6af3b", size = 1181954, upload-time = "2026-05-15T04:50:36.99Z" }, + { url = "https://files.pythonhosted.org/packages/a1/d0/1f8578c45b2f24759b46f0b50d31878c63c73e6bf0f2227e10ec5c5408dc/tiktoken-0.13.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:95097e4f89b06403976e498abf61a0ee73a7497e73fb599cb211d8197a054d91", size = 1240069, upload-time = "2026-05-15T04:50:38.221Z" }, + { url = "https://files.pythonhosted.org/packages/aa/90/28d7f154888610aa9237e541986beb62b479df29d193a5a0617dbb1514d0/tiktoken-0.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:8f2d16e7a7c783ad81f36e457d046d1f1c8af70b22aec8a13238efe531977c41", size = 874748, upload-time = "2026-05-15T04:50:39.587Z" }, + { url = "https://files.pythonhosted.org/packages/9c/83/b096c859c2a47c11731bf2f5885f4028b809dfe2396582883eed9cae372f/tiktoken-0.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5df5d1507bd245f1ccad4a074698240021239e455eb0bb4ced4e3d7181872154", size = 1034228, upload-time = "2026-05-15T04:50:40.988Z" }, + { url = "https://files.pythonhosted.org/packages/53/61/c68e123b6d753e3fc2751e9b18e732c9d8bf1e1926762e736eee935d931c/tiktoken-0.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8fe806a50664e83a6ffd56cbd1e4f5dcc6cd32a3e7538f70dc38b1a271384545", size = 982978, upload-time = "2026-05-15T04:50:42.195Z" }, + { url = "https://files.pythonhosted.org/packages/ef/8b/96cc178cc584e65d363134500f297790b06cd48cdeb1e8fcf7bbe60f4715/tiktoken-0.13.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:125bc05005e747f993a83dc67934249932d6e4209854452cd4c0b1d53fba3ba2", size = 1116355, upload-time = "2026-05-15T04:50:43.564Z" }, + { url = "https://files.pythonhosted.org/packages/86/f5/bab735d2c72ea55404b295d02d092644eb5f7cc6205e34d35eb9abfb9ab2/tiktoken-0.13.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:5e6358911cab4adee6712da27d65573496a4f68cf8a2b5fca6a4ad10fc5748cf", size = 1135772, upload-time = "2026-05-15T04:50:44.782Z" }, + { url = "https://files.pythonhosted.org/packages/4e/b9/6de04ebdf904edfaad87788011b3735087a0c9ea671b9027e1e4e965e8c8/tiktoken-0.13.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:975cbd78d085d75d26b59660e262736dcaed1e35f8f142cd6291025c01d25486", size = 1182415, upload-time = "2026-05-15T04:50:46.422Z" }, + { url = "https://files.pythonhosted.org/packages/0d/9c/470a05f3b1caf038f44880e334d47ab674e0c80d514c66b375d14d5afa10/tiktoken-0.13.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:75ab9bc99fa020a4c283424590ecd7f3afd70c1c281cb3fa3192a6c3af9f9615", size = 1239879, upload-time = "2026-05-15T04:50:48.052Z" }, + { url = "https://files.pythonhosted.org/packages/42/a6/c1936d16055436cb32e6c6128d68629622e00f4768562f55653752d34768/tiktoken-0.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:6b1615f0ff71953d19729ceb18865429c185b0a23c5353f1bbca34a394bf60f7", size = 874829, upload-time = "2026-05-15T04:50:49.202Z" }, + { url = "https://files.pythonhosted.org/packages/d6/07/acb5992c3772b5a36284f742cfb7a5895aa4471d1848ac31464ad50d7fdf/tiktoken-0.13.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:6eb4a5bfbc6426938026b1a334e898ac53541360d62d8c689870160cc80abd67", size = 1033600, upload-time = "2026-05-15T04:50:50.4Z" }, + { url = "https://files.pythonhosted.org/packages/14/e9/742e9aec30f59b9f161f7ff7cd072e02ea836c9e1c0854a8076dfcd40d5c/tiktoken-0.13.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:43cee3e5400573b2046fbf092cc7a5bc30164f9e4c95ce20714da929df48737a", size = 982516, upload-time = "2026-05-15T04:50:52.03Z" }, + { url = "https://files.pythonhosted.org/packages/72/74/ca1541b053e7648254d2e4b42a253e1bb4359f2c91a0a8d49228c794e1a0/tiktoken-0.13.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:7de52e3f566d19b3b11bd37eea552c6c305ad74081f736882bd44d148ed4c48d", size = 1115518, upload-time = "2026-05-15T04:50:53.543Z" }, + { url = "https://files.pythonhosted.org/packages/46/e3/93825eaf5a4a504795b787e5d5dea07fbeb3dabf97aa7b450be8bde59c89/tiktoken-0.13.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:51384448aa508e4df84c0f7c1dc3211c7f7b8096325660ee5fc82f3e11b381ce", size = 1136867, upload-time = "2026-05-15T04:50:55.191Z" }, + { url = "https://files.pythonhosted.org/packages/8c/46/002b68de6827091d5ae90b048f326e8aad8d953520950e5ce1508879414f/tiktoken-0.13.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e28157350f7ebf35008dd8e9e0fdb621f976e4230c881099c85e8cf07eaa50e2", size = 1181826, upload-time = "2026-05-15T04:50:56.296Z" }, + { url = "https://files.pythonhosted.org/packages/db/c6/d393e3185a276505182f7abd93fe714f3c444a2be9180798fa052347504e/tiktoken-0.13.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:165cf1820ea4a354985c2490a5205d4cc74661c934aca79dd0368232fff94e0f", size = 1239489, upload-time = "2026-05-15T04:50:57.918Z" }, + { url = "https://files.pythonhosted.org/packages/b7/4d/bc07d1f1635d4897a202acc0ae11c2886eaa7325c359ba4741b47bf8e225/tiktoken-0.13.0-cp313-cp313t-win_amd64.whl", hash = "sha256:6c43a675ca14f6f2749ba7f12075d37456015a24b859f2517b9beb4ef30807ec", size = 873820, upload-time = "2026-05-15T04:50:59.528Z" }, + { url = "https://files.pythonhosted.org/packages/8c/93/0dd6adca026a616c3a92974566b43381eea4b475ce1f36c062b8271a9ac5/tiktoken-0.13.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaaaef47c2406277181d2086484c317bf7fc433e2d5d03ff94f56b0dcec87471", size = 1034977, upload-time = "2026-05-15T04:51:00.957Z" }, + { url = "https://files.pythonhosted.org/packages/d9/77/5ec6e6bc5b30bed6d93f7f2162d8f6b32437b3ba27cb527cfe004f6109c9/tiktoken-0.13.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ca8b310bd93b3772cb1b7922d915446864860f562bdfe4825c63a0aed3fb28cd", size = 983635, upload-time = "2026-05-15T04:51:02.629Z" }, + { url = "https://files.pythonhosted.org/packages/94/b0/c8ae9aff00d625c50659b4513e707a0462c4bf5d4d6cc1b802103225c02e/tiktoken-0.13.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:32e0c12305105002c047b3bb1070b0dd9a73b0cb3b2856a8972b810e7a4f5881", size = 1116036, upload-time = "2026-05-15T04:51:04.082Z" }, + { url = "https://files.pythonhosted.org/packages/1b/ac/6a5dddd1d0a6018ecb389bd0353e6b4a515eb4d2286611bd0ace1937b9e1/tiktoken-0.13.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:5ba5fd62507a932d1241346179e3b39bc7bf7408f03c272652d93b3bedf5db24", size = 1135544, upload-time = "2026-05-15T04:51:05.229Z" }, + { url = "https://files.pythonhosted.org/packages/f4/b8/585032b4384b2f7dcdaddcb52865c83a701a420d09e3c2b4a2be1c450c57/tiktoken-0.13.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d108bc2d470fc53c8ecd24f2c0fd2b5f98c33e87cdb6aa2e9b8c5dced703d273", size = 1182217, upload-time = "2026-05-15T04:51:06.517Z" }, + { url = "https://files.pythonhosted.org/packages/cd/b6/993ff1ded3958215fd341a847b8e5ffeb5de473f435296870d314fc91ac4/tiktoken-0.13.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:cb99cb5127449f58d0a2d5f5ccfb390d8dbdfd919c221246caaee29d8725ed51", size = 1239404, upload-time = "2026-05-15T04:51:07.843Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3d/fef7e06e3b33e7538db0ced734cf9fe23b6832d2ac4990c119c377aec55e/tiktoken-0.13.0-cp314-cp314-win_amd64.whl", hash = "sha256:115c4f26ffa11caac8b54eea35c2ad38c612c20a48d35dd15d70a02ac6f51f58", size = 918686, upload-time = "2026-05-15T04:51:08.925Z" }, + { url = "https://files.pythonhosted.org/packages/c1/82/a7fc44582bc32ab00de988a2299bf77c077f59068b233109e34b7d6ca7e6/tiktoken-0.13.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:472527e9132952f2fbf77cd290658bacf003d4d5a3fabc18e5fbd407cbae4d9b", size = 1034454, upload-time = "2026-05-15T04:51:10.035Z" }, + { url = "https://files.pythonhosted.org/packages/37/d0/24d8a890c14f432a05cea669c17bebeaa99f96a7c79523b590f564246411/tiktoken-0.13.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:4e2f67d27c9626cdd25fe33d9313c5cdb3d8d82da646b68d6eb8e7e9c20e6448", size = 982976, upload-time = "2026-05-15T04:51:11.23Z" }, + { url = "https://files.pythonhosted.org/packages/49/b7/2ab43f62788a9266187a9bfc1d3af99ad83e5eaa25fbef168a69cd5ad14f/tiktoken-0.13.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:2b920b35805cd64585a37c3dc7ce65fba4d2d36016be01e1d7942482ca29093a", size = 1115526, upload-time = "2026-05-15T04:51:12.608Z" }, + { url = "https://files.pythonhosted.org/packages/64/39/1494321ed323ce7a14d88e3cd6cb9058625977df1c6961ddc492bd10a9f3/tiktoken-0.13.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:493af3aa28a4aaf2e3d2600a2ee717252c9bf5ab38fff94eb5a02db5ab77e5ad", size = 1136466, upload-time = "2026-05-15T04:51:13.926Z" }, + { url = "https://files.pythonhosted.org/packages/96/d9/dfd086aa2d918c563a140720e0ce296cada1634efd2783d5cf51e05f984e/tiktoken-0.13.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6644c9c2b5cf3916f5a3641d7d12fdb3f006a7b3d9ff6acdaec44e29ab1ff91e", size = 1181863, upload-time = "2026-05-15T04:51:15.025Z" }, + { url = "https://files.pythonhosted.org/packages/2f/68/a18b4f307086954fdae32714cb4f85562e34f9d34ab206e61f1816aa6018/tiktoken-0.13.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5cb65b60b9408563676d874a3a4ee573370066f0dc4e29d84e82e989c6517424", size = 1239218, upload-time = "2026-05-15T04:51:16.103Z" }, + { url = "https://files.pythonhosted.org/packages/16/5b/f2aa703a4fc5d2dff73460a7d46cc2f3f44aa0f3dd8eeb20d2a0ecf68862/tiktoken-0.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:85b78cc3a2c3d48723ca751fa981f1fedccd54194ca0471b957364353a898b07", size = 918110, upload-time = "2026-05-15T04:51:17.237Z" }, ] [[package]] @@ -2422,14 +3284,14 @@ wheels = [ [[package]] name = "tqdm" -version = "4.67.3" +version = "4.68.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/09/a9/6ba95a270c6f1fbcd8dac228323f2777d886cb206987444e4bce66338dd4/tqdm-4.67.3.tar.gz", hash = "sha256:7d825f03f89244ef73f1d4ce193cb1774a8179fd96f31d7e1dcde62092b960bb", size = 169598, upload-time = "2026-02-03T17:35:53.048Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ae/5f/57ff8b434839e70dab45601284ea413e947a63799891b7553e5960a793a8/tqdm-4.68.4.tar.gz", hash = "sha256:19829c9673638f2a0b8617da4cdcb927e831cd88bcfcb6e78d42a4d1af131520", size = 792418, upload-time = "2026-07-07T09:58:18.369Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl", hash = "sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf", size = 78374, upload-time = "2026-02-03T17:35:50.982Z" }, + { url = "https://files.pythonhosted.org/packages/22/2a/5e5e750890ada51017d18d0d4c30da696e5b5bd3180947729927628fc3cb/tqdm-4.68.4-py3-none-any.whl", hash = "sha256:5168118b2368f48c561afda8020fd79195b1bdb0bdf8086b88442c267a315dc2", size = 676612, upload-time = "2026-07-07T09:58:16.256Z" }, ] [[package]] @@ -2443,35 +3305,36 @@ wheels = [ [[package]] name = "ty" -version = "0.0.34" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c4/69/e24eefe2c35c0fdbdec9b60e162727af669bb76d64d993d982eb67b24c38/ty-0.0.34.tar.gz", hash = "sha256:a6efe66b0f13c03a65e6c72ec9abfe2792e2fd063c74fa67e2c4930e29d661be", size = 5585933, upload-time = "2026-05-01T23:06:46.388Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/83/7b/8b85003d6639ef17a97dcbb31f4511cfe78f1c81a964470db100c8c883e7/ty-0.0.34-py3-none-linux_armv6l.whl", hash = "sha256:9ecc3d14f07a95a6ceb88e07f8e62358dbd37325d3d5bd56da7217ff1fef7fb8", size = 11067094, upload-time = "2026-05-01T23:06:21.133Z" }, - { url = "https://files.pythonhosted.org/packages/d7/25/b0098f65b020b015c40567c763fc66fffbec88b2ba6f584bca1e92f05ebb/ty-0.0.34-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:0dccffd8a9d02321cd2dee3249df205e26d62694e741f4eeca36b157fd8b419f", size = 10840909, upload-time = "2026-05-01T23:06:18.409Z" }, - { url = "https://files.pythonhosted.org/packages/e4/55/5e4adcf7d2a1006b844903b27cb81244a9b748d850433a46a6c21776c401/ty-0.0.34-py3-none-macosx_11_0_arm64.whl", hash = "sha256:b0ea47a2998e167ab3b21d2f4b5309a9cf33c297809f6d7e3e753252223174d0", size = 10279378, upload-time = "2026-05-01T23:06:37.962Z" }, - { url = "https://files.pythonhosted.org/packages/4d/91/f537dca0db8fe2558e8ab04d8941d687b384fcc1df5eb9023b2db75ac26c/ty-0.0.34-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b37da00b41a118a459ae56d8947e70651073fb33ebfbceb820e4a10b22d5023", size = 10817423, upload-time = "2026-05-01T23:06:26.247Z" }, - { url = "https://files.pythonhosted.org/packages/2c/c4/55a3ad1da2815af1009bdc1b8c90dc11a364cd314e4b48c5128ba9d38859/ty-0.0.34-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:81cbbb93c2342fe3de43e625d3a9eb149633e9f485e816ebf6395d08685355d8", size = 10851826, upload-time = "2026-05-01T23:06:24.198Z" }, - { url = "https://files.pythonhosted.org/packages/ce/8c/9c7606af22d73fb43ea4369472d9c66ece11231be73b0efe8e3c61655559/ty-0.0.34-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c5b4dea1594a021289e172582df9cde7089dce14b276fc650e7b212b1772e12", size = 11356318, upload-time = "2026-05-01T23:06:51.139Z" }, - { url = "https://files.pythonhosted.org/packages/20/54/bb423f663721ab4138b216425c6b55eaefd3a068243b24d6d8fe988f4e13/ty-0.0.34-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:030fb00aa2d2a5b5ae9d9183d574e0c82dae80566700a7490c43669d8ece40cd", size = 11902968, upload-time = "2026-05-01T23:06:35.82Z" }, - { url = "https://files.pythonhosted.org/packages/b6/22/01122b21ab6b534a2f618c6bbe5f1f7f49fd56f4b2ec8887cd6d40d08fb3/ty-0.0.34-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ae9555e24e36c63a8218e037a5a63f15579eb6aa94f41017e57cd41d335cfb5", size = 11548860, upload-time = "2026-05-01T23:06:42.155Z" }, - { url = "https://files.pythonhosted.org/packages/d1/50/86008b1392ec64bed1957bbcc7aaa43b466b50dfc91bb131841c21d7c5c3/ty-0.0.34-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99eb23df9ed129fc26d1ab00d6f0b8dfe5253b09c2ac6abdb11523fa70d67f10", size = 11457097, upload-time = "2026-05-01T23:06:53.477Z" }, - { url = "https://files.pythonhosted.org/packages/92/3e/4558b2296963ba99c58d8409c57d7db4f3061b656c3613cb21c02c1ef4c2/ty-0.0.34-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:85de45382016eceae69e104815eb2cfa200787df104002e262a86cbd43ed2c02", size = 10798192, upload-time = "2026-05-01T23:06:40.004Z" }, - { url = "https://files.pythonhosted.org/packages/76/bf/650d24402be2ef678528d60caac1d9477a40fc37e3792ecef07834fd7a4a/ty-0.0.34-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:14cb575fb8fa5131f5129d100cfe23c1575d23faf5dfc5158432749a3e38c9b5", size = 10890390, upload-time = "2026-05-01T23:06:33.076Z" }, - { url = "https://files.pythonhosted.org/packages/5c/ef/ccd2ca13906079f7935fd7e067661b24233017f57d987d51d6a121d85bb5/ty-0.0.34-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c6fc0b69d8450e6910ba9db34572b959b81329a97ae273c391f70e9fb6c1aade", size = 11031564, upload-time = "2026-05-01T23:06:55.812Z" }, - { url = "https://files.pythonhosted.org/packages/ba/2d/d27b72005b6f43599e3bcabab0d7135ac0c230b7a307bb99f9eea02c1cda/ty-0.0.34-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:30dfcec2f0fde3993f4f912ed0e057dcbebc8615299f610a4c2ddb7b5a3e1e06", size = 11553430, upload-time = "2026-05-01T23:06:31.096Z" }, - { url = "https://files.pythonhosted.org/packages/a7/12/20812e1ad930b8d4af70eebf19ad23cff6e31efcfa613ef884531fcdbaa1/ty-0.0.34-py3-none-win32.whl", hash = "sha256:97b77ddf007271b812a313a8f0a14929bc5590958433e1fb83ef585676f53342", size = 10436048, upload-time = "2026-05-01T23:06:49.108Z" }, - { url = "https://files.pythonhosted.org/packages/b0/6a/afa095c5987868fbda27c0f731146ac8e3d07b357adfa83daccaee5b1a16/ty-0.0.34-py3-none-win_amd64.whl", hash = "sha256:1f543968accb952705134028d1fda8656882787dbbc667ad4d6c3ba23791d604", size = 11462526, upload-time = "2026-05-01T23:06:28.514Z" }, - { url = "https://files.pythonhosted.org/packages/63/8f/bf041a06260d77662c0605e56dacfe90b786bf824cbe1aed238d15fe5e84/ty-0.0.34-py3-none-win_arm64.whl", hash = "sha256:ea09108cbcb16b6b06d7596312b433bf49681e78d30e4dc7fb3c1b248a95e09a", size = 10846945, upload-time = "2026-05-01T23:06:44.428Z" }, +version = "0.0.56" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/55/07/fb29aea5235b0aa8ecfc4d1cc6ddf9fba8b863d67d96c6d345694d644c43/ty-0.0.56.tar.gz", hash = "sha256:84d114dc3796361c0fc72945016eabd74d46b9ee64f198cb0e485719704681e5", size = 6050123, upload-time = "2026-07-01T16:44:56.036Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/48/bce79e7ca5c1cc529d3e0d37ddd1121aea4b68a4f749974ad1cc77161871/ty-0.0.56-py3-none-linux_armv6l.whl", hash = "sha256:186d4a53e15747c947e1ec3d7eec8e345d8e40a1ca10e634c585db52497e87dd", size = 11643066, upload-time = "2026-07-01T16:44:18.374Z" }, + { url = "https://files.pythonhosted.org/packages/80/d1/22555d8a1d719661f10050f3865d877bbf497da908961c75fe22217dd18a/ty-0.0.56-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:aae1a980fd9535da0469b7ba2b2e1b54a907743a5e0f442dd57eee9f5bfd034c", size = 11407487, upload-time = "2026-07-01T16:44:20.956Z" }, + { url = "https://files.pythonhosted.org/packages/cf/2d/b3b7a74ce8bc59ef48843ad80179bb0d9598bbd6cfc0d11d519bdf6b1352/ty-0.0.56-py3-none-macosx_11_0_arm64.whl", hash = "sha256:afd3058c0a6c5f241e814734f133008c93ee805f61c9cf4ce7412b8822b5d9ad", size = 10962270, upload-time = "2026-07-01T16:44:22.959Z" }, + { url = "https://files.pythonhosted.org/packages/64/ac/6c2fd7de0304a8a7218a756af74f7e62a5e8540fdb175e0a869e51042345/ty-0.0.56-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:058b52f7a823ac13aae3cae30809dd6b5145794b64d8478f9ef38c75d79b4483", size = 11471406, upload-time = "2026-07-01T16:44:25.327Z" }, + { url = "https://files.pythonhosted.org/packages/50/b6/11d861156861c03c7726b74558f9a0e0092661aff83a4fda1279df28c425/ty-0.0.56-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c66e00c1522add1f2bbdd2e45828c953b35c306b7bef03ec9169c75a63699a0", size = 11445612, upload-time = "2026-07-01T16:44:27.531Z" }, + { url = "https://files.pythonhosted.org/packages/fb/ba/09df108582090f3c0770ec4bc8675affed60248f6793a78d909be16211d9/ty-0.0.56-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40903d71c669a30691b5a5d5728056c7877a1bd6be4f233a38883a8b28cf34d7", size = 12093889, upload-time = "2026-07-01T16:44:29.548Z" }, + { url = "https://files.pythonhosted.org/packages/d7/f7/dbb4b4ccb69cd64c209ae55b1ab788ace8222c2bc1f6845be9e7cbedbf25/ty-0.0.56-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63fe3947fe0c46c69a7d950e6832ee70a9ec17321fefbff3d2e3c20baf9e5bd0", size = 12666337, upload-time = "2026-07-01T16:44:31.586Z" }, + { url = "https://files.pythonhosted.org/packages/86/e9/73f903fe4a3d9ea02f26f57c1eb07e3b1029ec92b0e8c2364718893440e3/ty-0.0.56-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:71a0c1a72f9854532e710e119b6871ffe4542c8a65146f1f65dcd78fecd885b4", size = 12280247, upload-time = "2026-07-01T16:44:33.637Z" }, + { url = "https://files.pythonhosted.org/packages/d6/90/cebd222495832f1a00dcd321ba25f3cab804221a4991b992c2178bec68ee/ty-0.0.56-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70d1665596494e24d8ebd198438872b5a56ec3cae5f2bcf6c673be797acc4e3c", size = 11991107, upload-time = "2026-07-01T16:44:36.122Z" }, + { url = "https://files.pythonhosted.org/packages/b7/07/8f7337a07250f42d975cdb6decf47fc5b421e6c7da5e3e7be1e85f63a7e5/ty-0.0.56-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:778f99e51558afc1dbbe48ee38ab6aae7b31390ed8c1a1ef1499b295e9f1e82f", size = 12298970, upload-time = "2026-07-01T16:44:38.243Z" }, + { url = "https://files.pythonhosted.org/packages/3c/b9/a52cd59034a48f5f18c6b155cc2cc36861d874b6d0af204b12c898024c3d/ty-0.0.56-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:867bc5708e0066bb4ff6c7db524bd5deea2676c62bfe71d3303138b3be850af0", size = 11425683, upload-time = "2026-07-01T16:44:40.473Z" }, + { url = "https://files.pythonhosted.org/packages/1d/2e/48e42d33357d52eefb695c0c3fcfc96879b73668a7447d1d1e0ad774fedc/ty-0.0.56-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a6012f4189c928edb330a37deb9930f982380bd4aa7c4b8e0428eec9651c7551", size = 11469258, upload-time = "2026-07-01T16:44:42.513Z" }, + { url = "https://files.pythonhosted.org/packages/d5/01/ad1b4138be1e3fa97863af3925aa2134f17a593240c35dc38c3429fb5ad1/ty-0.0.56-py3-none-musllinux_1_2_i686.whl", hash = "sha256:8ee83de1a7ff4cc32837ec06134ce391d441bc5b35ecd8d3cfe053f120f3e4c1", size = 11758736, upload-time = "2026-07-01T16:44:44.567Z" }, + { url = "https://files.pythonhosted.org/packages/09/34/9d81967ff240eaa57e9249728ef7b7790747cf6d3c9a98ec86b2cfdcc8ee/ty-0.0.56-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:62619b3b0e2c6248ef30d3f0e2f2217ae9893040585be07f32324242f197cd6f", size = 12100242, upload-time = "2026-07-01T16:44:46.584Z" }, + { url = "https://files.pythonhosted.org/packages/c3/36/f51d4666d2de6cf33c1f3a1fcc4bb6b70b197dd6ceaa491eef71d78fe8e8/ty-0.0.56-py3-none-win32.whl", hash = "sha256:b30687bb5cd9729d34c889a289edf32770388d9bb05243e534e723fb45e0381b", size = 11093759, upload-time = "2026-07-01T16:44:49.171Z" }, + { url = "https://files.pythonhosted.org/packages/5e/b4/8fb5d4acfa4afb152245b20fa263069a7547bd1f8e4bfca4eda280c897d7/ty-0.0.56-py3-none-win_amd64.whl", hash = "sha256:ad4c8c47b6f4e3f9ed3fc0b1a5d650088d229e17dd8f63c1826d6bbe94cc3235", size = 12100327, upload-time = "2026-07-01T16:44:51.26Z" }, + { url = "https://files.pythonhosted.org/packages/b8/fc/6a183e71edde90d0c35c2303f23f7a45b6891d1a2c45daf7b8f869831e19/ty-0.0.56-py3-none-win_arm64.whl", hash = "sha256:57538f273d444a5f1293fa7860e967178afe3917611fc5eff16b64e1204fe0d6", size = 11538780, upload-time = "2026-07-01T16:44:53.8Z" }, ] [[package]] name = "typing-extensions" -version = "4.15.0" +version = "4.16.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, + { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" }, ] [[package]] @@ -2497,57 +3360,128 @@ wheels = [ [[package]] name = "uuid-utils" -version = "0.14.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7b/d1/38a573f0c631c062cf42fa1f5d021d4dd3c31fb23e4376e4b56b0c9fbbed/uuid_utils-0.14.1.tar.gz", hash = "sha256:9bfc95f64af80ccf129c604fb6b8ca66c6f256451e32bc4570f760e4309c9b69", size = 22195, upload-time = "2026-02-20T22:50:38.833Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/43/b7/add4363039a34506a58457d96d4aa2126061df3a143eb4d042aedd6a2e76/uuid_utils-0.14.1-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:93a3b5dc798a54a1feb693f2d1cb4cf08258c32ff05ae4929b5f0a2ca624a4f0", size = 604679, upload-time = "2026-02-20T22:50:27.469Z" }, - { url = "https://files.pythonhosted.org/packages/dd/84/d1d0bef50d9e66d31b2019997c741b42274d53dde2e001b7a83e9511c339/uuid_utils-0.14.1-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:ccd65a4b8e83af23eae5e56d88034b2fe7264f465d3e830845f10d1591b81741", size = 309346, upload-time = "2026-02-20T22:50:31.857Z" }, - { url = "https://files.pythonhosted.org/packages/ef/ed/b6d6fd52a6636d7c3eddf97d68da50910bf17cd5ac221992506fb56cf12e/uuid_utils-0.14.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b56b0cacd81583834820588378e432b0696186683b813058b707aedc1e16c4b1", size = 344714, upload-time = "2026-02-20T22:50:42.642Z" }, - { url = "https://files.pythonhosted.org/packages/a8/a7/a19a1719fb626fe0b31882db36056d44fe904dc0cf15b06fdf56b2679cf7/uuid_utils-0.14.1-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb3cf14de789097320a3c56bfdfdd51b1225d11d67298afbedee7e84e3837c96", size = 350914, upload-time = "2026-02-20T22:50:36.487Z" }, - { url = "https://files.pythonhosted.org/packages/1d/fc/f6690e667fdc3bb1a73f57951f97497771c56fe23e3d302d7404be394d4f/uuid_utils-0.14.1-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60e0854a90d67f4b0cc6e54773deb8be618f4c9bad98d3326f081423b5d14fae", size = 482609, upload-time = "2026-02-20T22:50:37.511Z" }, - { url = "https://files.pythonhosted.org/packages/54/6e/dcd3fa031320921a12ec7b4672dea3bd1dd90ddffa363a91831ba834d559/uuid_utils-0.14.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce6743ba194de3910b5feb1a62590cd2587e33a73ab6af8a01b642ceb5055862", size = 345699, upload-time = "2026-02-20T22:50:46.87Z" }, - { url = "https://files.pythonhosted.org/packages/04/28/e5220204b58b44ac0047226a9d016a113fde039280cc8732d9e6da43b39f/uuid_utils-0.14.1-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:043fb58fde6cf1620a6c066382f04f87a8e74feb0f95a585e4ed46f5d44af57b", size = 372205, upload-time = "2026-02-20T22:50:28.438Z" }, - { url = "https://files.pythonhosted.org/packages/c7/d9/3d2eb98af94b8dfffc82b6a33b4dfc87b0a5de2c68a28f6dde0db1f8681b/uuid_utils-0.14.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c915d53f22945e55fe0d3d3b0b87fd965a57f5fd15666fd92d6593a73b1dd297", size = 521836, upload-time = "2026-02-20T22:50:23.057Z" }, - { url = "https://files.pythonhosted.org/packages/a8/15/0eb106cc6fe182f7577bc0ab6e2f0a40be247f35c5e297dbf7bbc460bd02/uuid_utils-0.14.1-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:0972488e3f9b449e83f006ead5a0e0a33ad4a13e4462e865b7c286ab7d7566a3", size = 625260, upload-time = "2026-02-20T22:50:25.949Z" }, - { url = "https://files.pythonhosted.org/packages/3c/17/f539507091334b109e7496830af2f093d9fc8082411eafd3ece58af1f8ba/uuid_utils-0.14.1-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:1c238812ae0c8ffe77d8d447a32c6dfd058ea4631246b08b5a71df586ff08531", size = 587824, upload-time = "2026-02-20T22:50:35.225Z" }, - { url = "https://files.pythonhosted.org/packages/2e/c2/d37a7b2e41f153519367d4db01f0526e0d4b06f1a4a87f1c5dfca5d70a8b/uuid_utils-0.14.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:bec8f8ef627af86abf8298e7ec50926627e29b34fa907fcfbedb45aaa72bca43", size = 551407, upload-time = "2026-02-20T22:50:44.915Z" }, - { url = "https://files.pythonhosted.org/packages/65/36/2d24b2cbe78547c6532da33fb8613debd3126eccc33a6374ab788f5e46e9/uuid_utils-0.14.1-cp39-abi3-win32.whl", hash = "sha256:b54d6aa6252d96bac1fdbc80d26ba71bad9f220b2724d692ad2f2310c22ef523", size = 183476, upload-time = "2026-02-20T22:50:32.745Z" }, - { url = "https://files.pythonhosted.org/packages/83/92/2d7e90df8b1a69ec4cff33243ce02b7a62f926ef9e2f0eca5a026889cd73/uuid_utils-0.14.1-cp39-abi3-win_amd64.whl", hash = "sha256:fc27638c2ce267a0ce3e06828aff786f91367f093c80625ee21dad0208e0f5ba", size = 187147, upload-time = "2026-02-20T22:50:45.807Z" }, - { url = "https://files.pythonhosted.org/packages/d9/26/529f4beee17e5248e37e0bc17a2761d34c0fa3b1e5729c88adb2065bae6e/uuid_utils-0.14.1-cp39-abi3-win_arm64.whl", hash = "sha256:b04cb49b42afbc4ff8dbc60cf054930afc479d6f4dd7f1ec3bbe5dbfdde06b7a", size = 188132, upload-time = "2026-02-20T22:50:41.718Z" }, - { url = "https://files.pythonhosted.org/packages/91/f9/6c64bdbf71f58ccde7919e00491812556f446a5291573af92c49a5e9aaef/uuid_utils-0.14.1-pp311-pypy311_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:b197cd5424cf89fb019ca7f53641d05bfe34b1879614bed111c9c313b5574cd8", size = 591617, upload-time = "2026-02-20T22:50:24.532Z" }, - { url = "https://files.pythonhosted.org/packages/d0/f0/758c3b0fb0c4871c7704fef26a5bc861de4f8a68e4831669883bebe07b0f/uuid_utils-0.14.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:12c65020ba6cb6abe1d57fcbfc2d0ea0506c67049ee031714057f5caf0f9bc9c", size = 303702, upload-time = "2026-02-20T22:50:40.687Z" }, - { url = "https://files.pythonhosted.org/packages/85/89/d91862b544c695cd58855efe3201f83894ed82fffe34500774238ab8eba7/uuid_utils-0.14.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b5d2ad28063d422ccc2c28d46471d47b61a58de885d35113a8f18cb547e25bf", size = 337678, upload-time = "2026-02-20T22:50:39.768Z" }, - { url = "https://files.pythonhosted.org/packages/ee/6b/cf342ba8a898f1de024be0243fac67c025cad530c79ea7f89c4ce718891a/uuid_utils-0.14.1-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:da2234387b45fde40b0fedfee64a0ba591caeea9c48c7698ab6e2d85c7991533", size = 343711, upload-time = "2026-02-20T22:50:43.965Z" }, - { url = "https://files.pythonhosted.org/packages/b3/20/049418d094d396dfa6606b30af925cc68a6670c3b9103b23e6990f84b589/uuid_utils-0.14.1-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50fffc2827348c1e48972eed3d1c698959e63f9d030aa5dd82ba451113158a62", size = 476731, upload-time = "2026-02-20T22:50:30.589Z" }, - { url = "https://files.pythonhosted.org/packages/77/a1/0857f64d53a90321e6a46a3d4cc394f50e1366132dcd2ae147f9326ca98b/uuid_utils-0.14.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1dbe718765f70f5b7f9b7f66b6a937802941b1cc56bcf642ce0274169741e01", size = 338902, upload-time = "2026-02-20T22:50:33.927Z" }, - { url = "https://files.pythonhosted.org/packages/ed/d0/5bf7cbf1ac138c92b9ac21066d18faf4d7e7f651047b700eb192ca4b9fdb/uuid_utils-0.14.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:258186964039a8e36db10810c1ece879d229b01331e09e9030bc5dcabe231bd2", size = 364700, upload-time = "2026-02-20T22:50:21.732Z" }, +version = "0.16.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/5a/5da7ae85b38e3eddba0be3e8e4328f90882fe92989728e6fb552963d4c42/uuid_utils-0.16.2.tar.gz", hash = "sha256:fa637e4f314ad5b59ff6d8e809d506443d68bef30bfaecdfcfe02cce689abb2f", size = 42962, upload-time = "2026-06-18T13:36:48.735Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0a/96/4023966d42fd9bbf9e2a8ce2b25930113688128b569f68bc4697cb18181d/uuid_utils-0.16.2-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:fadd23eee409237fb8637a35796a6e108873c28b40f7de89a36685f18ca055ad", size = 567776, upload-time = "2026-06-18T13:35:02.902Z" }, + { url = "https://files.pythonhosted.org/packages/fc/30/764d2a76e8e7688abd5577e6024787c13692095eb1230fd1936f27205cd9/uuid_utils-0.16.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:79c5a3bd4301257b9a524efd16baf61ea65cd0d1b60b47d80f20b151fd65a09f", size = 288938, upload-time = "2026-06-18T13:35:04.285Z" }, + { url = "https://files.pythonhosted.org/packages/45/ef/58077250fe04eda4a3f9fba8c35be8d0937b7d3e02302ac1a6d942b77dae/uuid_utils-0.16.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90903ab7fcdfb0300390c15f5a68cb91f15139d9a1a93f134c783d7a973fa269", size = 327387, upload-time = "2026-06-18T13:35:05.406Z" }, + { url = "https://files.pythonhosted.org/packages/c6/fd/a9172970fa07ce0b9148ccc679a99540375c7bb32f8fbd72cf1e6cca43ef/uuid_utils-0.16.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f7a44f8250ec178c0af703c3f1b6e81865a771272ae735ca403f27c95c62f132", size = 334212, upload-time = "2026-06-18T13:35:06.611Z" }, + { url = "https://files.pythonhosted.org/packages/ca/58/d8fb393b44ad0b719d96a5b7809d0ee727f7e266d9e88a4da235cbfbf9f8/uuid_utils-0.16.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9e97ab941660f781a8e45f15aba9ee01b40dbb96adb5c43617c1671a4604b25b", size = 450379, upload-time = "2026-06-18T13:35:07.97Z" }, + { url = "https://files.pythonhosted.org/packages/00/70/b3cf708e8942e6494742404a66f1586195a20c8fd235bdc79f385db383f1/uuid_utils-0.16.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a30b6a5790acb854e4b65fae7875e5d3c6f8076fa9c91dac43ff9e28380bc52", size = 327231, upload-time = "2026-06-18T13:35:09.327Z" }, + { url = "https://files.pythonhosted.org/packages/a8/9c/4c5b16e752a2402259a3a9d1371227025e5b85182024c82a446cbe3ed6ea/uuid_utils-0.16.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5dfc3e9e75139a84898771d31958ece6cdee8e8f127700aa8aa26a4f1a348d57", size = 353455, upload-time = "2026-06-18T13:35:10.67Z" }, + { url = "https://files.pythonhosted.org/packages/0c/0f/3b14c47fab1544bcfb92d28bc468160a4fc6ff342d0e6defa8ff40d5e4bd/uuid_utils-0.16.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0529b1ef0788f663e1211d221b59a38ec67f9b084f1ea5342ba84358b3d87e98", size = 504028, upload-time = "2026-06-18T13:35:12.006Z" }, + { url = "https://files.pythonhosted.org/packages/39/79/1a133214626eb0e18c51ef196946b1263d65b578ffee432ad1b7afffa5d3/uuid_utils-0.16.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:cae08df8695f4b01fce2a8ab50e9e310971276d85dfc7103e977bed52d365094", size = 609803, upload-time = "2026-06-18T13:35:13.286Z" }, + { url = "https://files.pythonhosted.org/packages/87/49/22bff932af63764b4cad9c01299ed64c60d101962988efc13964b4165345/uuid_utils-0.16.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f69658c42411540cf58be958a47e317fd2302cc0b613ea5cff1e60d87be2846d", size = 569512, upload-time = "2026-06-18T13:35:14.661Z" }, + { url = "https://files.pythonhosted.org/packages/3f/98/371cc1f332f7463b9cfac0a66f984af00f4e3ada4a196b20879e35404e8b/uuid_utils-0.16.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:503f020acc7dbeb39c47fa33cf2971cf5960fa11f8394513fac461762a90c556", size = 532855, upload-time = "2026-06-18T13:35:15.99Z" }, + { url = "https://files.pythonhosted.org/packages/f1/06/f7ef7f6dabf68021eb6e961c09d16d517ed7587cedfff18969ba7f61798c/uuid_utils-0.16.2-cp311-cp311-win32.whl", hash = "sha256:aab7cdf28a3e2859ca4f40a3e3bf53eb35895039c80d4d8d8c5e15b90346c55c", size = 169971, upload-time = "2026-06-18T13:35:17.294Z" }, + { url = "https://files.pythonhosted.org/packages/75/8b/1e4b51c075eaadd23828b708249374db0bc40146f7b673027942d3383f45/uuid_utils-0.16.2-cp311-cp311-win_amd64.whl", hash = "sha256:71192a59d473f3f638e2a238905046e2942006ad90ac5ec10d578e58ff9a08ce", size = 176464, upload-time = "2026-06-18T13:35:18.459Z" }, + { url = "https://files.pythonhosted.org/packages/d4/71/18a43b6e632adf3cb3cf5db777ea03f9d3b2b259de65de5e41419004c2a1/uuid_utils-0.16.2-cp311-cp311-win_arm64.whl", hash = "sha256:ea175649789f1e93edbf1a0440cab18c9838977703917221777691d8d988d7bf", size = 176056, upload-time = "2026-06-18T13:35:19.826Z" }, + { url = "https://files.pythonhosted.org/packages/fd/07/294b72a572218bf6e92355203b832b3356c58a7e1e0b92a034497d15bef9/uuid_utils-0.16.2-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:6f064dc54c6abecb09eb104d953bfb079f3c395e0d6b18899979f852d1083549", size = 560726, upload-time = "2026-06-18T13:35:21.053Z" }, + { url = "https://files.pythonhosted.org/packages/e5/3c/1095b6ab574a7fa69136d47bab5a43f320a8f00a0ecb96059fd49b1747b2/uuid_utils-0.16.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:dd7aa18db5cc826d482d876a826fee445839701f81f78567e7c74b4458d57a84", size = 288065, upload-time = "2026-06-18T13:35:22.547Z" }, + { url = "https://files.pythonhosted.org/packages/4c/9d/6404d48fe71def0733c9568d96043b2e1945e2e4205c4eb525db3da42ba3/uuid_utils-0.16.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc25ad320c9b44c2d3ed33aff4f85b0b277bef4ff79b12c01ee58b52ea44be1d", size = 322946, upload-time = "2026-06-18T13:35:23.648Z" }, + { url = "https://files.pythonhosted.org/packages/74/00/8a009762015a134aa04b5451400e0ec9832ccd598ed4845f9aecb0be6299/uuid_utils-0.16.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d0ca752d51d1004caff65fccffd44b32a26cb099b546e0512cfa09facb683d6c", size = 330186, upload-time = "2026-06-18T13:35:24.757Z" }, + { url = "https://files.pythonhosted.org/packages/b7/b0/1613bb98ac11234145aa5bc1de618be536818fef05dec595efb3e2b37097/uuid_utils-0.16.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8323136bb02355c1b973492ab98b0722206dfdedfb148e4115c35fcdf3889bad", size = 444583, upload-time = "2026-06-18T13:35:25.999Z" }, + { url = "https://files.pythonhosted.org/packages/93/66/83e62c7a152bbbb8b30ac58eaad81f3860ba2fba91a334c50f223f9ce878/uuid_utils-0.16.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9bf8bfdffb22f620635580b17fd178272f30a9841b824b19b935c8db64bf09b6", size = 323064, upload-time = "2026-06-18T13:35:27.356Z" }, + { url = "https://files.pythonhosted.org/packages/15/37/c1b2faaf3a9d7952f321a9fee3ad74e05b25878bd9b7cd6b0398fe77f279/uuid_utils-0.16.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:61454f2139424a6cff14eca7849c28b3350f261453b74075aa20fe99592dbb16", size = 347967, upload-time = "2026-06-18T13:35:28.538Z" }, + { url = "https://files.pythonhosted.org/packages/24/d8/cdf79b242e41ae47b7cd617ac5d48f15ce44e81da8000379c757091ae5f8/uuid_utils-0.16.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:725110434a1d482a639a9ac467a24f1cb531d84ab52e454a13fe145b10b42cae", size = 499187, upload-time = "2026-06-18T13:35:30.042Z" }, + { url = "https://files.pythonhosted.org/packages/be/10/978d5ad82bc0fe7ff02d5be6f1eb83b090849f0a95bf8438593565273b7a/uuid_utils-0.16.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:8197870739a3094990743a80f075fa0b17beafd6c187e5f360e021d90a12a6d1", size = 605696, upload-time = "2026-06-18T13:35:31.289Z" }, + { url = "https://files.pythonhosted.org/packages/3a/28/e382ee44a592e35b80397b493bf3fbbdb8e30a64eaaefc7dabc246aeb253/uuid_utils-0.16.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e10a02b3a31ed44c7c9a96abde335f5fa222735e73f3081d693414377eb3b016", size = 564975, upload-time = "2026-06-18T13:35:32.419Z" }, + { url = "https://files.pythonhosted.org/packages/a3/d0/f6011dbe4e5d751a8494715e014019cb5b242d8cd6dbec1cfec3d3fb2e81/uuid_utils-0.16.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fd32dbca0792b9683160151dc07fad11b915020eed7c82b43faf0862c2ff06a0", size = 528462, upload-time = "2026-06-18T13:35:33.685Z" }, + { url = "https://files.pythonhosted.org/packages/42/7f/279e6159c37f43feb9dd70218b49a26696cefddaef1db7f4b79895eaf5d5/uuid_utils-0.16.2-cp312-cp312-win32.whl", hash = "sha256:dcdfcab60562d12dd43c1a6f495b1d089e41f0e10fac37d94db285d72b678c23", size = 167047, upload-time = "2026-06-18T13:35:34.862Z" }, + { url = "https://files.pythonhosted.org/packages/47/38/f72f7bed062601448ec2db47351e6c1faccd78fd693bbc6e067299d1fa11/uuid_utils-0.16.2-cp312-cp312-win_amd64.whl", hash = "sha256:97ee6f5e803ea571f5f6da42efc97d8c5a13f121043680177f8470529b94e855", size = 173821, upload-time = "2026-06-18T13:35:36.117Z" }, + { url = "https://files.pythonhosted.org/packages/37/61/8a025284a31c85b7c0c5319e96868c2c09dea3fc5f676c979a4cd4baf2e7/uuid_utils-0.16.2-cp312-cp312-win_arm64.whl", hash = "sha256:72cfd9ff1e8a7c371a044687e77eb873721c4a9f4814e453439bfba595b84303", size = 172206, upload-time = "2026-06-18T13:35:37.339Z" }, + { url = "https://files.pythonhosted.org/packages/ed/a1/3b48859953ee74fc26628ca5d9e5f848209655a0a8c934032fc596035976/uuid_utils-0.16.2-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:c19b7d595d12923da682ed13d313c2333b9ebf214e65a47a24927a8a3a81b191", size = 560753, upload-time = "2026-06-18T13:35:38.531Z" }, + { url = "https://files.pythonhosted.org/packages/ba/1c/77635489de5454f2a25411030f78d31931dbdc0c86114da00adb9b91f120/uuid_utils-0.16.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:909e26fa2451c8db31b9ed1d3c8e4ecf513b6d1619db4205997fe99eb6b4ef4f", size = 288056, upload-time = "2026-06-18T13:35:39.966Z" }, + { url = "https://files.pythonhosted.org/packages/ad/0e/8e799537ea458abaefb0f5c3b3b05304d3faf413feb0997605a3f8ae2484/uuid_utils-0.16.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27271b37fbc6812bb1542c4b8e22ee00223a6bf7f62b1f38d3bcf8e92f6d9acd", size = 323196, upload-time = "2026-06-18T13:35:41.534Z" }, + { url = "https://files.pythonhosted.org/packages/e8/92/4e5b412d4710617fb83ed77b361f5fa6247b99bde2fa6ee07ddf851b59d1/uuid_utils-0.16.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dc4b9d96a2c689d664cf3fc7f7db46b82d2821fb2ce8a4f0798fc0a92c1569f8", size = 330858, upload-time = "2026-06-18T13:35:42.709Z" }, + { url = "https://files.pythonhosted.org/packages/ae/e3/8173202b7cfcfeb4a588c5f8b85d3e2b44973384eb33167ee25c5c78867f/uuid_utils-0.16.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c3bf41b696b0fe808df1b4091c70273a52ea033b0fe97341cd67ecd76d22bb3a", size = 444813, upload-time = "2026-06-18T13:35:43.917Z" }, + { url = "https://files.pythonhosted.org/packages/37/0d/c3918356932ce467b11e954d0c93697fb4652cf664957e3d9521f7ece22f/uuid_utils-0.16.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fcc329be41bb6534ecb03e50596179ab76c7643ced33d13c66967d5ae1869663", size = 322828, upload-time = "2026-06-18T13:35:45.134Z" }, + { url = "https://files.pythonhosted.org/packages/f0/80/4020556682441b62a25b7d07798812115fca97d417a3498d5af6dce36504/uuid_utils-0.16.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4125bf6ed3ae443c05e140f8585d174b9d647295b12034d5ec94ae2ae38edefa", size = 347909, upload-time = "2026-06-18T13:35:46.364Z" }, + { url = "https://files.pythonhosted.org/packages/48/2f/a1e87e268df98f6740af81abf225532c173a971c64df0258c84b630e35a7/uuid_utils-0.16.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:840b21e609a9b203eee06bdc73e18397154447a9814a8e78d9b68e5104d9802f", size = 499469, upload-time = "2026-06-18T13:35:47.584Z" }, + { url = "https://files.pythonhosted.org/packages/25/75/5a1f297a09556c27d9617c44ab0510de5f3a70120df236f66b9d0fdd1976/uuid_utils-0.16.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:5119bec75f56bd028d97472f72b1ed723a0d60b09a48017dc70a3cb1892ed081", size = 606160, upload-time = "2026-06-18T13:35:48.963Z" }, + { url = "https://files.pythonhosted.org/packages/7c/de/140f1d2a161320d1ac9073a03b9eb31fe35ae70f56f8971ec1fb45c14a44/uuid_utils-0.16.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:9fe600ab7d3d4eb56986e814042c917e728ac92cd8a41f099a6b59b84d8bf9e6", size = 564856, upload-time = "2026-06-18T13:35:50.244Z" }, + { url = "https://files.pythonhosted.org/packages/01/3b/9a5fe6691f8f6d72899cdc2713ffbd845b8c6981eeeab66d98a71b721116/uuid_utils-0.16.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e44020a4532229ccfbba353138539774686350dda71cf4368e257973dd8ba403", size = 528376, upload-time = "2026-06-18T13:35:51.825Z" }, + { url = "https://files.pythonhosted.org/packages/87/ad/47c93dcabd00f6749803a00be361c75d7079c78ad5e67077dee63d30b687/uuid_utils-0.16.2-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:280d4f1f22dd2e79c1cc31ffc7fc26dc3534ffc114dedcdd29cc8489c5ce9c98", size = 98033, upload-time = "2026-06-18T13:35:53.385Z" }, + { url = "https://files.pythonhosted.org/packages/c0/fd/8de85eeb8dd59354ad46e897ab0d0f0fe6bc48702239a6c9f2613f961c8e/uuid_utils-0.16.2-cp313-cp313-win32.whl", hash = "sha256:4942b26ad12c5187bac52b7fb4685040139ff0df9a19cde33e5025326f6180fc", size = 167054, upload-time = "2026-06-18T13:35:54.495Z" }, + { url = "https://files.pythonhosted.org/packages/86/b3/b5ba393fbe5142eb9d5db23d4b9b16dde2a4e1aee6f2fcb7fadef97e419a/uuid_utils-0.16.2-cp313-cp313-win_amd64.whl", hash = "sha256:01f81c71cf2185de0707e9d2f248e17025ba50af0acd3cbf51cd8aea96c2e0be", size = 173481, upload-time = "2026-06-18T13:35:55.684Z" }, + { url = "https://files.pythonhosted.org/packages/b2/79/4e5d63d605b13201ae9af6fcc36ec77949cccc99486c430c016d8f8ed274/uuid_utils-0.16.2-cp313-cp313-win_arm64.whl", hash = "sha256:c1dbe65ce6d46c5f645356d64bfb2de7564e2426ca8c9b1a0a401d6f7ae5cc22", size = 172197, upload-time = "2026-06-18T13:35:56.817Z" }, + { url = "https://files.pythonhosted.org/packages/89/3a/0e5a0c1e1e3243cf5f12efd2b88a33e63c38b6a79483d3c84b2f5e7265cf/uuid_utils-0.16.2-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:617955f4b3f649617c0388127d8a257202189d5cc3c720313f8b207df1cdb2a4", size = 566227, upload-time = "2026-06-18T13:35:57.925Z" }, + { url = "https://files.pythonhosted.org/packages/28/b3/2b6f9d6832e939aaf2b2ba89ff70b3994cfa3ae9b14daac3329eb9202ef8/uuid_utils-0.16.2-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:0aa2569908bdb21ccb216cd6bd06cb934351ee65ea7cd5e351e19f633a99b577", size = 290301, upload-time = "2026-06-18T13:35:59.467Z" }, + { url = "https://files.pythonhosted.org/packages/f5/27/8bb31429884b9f340f964ed70b68bfd81cec61f6e6877633f6a014358e78/uuid_utils-0.16.2-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4af7673e84e1ec6029f18d3a0408095c471c4e2691b6e46b4e1f0a2051734ba", size = 325409, upload-time = "2026-06-18T13:36:00.786Z" }, + { url = "https://files.pythonhosted.org/packages/1f/87/3b59aa97e788ca4fa46e2a3856ef567b51e03fd7fbf27d39ce36e46478b6/uuid_utils-0.16.2-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ecadf55ed6b8fb72e7966b52fd02919e7d7bb8e7bffeaf285803b82e774debfb", size = 332071, upload-time = "2026-06-18T13:36:02.043Z" }, + { url = "https://files.pythonhosted.org/packages/1c/21/8c21bf6cf3ce9447b73cee6a38ca63c9bb2f3145259422646bae8e8ddc21/uuid_utils-0.16.2-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:026b96b2f1e6b004579e030692d2f6568ccd0b29d40687213c31694abf570c78", size = 447075, upload-time = "2026-06-18T13:36:03.305Z" }, + { url = "https://files.pythonhosted.org/packages/95/43/77e83019effe1a5ab7169a2d4bf1bd654bebd850b81c8a937b96bd6b5c9c/uuid_utils-0.16.2-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:273679723e88544dd2de0564ab7f2fddfa2270faf05cabfdf63c275be67ec2a1", size = 325061, upload-time = "2026-06-18T13:36:04.972Z" }, + { url = "https://files.pythonhosted.org/packages/f3/a6/7bf6e0165dc191c09bc4e8c011de5463d64c5a651ed38ad6698bfc552a52/uuid_utils-0.16.2-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ec5b1a338b92d1eb121e9eaf06ae3db1b9a5cd794ce318a475f6dc6f9e89c3a8", size = 350302, upload-time = "2026-06-18T13:36:06.172Z" }, + { url = "https://files.pythonhosted.org/packages/45/66/260836aaef14b8254bc449b3163fedec06ef0a0bba0d6a999c918479b2f9/uuid_utils-0.16.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e75f9429d4533ce275c98bc68bf47fb237ae7b32c954266dabc5edab0c7d682e", size = 501834, upload-time = "2026-06-18T13:36:07.469Z" }, + { url = "https://files.pythonhosted.org/packages/9d/0b/84c1542bf8c465b456f742318ad83eace63551e7f603b06c817b726670af/uuid_utils-0.16.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:7f3cca9ca5e2c2dfd7b885f0d34c10b993a070d3593f3cdfef785195da36fb0f", size = 607406, upload-time = "2026-06-18T13:36:08.913Z" }, + { url = "https://files.pythonhosted.org/packages/48/7f/1024c22657a0c0572c4fd5189fad3127cb46731fb26fad3be1e8a4a64972/uuid_utils-0.16.2-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:1ef8c561fdf88fec205e3d54037824cfe2addce16b509a8d2ecb69daa904cbb7", size = 567623, upload-time = "2026-06-18T13:36:10.14Z" }, + { url = "https://files.pythonhosted.org/packages/15/0e/ad7424a6444e3e108a22781c2e164e82752da5db23ccc5cba8b4470c3164/uuid_utils-0.16.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:3e3acb5e1451232381daea01645a98c69de4bb9ad88d77a1f7c1df4d83d54e62", size = 530659, upload-time = "2026-06-18T13:36:11.649Z" }, + { url = "https://files.pythonhosted.org/packages/69/60/cf1666d0dbd6fa869b6de3b85a17254ff0ab10ed286fd59366148bf08e89/uuid_utils-0.16.2-cp314-cp314-win32.whl", hash = "sha256:b5f8e7d0bb2c6e6180176237f92d2e949626e04fcf701c49d73f128e1f64e1d1", size = 169272, upload-time = "2026-06-18T13:36:12.846Z" }, + { url = "https://files.pythonhosted.org/packages/fe/5e/111908bdc7287b2589e9a9f10be8e0358844fb4a0554677cbbe0ade49766/uuid_utils-0.16.2-cp314-cp314-win_amd64.whl", hash = "sha256:bf922bad7df257336b594d316a1657df569860bb5389602919001fa6fb17f06e", size = 175435, upload-time = "2026-06-18T13:36:14.114Z" }, + { url = "https://files.pythonhosted.org/packages/ce/5d/b3bd7415622060dd17d587545e3c037f83dc0dffb8880ac798ca7936f630/uuid_utils-0.16.2-cp314-cp314-win_arm64.whl", hash = "sha256:fad82e6482129c58ba9b00da6c247ab6e767645ab17981599229cce19d7b2ce9", size = 173553, upload-time = "2026-06-18T13:36:15.561Z" }, + { url = "https://files.pythonhosted.org/packages/92/43/401acf6fc0e0665dd11a095a28f6d22708c6f8f148c326cfc5b0b1ae9882/uuid_utils-0.16.2-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e0609e7e906c08386b7f33141254df05dcab24f1c4884150988dc7a287516aca", size = 567548, upload-time = "2026-06-18T13:36:16.848Z" }, + { url = "https://files.pythonhosted.org/packages/4e/2c/cc2bb8273d414d651acafccc3705a8843c130a541fcce65fbeaac22266ba/uuid_utils-0.16.2-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:9ad2adeb941292fe02e1e5c70b80a5746c45b1b77594506c2a1421455d8384f9", size = 291348, upload-time = "2026-06-18T13:36:18.145Z" }, + { url = "https://files.pythonhosted.org/packages/4e/a8/fdadd7ada0de53dbc03f719da0948cc275abd24d8013a26e42e50d3665c1/uuid_utils-0.16.2-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d906c00f965d5c5f4812d0086dc49bf813285ea84c97e8816405200e146f805b", size = 325495, upload-time = "2026-06-18T13:36:19.417Z" }, + { url = "https://files.pythonhosted.org/packages/16/42/e397a1eda06b20dd3a206e3a55b346ff2caad23906586801a87359530864/uuid_utils-0.16.2-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a59205fc15463dd0f978f14df14307737e3d4e8ef4aefa29a9d0fa766d84d16b", size = 332301, upload-time = "2026-06-18T13:36:20.747Z" }, + { url = "https://files.pythonhosted.org/packages/46/be/12d3df7bd824e3ce71630c022184a5aecfea92b0a7fa70459542b237777a/uuid_utils-0.16.2-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aac82500329ffaf2788dac36cf133e1e4e23b6d5e1118274ea6749c3b512f4f1", size = 446760, upload-time = "2026-06-18T13:36:22.198Z" }, + { url = "https://files.pythonhosted.org/packages/f7/10/0c5d1dd6874fa35e2cb66a8499ce303eb8678bef226951182603bd30017d/uuid_utils-0.16.2-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d8257329f26905f009aed694bd3b17f334f43748b03134dc7bc99d6c5b4e371", size = 325781, upload-time = "2026-06-18T13:36:23.566Z" }, + { url = "https://files.pythonhosted.org/packages/04/e2/9ebb8414875e5c14737fa7145a023458c9b15754f1d129cefe7824197256/uuid_utils-0.16.2-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e04b5c10c6fcf9d9801084d1e86c9d7ada7eb48fe07ee4ae5e7fe5b1a852db8a", size = 351189, upload-time = "2026-06-18T13:36:25.09Z" }, + { url = "https://files.pythonhosted.org/packages/1b/5c/168d1f4d30b33c08365debfe4176c2f713a0940f1f11a64128a186d050c6/uuid_utils-0.16.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3d4805c4739dd06d539f8f4fa94f5aaf26eca4b3ece1ef134d4ff904c6b08dcf", size = 501866, upload-time = "2026-06-18T13:36:26.31Z" }, + { url = "https://files.pythonhosted.org/packages/aa/8d/003865d5ed5bf82ece80bd61edb2692985f7548051749fd10f34edb16705/uuid_utils-0.16.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:76632d2e16e26de777851ec07961ceaea14e65167d0603a0b17fb169fa9ca37b", size = 607632, upload-time = "2026-06-18T13:36:27.704Z" }, + { url = "https://files.pythonhosted.org/packages/ea/52/6102f21f28323b27122a6aa3d4cea183b4fc401868c5c40767e1b9f53beb/uuid_utils-0.16.2-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:6c02f85f49c9c2abbf247a8622458c30232332a28711755aa191da5f38015af6", size = 568216, upload-time = "2026-06-18T13:36:29.377Z" }, + { url = "https://files.pythonhosted.org/packages/68/50/644e4e55f47048d12bc20665fac85bc1fecbed9c892acfb91626abf8ad8d/uuid_utils-0.16.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f668035ea9faa763e8f1ea42040e8439db88cf2517056d47c348a62a257a1d02", size = 531370, upload-time = "2026-06-18T13:36:30.804Z" }, + { url = "https://files.pythonhosted.org/packages/6f/5d/d98d99f601d70cc00287dce5aadef9c199912f0d64343962542f35e7db59/uuid_utils-0.16.2-cp314-cp314t-win32.whl", hash = "sha256:62b8841895eff1c0afbaf5f0050411667231160478c8ff9f411742abffd3b619", size = 169424, upload-time = "2026-06-18T13:36:32.246Z" }, + { url = "https://files.pythonhosted.org/packages/a6/af/c0d482bdd637a8a742d3274cec462b770919f032e179216f2fc2851afaf9/uuid_utils-0.16.2-cp314-cp314t-win_amd64.whl", hash = "sha256:e9064805881c30dd80a4189a0da7130e3d684de353ea36edd99c1b994bdf429e", size = 175544, upload-time = "2026-06-18T13:36:33.75Z" }, + { url = "https://files.pythonhosted.org/packages/86/fc/aff8b0456e8a63672fa89ea9c773f7547a31ff7b596a40f226bf148921a3/uuid_utils-0.16.2-cp314-cp314t-win_arm64.whl", hash = "sha256:3324bac95084e63e28553c92fac5a0394c636a76e03e50a7dab0c0bbddf87fa5", size = 173972, upload-time = "2026-06-18T13:36:35.076Z" }, + { url = "https://files.pythonhosted.org/packages/0e/48/8c9fee7d75571f2f4b2386eac798fe5f826155d13797f7c86d45eb3fdc23/uuid_utils-0.16.2-pp311-pypy311_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:8b8e325e61f918caf74ca540e3384b81e6e22aea782e57f615d15fc9773b96c8", size = 571003, upload-time = "2026-06-18T13:36:36.42Z" }, + { url = "https://files.pythonhosted.org/packages/de/78/754eaaa49509be6fdb705de61d1e3889de32002132d5f00e8c1e5d212da3/uuid_utils-0.16.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:9282677ebf2ea5b437c20d16e75bcd7629bdc205018f95557b33b76868d8bb5b", size = 290244, upload-time = "2026-06-18T13:36:38.066Z" }, + { url = "https://files.pythonhosted.org/packages/8e/e2/bfcbcf7eb9dfb17701104c569ed771eb359737bc70b7309e439610d089ef/uuid_utils-0.16.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e9ca7f5e215373cc9c147172170a0b1a4ab0dee9cc62fe446d9b075f31e3241", size = 328551, upload-time = "2026-06-18T13:36:39.605Z" }, + { url = "https://files.pythonhosted.org/packages/72/bf/bbdbc39d1421953edcee0bad13a1893521a636eccf381580f53e530a4feb/uuid_utils-0.16.2-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:43cc72a92694d08ade8faadacf928857d9cceb84b449473246ae4e4f263d7d22", size = 335468, upload-time = "2026-06-18T13:36:41Z" }, + { url = "https://files.pythonhosted.org/packages/04/2a/e8d4e6f1f2d2e567cf6e3202d125afe7da52ad7680bba048b106c09f01b9/uuid_utils-0.16.2-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:511b5fde12d29c37a9badd399af62105bb2f4696aa10eb18be74e7b9ca84413a", size = 450984, upload-time = "2026-06-18T13:36:42.635Z" }, + { url = "https://files.pythonhosted.org/packages/6a/da/ddb1dcf0fe9bfcb0dfcddec8ae52c8f95e7088e44719f58477f5fb2c5586/uuid_utils-0.16.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:585d3adf73afa60348bf2bd529491c640a692350e76d8ff3974455e273aadfe7", size = 327940, upload-time = "2026-06-18T13:36:44.138Z" }, + { url = "https://files.pythonhosted.org/packages/37/fb/39305fbfffee1fdaccdb88fc0499ac9dcb7289a77ebc31938dcdd933cf95/uuid_utils-0.16.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ae5fa2007fd26d26f7b09e76259d5ca99bec191616207ca929f8dca12da08129", size = 355368, upload-time = "2026-06-18T13:36:45.682Z" }, + { url = "https://files.pythonhosted.org/packages/b4/70/b708edc3b776d7624b4354f43d443f14d951d3ac4d7d8867d94f2e59c3ae/uuid_utils-0.16.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:9b4520521aa46a2582fe1829c535fe60b78999b89257db998df3816eb895bdf3", size = 178221, upload-time = "2026-06-18T13:36:47.291Z" }, ] [[package]] name = "uv" -version = "0.11.11" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ba/02/69a3b06fd8a91f95b79e95e14f5ccdd4df0f124c381aefe9d1e2784d5a65/uv-0.11.11.tar.gz", hash = "sha256:2ba46a912a1775957c579a1a42c8c8b480418502326b72427b1cad972c8f659f", size = 4112827, upload-time = "2026-05-06T20:04:47.982Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6c/54/39d3c58de992767834120fe3735b85cc60dd00a69b377c3d947ca6f172a1/uv-0.11.11-py3-none-linux_armv6l.whl", hash = "sha256:4977a1193e5dc9c2934b9f97d6cf787382f80deae17646640ee583cfc61486c0", size = 23537936, upload-time = "2026-05-06T20:04:58.626Z" }, - { url = "https://files.pythonhosted.org/packages/de/c9/d2d7ca30abf4c2d5ae0d9360a1e154115af176308ef1ecdc8bf7af724cf8/uv-0.11.11-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:92817f276758e41b4160fcb6d457ebd9f228f0473efe3808891164f326fdea38", size = 23068282, upload-time = "2026-05-06T20:05:01.466Z" }, - { url = "https://files.pythonhosted.org/packages/fa/37/f64decba47d7afaace3f238aa4a416dca947bd0a1a9b534c3a0f179e1016/uv-0.11.11-py3-none-macosx_11_0_arm64.whl", hash = "sha256:6eec6ad051e6e5d922cd547b9f7b09a7f821597ae01900a6f01b0a01317e5fd0", size = 21671522, upload-time = "2026-05-06T20:05:04.382Z" }, - { url = "https://files.pythonhosted.org/packages/93/a6/c129878d7c2a66ffdaa12dc253d3135c5e10fc5b5e15812791e188c6dbec/uv-0.11.11-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:1d227bb53b701e533f0aa074dd145a6fa31492dc7d6d57a6e72a700b9a4a1991", size = 23283200, upload-time = "2026-05-06T20:04:39.879Z" }, - { url = "https://files.pythonhosted.org/packages/8f/c2/cff1f9ab7eda3d863e9866fca0e14df37c0fd734b66ebb77d751258b2fae/uv-0.11.11-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:05ee9f18701692fcb22db98085c041a3be7a35b88c710dea4487c293f42a4b95", size = 23081561, upload-time = "2026-05-06T20:05:07.149Z" }, - { url = "https://files.pythonhosted.org/packages/ca/44/ebd02ca8fae5961d1bcbcee11019dd170dd0d42517afad753281335700cc/uv-0.11.11-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0632af539d6a1ee00f58da9e7db32fd99e12187aa67426cb90d871154ab5debb", size = 23105780, upload-time = "2026-05-06T20:04:50.107Z" }, - { url = "https://files.pythonhosted.org/packages/86/f7/0741abcd70591a65f85fc4e8fecd3fb3fb4bdfe50042cccf016714955fd9/uv-0.11.11-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb3f2715551d2fc9ef44b6cf0918fcc556cd99e9bf6caa1d8a870a4657d2b180", size = 24542681, upload-time = "2026-05-06T20:04:53.014Z" }, - { url = "https://files.pythonhosted.org/packages/b1/42/46e7e35f1f39e39d4bf0f712479768cf8d33eb7f35b67fceaea43e975dfd/uv-0.11.11-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c86bd6460579857d7e359bdbfe6f688076c654481ae933151d1449f9ea672fb6", size = 25459284, upload-time = "2026-05-06T20:04:34.168Z" }, - { url = "https://files.pythonhosted.org/packages/e8/fc/efdb16e1a6c619b021259ac8d8e4b6afd97efb446054ea28761eb2e1a177/uv-0.11.11-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0f69f4df007c7506db8d7f77ccabd466a886ac21e9b04a479dd0cd22e26d2262", size = 24560769, upload-time = "2026-05-06T20:04:42.648Z" }, - { url = "https://files.pythonhosted.org/packages/4c/f8/a5d5bac297b1379719050788c6b852c6b3eefcb1e82d8465ed22c10cede7/uv-0.11.11-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5b9f31dab557b5ee4257d8c6ba2608a63c7278537cb0cd102cf6fc518e3fb5c", size = 24639659, upload-time = "2026-05-06T20:04:31.491Z" }, - { url = "https://files.pythonhosted.org/packages/ee/d5/f3be167a43192062f1409fd6b857a612665d331174293b4ffc73218872e1/uv-0.11.11-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:8e8faf2e5b3517155fd18e509b19b21135247d43b7fb9a8d61a44a53118d5ab7", size = 23388445, upload-time = "2026-05-06T20:04:25.199Z" }, - { url = "https://files.pythonhosted.org/packages/9f/cd/ef1f573ee8edd2beab9fcd2449121483829621b3b57f7ba3f35c56ef373b/uv-0.11.11-py3-none-manylinux_2_31_riscv64.musllinux_1_1_riscv64.whl", hash = "sha256:3f8c9a1bea743a3fe39e956455686f4d0dd25ef58e8d70dc11a45381fd7c50e5", size = 24114301, upload-time = "2026-05-06T20:04:28.586Z" }, - { url = "https://files.pythonhosted.org/packages/9d/be/9181158465719e875a6995c10af24e00cdefba3fe6c9c8cbb02d34b2ade7/uv-0.11.11-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:f68dc7b62050a26ac6b1491398aebbbf0fa5485627e73b1d626666a097dbab07", size = 24155126, upload-time = "2026-05-06T20:04:55.98Z" }, - { url = "https://files.pythonhosted.org/packages/71/9c/bb306f9964870847f02a931d1fff896726f8bafcf9ce917122ac1bfef14c/uv-0.11.11-py3-none-musllinux_1_1_i686.whl", hash = "sha256:29ddb0d9b24a30ff4360b94e3cb704e82cd5fda86dc224032251f33ab5ceb79e", size = 23824684, upload-time = "2026-05-06T20:05:10.305Z" }, - { url = "https://files.pythonhosted.org/packages/56/48/434a1cf4798ca200e0dcb36411ba38013edb6d3e1aeb4cd85e8a2d7db9ca/uv-0.11.11-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:505a31f2c30fa9e83b1853cab06c5b92e66341c914c6f20f3878903aa09a6f34", size = 24862560, upload-time = "2026-05-06T20:04:37.287Z" }, - { url = "https://files.pythonhosted.org/packages/63/3a/997cddf82917f084d486e1c268c7e94836190fd928c93aa3fb92caee9a7f/uv-0.11.11-py3-none-win32.whl", hash = "sha256:c1e0e3e18cc94680642eac3c3f19f2635c17dd058edcb41b78cbdc459f574eb4", size = 22573619, upload-time = "2026-05-06T20:04:45.35Z" }, - { url = "https://files.pythonhosted.org/packages/30/5f/db34b840f8d86833ef810de8150fc9ce01a03c779393e08eadbcc4c010d5/uv-0.11.11-py3-none-win_amd64.whl", hash = "sha256:36412b13f6287304789abdf40122d268cee548fce3573e07d148a29370181421", size = 25170135, upload-time = "2026-05-06T20:05:13.001Z" }, - { url = "https://files.pythonhosted.org/packages/2d/3e/f3ba2557b437ec5b1fde1e0d5248b723432dc90f09b0050f52695596fd2e/uv-0.11.11-py3-none-win_arm64.whl", hash = "sha256:011f42faf5d267a6681ea77e3f236f275cb4490efeecb9599de74dc7ad7df8f6", size = 23597162, upload-time = "2026-05-06T20:05:16.095Z" }, +version = "0.11.27" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8f/ed/b8bb8bf2044561e3349ebe75be0d8abdeb19577886753b49200ec6caea0d/uv-0.11.27.tar.gz", hash = "sha256:3469204521869f0e6bdea17b02c1d86db2d0150820895653a6152cab206fb00b", size = 5978029, upload-time = "2026-07-06T21:00:29.995Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b2/fe/8a080fb603f276ceb2d960454b2b5998cc6e5c0c6d5dbbbeb48b141de4f2/uv-0.11.27-py3-none-linux_armv6l.whl", hash = "sha256:6cedad2185b16bd5da77096d4813159c9c3c572897537256eecdb4092941adc0", size = 25490659, upload-time = "2026-07-06T20:59:29.003Z" }, + { url = "https://files.pythonhosted.org/packages/d1/15/886a2ef7b00c1a4fcf706e7a6b946b3f7485a55f42d0aa9b5572caed58b6/uv-0.11.27-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:42b273459864c67f3736ae2a63929df463975d885bbc1afd8f53f7e0fb1f2269", size = 24498434, upload-time = "2026-07-06T20:59:33.042Z" }, + { url = "https://files.pythonhosted.org/packages/2d/6e/45335717c4372bf955c87bc05c6462dd4c0c6087ed12c3991b14cbba77cd/uv-0.11.27-py3-none-macosx_11_0_arm64.whl", hash = "sha256:b316464a1028a43478b74424b4b78925c463758baec93cb754fb2392ba175138", size = 23248727, upload-time = "2026-07-06T20:59:36.201Z" }, + { url = "https://files.pythonhosted.org/packages/0a/fa/41dde1e350c5a277b797371faf96fb013c2c13ed18df6efc51ed8ec9bb5b/uv-0.11.27-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:3ca478883d78270ceed57f229d1b480dbcadf5d79b2ce9624574807d6ec48554", size = 25208126, upload-time = "2026-07-06T20:59:39.984Z" }, + { url = "https://files.pythonhosted.org/packages/00/e3/bc6d4af24ab533db4c741cebade3a58b91fc0563059d39e838161dd210c8/uv-0.11.27-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:232dfb7549c8a4217ab1970dea0de731926b8ca21769ed89951ad8f8c3bce8b6", size = 25030974, upload-time = "2026-07-06T20:59:43.378Z" }, + { url = "https://files.pythonhosted.org/packages/c3/0c/82e736930d3f78ca6c3286ef31627d7155e20191af88afc40ec29486f400/uv-0.11.27-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4c0cf7c7960587a231252cbe4d7a032b5a02c29cfab3fcc4e75a915b1c5cacee", size = 25015115, upload-time = "2026-07-06T20:59:46.694Z" }, + { url = "https://files.pythonhosted.org/packages/a0/5b/512ebf3b24b708ea2adda4ec4d4bd23b2404d7a7ea3bd24d2b92210ab680/uv-0.11.27-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:47b5863ef715ffe4c29e792c9884a4e8b8016b0628d3613ac84c696acc128a78", size = 26487914, upload-time = "2026-07-06T20:59:50.414Z" }, + { url = "https://files.pythonhosted.org/packages/98/d5/3871185331266156fbd09ab0ad7ddc69ca759b3a28ece5488bdb64f152d9/uv-0.11.27-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a5764155d2a578a41d2827f464d4ce5b7788632e732cb304e2025fb3d043b46f", size = 27393306, upload-time = "2026-07-06T20:59:53.852Z" }, + { url = "https://files.pythonhosted.org/packages/24/0f/9fe3cc9b8d498f2e426b3cda90d337b076d64f19c2d55cb0b7d091c4bfe9/uv-0.11.27-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d806e1067c8eb9f8ba5dbdca46484512d224070e8473442319d4c1fbc3246f4d", size = 26563495, upload-time = "2026-07-06T20:59:56.945Z" }, + { url = "https://files.pythonhosted.org/packages/e7/be/18393c15ac0c982fefa34944135ead3adc565da5023d973eff5081a95a62/uv-0.11.27-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cb783b9db3868e51e8da1956aaa7e800262ad1af03dfc8b024f3b04ecb447c2", size = 26652374, upload-time = "2026-07-06T21:00:00.256Z" }, + { url = "https://files.pythonhosted.org/packages/b8/93/1bb8bee2b0bcc6e9655518ecaa9a792b1952dd99ae7366fe4f6c82754361/uv-0.11.27-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:8e2b86d3dee515eeba6ea001d8b3eac20b204db07d39b04187c755a490a4fba6", size = 25341573, upload-time = "2026-07-06T21:00:03.789Z" }, + { url = "https://files.pythonhosted.org/packages/e6/e0/fae0d1c972b25ac192ac807c1b1baf0f12070c40c8af2eb8e22310ea8846/uv-0.11.27-py3-none-manylinux_2_31_riscv64.musllinux_1_1_riscv64.whl", hash = "sha256:d325b8bd2665ce3ac58d33f977683cfb2cb8eb951effab06fad8518426bc0a90", size = 26051363, upload-time = "2026-07-06T21:00:07.281Z" }, + { url = "https://files.pythonhosted.org/packages/e5/a2/4c0c103ea431f5d70cd33f10c754b5b1de9687fea982ca1a20a4eee0a4a7/uv-0.11.27-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:3d5c9036b558a323f254e3d16038183c22c55e0d06b921f1ed9706953311e52f", size = 26148896, upload-time = "2026-07-06T21:00:10.56Z" }, + { url = "https://files.pythonhosted.org/packages/bb/b7/a514307a90ca9f1cb59efd0898958dea6c1092ad5e4e6b6f2eb4d55109db/uv-0.11.27-py3-none-musllinux_1_1_i686.whl", hash = "sha256:4cc04e625e7bfac6975fd384d6598169cea0030995ff3b557950ec3077974a4d", size = 25701138, upload-time = "2026-07-06T21:00:13.772Z" }, + { url = "https://files.pythonhosted.org/packages/bf/46/c6cfa675d727a199cfce32f7a30350ce6e47f699c3cd7f0433a619c671d4/uv-0.11.27-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:109d8e145b390d0e14f2aefd9708a7522a4236d6bee20361a7558e77a14c0531", size = 26913232, upload-time = "2026-07-06T21:00:17.233Z" }, + { url = "https://files.pythonhosted.org/packages/a4/04/0070ecdea37baa9d38187abedc78eed9a52a2e6cb1d4f175c580640f3456/uv-0.11.27-py3-none-win32.whl", hash = "sha256:b330d2ab6af0f79396fb350a9fed8ed1aa92516310f7533de9a8dfebc4e147cd", size = 24374672, upload-time = "2026-07-06T21:00:20.399Z" }, + { url = "https://files.pythonhosted.org/packages/d0/b9/f3df522d2e609fe511e5bee24b34c91ce281ce472594121fa1d5fa159d9d/uv-0.11.27-py3-none-win_amd64.whl", hash = "sha256:e20f25921ed4c46d32ac18a9b2e610c0384439fd367f647f2b68e0e1d90e9885", size = 27275452, upload-time = "2026-07-06T21:00:23.903Z" }, + { url = "https://files.pythonhosted.org/packages/8d/2e/4ea9c3bbf95a21c627a3dfa359f5a3266e648cd103c5ade374a6e4265c5f/uv-0.11.27-py3-none-win_arm64.whl", hash = "sha256:a41da27667e95c0df939e99e77a4d9169fb895df0f6788b2ab65ed5efdc1395f", size = 25561477, upload-time = "2026-07-06T21:00:27.333Z" }, +] + +[[package]] +name = "uvicorn" +version = "0.50.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9f/f6/cc9aadc0e481344a42095d222bfa764122fb8cfba708d1922917bd8bfb01/uvicorn-0.50.2.tar.gz", hash = "sha256:b92bf03509b82bcb9d49e7335b4fd364518ad021c2dc18b4e6a2fec8c955a0bb", size = 93716, upload-time = "2026-07-06T10:38:31.984Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/aa/f0/7c228ee10c7ab8fd3a21d06579a6f7c6075c6ce72594a20fb5d2f206ff24/uvicorn-0.50.2-py3-none-any.whl", hash = "sha256:4ae72a385630bcc17a0adb8290f26c993865e0b43a2114c2aab96420172c056a", size = 72846, upload-time = "2026-07-06T10:38:30.543Z" }, ] [[package]] @@ -2590,7 +3524,7 @@ wheels = [ [[package]] name = "virtualenv" -version = "21.3.1" +version = "21.6.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib" }, @@ -2598,9 +3532,9 @@ dependencies = [ { name = "platformdirs" }, { name = "python-discovery" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ec/0d/915c02c94d207b85580eb09bffab54438a709e7288524094fe781da526c2/virtualenv-21.3.1.tar.gz", hash = "sha256:c2305bc1fddeec40699b8370d13f8d431b0701f00ce895061ce493aeded4426b", size = 7613791, upload-time = "2026-05-05T01:34:31.402Z" } +sdist = { url = "https://files.pythonhosted.org/packages/74/65/ec1d92091671e6407d3e7c1f5801413bb7b2b57630a50cae7750456ba0ed/virtualenv-21.6.0.tar.gz", hash = "sha256:e18a4d750f2b64dea73e72ffde3922f3c52365fabdc8157ebd3da20d031c4734", size = 5526111, upload-time = "2026-07-06T22:49:56.972Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl", hash = "sha256:d1a71cf58f2f9228fff23a1f6ec15d39785c6b32e03658d104974247145edd35", size = 7594539, upload-time = "2026-05-05T01:34:28.98Z" }, + { url = "https://files.pythonhosted.org/packages/b8/e7/2fbd0cc1653c53eed8f10670538bb547de2b3e37aacad283faa82a71094b/virtualenv-21.6.0-py3-none-any.whl", hash = "sha256:bce9d097950fef9d81129b333babfb7767072850c2f1acce0ec536708401bfd1", size = 5506216, upload-time = "2026-07-06T22:49:54.941Z" }, ] [[package]] @@ -2632,14 +3566,23 @@ wheels = [ [[package]] name = "wcmatch" -version = "10.1" +version = "10.2.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "bracex" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/79/3e/c0bdc27cf06f4e47680bd5803a07cb3dfd17de84cde92dd217dcb9e05253/wcmatch-10.1.tar.gz", hash = "sha256:f11f94208c8c8484a16f4f48638a85d771d9513f4ab3f37595978801cb9465af", size = 117421, upload-time = "2025-06-22T19:14:02.49Z" } +sdist = { url = "https://files.pythonhosted.org/packages/11/15/dc61746d8c0852f6d711ad09c774b63cf7c8211aa49e30871ac3d342b7e2/wcmatch-10.2.1.tar.gz", hash = "sha256:ecac70a5c70e62ba854b78318d3a1408e8651f8f1c96e5837743b71aa6a4fb92", size = 132497, upload-time = "2026-07-02T17:21:48.484Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/eb/d8/0d1d2e9d3fabcf5d6840362adcf05f8cf3cd06a73358140c3a97189238ae/wcmatch-10.1-py3-none-any.whl", hash = "sha256:5848ace7dbb0476e5e55ab63c6bbd529745089343427caa5537f230cc01beb8a", size = 39854, upload-time = "2025-06-22T19:14:00.978Z" }, + { url = "https://files.pythonhosted.org/packages/82/ba/20b48eedeab5316bf9a502bb9eb7e3b1588bd61d0f565822fefa8f06e10b/wcmatch-10.2.1-py3-none-any.whl", hash = "sha256:2d775395b93f233af66690f62cb9d52b084ec159a31cc4084f4069d72f437acd", size = 39763, upload-time = "2026-07-02T17:21:47.134Z" }, +] + +[[package]] +name = "wcwidth" +version = "0.8.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/34/74/c6428f875774288bec1396f5bfcbc2d925700a4dad61727fd5f2b12f249d/wcwidth-0.8.2.tar.gz", hash = "sha256:91fbef97204b96a3d4d421609b80340b760cf33e26da123ff243d76b1fda8dda", size = 1466253, upload-time = "2026-06-29T18:11:11.601Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/42/3e5985a0a7e57de470b320c6d6a1a67c844f6737a587f3d44dd13d1819e7/wcwidth-0.8.2-py3-none-any.whl", hash = "sha256:d63947694a0539a1d51e01eda7caf800c291020e6cdd7e28ad7b14dd33ad4f85", size = 323166, upload-time = "2026-06-29T18:11:09.888Z" }, ] [[package]] @@ -2684,151 +3627,226 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743, upload-time = "2025-03-05T20:03:39.41Z" }, ] +[[package]] +name = "wrapt" +version = "2.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/a4/282c8e64300a59fc834518a54bf0afabb4ff9218b5fa76958b450459a844/wrapt-2.2.2.tar.gz", hash = "sha256:0788e321027c999bf221b667bd4a54aaefd1a36283749a860ac3eb77daed0302", size = 129068, upload-time = "2026-06-20T23:49:44.49Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/15/0c2d55168707465abfc41f33c0b23d792a5fa9b65c26983606940900a120/wrapt-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f1a2ff355ece6a111ca7a20dc86df6659c9205d3fcee674ca34f2a2854fd4e73", size = 80782, upload-time = "2026-06-20T23:47:44.367Z" }, + { url = "https://files.pythonhosted.org/packages/7d/b5/5c0b093eb48f8a062ef6267d3cb36e9bb1b88440181f6545a383c60efdf8/wrapt-2.2.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:55b9a899e6fff5444f229d30aa6e9ac92d2216d9d60f33c771b5d76a760d5f8e", size = 81678, upload-time = "2026-06-20T23:47:45.857Z" }, + { url = "https://files.pythonhosted.org/packages/34/f3/de70937472dd3e8a4e6811192f9c6075efdffd4a2cd9b4596bf160f89668/wrapt-2.2.2-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a2d78c363f97d8bd718ee40432c66395685e9e98528ccaa423c3355d1715a26d", size = 159671, upload-time = "2026-06-20T23:47:47.345Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ec/40aed2330e7f02ecf74386ffcfef9ccb7108c6a430f15b6a252b663b1bed/wrapt-2.2.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d619e1eed9bd4f6ed9f24cd61971aa086fa86505289628d464bcf8a2c2e3f328", size = 160785, upload-time = "2026-06-20T23:47:48.759Z" }, + { url = "https://files.pythonhosted.org/packages/45/04/aa5309beed5344b00220ae6b3b24055852192656194c27947bee1736306a/wrapt-2.2.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:518b0c5e323511ec56a38894802ddd5e1222626484e68efe63f201854ad788e5", size = 153699, upload-time = "2026-06-20T23:47:50.177Z" }, + { url = "https://files.pythonhosted.org/packages/01/df/2def7e99d1fe87eea413f95f671924cdddcb08823b1ffd212748dfa6d062/wrapt-2.2.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4bccea5cdecffa9dd70e343741f0e41e0a16619313d04b72f78bb525162ebcd0", size = 159695, upload-time = "2026-06-20T23:47:51.602Z" }, + { url = "https://files.pythonhosted.org/packages/c7/f6/a906d01a2ce12157bad2404957b3e2140da354b8a70b2fa48bbf282871c0/wrapt-2.2.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:209112cafd963710a05d199aae431d79a28bc76eb8e6d1bbbb8ad24340722cae", size = 152813, upload-time = "2026-06-20T23:47:53.03Z" }, + { url = "https://files.pythonhosted.org/packages/02/49/bc0086292d239575b4c08f4cf8a4079fa58abbad58ec23abf84833a283ed/wrapt-2.2.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e5a5290e4bf2f332fc29ce72ffb9a2fff678aaac047e2e9f5f7165cd7792e099", size = 158809, upload-time = "2026-06-20T23:47:54.391Z" }, + { url = "https://files.pythonhosted.org/packages/55/83/8fbd034de1f3e907edaa18786d5dd8f6932874edee0826c7cecb5cab03a1/wrapt-2.2.2-cp311-cp311-win32.whl", hash = "sha256:5499236ad1dc116012e2a5dd943f3f31af12fce452128e2bbcbd55a7d3d4d14c", size = 77414, upload-time = "2026-06-20T23:47:55.882Z" }, + { url = "https://files.pythonhosted.org/packages/7e/9c/23695baa331c6de4e874c3d78b8e0bed92e1d2a274e665b29858f6841672/wrapt-2.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:8636809939152be6ae20a6cef0fed9fe60f411b47847d0426a826884b469e971", size = 80368, upload-time = "2026-06-20T23:47:57.237Z" }, + { url = "https://files.pythonhosted.org/packages/08/49/40cefc342bf89b234a4490d741290fce781774b831aefb39c25471da96c9/wrapt-2.2.2-cp311-cp311-win_arm64.whl", hash = "sha256:5d0a142f7af07caeb5e5da87493162a7b8efa19ba919e550a746f7446e13fb30", size = 79489, upload-time = "2026-06-20T23:47:58.56Z" }, + { url = "https://files.pythonhosted.org/packages/2a/85/180b40628b23772692a0c76e8030114e1c0ae068470ed531919f0a5f2a4a/wrapt-2.2.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8417fd3c674d3c8023d080292d29301531a12daf8bd938dd419710dd2f464f2b", size = 81484, upload-time = "2026-06-20T23:47:59.924Z" }, + { url = "https://files.pythonhosted.org/packages/94/f2/21c90f2a16689702e2aaff45795b11018dff2c9b1242bac10d225483f676/wrapt-2.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0e7070c7472582e31af3dfc2622b2381a0df7435110a9388ed8db5ffbce67efb", size = 82151, upload-time = "2026-06-20T23:48:01.303Z" }, + { url = "https://files.pythonhosted.org/packages/5f/b3/7e6e9fcf4fe7e1b69a49fe6cc5a44e8224bab6283c5233c97e132f14908e/wrapt-2.2.2-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2e096c9d39a59b35b63c9aacfbbbec2088ff51ff1fc31051acc60a07f42f273a", size = 169828, upload-time = "2026-06-20T23:48:02.719Z" }, + { url = "https://files.pythonhosted.org/packages/0b/43/894f132d857ed5a9904d937baf368badcbe5ea9e436e2f1930fe21c9f1f0/wrapt-2.2.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d1a6050405bf334be33bf66296f113563622972a34900ae6fa60fd283a1a900", size = 171544, upload-time = "2026-06-20T23:48:04.266Z" }, + { url = "https://files.pythonhosted.org/packages/29/de/3c833e03725b477e9ea34028224dd21a48781830101e4e036f77e8b6b102/wrapt-2.2.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:10adb01371408c6de504a6658b9886480f1a4919a83752748a387a504a21df79", size = 160663, upload-time = "2026-06-20T23:48:05.708Z" }, + { url = "https://files.pythonhosted.org/packages/33/be/27edce350b24e3054d9d047f65f16d4c4d4c1f3f31c4278a1f8a95c723c8/wrapt-2.2.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3442eee2a5798f9b451f1b2cd7518ce8b7e28a2a364696c414460a0e295c012a", size = 169387, upload-time = "2026-06-20T23:48:07.243Z" }, + { url = "https://files.pythonhosted.org/packages/e2/c4/9fd9679af8bf38e146652c7f47b6b352c3e5795b4ad1c0b7f94e15ac2aa7/wrapt-2.2.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:6c99012a22f735a85eed7c4b86a3e99c30fdd57d9e115b2b45f796264b58d0bf", size = 158849, upload-time = "2026-06-20T23:48:08.91Z" }, + { url = "https://files.pythonhosted.org/packages/bc/c2/aa6c0c2206803068c6859dabe01f8c84c43744da93d4c67b8946d21655ee/wrapt-2.2.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3b686cfc008776a3952d6213cb296ed7f45d782a8453936406faa89eac0835ab", size = 168147, upload-time = "2026-06-20T23:48:10.374Z" }, + { url = "https://files.pythonhosted.org/packages/42/63/3eb25da41049d20ae18fcab2dd8b056e02387c4bfa626cbdfb7c3b872e4f/wrapt-2.2.2-cp312-cp312-win32.whl", hash = "sha256:ef2cce266b5b0b07e19fa82e59673b81142b7a3607c8ed1254113d048ed668da", size = 77734, upload-time = "2026-06-20T23:48:11.769Z" }, + { url = "https://files.pythonhosted.org/packages/da/09/0390e008a305360948fa9ce69507d041ac12cb2ee5d28e34467e2ee79391/wrapt-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:abf8c20a2d72ee69e16328b3c91342c446e723bfe48bfcc4dded3b9722ac027f", size = 80585, upload-time = "2026-06-20T23:48:13.117Z" }, + { url = "https://files.pythonhosted.org/packages/d3/b3/84c445c66969f2d3457276b183a48c91097d59bbef9af6c075366b0f8c36/wrapt-2.2.2-cp312-cp312-win_arm64.whl", hash = "sha256:c6c64c5d02578bc4c4bca4f0aef1504de933c1d5b4ac2710b9131111459506c8", size = 79553, upload-time = "2026-06-20T23:48:14.5Z" }, + { url = "https://files.pythonhosted.org/packages/43/fc/f32f4b22c6511173c11d9e541ab4e7d8467a0f1b3455acaf784115d31ff8/wrapt-2.2.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9e8b648270c613720a202d9a45ebabc33261b22c3a839b115ac5bce8c0bb0d69", size = 81296, upload-time = "2026-06-20T23:48:15.881Z" }, + { url = "https://files.pythonhosted.org/packages/72/06/4d117d5d77a9344776c0248b24dae3d3dd2f58e5f765fa08cf887072e719/wrapt-2.2.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e6fb7e94e8fe3e4c3067bb1653a91cce7c5e83acc119fdd41501b1bf74654617", size = 81841, upload-time = "2026-06-20T23:48:17.262Z" }, + { url = "https://files.pythonhosted.org/packages/15/ff/63ad96f98eb58a742b1a20d80f21da88924405910149950b912368150468/wrapt-2.2.2-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fb18fc51e813df0d9c98049e3bf2298a5495a648602040e21fa3c7329371159e", size = 167882, upload-time = "2026-06-20T23:48:18.764Z" }, + { url = "https://files.pythonhosted.org/packages/20/1f/8bb62d8933df7acf3247194e6e9fc68edf9d2fa203252c89c94b319dd472/wrapt-2.2.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94b00b00f806eb3ef2abe9049ed45994a81ee9284884d96e6b8314927c6cea3d", size = 167411, upload-time = "2026-06-20T23:48:20.315Z" }, + { url = "https://files.pythonhosted.org/packages/17/09/8789dcb09ee1de715727db7521aabbb68ffa68dfade3a49468440cfced49/wrapt-2.2.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:62415fd095bc590b842b6d092f2b5d9ccbaeb7e0b28535c03dcea2718b48636b", size = 158607, upload-time = "2026-06-20T23:48:21.728Z" }, + { url = "https://files.pythonhosted.org/packages/9c/20/66e02562d53ee67d841f175e38e3c993c2d78a3e104c576cad61c028b43c/wrapt-2.2.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a41e758d80dc0ab8c210f641ac892009d356cf1f955d97db544c8dd317b4d14c", size = 166367, upload-time = "2026-06-20T23:48:23.177Z" }, + { url = "https://files.pythonhosted.org/packages/bd/a3/832ac4e41222fb263b3042d42c2f08d305db7d0f0c9b1d3a271a9eede8f6/wrapt-2.2.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:b84cd4058001c9727b0e9980b7a9e66325b5ca748b1b578e822cade1bc6b304f", size = 157176, upload-time = "2026-06-20T23:48:24.711Z" }, + { url = "https://files.pythonhosted.org/packages/b7/01/1bd5e4d2df9c0178989ac8da9186543465388588ee2ef153e2591accebef/wrapt-2.2.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:26fc73a1b15e0946d2942b9a4426d162b51676338327dc067ccd8d2d76385f94", size = 167025, upload-time = "2026-06-20T23:48:26.118Z" }, + { url = "https://files.pythonhosted.org/packages/1c/69/583ed25291ab53e1ec117135fb1c33425e2f46d2bc8f29c17f7a94cf4274/wrapt-2.2.2-cp313-cp313-win32.whl", hash = "sha256:3c4095803491f6ef72128914c28ec05bbad9758433bb35f6715a3e9c8e46fb2d", size = 77605, upload-time = "2026-06-20T23:48:27.643Z" }, + { url = "https://files.pythonhosted.org/packages/29/68/e69fc6d06e1523c68e0d00f95c9aed1158ce9908ee41603f7f2eae3d5db6/wrapt-2.2.2-cp313-cp313-win_amd64.whl", hash = "sha256:2cb07f414fab25dbe6b5c7398e1491423a5c81a6209533639969a6c928d474a4", size = 80508, upload-time = "2026-06-20T23:48:29.013Z" }, + { url = "https://files.pythonhosted.org/packages/55/21/fe7a393d9e5dc0923bed8f5d857e9dcff210f1fa0888c02cc8f3ffaa55aa/wrapt-2.2.2-cp313-cp313-win_arm64.whl", hash = "sha256:1fc7691f070220215cccb2a20836b9adbaecb8ff22ad47abe63de5f110994fac", size = 79565, upload-time = "2026-06-20T23:48:30.429Z" }, + { url = "https://files.pythonhosted.org/packages/b6/e5/c120d13bf5091164f68c3c1657e84f16f57e71d978421b626393ac5bd7eb/wrapt-2.2.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:ec8f83949028366531383603139403cac7a826e4011955813cdd640017845ce5", size = 83264, upload-time = "2026-06-20T23:48:31.807Z" }, + { url = "https://files.pythonhosted.org/packages/d3/b0/d4a1eb97e0e286625bdf21bc7f702637f9607787ffbbdb5ec14d50c79dbf/wrapt-2.2.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4b481fb0c40d9fd90a5809911208da700987d373a20a4709dc9e3944af7a6bec", size = 83791, upload-time = "2026-06-20T23:48:33.482Z" }, + { url = "https://files.pythonhosted.org/packages/18/1e/f060df47755e87b57684cee7bfc1362b204df55fac96ffebc0631b697b79/wrapt-2.2.2-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0065a3b657cec06813b4241d2462ccec287f6863103d7445b725fb3a889736f9", size = 203399, upload-time = "2026-06-20T23:48:34.97Z" }, + { url = "https://files.pythonhosted.org/packages/c4/de/2316a757a1abb6453700b79d83e532146dcef2611348282d4d8889792161/wrapt-2.2.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:30f7424af5c5c345b7f26490e097f74a2ef45b3d08b664dc33571aee3bd3b56c", size = 210461, upload-time = "2026-06-20T23:48:36.569Z" }, + { url = "https://files.pythonhosted.org/packages/ed/29/d1160785ae18ca2495a6d82a21154103d74f656c9fd457fb35f6b11b965a/wrapt-2.2.2-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:07fdcb012821859168641acf68afad61ef9783cf37100af85f152550e9677194", size = 195313, upload-time = "2026-06-20T23:48:38.175Z" }, + { url = "https://files.pythonhosted.org/packages/f5/2d/7caa9598ae61a9cf0989cc501739cbeeb7d650ab3193cca1407b9af0c6ab/wrapt-2.2.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f90038ab58fafb584801ca62d72384d7d5225d93c76f7b773c22fae545bd8066", size = 206116, upload-time = "2026-06-20T23:48:39.804Z" }, + { url = "https://files.pythonhosted.org/packages/ac/02/281ea1088b8650d865f311b35cf86fd21df89128e2909714f1161e01c9d0/wrapt-2.2.2-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:c5d7825491bfa2d08b97e9557768987952c7b9ae687d06c3320b40a37ccb7f20", size = 192668, upload-time = "2026-06-20T23:48:41.346Z" }, + { url = "https://files.pythonhosted.org/packages/be/7d/976e2d5b4b5c5babda40974edd54d0a5585cb60132ed86b46f4b80239b16/wrapt-2.2.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0ad520e6daa9bbf136f14de735474dbec7dcc0891f718e1d274ce8dc92e645af", size = 198891, upload-time = "2026-06-20T23:48:43.056Z" }, + { url = "https://files.pythonhosted.org/packages/59/b7/e47651797c097f75a37e2ce86dcf04048ff576f3a674f7c558df7b5e9622/wrapt-2.2.2-cp313-cp313t-win32.whl", hash = "sha256:25904acb9475f46c24fe0423dbc8fda8cc5fbc282ab3dc6e72e919748c53f4e9", size = 78537, upload-time = "2026-06-20T23:48:44.509Z" }, + { url = "https://files.pythonhosted.org/packages/d1/6f/9fa5d59fb06d890defb5a8f727ce6a14d2932c8760153f96956628559fee/wrapt-2.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:305d4c247d61c4115794a169141823c62f719525ddb90b23aa332741c77d2c28", size = 82005, upload-time = "2026-06-20T23:48:46.391Z" }, + { url = "https://files.pythonhosted.org/packages/15/80/4c7bd9873d1f9f7d138d93556b500469dbe24f42710b877519c2b9eb380d/wrapt-2.2.2-cp313-cp313t-win_arm64.whl", hash = "sha256:c20279cd1a29800815d7b2d6338b60a6c6e78263f9d6e62e0eda251ba9cae2d0", size = 80762, upload-time = "2026-06-20T23:48:47.964Z" }, + { url = "https://files.pythonhosted.org/packages/24/05/7fd9c3f83b2c74cbfc572a0b88aa37431e04bd8aed70d2c0efd3464206de/wrapt-2.2.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:0e64826f920c42d9d9f87e8cc09ffae66c51ede12d59061a5a426deb9aa71745", size = 81341, upload-time = "2026-06-20T23:48:49.39Z" }, + { url = "https://files.pythonhosted.org/packages/4b/68/1bfa43100dd90d4ef74a05897b86275cf57e1313ca14aae2545bc9f872c9/wrapt-2.2.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:dcaa5e1451bd8751d7bd1568dfa3321c78092a52a7ecb5d1a0f18a5791e1fd00", size = 81921, upload-time = "2026-06-20T23:48:50.986Z" }, + { url = "https://files.pythonhosted.org/packages/74/eb/df7b7f0b631dbbc750f39be27d8b55f65777d8ac86da80e12be41a644c4b/wrapt-2.2.2-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0abfd648dac9ac9c5b3aa9b523d27f1789046640b58dcd5652a720ddb325e1fc", size = 167713, upload-time = "2026-06-20T23:48:52.598Z" }, + { url = "https://files.pythonhosted.org/packages/4d/9a/d1bd36f6d088c8e652a9383cabbd49af30b8c576302a7eccddbab6963e3f/wrapt-2.2.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f4bfd8d1eb438153eff8b8cfe87f032ba65731e1ce06138b5090f745a33f6f95", size = 166779, upload-time = "2026-06-20T23:48:54.33Z" }, + { url = "https://files.pythonhosted.org/packages/4c/ae/24ffacd4187fac2740a1972093929e836dea092d42c87d728cd98fee11a6/wrapt-2.2.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c427c9d06d859848a69f0d928fe28b5c33a941b2265d10a0e1f15cd244f1ee33", size = 158407, upload-time = "2026-06-20T23:48:55.944Z" }, + { url = "https://files.pythonhosted.org/packages/a3/ed/974427668249a356051e8d67d47fa54ef6c777f0fcf3bae9d292c047d4b6/wrapt-2.2.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4250b43d1a129d947e083c4dc6baf333c9bb34edd26f912d5b0457841fc858ab", size = 166594, upload-time = "2026-06-20T23:48:57.617Z" }, + { url = "https://files.pythonhosted.org/packages/fb/5f/e1d7c6e4523f78db2fbd7826babd0348da1d5e0834c4f918b9ab5757dfae/wrapt-2.2.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:173e5bb5ca350a6e0abab60b7ec7cdd7992a814cb14b4de670a28f067f105663", size = 157068, upload-time = "2026-06-20T23:48:59.171Z" }, + { url = "https://files.pythonhosted.org/packages/1e/c1/7ebd1027f00700c0b0233b20aceef2b4784294ed64971424c4a78e069e34/wrapt-2.2.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:aa14b01804bce36c6d63d7b6a4f55df390f29f8648cc13a1f40b166f4d54680d", size = 166470, upload-time = "2026-06-20T23:49:00.737Z" }, + { url = "https://files.pythonhosted.org/packages/99/eb/974e471a6a978b8180186b8a9dc5ae3361ce269a967190b709b8ce17abfb/wrapt-2.2.2-cp314-cp314-win32.whl", hash = "sha256:58f9f8d637c9a6e245c6ef5b109b67ec187d2faed23d1405656b51d96e0a5b56", size = 78062, upload-time = "2026-06-20T23:49:02.327Z" }, + { url = "https://files.pythonhosted.org/packages/49/ec/e1281156cdc7a66693838ad7a0865ad641c74abd337a957d668b575aaffb/wrapt-2.2.2-cp314-cp314-win_amd64.whl", hash = "sha256:385cb1866f20479e83299af585375bfa0a4b0c6c9907a981483ea782ea8ae406", size = 80832, upload-time = "2026-06-20T23:49:03.837Z" }, + { url = "https://files.pythonhosted.org/packages/45/7d/1b6b5ddd94005a2dac97a4490c9838f3154977850d633abcb65b30089437/wrapt-2.2.2-cp314-cp314-win_arm64.whl", hash = "sha256:8ffbeaea6771a6eba6e6eeb09767864995726bc8240bb54baf88a9bb1db34d5c", size = 80029, upload-time = "2026-06-20T23:49:05.237Z" }, + { url = "https://files.pythonhosted.org/packages/b0/33/9ebcf8aafe91c601127cbd93708c16aa8f688f34a10bf004046803ecdc4f/wrapt-2.2.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:09f811d43f6f33ec7515f0be76b159569f4057ab54d3e079c3204dddb90afa2a", size = 83357, upload-time = "2026-06-20T23:49:06.632Z" }, + { url = "https://files.pythonhosted.org/packages/39/38/ec45b635153327b52e52732a0ea980e5f00b7efba65f9e018828f1e69daa/wrapt-2.2.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a795d3c06e5fbf9ea2f13196180b77aeab1b4685917256ee0d014cc163d90063", size = 83794, upload-time = "2026-06-20T23:49:08.098Z" }, + { url = "https://files.pythonhosted.org/packages/4e/ea/1a89e6d3b7a83c3affe5c09cde77792c947e63e4bc85ad84cd5bb9abb0d8/wrapt-2.2.2-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:45c2f2768e790c9f8db90f239ef23a2af8e7570f25a35619ef902df4a738447f", size = 203362, upload-time = "2026-06-20T23:49:09.811Z" }, + { url = "https://files.pythonhosted.org/packages/19/d8/3b58763d9863b5a73771c0d97110f9595d248db454009e07e1535ee905a4/wrapt-2.2.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bbf00ee0cb55ec24e2b0995a71942b85b21a066db8f3f46e1dbfdb9433ffba81", size = 210449, upload-time = "2026-06-20T23:49:11.521Z" }, + { url = "https://files.pythonhosted.org/packages/2d/6f/17fd9e053103d8be148d20d5d7505facc72d5fe1f9127973904ceaed79cf/wrapt-2.2.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2252f77663651b89255895f58cc6ac08fcb206d4371813e5af61bb62d4f7689c", size = 195349, upload-time = "2026-06-20T23:49:13.346Z" }, + { url = "https://files.pythonhosted.org/packages/ef/04/d0d1ccaaa12cb7dccf28a23f0279a608ba498f71e81d949d5ed54bcfd5c1/wrapt-2.2.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2cd7181ab1c31192ff5219269830744b5a62020b3a6d433588c4f1c95b8f8bff", size = 206099, upload-time = "2026-06-20T23:49:15.051Z" }, + { url = "https://files.pythonhosted.org/packages/44/b3/e8aa07b619890a2aa6cde1931b1887abb08820721b564a5f80b7ca3f3aa0/wrapt-2.2.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:6fe35fd51b74867d8b80174c277bd6bbf6a73e443f908129dc531c4b688a20d5", size = 192728, upload-time = "2026-06-20T23:49:16.854Z" }, + { url = "https://files.pythonhosted.org/packages/b7/f0/1819fb50f0d3c9bd758d8a83b56f1b470dee8b5b8eac8702b7c137cea9d4/wrapt-2.2.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:11d95fc2fbad3163596c39d440e6f21ca9fccece74b56e30a37ac2fca786a07c", size = 198842, upload-time = "2026-06-20T23:49:18.504Z" }, + { url = "https://files.pythonhosted.org/packages/67/7c/e88313f16a99930b899ef970d91c281544a470749a359decad994483bbda/wrapt-2.2.2-cp314-cp314t-win32.whl", hash = "sha256:d8a15813215f33fa83667bfc978b300e35669ea8bb424e970a1426bcb7bc6cca", size = 79059, upload-time = "2026-06-20T23:49:20.107Z" }, + { url = "https://files.pythonhosted.org/packages/a0/4f/ac12fda57a55068a094ec42851fb0a40e8489d8941863d517452de62e507/wrapt-2.2.2-cp314-cp314t-win_amd64.whl", hash = "sha256:d09db0f7e8357060d3c38fc22a018aba683a796bf184360fd1a58f6fc180dc77", size = 82462, upload-time = "2026-06-20T23:49:21.631Z" }, + { url = "https://files.pythonhosted.org/packages/48/a7/df732dac86d9b2027c56bd163dbc883e037b16c3469614752e148d219c61/wrapt-2.2.2-cp314-cp314t-win_arm64.whl", hash = "sha256:f32fe639c39561ccc187bcae17e9271be0eb45f1c2952510d2f29b33ab577347", size = 81182, upload-time = "2026-06-20T23:49:23.199Z" }, + { url = "https://files.pythonhosted.org/packages/6e/d2/6317eb6d4554855bbf12d61857774af34747bf88a42c19bf306de67e2fa3/wrapt-2.2.2-py3-none-any.whl", hash = "sha256:5bad217350f19ce99ca5b5e71d406765ea86fe541628426772b657375ee1c048", size = 61460, upload-time = "2026-06-20T23:49:42.966Z" }, +] + [[package]] name = "xxhash" -version = "3.7.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/24/2f/e183a1b407002f5af81822bee18b61cdb94b8670208ef34734d8d2b8ebe9/xxhash-3.7.0.tar.gz", hash = "sha256:6cc4eefbb542a5d6ffd6d70ea9c502957c925e800f998c5630ecc809d6702bae", size = 82022, upload-time = "2026-04-25T11:10:32.553Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3b/f4/7bd35089ff1f8e2c96baa2dce05775a122aacd2e3830a73165e27a4d0848/xxhash-3.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fdc7d06929ae28dda98297a18eef7b0fd38991a3b405d8d7b55c9ef24c296958", size = 33423, upload-time = "2026-04-25T11:05:47.628Z" }, - { url = "https://files.pythonhosted.org/packages/a3/26/4e00c88a6a2c8a759cfb77d2a9a405f901e8aa66e60ef1fd0aeb35edda48/xxhash-3.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea6daa712f4e094a30830cf01e9b47d03b24d05cc9dab8609f0d9a9db8454712", size = 30857, upload-time = "2026-04-25T11:05:49.189Z" }, - { url = "https://files.pythonhosted.org/packages/82/2f/eeb942c17a5a761a8f01cb9180a0b76bfb62a2c39e6f46b1f9001899027a/xxhash-3.7.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9e6c0d843f1daf85ea23aeb053579135552bde575b7b98af20bfc667b6e4548d", size = 194702, upload-time = "2026-04-25T11:05:50.457Z" }, - { url = "https://files.pythonhosted.org/packages/0e/fd/96f132c08b1e5951c68691d3b9ec351ec2edc028f6a01fcd294f46b9d9f0/xxhash-3.7.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:363c139bf15e1ac5f136b981d3c077eb551299b1effede7f12faa010b8590a60", size = 213613, upload-time = "2026-04-25T11:05:52.571Z" }, - { url = "https://files.pythonhosted.org/packages/82/89/d4e92b796c5ed052d29ed324dbfc1dc1188e0c4bf64bebbf0f8fc20698df/xxhash-3.7.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a778b25874cb0f862eaab5986bff4ca49ffb0def7c0a34c237b948b3c6c775b2", size = 236726, upload-time = "2026-04-25T11:05:54.395Z" }, - { url = "https://files.pythonhosted.org/packages/40/f1/81fc4361921dc6e557a9c60cb3712f36d244d06eeeb71cd2f4252ac42678/xxhash-3.7.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3e1860f1e43d40e9d904cf22d93e587ea42e010ebce4160877e46bcab4bc232a", size = 212443, upload-time = "2026-04-25T11:05:56.334Z" }, - { url = "https://files.pythonhosted.org/packages/6a/d0/afeddd4cff50a332f50d4b8a2e8857673153ab0564ef472fcdeb0b5430df/xxhash-3.7.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9122ad6f867c4a0f5e655f5c3bdf89103852009dbb442a3d23e688b9e699e800", size = 445793, upload-time = "2026-04-25T11:05:58.953Z" }, - { url = "https://files.pythonhosted.org/packages/f7/d0/3c91e4e6a05ca4d7df8e39ec3a75b713609258ec84705ab34be6430826a1/xxhash-3.7.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7d9110d0c3fb02679972837a033251fd186c529aa62f19c132fc909c74052b8", size = 193937, upload-time = "2026-04-25T11:06:00.546Z" }, - { url = "https://files.pythonhosted.org/packages/4e/3a/a6b0772d9801dd4bea4ca4fd34734d6e9b51a711c8a611a24a79de26a878/xxhash-3.7.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:347a93f2b4ce67ce61959665e32a7447c380f8347e55e100daa23766baacf0e5", size = 285188, upload-time = "2026-04-25T11:06:01.96Z" }, - { url = "https://files.pythonhosted.org/packages/6c/f8/cf8e31fd7282230fe7367cd501a2e75b4b67b222bfc7eacccfc20d2652cb/xxhash-3.7.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:acbb48679ddf3852c45280c10ff10d52ca2cd1da2e552fb81db1ff786c75d0e4", size = 210966, upload-time = "2026-04-25T11:06:03.453Z" }, - { url = "https://files.pythonhosted.org/packages/cc/f0/fd36cc4a81bf52ee5633275daae2b93dd958aace67fd4f5d466ec83b5f35/xxhash-3.7.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:fe14c356f8b23ad811dc026077a6d4abccdaa7bce5ca98579605550657b6fcfb", size = 241994, upload-time = "2026-04-25T11:06:05.264Z" }, - { url = "https://files.pythonhosted.org/packages/08/e1/67f5d9c9369be42eaf99ba02c01bf14c5ecd67087b02567960bfcee43b63/xxhash-3.7.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f420ad3d41e38194353a498bbc9561fd5a9973a27b536ce46d8583479cf44335", size = 198707, upload-time = "2026-04-25T11:06:07.044Z" }, - { url = "https://files.pythonhosted.org/packages/50/17/a4c865ca22d2da6b1bc7d739bf88cab209533cf52ba06ca9da27c3039bee/xxhash-3.7.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:693d02c6dc7d1aa0a45921d54cd8c1ff629e09dfdc2238471507af1f7a1c6f04", size = 210917, upload-time = "2026-04-25T11:06:08.853Z" }, - { url = "https://files.pythonhosted.org/packages/49/8b/453b35810d697abac3c96bde3528bece685869227da274eb80a4a4d4a119/xxhash-3.7.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:14bf7a54e43825ec131ee7fe3c60e142e7c2c1e676ad0f93fc893432d15414af", size = 275772, upload-time = "2026-04-25T11:06:10.645Z" }, - { url = "https://files.pythonhosted.org/packages/b5/ad/4eed7eab07fd3ee6678f416190f0413d097ab5d7c1278906bf1e9549d789/xxhash-3.7.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ae3a39a4d96bdb6f8d154fd7f490c4ad06f0532fcd2bb656052a9a7762cf5d31", size = 414068, upload-time = "2026-04-25T11:06:12.511Z" }, - { url = "https://files.pythonhosted.org/packages/d3/4e/fd6f8a680ba248fdb83054fa71a8bfa3891225200de1708b888ef2c49829/xxhash-3.7.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1cc07c639e3a77ef1d32987464d3e408565b8a3be57b545d3542b191054d9923", size = 191459, upload-time = "2026-04-25T11:06:14.07Z" }, - { url = "https://files.pythonhosted.org/packages/50/7c/8cb34b3bed4f44ca6827a534d50833f9bc6c006e83b0eb410ac9fa0793bd/xxhash-3.7.0-cp311-cp311-win32.whl", hash = "sha256:3281ba1d1e60ee7a382a7b958513ba03c2c0d5fcbd9a6f7517c0a81251a23422", size = 30628, upload-time = "2026-04-25T11:06:15.802Z" }, - { url = "https://files.pythonhosted.org/packages/0b/47/a49767bd7b40782bedae9ff0721bfe1d7e4dd9dc1585dea684e57ba67c20/xxhash-3.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:a7f25baec4c5d851d40718d6fae52285b31683093d4ff5207e63ab306ccf14a5", size = 31461, upload-time = "2026-04-25T11:06:17.104Z" }, - { url = "https://files.pythonhosted.org/packages/7c/c6/3957bfacfb706bd687be246dfa8dd60f8df97c44186d229f7fd6e26c4b7e/xxhash-3.7.0-cp311-cp311-win_arm64.whl", hash = "sha256:4c2454448ce847c72635827bb75c15c5a3434b03ee1afd28cb6dc6fb2597d830", size = 27746, upload-time = "2026-04-25T11:06:18.716Z" }, - { url = "https://files.pythonhosted.org/packages/f2/8a/51a14cdef4728c6c2337db8a7d8704422cc65676d9199d77215464c880af/xxhash-3.7.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:082c87bfdd2b9f457606c7a4a53457f4c4b48b0cdc48de0277f4349d79bb3d7a", size = 33357, upload-time = "2026-04-25T11:06:20.44Z" }, - { url = "https://files.pythonhosted.org/packages/b9/1b/0c2c933809421ffd9bf42b59315552c143c755db5d9a816b2f1ae273e884/xxhash-3.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5e7ce913b61f35b0c1c839a49ac9c8e75dd8d860150688aed353b0ce1bf409d8", size = 30869, upload-time = "2026-04-25T11:06:21.989Z" }, - { url = "https://files.pythonhosted.org/packages/03/a8/89d5fdd6ee12d70ba99451de46dd0e8010167468dcd913ec855653f4dd50/xxhash-3.7.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3beb1de3b1e9694fcdd853e570ee64c631c7062435d2f8c69c1adf809bc086f0", size = 194100, upload-time = "2026-04-25T11:06:23.586Z" }, - { url = "https://files.pythonhosted.org/packages/87/ee/2f9f2ed993e77206d1e66991290a1ebe22e843351ca3ebec8e49e01ba186/xxhash-3.7.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3e7b689c3bce16699efcf736066f5c6cc4472c3840fe4b22bd8279daf4abdac", size = 212977, upload-time = "2026-04-25T11:06:25.019Z" }, - { url = "https://files.pythonhosted.org/packages/de/60/5a91644615a9e9d4e42c2e9925f1908e3a24e4e691d9de7340d565bea024/xxhash-3.7.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a6545e6b409e3d5cbafc850fb84c55a1ca26ed15a6b11e3bf07a0e0cd84517c8", size = 236373, upload-time = "2026-04-25T11:06:26.482Z" }, - { url = "https://files.pythonhosted.org/packages/22/c0/f3a9384eaaed9d14d4d062a5d953aa0da489bfe9747877aa994caa87cd0b/xxhash-3.7.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:31ab1461c77a11461d703c88eb949e132a1c6515933cf675d97ec680f4bd18de", size = 212229, upload-time = "2026-04-25T11:06:28.065Z" }, - { url = "https://files.pythonhosted.org/packages/2e/67/02f07a9fd79726804190f2172c4894c3ed9a4ebccaca05653c84beb58025/xxhash-3.7.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7c4d596b7676f811172687ec567cbafb9e4dea2f9be1bbb4f622410cb7f40f40", size = 445462, upload-time = "2026-04-25T11:06:30.048Z" }, - { url = "https://files.pythonhosted.org/packages/40/37/558f5a90c0672fc9b4402dc25d87ac5b7406616e8969430c9ca4e52ee74d/xxhash-3.7.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13805f0461cba0a857924e70ff91ae6d52d2598f79a884e788db80532614a4a1", size = 193932, upload-time = "2026-04-25T11:06:31.857Z" }, - { url = "https://files.pythonhosted.org/packages/d5/90/aaa09cd58661d32044dbbad7df55bbe22a623032b810e7ed3b8c569a2a6f/xxhash-3.7.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1d398f372496152f1c6933a33566373f8d1b37b98b8c9d608fa6edc0976f23b2", size = 284807, upload-time = "2026-04-25T11:06:33.697Z" }, - { url = "https://files.pythonhosted.org/packages/d6/f3/53df3719ab127a02c174f0c1c74924fcd110866e89c966bc7909cfa8fa84/xxhash-3.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d610aa62cdb7d4d497740741772a24a794903bf3e79eaa51d2e800082abe11e5", size = 210445, upload-time = "2026-04-25T11:06:35.488Z" }, - { url = "https://files.pythonhosted.org/packages/72/33/d219975c0e8b6fa2eb9ccd486fe47e21bf1847985b878dd2fbc3126e0d5c/xxhash-3.7.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:073c23900a9fbf3d26616c17c830db28af9803677cd5b33aea3224d824111514", size = 241273, upload-time = "2026-04-25T11:06:37.24Z" }, - { url = "https://files.pythonhosted.org/packages/3e/50/49b1afe610eb3964cedcb90a4d4c3d46a261ee8669cbd4f060652619ae3c/xxhash-3.7.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:418a463c3e6a590c0cdc890f8be19adb44a8c8acd175ca5b2a6de77e61d0b386", size = 197950, upload-time = "2026-04-25T11:06:39.148Z" }, - { url = "https://files.pythonhosted.org/packages/c6/75/5f42a1a4c78717d906a4b6a140c6dbf837ab1f547a54d23c4e2903310936/xxhash-3.7.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:03f8ff4474ee61c845758ce00711d7087a770d77efb36f7e74a6e867301000b8", size = 210709, upload-time = "2026-04-25T11:06:40.958Z" }, - { url = "https://files.pythonhosted.org/packages/8a/85/237e446c25abced71e9c53d269f2cef5bab8a82b3f88a12e00c5368e7368/xxhash-3.7.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:44fba4a5f1d179b7ddc7b3dc40f56f9209046421679b57025d4d8821b376fd8d", size = 275345, upload-time = "2026-04-25T11:06:42.525Z" }, - { url = "https://files.pythonhosted.org/packages/62/34/c2c26c0a6a9cc739bc2a5f0ae03ba8b87deb12b8bce35f7ac495e790dc6d/xxhash-3.7.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31e3516a0f829d06ded4a2c0f3c7c5561993256bfa1c493975fb9dc7bfa828a1", size = 414056, upload-time = "2026-04-25T11:06:44.343Z" }, - { url = "https://files.pythonhosted.org/packages/a0/aa/5c58e9bc8071b8afd8dcf297ff362f723c4892168faba149f19904132bf4/xxhash-3.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b59ee2ac81de57771a09ecad09191e840a1d2fae1ef684208320591055768f83", size = 191485, upload-time = "2026-04-25T11:06:46.262Z" }, - { url = "https://files.pythonhosted.org/packages/d4/69/a929cf9d1e2e65a48b818cdce72cb6b69eab2e6877f21436d0a1942aff43/xxhash-3.7.0-cp312-cp312-win32.whl", hash = "sha256:74bbd92f8c7fcc397ba0a11bfdc106bc72ad7f11e3a60277753f87e7532b4d81", size = 30671, upload-time = "2026-04-25T11:06:48.039Z" }, - { url = "https://files.pythonhosted.org/packages/b9/1b/104b41a8947f4e1d4a66ce1e628eea752f37d1890bfd7453559ca7a3d950/xxhash-3.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:7bd7bc82dd4f185f28f35193c2e968ef46131628e3cac62f639dadf321cba4d1", size = 31514, upload-time = "2026-04-25T11:06:49.279Z" }, - { url = "https://files.pythonhosted.org/packages/98/a0/1fd0ea1f1b886d9e7c73f0397571e22333a7d79e31da6d7127c2a4a71d75/xxhash-3.7.0-cp312-cp312-win_arm64.whl", hash = "sha256:7d7148180ec99ba36585b42c8c5de25e9b40191613bc4be68909b4d25a77a852", size = 27761, upload-time = "2026-04-25T11:06:50.448Z" }, - { url = "https://files.pythonhosted.org/packages/c1/ca/d5174b4c36d10f64d4ca7050563138c5a599efb01a765858ddefc9c1202a/xxhash-3.7.0-cp313-cp313-android_21_arm64_v8a.whl", hash = "sha256:4b6d6b33f141158692bd4eafbb96edbc5aa0dabdb593a962db01a91983d4f8fa", size = 36813, upload-time = "2026-04-25T11:06:51.73Z" }, - { url = "https://files.pythonhosted.org/packages/41/d0/abc6c9d347ba1f1e1e1d98125d0881a0452c7f9a76a9dd03a7b5d2197f23/xxhash-3.7.0-cp313-cp313-android_21_x86_64.whl", hash = "sha256:845d347df254d6c619f616afa921331bada8614b8d373d58725c663ba97c3605", size = 35121, upload-time = "2026-04-25T11:06:53.048Z" }, - { url = "https://files.pythonhosted.org/packages/bf/11/4cc834eb3d79f2f2b3a6ef7324195208bcdfbdcf7534d2b17267aa5f3a8f/xxhash-3.7.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:fddbbb69a6fff4f421e7a0d1fa28f894b20112e9e3fab306af451e2dfd0e459b", size = 29624, upload-time = "2026-04-25T11:06:54.311Z" }, - { url = "https://files.pythonhosted.org/packages/23/83/e97d3e7b635fe73a1dfb1e91f805324dd6d930bb42041cbf18f183bc0b6d/xxhash-3.7.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:54876a4e45101cec2bf8f31a973cda073a23e2e108538dad224ba07f85f22487", size = 30638, upload-time = "2026-04-25T11:06:55.864Z" }, - { url = "https://files.pythonhosted.org/packages/f4/40/d84951d80c35db1f4c40a29a64a8520eea5d56e764c603906b4fe763580f/xxhash-3.7.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:0c72fe9c7e3d6dfd7f1e21e224a877917fa09c465694ba4e06464b9511b65544", size = 33323, upload-time = "2026-04-25T11:06:57.336Z" }, - { url = "https://files.pythonhosted.org/packages/89/cc/c7dc6558d97e9ab023f663d69ab28b340ed9bf4d2d94f2c259cf896bb354/xxhash-3.7.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a6d73a830b17ef49bc04e00182bd839164c1b3c59c127cd7c54fcb10c7ed8ee8", size = 33362, upload-time = "2026-04-25T11:06:58.656Z" }, - { url = "https://files.pythonhosted.org/packages/2a/6e/46b84017b1301d54091430353d4ad5901654a3e0871649877a416f7f1644/xxhash-3.7.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:91c3b07cf3362086d8f126c6aecd8e5e9396ad8b2f2219ea7e49a8250c318acd", size = 30874, upload-time = "2026-04-25T11:06:59.834Z" }, - { url = "https://files.pythonhosted.org/packages/df/5e/8f9158e3ab906ad3fec51e09b5ea0093e769f12207bfa42a368ca204e7ab/xxhash-3.7.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:50e879ebbac351c81565ca108db766d7832f5b8b6a5b14b8c0151f7190028e3d", size = 194185, upload-time = "2026-04-25T11:07:01.658Z" }, - { url = "https://files.pythonhosted.org/packages/f3/29/a804ded9f5d3d3758292678d23e7528b08fda7b7e750688d08b052322475/xxhash-3.7.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:921c14e93817842dd0dd9f372890a0f0c72e534650b6ab13c5be5cd0db11d47e", size = 213033, upload-time = "2026-04-25T11:07:03.606Z" }, - { url = "https://files.pythonhosted.org/packages/8b/91/1ce5a7d2fdc975267320e2c78fc1cecfe7ab735ccbcf6993ec5dd541cb2c/xxhash-3.7.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e64a7c9d7dfca3e0fafcbc5e455519090706a3e36e95d655cec3e04e79f95aaa", size = 236140, upload-time = "2026-04-25T11:07:05.396Z" }, - { url = "https://files.pythonhosted.org/packages/34/04/fd595a4fd8617b05fa27bd9b684ecb4985bfed27917848eea85d54036d06/xxhash-3.7.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2220af08163baf5fa36c2b8af079dc2cbe6e66ae061385267f9472362dfd53c6", size = 212291, upload-time = "2026-04-25T11:07:06.966Z" }, - { url = "https://files.pythonhosted.org/packages/03/fb/f1a379cbc372ae5b9f4ab36154c48a849ca6ebe3ac477067a57865bf3bc6/xxhash-3.7.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f14bb8b22a4a91325813e3d553b8963c10cf8c756cff65ee50c194431296c655", size = 445532, upload-time = "2026-04-25T11:07:08.525Z" }, - { url = "https://files.pythonhosted.org/packages/65/59/172424b79f8cfd4b6d8a122b2193e6b8ad4b11f7159bb3b6f9b3191329bb/xxhash-3.7.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:496736f86a9bedaf64b0dc70e3539d0766df01c71ea22032698e88f3f04a1ce9", size = 193990, upload-time = "2026-04-25T11:07:10.315Z" }, - { url = "https://files.pythonhosted.org/packages/b9/19/aeac22161d953f139f07ba5586cb4a17c5b7b6dff985122803bb12933500/xxhash-3.7.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0ff71596bd79816975b3de7130ab1ff4541410285a3c084584eeb1c8239996fd", size = 284876, upload-time = "2026-04-25T11:07:12.15Z" }, - { url = "https://files.pythonhosted.org/packages/77/d5/4fd0b59e7a02242953da05ff679fbb961b0a4368eac97a217e11dae110c1/xxhash-3.7.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1ad86695c19b1d46fe106925db3c7a37f16be37669dcf58dcc70a9dd6e324676", size = 210495, upload-time = "2026-04-25T11:07:13.952Z" }, - { url = "https://files.pythonhosted.org/packages/aa/fb/976a3165c728c7faf74aa1b5ab3cf6a85e6d731612894741840524c7d28c/xxhash-3.7.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:970f9f8c50961d639cbd0d988c96f80ddf66006de93641719282c4fe7a87c5e6", size = 241331, upload-time = "2026-04-25T11:07:15.557Z" }, - { url = "https://files.pythonhosted.org/packages/4a/2c/6763d5901d53ac9e6ba296e5717ae599025c9d268396e8faa8b4b0a8e0ac/xxhash-3.7.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5886ad85e9e347911783760a1d16cb6b393e8f9e3b52c982568226cb56927bdc", size = 198037, upload-time = "2026-04-25T11:07:17.563Z" }, - { url = "https://files.pythonhosted.org/packages/61/2b/876e722d533833f5f9a83473e6ba993e48745701096944e77bbecf29b2c3/xxhash-3.7.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:6e934bbae1e0ec74e27d5f0d7f37ef547ce5ff9f0a7e63fb39e559fc99526734", size = 210744, upload-time = "2026-04-25T11:07:19.055Z" }, - { url = "https://files.pythonhosted.org/packages/21/e6/d7e7baef7ce24166b4668d3c48557bb35a23b92ecadcac7e7718d099ab69/xxhash-3.7.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:3b6b3d28228af044ebcded71c4a3dd86e1dbd7e2f4645bf40f7b5da65bb5fb5a", size = 275406, upload-time = "2026-04-25T11:07:20.908Z" }, - { url = "https://files.pythonhosted.org/packages/92/fe/198b3763b2e01ca908f2154969a2352ec99bda892b574a11a9a151c5ede4/xxhash-3.7.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:6be4d70d9ab76c9f324ead9c01af6ff52c324745ea0c3731682a0cf99720f1fe", size = 414125, upload-time = "2026-04-25T11:07:23.037Z" }, - { url = "https://files.pythonhosted.org/packages/3a/6d/019a11affd5a5499137cacca53808659964785439855b5aa40dfd3412916/xxhash-3.7.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:151d7520838d4465461a0b7f4ae488b3b00de16183dd3214c1a6b14bf89d7fb6", size = 191555, upload-time = "2026-04-25T11:07:24.991Z" }, - { url = "https://files.pythonhosted.org/packages/76/21/b96d58568df2d01533244c3e0e5cbdd0c8b2b25c4bec4d72f19259a292d7/xxhash-3.7.0-cp313-cp313-win32.whl", hash = "sha256:d798c1e291bffb8e37b5bbe0dda77fc767cd19e89cadaf66e6ed5d0ff88c9fe6", size = 30668, upload-time = "2026-04-25T11:07:26.665Z" }, - { url = "https://files.pythonhosted.org/packages/99/57/d849a8d3afa1f8f4bc6a831cd89f49f9706fbbad94d2975d6140a171988c/xxhash-3.7.0-cp313-cp313-win_amd64.whl", hash = "sha256:875811ba23c543b1a1c3143c926e43996eb27ebb8f52d3500744aa608c275aed", size = 31524, upload-time = "2026-04-25T11:07:27.92Z" }, - { url = "https://files.pythonhosted.org/packages/81/52/bacc753e92dee78b058af8dcef0a50815f5f860986c664a92d75f965b6a5/xxhash-3.7.0-cp313-cp313-win_arm64.whl", hash = "sha256:54a675cb300dda83d71daae2a599389d22db8021a0f8db0dd659e14626eb3ecc", size = 27768, upload-time = "2026-04-25T11:07:29.113Z" }, - { url = "https://files.pythonhosted.org/packages/1c/47/ddbd683b7fc7e592c1a8d9d65f73ce9ab513f082b3967eee2baf549b8fc6/xxhash-3.7.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a3b19a42111c4057c1547a4a1396a53961dca576a0f6b82bfa88a2d1561764b2", size = 33576, upload-time = "2026-04-25T11:07:30.469Z" }, - { url = "https://files.pythonhosted.org/packages/07/f2/36d3310161db7f72efb4562aadde0ed429f1d0531782dd6345b12d2da527/xxhash-3.7.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8f4608a06e4d61b7a3425665a46d00e0579122e1a2fae97a0c52953a3aad9aa3", size = 31123, upload-time = "2026-04-25T11:07:31.989Z" }, - { url = "https://files.pythonhosted.org/packages/0d/3f/75937a5c69556ed213021e43cbedd84c8e0279d0d74e7d41a255d84ba4b1/xxhash-3.7.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ad37c7792479e49cf96c1ab25517d7003fe0d93687a772ba19a097d235bbe41e", size = 196491, upload-time = "2026-04-25T11:07:33.358Z" }, - { url = "https://files.pythonhosted.org/packages/22/29/f10d7ff8c7a733d4403a43b9de18c8fabc005f98cec054644f04418659ee/xxhash-3.7.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc026e3b89d98e30a8288c95cb696e77d150b3f0fb7a51f73dcd49ee6b5577fa", size = 215793, upload-time = "2026-04-25T11:07:34.919Z" }, - { url = "https://files.pythonhosted.org/packages/8b/fd/778f60aa295f58907938f030a8b514611f391405614a525cccd2ffc00eb5/xxhash-3.7.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c9b31ab1f28b078a6a1ac1a54eb35e7d5390deddd56870d0be3a0a733d1c321c", size = 237993, upload-time = "2026-04-25T11:07:36.638Z" }, - { url = "https://files.pythonhosted.org/packages/70/f5/736db5de387b4a540e37a05b84b40dc58a1ce974bfd2b4e5754ce29b68c3/xxhash-3.7.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3bb5fd680c038fd5229e44e9c493782f90df9bef632fd0499d442374688ff70b", size = 214887, upload-time = "2026-04-25T11:07:38.564Z" }, - { url = "https://files.pythonhosted.org/packages/4d/aa/09a095f22fdb9a27fbb716841fbff52119721f9ca4261952d07a912f7839/xxhash-3.7.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:030c0fd688fce3569fbb49a2feefd4110cbb0b650186fb4610759ecfac677548", size = 448407, upload-time = "2026-04-25T11:07:40.552Z" }, - { url = "https://files.pythonhosted.org/packages/74/8a/b745efeeca9e34a91c26fdc97ad8514c43d5a81ac78565cba80a1353870a/xxhash-3.7.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5b1bde10324f4c31812ae0d0502e92d916ae8917cad7209353f122b8b8f610c3", size = 196119, upload-time = "2026-04-25T11:07:42.101Z" }, - { url = "https://files.pythonhosted.org/packages/8a/5c/0cfceb024af90c191f665c7933b1f318ee234f4797858383bebd1881d52f/xxhash-3.7.0-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:503722d52a615f2604f5e7611de7d43878df010dc0053094ef91cb9a9ac3d987", size = 286751, upload-time = "2026-04-25T11:07:43.568Z" }, - { url = "https://files.pythonhosted.org/packages/0b/0a/0793e405dc3cf8f4ebe2c1acec1e4e4608cd9e7e50ea691dabbc2a95ccbb/xxhash-3.7.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c72500a3b6d6c30ebfc135035bcace9eb5884f2dc220804efcaaba43e9f611dd", size = 212961, upload-time = "2026-04-25T11:07:45.388Z" }, - { url = "https://files.pythonhosted.org/packages/0c/7e/721118ffc63bfff94aa565bcf2555a820f9f4bdb0f001e0d609bdfad70de/xxhash-3.7.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:43475925a766d01ca8cd9a857fd87f3d50406983c8506a4c07c4df12adcc867f", size = 243703, upload-time = "2026-04-25T11:07:47.053Z" }, - { url = "https://files.pythonhosted.org/packages/6e/18/16f6267160488b8276fd3d449d425712512add292ba545c1b6946bfdb7dd/xxhash-3.7.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8d09dfd2ab135b985daf868b594315ebe11ad86cd9fea46e6c69f19b28f7d25a", size = 200894, upload-time = "2026-04-25T11:07:48.657Z" }, - { url = "https://files.pythonhosted.org/packages/2d/94/80ba841287fd97e3e9cac1d228788c8ef623746f570404961eec748ecb5c/xxhash-3.7.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:c50269d0055ac1faecfd559886d2cbe4b730de236585aba0e873f9d9dadbe585", size = 213357, upload-time = "2026-04-25T11:07:50.257Z" }, - { url = "https://files.pythonhosted.org/packages/a1/7e/106d4067130c59f1e18a55ffadcd876d8c68534883a1e02685b29d3d8153/xxhash-3.7.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:1910df4756a5ab58cfad8744fc2d0f23926e3efcc346ee76e87b974abab922f4", size = 277600, upload-time = "2026-04-25T11:07:51.745Z" }, - { url = "https://files.pythonhosted.org/packages/c5/86/a081dd30da71d720b2612a792bfd55e45fa9a07ac76a0507f60487473c25/xxhash-3.7.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:d006faf3b491957efcb433489be3c149efe4787b7063d5cddb8ddaefdc60e0c1", size = 416980, upload-time = "2026-04-25T11:07:53.504Z" }, - { url = "https://files.pythonhosted.org/packages/35/29/1a95221a029a3c1293773869e1ab47b07cbbdd82444a42809e8c60156626/xxhash-3.7.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:abb65b4e947e958f7b3b0d71db3ce447d1bc5f37f5eab871ce7223bda8768a04", size = 193840, upload-time = "2026-04-25T11:07:55.103Z" }, - { url = "https://files.pythonhosted.org/packages/c5/e0/db909dd0823285de2286f67e10ee4d81e96ad35d7d8e964ecb07fccd8af9/xxhash-3.7.0-cp313-cp313t-win32.whl", hash = "sha256:178959906cb1716a1ce08e0d69c82886c70a15a6f2790fc084fdd146ca30cd49", size = 30966, upload-time = "2026-04-25T11:07:56.524Z" }, - { url = "https://files.pythonhosted.org/packages/7b/ff/d705b15b22f21ee106adce239cb65d35067a158c630b240270f09b17c2e6/xxhash-3.7.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2524a1e20d4c231d13b50f7cf39e44265b055669a64a7a4b9a2a44faa03f19b6", size = 31784, upload-time = "2026-04-25T11:07:57.758Z" }, - { url = "https://files.pythonhosted.org/packages/a2/1f/b2cf83c3638fd0588e0b17f22e5a9400bdfb1a3e3755324ac0aee2250b88/xxhash-3.7.0-cp313-cp313t-win_arm64.whl", hash = "sha256:37d994d0ffe81ef087bb330d392caa809bb5853c77e22ea3f71db024a0543dba", size = 27932, upload-time = "2026-04-25T11:07:59.109Z" }, - { url = "https://files.pythonhosted.org/packages/0e/cc/431db584f6fbb9312e40a173af027644e5580d39df1f73603cbb9dca4d6b/xxhash-3.7.0-cp314-cp314-android_24_arm64_v8a.whl", hash = "sha256:8c5fcfd806c335bfa2adf1cd0b3110a44fc7b6995c3a648c27489bae85801465", size = 36644, upload-time = "2026-04-25T11:08:00.658Z" }, - { url = "https://files.pythonhosted.org/packages/bc/01/255ec513e0a705d1f9a61413e78dfce4e3235203f0ed525a24c2b4b56345/xxhash-3.7.0-cp314-cp314-android_24_x86_64.whl", hash = "sha256:506a0b488f190f0a06769575e30caf71615c898ed93ab18b0dbcb6dec5c3713c", size = 35003, upload-time = "2026-04-25T11:08:02.338Z" }, - { url = "https://files.pythonhosted.org/packages/68/70/c55fc33c93445b44d8fc5a17b41ed99e3cebe92bcf8396809e63fc9a1165/xxhash-3.7.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:ec68dbba21532c0173a9872298e65c89749f7c9d21538c3a78b5bb6105871568", size = 29655, upload-time = "2026-04-25T11:08:03.701Z" }, - { url = "https://files.pythonhosted.org/packages/c2/72/ff8de73df000d74467d12a59ce6d6e2b2a368b978d41ab7b1fba5ed442be/xxhash-3.7.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:fa77e7ec1450d415d20129961814787c9abd9a07f98872f070b1fe96c5084611", size = 30664, upload-time = "2026-04-25T11:08:05.011Z" }, - { url = "https://files.pythonhosted.org/packages/b6/91/08416d9bd9bc3bf39d831abe8a5631ac2db5141dfd6fe81c3fe59a1f9264/xxhash-3.7.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:fe32736295ea38e43e7d9424053c8c47c9f64fecfc7c895fb3da9b30b131c9ee", size = 33317, upload-time = "2026-04-25T11:08:06.413Z" }, - { url = "https://files.pythonhosted.org/packages/0e/3b/86b1caa4dee10a99f4bf9521e623359341c5e50d05158fa10c275b2bd079/xxhash-3.7.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:ab9dd2c83c4bbd63e422181a76f13502d049d3ddcac9a1bdc29196263d692bb8", size = 33457, upload-time = "2026-04-25T11:08:08.099Z" }, - { url = "https://files.pythonhosted.org/packages/ed/38/98ea14ad1517e1461292a65906951458d520689782bfbae111050145bdba/xxhash-3.7.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3afec3a336a2286601a437cb07562ab0227685e6fbb9ec17e8c18457ff348ecf", size = 30894, upload-time = "2026-04-25T11:08:09.429Z" }, - { url = "https://files.pythonhosted.org/packages/61/a2/074654d0b893606541199993c7db70067d9fc63b748e0d60020a52a1bd36/xxhash-3.7.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:565df64437a9390f84465dcca33e7377114c7ede8d05cd2cf20081f831ea788e", size = 194409, upload-time = "2026-04-25T11:08:10.91Z" }, - { url = "https://files.pythonhosted.org/packages/e2/26/6d2a1afc468189f77ca28c32e1c83e1b9da1178231e05641dbc1b350e332/xxhash-3.7.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:12eca820a5d558633d423bf8bb78ce72a55394823f64089247f788a7e0ae691e", size = 213135, upload-time = "2026-04-25T11:08:12.575Z" }, - { url = "https://files.pythonhosted.org/packages/8e/0e/d8aecf95e09c42547453137be74d2f7b8b14e08f5177fa2fab6144a19061/xxhash-3.7.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f262b8f7599516567e070abf607b9af649052b2c4bd6f9be02b0cb41b7024805", size = 236379, upload-time = "2026-04-25T11:08:14.206Z" }, - { url = "https://files.pythonhosted.org/packages/f2/74/8140e8210536b3dd0cc816c4faaeb5ba6e63e8125ab25af4bcddd6a037b3/xxhash-3.7.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1598916cb197681e03e601901e4ab96a9a963de398c59d0964f8a6f44a2b361", size = 212447, upload-time = "2026-04-25T11:08:15.79Z" }, - { url = "https://files.pythonhosted.org/packages/a0/d2/462001d2903b4bee5a5689598a0a55e5e7cd1ac7f4247a5545cff10d3ebb/xxhash-3.7.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:322b2f0622230f526aeb1738149948a7ae357a9e2ceb1383c6fd1fdaecdafa16", size = 445660, upload-time = "2026-04-25T11:08:17.441Z" }, - { url = "https://files.pythonhosted.org/packages/23/09/2bd1ed7f8689b20e51727952cac8329d50c694dc32b2eba06ba5bc742b37/xxhash-3.7.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:24cc22070880cc57b830a65cde4e65fa884c6d9b28ae4803b5ee05911e7bafba", size = 194076, upload-time = "2026-04-25T11:08:19.134Z" }, - { url = "https://files.pythonhosted.org/packages/c9/6e/692302cd0a5f4ac4e6289f37fa888dc2e1e07750b68fe3e4bfe939b8cea3/xxhash-3.7.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb5a888a968b2434abf9ecda357b5d43f10d7b5a6da6fdbbe036208473aff0e2", size = 284990, upload-time = "2026-04-25T11:08:20.618Z" }, - { url = "https://files.pythonhosted.org/packages/05/d9/e54b159b3d9df7999d2a7c676ce7b323d1b5588a64f8f51ed8172567bd87/xxhash-3.7.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a999771ff97bec27d18341be4f3a36b163bb1ac41ec17bef6d2dabd84acd33c7", size = 210590, upload-time = "2026-04-25T11:08:22.24Z" }, - { url = "https://files.pythonhosted.org/packages/50/93/0e0df1a3a196ced4ca71de76d65ead25d8e87bbfb87b64306ea47a40c00d/xxhash-3.7.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:ed4a6efe2dee1655adb73e7ad40c6aa955a6892422b1e3b95de6a34de56e3cbb", size = 241442, upload-time = "2026-04-25T11:08:23.844Z" }, - { url = "https://files.pythonhosted.org/packages/9a/a9/d917a7a814e90b218f8a0d37967105eea91bf752c3303683c99a1f7bfc1f/xxhash-3.7.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:9fd17f14ac0faa12126c2f9ca774a8cf342957265ec3c8669c144e5e6cdb478c", size = 198356, upload-time = "2026-04-25T11:08:25.99Z" }, - { url = "https://files.pythonhosted.org/packages/89/5e/f2ba1877c39469abbefc72991d6ebdcbd4c0880db01ae8cb1f553b0c537d/xxhash-3.7.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:05fd1254268c59b5cb2a029dfc204275e9fc52de2913f1e53aa8d01442c96b4d", size = 210898, upload-time = "2026-04-25T11:08:27.608Z" }, - { url = "https://files.pythonhosted.org/packages/90/c6/be56b58e73de531f39a10de1355bb77ceb663900dc4bf2d6d3002a9c3f9e/xxhash-3.7.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:a2eae53197c6276d5b317f75a1be226bbf440c20b58bf525f36b5d0e1f657ca6", size = 275519, upload-time = "2026-04-25T11:08:29.301Z" }, - { url = "https://files.pythonhosted.org/packages/92/e2/17ddc85d5765b9c709f192009ed8f5a1fc876f4eb35bba7c307b5b1169f9/xxhash-3.7.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:bfe6f92e3522dcbe8c4281efd74fa7542a336cb00b0e3272c4ec0edabeaeaf67", size = 414191, upload-time = "2026-04-25T11:08:31.16Z" }, - { url = "https://files.pythonhosted.org/packages/9c/42/85f5b79f4bf1ec7ba052491164adfd4f4e9519f5dc7246de4fbd64a1bd56/xxhash-3.7.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7ab9a49c410d8c6c786ab99e79c529938d894c01433130353dd0fe999111077a", size = 191604, upload-time = "2026-04-25T11:08:32.862Z" }, - { url = "https://files.pythonhosted.org/packages/b8/d0/6127b623aa4cca18d8b7743592b048d689fd6c6e37ff26a22cddf6cd9d7f/xxhash-3.7.0-cp314-cp314-win32.whl", hash = "sha256:040ea63668f9185b92bc74942df09c7e65703deed71431333678fc6e739a9955", size = 31271, upload-time = "2026-04-25T11:08:34.651Z" }, - { url = "https://files.pythonhosted.org/packages/64/4f/44fc4788568004c43921701cbc127f48218a1eede2c9aea231115323564d/xxhash-3.7.0-cp314-cp314-win_amd64.whl", hash = "sha256:2a61e2a3fb23c892496d587b470dee7fa1b58b248a187719c65ea8e94ec13257", size = 32284, upload-time = "2026-04-25T11:08:35.987Z" }, - { url = "https://files.pythonhosted.org/packages/6d/77/18bb895eb60a49453d16e17d67990e5caff557c78eafc90ad4e2eabf4570/xxhash-3.7.0-cp314-cp314-win_arm64.whl", hash = "sha256:c7741c7524961d8c0cb4d4c21b28957ff731a3fd5b5cd8b856dc80a40e9e5acc", size = 28701, upload-time = "2026-04-25T11:08:37.767Z" }, - { url = "https://files.pythonhosted.org/packages/45/a0/46f72244570c550fbbb7db1ef554183dd5ebe9136385f30e032b781ae8f6/xxhash-3.7.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:fc84bf7aa7592f31ec63a3e7b11d624f468a3f19f5238cec7282a42e838ab1d7", size = 33646, upload-time = "2026-04-25T11:08:39.109Z" }, - { url = "https://files.pythonhosted.org/packages/4a/3a/453846a7eceea11e75def361eed01ec6a0205b9822c19927ed364ccae7cc/xxhash-3.7.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:9f1563fdc8abfc389748e6932c7e4e99c89a53e4ec37d4563c24fc06f5e5644b", size = 31125, upload-time = "2026-04-25T11:08:40.467Z" }, - { url = "https://files.pythonhosted.org/packages/bd/3e/49434aba738885d512f9e486db1bdd19db28dfa40372b56da26ef7a4e738/xxhash-3.7.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:2d415f18becf6f153046ab6adc97da77e3643a0ee205dae61c4012604113a020", size = 196633, upload-time = "2026-04-25T11:08:41.943Z" }, - { url = "https://files.pythonhosted.org/packages/a4/e9/006cb6127baeb9f8abe6d15e62faa01349f09b34e2bfd65175b2422d026b/xxhash-3.7.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bb16aa13ed175bc9be5c2491ba031b85a9b51c4ed90e0b3d4ebe63cf3fb54f8e", size = 215899, upload-time = "2026-04-25T11:08:43.645Z" }, - { url = "https://files.pythonhosted.org/packages/27/e4/cc57d72e66df0ae29b914335f1c6dcf61e8f3746ddf0ae3c471aa4f15e00/xxhash-3.7.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f9fd595f1e5941b3d7863e4774e4b30caa6731fc34b9277da032295aa5656ee5", size = 238116, upload-time = "2026-04-25T11:08:45.698Z" }, - { url = "https://files.pythonhosted.org/packages/af/78/3531d4a3fd8a0038cc6be1f265a69c1b3587f557a10b677dd736de2202c1/xxhash-3.7.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1295325c5a98d552333fa53dc2b026b0ef0ec9c8e73ca3a952990b4c7d65d459", size = 215012, upload-time = "2026-04-25T11:08:47.355Z" }, - { url = "https://files.pythonhosted.org/packages/b4/f6/259fb1eaaec921f59b17203b0daee69829761226d3b980d5191d7723dd83/xxhash-3.7.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3573a651d146912da9daa9e29e5fbc45994420daaa9ef1e2fa5823e1dc485513", size = 448534, upload-time = "2026-04-25T11:08:49.149Z" }, - { url = "https://files.pythonhosted.org/packages/7b/16/a66d0eaf6a7e68532c07714361ddc904c663ec940f3b028c1ae4a21a7b9d/xxhash-3.7.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ec1e080a3d02d94ea9335bfab0e3374b877e25411422c18f51a943fa4b46381", size = 196217, upload-time = "2026-04-25T11:08:50.805Z" }, - { url = "https://files.pythonhosted.org/packages/8d/ef/d2efc7fc51756dc52509109d1a25cefc859d74bc4b19a167b12dbd8c2786/xxhash-3.7.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:84415265192072d8638a3afc3c1bc5995e310570cd9acb54dc46d3939e364fe0", size = 286906, upload-time = "2026-04-25T11:08:52.418Z" }, - { url = "https://files.pythonhosted.org/packages/fc/67/25decd1d4a4018582ec4db2a868a2b7e40640f4adb20dfeb19ac923aa825/xxhash-3.7.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8d4dea659b57443989ef32f4295104fd6912c73d0bf26d1d148bb88a9f159b02", size = 213057, upload-time = "2026-04-25T11:08:54.105Z" }, - { url = "https://files.pythonhosted.org/packages/0d/5d/17651eb29d06786cdc40c60ae3d27d645aa5d61d2eca6237a7ba0b94789b/xxhash-3.7.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:05ece0fe4d9c9c2728912d1981ae1566cfc83a011571b24732cbf76e1fb70dca", size = 243886, upload-time = "2026-04-25T11:08:56.109Z" }, - { url = "https://files.pythonhosted.org/packages/8a/d4/174d9cf7502243d586e6a9ae842b1ae23026620995114f85f1380e588bc9/xxhash-3.7.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:fd880353cf1ffaf321bc18dd663e111976dbd0d3bbd8a66d58d2b470dfa7f396", size = 201015, upload-time = "2026-04-25T11:08:57.777Z" }, - { url = "https://files.pythonhosted.org/packages/91/8c/2254e2d06c3ac5e6fe22eaf3da791b87ea823ae9f2c17b4af66755c5752d/xxhash-3.7.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:4e15cc9e2817f6481160f930c62842b3ff419e20e13072bcbab12230943092bc", size = 213457, upload-time = "2026-04-25T11:08:59.826Z" }, - { url = "https://files.pythonhosted.org/packages/79/a2/e3daa762545921173e3360f3b4ff7fc63c2d27359f7230ec1a7a74e117f6/xxhash-3.7.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:90b9d1a8bd37d768ffc92a1f651ec69afc532a96fa1ac2ea7abbed5d630b3237", size = 277738, upload-time = "2026-04-25T11:09:01.423Z" }, - { url = "https://files.pythonhosted.org/packages/e1/4c/e186da2c46b87f5204640e008d42730bf3c1ee9f0efb71ae1ebcdfeac681/xxhash-3.7.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:157c49475b34ecea8809e51123d9769a534e139d1247942f7a4bc67710bb2533", size = 417127, upload-time = "2026-04-25T11:09:03.592Z" }, - { url = "https://files.pythonhosted.org/packages/17/28/3798e15007a3712d0da3d3fe70f8e11916569858b5cc371053bc26270832/xxhash-3.7.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5a6ddec83325685e729ca119d1f5c518ec39294212ecd770e60693cdc5f7eb79", size = 193962, upload-time = "2026-04-25T11:09:06.228Z" }, - { url = "https://files.pythonhosted.org/packages/ad/95/a26baa93b5241fd7630998816a4ec47a5a0bad193b3f8fc8f3593e1a4a67/xxhash-3.7.0-cp314-cp314t-win32.whl", hash = "sha256:a04a6cab47e2166435aaf5b9e5ee41d1532cc8300efdef87f2a4d0acb7db19ed", size = 31643, upload-time = "2026-04-25T11:09:08.153Z" }, - { url = "https://files.pythonhosted.org/packages/44/36/5454f13c447e395f9b06a3e91274c59f503d31fad84e1836efe3bdb71f6a/xxhash-3.7.0-cp314-cp314t-win_amd64.whl", hash = "sha256:8653dd7c2eda020545bb2c71c7f7039b53fe7434d0fc1a0a9deb79ab3f1a4fc1", size = 32522, upload-time = "2026-04-25T11:09:09.534Z" }, - { url = "https://files.pythonhosted.org/packages/74/35/698e7e3ff38e22992ea24870a511d8762474fb6783627a2910ff22a185c2/xxhash-3.7.0-cp314-cp314t-win_arm64.whl", hash = "sha256:468f0fc114faaa4b36699f8e328bbc3bb11dc418ba94ac52c26dd736d4b6c637", size = 28807, upload-time = "2026-04-25T11:09:11.234Z" }, - { url = "https://files.pythonhosted.org/packages/54/c1/e57ac7317b1f58a92bab692da6d497e2a7ce44735b224e296347a7ecc754/xxhash-3.7.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ad3aa71e12ee634f22b39a0ff439357583706e50765f17f05550f92dbf128a23", size = 31232, upload-time = "2026-04-25T11:10:21.51Z" }, - { url = "https://files.pythonhosted.org/packages/4f/4e/075559bd712bc62e84915ea46bbee859f935d285659082c129bdbff679dd/xxhash-3.7.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:5de686e73690cdaf72b96d4fa083c230ec9020bcc2627ce6316138e2cf2fe2d1", size = 28553, upload-time = "2026-04-25T11:10:23.1Z" }, - { url = "https://files.pythonhosted.org/packages/92/ca/a9c78cb384d4b033b0c58196bd5c8509873cabe76389e195127b0302a741/xxhash-3.7.0-pp311-pypy311_pp73-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7fbec49f5341bbdea0c471f7d1e2fb41ae8925af9b6f28025c28defd8eb94274", size = 41109, upload-time = "2026-04-25T11:10:25.022Z" }, - { url = "https://files.pythonhosted.org/packages/bd/b1/dfe2629f7c77eb2fa234c72ff537cdd64939763df704e256446ed364a16d/xxhash-3.7.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48b542c347c2089f43dc5a6db31d2a6f3cdb04ee33505ec6e9f653834dbb0bde", size = 36307, upload-time = "2026-04-25T11:10:26.949Z" }, - { url = "https://files.pythonhosted.org/packages/e7/f7/5a484afce0f48dd8083208b42e4911f290a82c7b52458ef2927e4d421a45/xxhash-3.7.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a169a036bed0995e090d1493b283cc2cc8a6f5046821086b843abefff80643bc", size = 32534, upload-time = "2026-04-25T11:10:29.01Z" }, - { url = "https://files.pythonhosted.org/packages/0f/5f/4acfcd490db9780cf36c58534d828003c564cde5350220a1c783c4d10776/xxhash-3.7.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:ec101643395d7f21405b640f728f6f627e6986557027d740f2f9b220955edafe", size = 31552, upload-time = "2026-04-25T11:10:30.727Z" }, +version = "3.8.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8e/63/71aa56b151a1b28770037a61bd4e461c2619cfc8866a4fcaf1548605e325/xxhash-3.8.1.tar.gz", hash = "sha256:b0de4bf3aa66363552d52c6a89003c479911f12098cd48a53d44a0f7a25f7c46", size = 86223, upload-time = "2026-07-06T10:49:58.937Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/5a/05eaa129555f85476a3e16ff869e95f81a78bbe4647eef9d0229f515a317/xxhash-3.8.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:602efcad4a42c184e81d43a2b7e6e4f524d619878f2b6ee2ba469011f47c8147", size = 34699, upload-time = "2026-07-06T10:44:10.14Z" }, + { url = "https://files.pythonhosted.org/packages/80/59/0df1133958b2228929355e022aab1e958c7b2c43e27bf7f59bc9edfa8a54/xxhash-3.8.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:131324f719957b988861714de7d6ddf57b47abec3b0cc691302ffeaba0e05e10", size = 32373, upload-time = "2026-07-06T10:44:11.353Z" }, + { url = "https://files.pythonhosted.org/packages/3e/bf/1cfda5b5e6bf26617812b4a31662ef2220d2ad04e0a55b8ff9eb36e56a5c/xxhash-3.8.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:db77278a6eddadbf44ce5aae2fee5ebb4d061f026b1ce2130d058cd4d7a7b670", size = 220284, upload-time = "2026-07-06T10:44:12.683Z" }, + { url = "https://files.pythonhosted.org/packages/70/93/45dc0ad7913b69e5b08bd039236cf628380e4c9cc76a8a4c6625a328e058/xxhash-3.8.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c332dd48b8cb050da2bb2a3c96d72b1664168650a250ef9718e423df7989e05", size = 240980, upload-time = "2026-07-06T10:44:14.297Z" }, + { url = "https://files.pythonhosted.org/packages/e9/02/f28ba7d17f2c1410ee397982c817ab1bd5b2701070c2d2c373539aad000a/xxhash-3.8.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a5cd96f6dcdf4fa657b2d95668d71d58455248f98712ecffaa9c528edf40ccae", size = 264526, upload-time = "2026-07-06T10:44:16.017Z" }, + { url = "https://files.pythonhosted.org/packages/5c/d0/f10651cec2c7981b20d693deae6bdfc438427d92be2db4ccabb6181f0021/xxhash-3.8.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c959f88160b13b4e730b0d75b459b7929fc0d2225c284c9683ac95d6feeeac6a", size = 241369, upload-time = "2026-07-06T10:44:17.698Z" }, + { url = "https://files.pythonhosted.org/packages/ff/40/136e0cbaf5db51e191423b1c98643593189f02b6cd90837bf64b19113d70/xxhash-3.8.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:027dee4355f3fcc41481650d846cf6cfc895c85a1ab7acd063063821a0df5b4c", size = 473186, upload-time = "2026-07-06T10:44:19.354Z" }, + { url = "https://files.pythonhosted.org/packages/4b/3f/6aa808a96bdc43dba9a740dec56c744526ee3c0019e32c75e810fa90ae4d/xxhash-3.8.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ad52a0e4bcc0ba956a953a169d1feec2734a64981d689e4fc8f490f7bf91af60", size = 220092, upload-time = "2026-07-06T10:44:20.956Z" }, + { url = "https://files.pythonhosted.org/packages/47/28/a8675e78a9ced96dab853416162268e10e05b452e95db7888cf69f58ac5f/xxhash-3.8.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5d3dfb1f0ff146da7952867a9414f0c7a29762f8825a84879592612fd6139342", size = 309846, upload-time = "2026-07-06T10:44:22.543Z" }, + { url = "https://files.pythonhosted.org/packages/89/0f/7fe4d4ef4e69f0033e012396ee2a115886bca7b10b7e45ce398626436bfc/xxhash-3.8.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4482380b462ca9e59994d072a877ecadd1cf51102daeeab2db696f96ab763723", size = 237659, upload-time = "2026-07-06T10:44:24.135Z" }, + { url = "https://files.pythonhosted.org/packages/38/8f/83e9e31d4ed57fe963b99cb5b13a23e3e0f0dad1885aa0ebd2a7819dd423/xxhash-3.8.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:950ac754d16daea42038f38e7465eb84cda4d08d7343c1c915771b29470f065a", size = 268737, upload-time = "2026-07-06T10:44:25.875Z" }, + { url = "https://files.pythonhosted.org/packages/57/79/7e7de46dbe5d1f49afc96a0bc42e6b8df24eae3d6bad6007b99e42f48430/xxhash-3.8.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0418ec8b2331b9d4d575fc9284427e8e69449d7172e99e1a86fcdd1f51a0a937", size = 224955, upload-time = "2026-07-06T10:44:27.777Z" }, + { url = "https://files.pythonhosted.org/packages/ec/34/b8540839e958d5ef5c6101af6f16032109e7099698ae8edbc8dcefe4d8f4/xxhash-3.8.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:32a94ad2763e0263d9102037d349002c3d3c401e42770542c3eeb4801f311661", size = 239653, upload-time = "2026-07-06T10:44:29.422Z" }, + { url = "https://files.pythonhosted.org/packages/ce/87/a735d05f7f859354acadabe470ff40e2c46672275f96dcf096a761904def/xxhash-3.8.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:89b11a5cdd441aa463f6d34ca0241602bc09b001a76994b6059828494108c673", size = 300213, upload-time = "2026-07-06T10:44:31.401Z" }, + { url = "https://files.pythonhosted.org/packages/98/31/3e1cb020237b68117fc212dc5f9753b87f865b4dfee7c1ce62d0836955b5/xxhash-3.8.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:09a204dd4bb0823daf938cdd0dc8057d5f1e14fe3cbde929424255f23f9de872", size = 442508, upload-time = "2026-07-06T10:44:33.023Z" }, + { url = "https://files.pythonhosted.org/packages/23/bf/f80090622141cc734b039ce1d15ce3ff6dced375e9680249bf5b9b8c6bf9/xxhash-3.8.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e710ad822c493fb80a4fbc1e3d0a807b1422cb90adbe64378f98291b7fa48fef", size = 216853, upload-time = "2026-07-06T10:44:34.983Z" }, + { url = "https://files.pythonhosted.org/packages/a6/a3/60157acecc307b238d3651c2483168e224b48b23a36ae6d6903588341d80/xxhash-3.8.1-cp311-cp311-win32.whl", hash = "sha256:5013be3bea7612852c62a7437f3302c1cfb91ca7e703b194459db0b2b2e0d792", size = 31936, upload-time = "2026-07-06T10:44:36.542Z" }, + { url = "https://files.pythonhosted.org/packages/59/5c/ef70c418d878d187b8da56d4cdc06aea6cf5e456b301e96e51e1d2cc8625/xxhash-3.8.1-cp311-cp311-win_amd64.whl", hash = "sha256:f377012b86c0a23a1df0cf5a1b05aa7187649e472f71c7892e5f2c2815bbe74f", size = 32724, upload-time = "2026-07-06T10:44:38.177Z" }, + { url = "https://files.pythonhosted.org/packages/2c/25/f008db952cec6b2a26445b456eeed2ebebd65e08e848ebe09ed6ac0634e6/xxhash-3.8.1-cp311-cp311-win_arm64.whl", hash = "sha256:836f11d4474d3228e9909d97216faa4f7505df41cfaf3927eb29809de785a78d", size = 29212, upload-time = "2026-07-06T10:44:39.577Z" }, + { url = "https://files.pythonhosted.org/packages/42/91/f65c34a7aa7b4e7cf4854f8e6ef3f7ee32ceac41d4f008da0780db0612f6/xxhash-3.8.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e6e49370822c1f4d8d90e678b06dbcb08b51a026a7c4b55479e7d467f2e813bc", size = 34680, upload-time = "2026-07-06T10:44:40.932Z" }, + { url = "https://files.pythonhosted.org/packages/57/04/b10a245a4c09a9cfa88f8e9ae755029413ad1ac17047f9a61906e5ae0799/xxhash-3.8.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:220d68130f83f7cc86d6edfdeab176adc73d7200bf3a8ec10c629e8cf605c215", size = 32397, upload-time = "2026-07-06T10:44:42.196Z" }, + { url = "https://files.pythonhosted.org/packages/3a/75/45ab795b5945b6388583bd75202106af505537935566c15a1577797a0e08/xxhash-3.8.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:4d365ee1892c1fa803536f8c6ce21d24b29c9718ec75eb856095c07830f8c478", size = 220549, upload-time = "2026-07-06T10:44:43.603Z" }, + { url = "https://files.pythonhosted.org/packages/13/44/5ba2bd0a14ddf4193fc7d8ec29625f659f22c06d60b28f04bf46305d8330/xxhash-3.8.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:852bfe059720632e2f16a6a4745e41d20937b2bf2a42a401e2412046bb6971cc", size = 241186, upload-time = "2026-07-06T10:44:45.534Z" }, + { url = "https://files.pythonhosted.org/packages/23/32/c4147def4d1e4538b906f82731e0ba23424377fc50a7cddd03cd284c8f63/xxhash-3.8.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2f8c25a7061d952de589bd0ea0eaadee32378ff83dd6a677b267f9cd86f401f8", size = 264852, upload-time = "2026-07-06T10:44:47.199Z" }, + { url = "https://files.pythonhosted.org/packages/6c/bd/71ed14f4f0318bb7fd7b2ec51999413487fa8da8d41208e84d50d1ef0f98/xxhash-3.8.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:868a8dcaff1a84ba78038e1cef14fc88ccf84d9b4d12ea604696e0693296aa56", size = 242663, upload-time = "2026-07-06T10:44:48.846Z" }, + { url = "https://files.pythonhosted.org/packages/91/09/70af22c565a8473b3f2ae73f88e7721af281bc4a575236dbd1970c9f76f6/xxhash-3.8.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6536d8677d2fff7e64cd0b98b976df9de7aee0e69590044c2af5f51b76b7a170", size = 473510, upload-time = "2026-07-06T10:44:50.695Z" }, + { url = "https://files.pythonhosted.org/packages/18/96/34db781c8f0cf99c544ca1f2bc2e5bf55426e1eb4ca6de8ea5da56a9f352/xxhash-3.8.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:82c0cedd280eab2e8291270e6c04894dbc096f8159a39dcf1807429f026ca3cc", size = 220469, upload-time = "2026-07-06T10:44:52.422Z" }, + { url = "https://files.pythonhosted.org/packages/93/5f/9a184f615fa5a4dce30c01534f62946ce5a11ce40f73785cbd356ccabaa9/xxhash-3.8.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:daa86e4b68221d38e669bb236ba112d0335353829fb627c82e5909e4bbe8694c", size = 310290, upload-time = "2026-07-06T10:44:54.142Z" }, + { url = "https://files.pythonhosted.org/packages/a9/dc/9b9a9789011ee153723a5eb9e7dd7fcbae2ba9b3fe7a729249ca7c252056/xxhash-3.8.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2bc7113e6f2b6b3922dd61796ca9f36af09da3773898e7003038dc992fc83b8d", size = 238173, upload-time = "2026-07-06T10:44:55.693Z" }, + { url = "https://files.pythonhosted.org/packages/ec/4d/71c6005ada9dcb608a4e1902e8475ecadb5f3fbfa04e1e244d276a2d0c43/xxhash-3.8.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5eed32dad81d6ba8e62dc7b9ffa0500199385d7810a8dd9d4eafaceb8c6e20bb", size = 269026, upload-time = "2026-07-06T10:44:57.424Z" }, + { url = "https://files.pythonhosted.org/packages/2f/87/d6c036ba25dfbd9c8633be5aa86fc9474bbb9e2c68212a841d090abe7344/xxhash-3.8.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:83697b0ea1f10e7f5d8b26a4906fa851393c61546c63839643a2b7fe2d868061", size = 224970, upload-time = "2026-07-06T10:44:59.085Z" }, + { url = "https://files.pythonhosted.org/packages/48/62/4c1f035a41c5752aa05e195b6c904c07b94fe9061a16de61e72a6e6b135f/xxhash-3.8.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:36fc69160465ae75c6ec4ac9f781bb2aa16ae7ff869e73c26fee85fbb11b9887", size = 240820, upload-time = "2026-07-06T10:45:00.746Z" }, + { url = "https://files.pythonhosted.org/packages/da/14/d39d565069b87e86d21a2af2a31d04db79249d25aa8d5b62959056a89857/xxhash-3.8.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:445e0f5a31f2f3546ae0895d4811e159518cdc9d824c11419898d40cfadb677e", size = 300619, upload-time = "2026-07-06T10:45:02.716Z" }, + { url = "https://files.pythonhosted.org/packages/13/22/75467acc887edc8cf71c97ab1708feb3df7a88bda589b9f399765c6387d2/xxhash-3.8.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:dfe0580fbfd5e4af87d0cc52d2044f155d55ebd8c8a93568758a2ea7d8e15975", size = 443267, upload-time = "2026-07-06T10:45:04.653Z" }, + { url = "https://files.pythonhosted.org/packages/a4/b6/1da3baa5fa6ef705e3425fddd382be7dfc4dfba2686df90a20f16e9c7b1b/xxhash-3.8.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:095e1323fa108be1292c54c86da3ef3c7a7dc015b105a52133973bc07a6ad11a", size = 217338, upload-time = "2026-07-06T10:45:06.304Z" }, + { url = "https://files.pythonhosted.org/packages/78/dd/b5295a9f97484e7a1c2b283a742ca45e3104991c55a1ef670dde161829ba/xxhash-3.8.1-cp312-cp312-win32.whl", hash = "sha256:bf28f55e427e0483acb1f666bd0d869b6d5e5a716680c216ad7befe3d4cfba2e", size = 31970, upload-time = "2026-07-06T10:45:07.823Z" }, + { url = "https://files.pythonhosted.org/packages/ec/31/3fa0b807d7e21515cd975e7fe5c039d52ac3e9401a96d6ad68dae6305215/xxhash-3.8.1-cp312-cp312-win_amd64.whl", hash = "sha256:2256e80e4960ee282f63428adb349cb7f8bd8efe4db770d88eb815f4b9860724", size = 32741, upload-time = "2026-07-06T10:45:09.42Z" }, + { url = "https://files.pythonhosted.org/packages/b8/05/86feada74e239600e6875aa507afb40482a89b92700aa74a92da83bdcb77/xxhash-3.8.1-cp312-cp312-win_arm64.whl", hash = "sha256:9df56e6df96a60590935e22373041cccc91fd55858763dcffb55bf63b3a2b396", size = 29234, upload-time = "2026-07-06T10:45:10.809Z" }, + { url = "https://files.pythonhosted.org/packages/6b/8c/446bb782cd0d27007a917b5569a08dd73219c3e8d6e459014db104b27bdb/xxhash-3.8.1-cp313-cp313-android_21_arm64_v8a.whl", hash = "sha256:3c682fcd96eb4bf64be32a4d95f96107e1588005831bd8a741b324fdda01b913", size = 38562, upload-time = "2026-07-06T10:45:12.425Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ec/c0c45627eaa6be7a5d6117423adf8f7a15b17ee74b4b17072cca5959a225/xxhash-3.8.1-cp313-cp313-android_21_x86_64.whl", hash = "sha256:036a024d8b9c01f70782e09ed98d532e76fd23f950ae7154bd950fe94e90ebec", size = 36656, upload-time = "2026-07-06T10:45:13.932Z" }, + { url = "https://files.pythonhosted.org/packages/f6/94/8324c04cc7597154caaeba6c094e01fbd2e7601d01e7a13eea9f5420e77b/xxhash-3.8.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d6a5c0bce213b23b0166fe0d35bcbbe23ce4b968f257cc7eb6fd57cb8e1e6297", size = 31169, upload-time = "2026-07-06T10:45:15.687Z" }, + { url = "https://files.pythonhosted.org/packages/40/a4/beb6bb26e1184e126dbe7a5682330214ef54dcfbf882078aa9f4b5428d42/xxhash-3.8.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:5177aa44eddaa97c6ef0cc00c6d540edb64d51781d2f8fb941612ec61a92c9ed", size = 32177, upload-time = "2026-07-06T10:45:17.035Z" }, + { url = "https://files.pythonhosted.org/packages/56/0f/fc4c92a5a528f839b34b6419b2e53c8597f2a629d5a1f5d721f65bfa1fd6/xxhash-3.8.1-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:7801b7223db017b9c0c9ccf37e44524edb35a1544a1c032add22c061c6af0276", size = 34642, upload-time = "2026-07-06T10:45:18.39Z" }, + { url = "https://files.pythonhosted.org/packages/d4/58/edbfb141d4000767ac6a9694f8ac0763e2c2e983e65c9e31620ba56e2667/xxhash-3.8.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9e80238259655bf69d7bcd08226a970d7f42605f3157786bfa76dd13472d7fa0", size = 34684, upload-time = "2026-07-06T10:45:20.033Z" }, + { url = "https://files.pythonhosted.org/packages/07/3f/5072f1f0f5714186f0ac2a0b5a4929ce30d4b845e94886b6c01b6ebda0be/xxhash-3.8.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bcab50a389cc04d87f90092af78a6adba2ab3deca63175a3344ca83514045315", size = 32401, upload-time = "2026-07-06T10:45:21.414Z" }, + { url = "https://files.pythonhosted.org/packages/49/c7/802ea2f9c2ed59219934d6d65c470d502b1788043eae277a52af8658bda6/xxhash-3.8.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a2489d3a776fa380cb8e71f54c7fda268a9baf3de9b1395093fd280f95735907", size = 220617, upload-time = "2026-07-06T10:45:23.234Z" }, + { url = "https://files.pythonhosted.org/packages/99/a8/e10488efd31fcb13fcd6acbc6e788f10c6f8e3a0cc4ae3eb89dc19c55a12/xxhash-3.8.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:32ab1e5432690276e71192be7401b55f96db2d0eedea5d44eb1f164505669cc0", size = 241295, upload-time = "2026-07-06T10:45:25.364Z" }, + { url = "https://files.pythonhosted.org/packages/18/cc/14180b17d44892a631f8ae7323c30bfbb1328efc8209e528a480293528ac/xxhash-3.8.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b30e01a0b97a4bc3f519a4d7a82da3dc53251fb0de5eeea8660dcd4ff094c0c2", size = 264688, upload-time = "2026-07-06T10:45:27.09Z" }, + { url = "https://files.pythonhosted.org/packages/a9/72/a14019d0c5f6c41ee407a503036ae32787c91325ca218a96a9b5627be651/xxhash-3.8.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1f44275ddb0978b67a58a951501903f04d49335a91f7681c9ce122ecb8ccb329", size = 242740, upload-time = "2026-07-06T10:45:28.753Z" }, + { url = "https://files.pythonhosted.org/packages/68/08/92550e556c6fcfcb96c6a336945eb53a431ed43120ed749636debb16c5cf/xxhash-3.8.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e3b87cbd974512c0c5fc7b469c36b2cdc9ee6d76e4ec78bccb2c7184611c49b0", size = 473599, upload-time = "2026-07-06T10:45:30.524Z" }, + { url = "https://files.pythonhosted.org/packages/29/83/e361d3c1acd1b21e1d489616de6fa4aaf843365d8179f612e3743eac20a9/xxhash-3.8.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:98ee81b4b7f3023c9cb04a78cc67610baffcb5812d92f2096cb5a5efc6f19437", size = 220559, upload-time = "2026-07-06T10:45:32.979Z" }, + { url = "https://files.pythonhosted.org/packages/05/01/006a4243c2c2a6831827f9999f6d1c23feeef100eb023c1f886022a00bf3/xxhash-3.8.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2666f059a1588a99267e33605365ed89cea92f424b3522806a9f4bd8ad2e3d62", size = 310383, upload-time = "2026-07-06T10:45:35.875Z" }, + { url = "https://files.pythonhosted.org/packages/d8/20/af388e8bf9f9a0f89eeef7d2a1935d176ee1c20bc6adeda05035879379cf/xxhash-3.8.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0093cf7eeb91b84776e8742113afa4bdf47533d36cf719179aaaf1f56f6f8bf", size = 238228, upload-time = "2026-07-06T10:45:38.02Z" }, + { url = "https://files.pythonhosted.org/packages/63/6b/4666579a87eebd1744663c404297355fa0658617b015cedfa58810ee7036/xxhash-3.8.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:3a800912a2e5e975d4128969d645c4a2a80aa886ccd6c9b1c6f44529e327e8cf", size = 269137, upload-time = "2026-07-06T10:45:39.954Z" }, + { url = "https://files.pythonhosted.org/packages/de/d3/e963a8a46f900a137d91b02144d8ea07a8f812971b138204a3b2f8b8e55c/xxhash-3.8.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0fe37f72a207223d22a4eddc3149d4298993385aa9daef25c039246ca5a309f3", size = 225068, upload-time = "2026-07-06T10:45:41.718Z" }, + { url = "https://files.pythonhosted.org/packages/aa/80/9d181dbcde4b0fe48375f48833a5832d4b8cd2b349b15110c92ee472d874/xxhash-3.8.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5db43f249b4be9f99ef4b967863f37094fb40e67effafb78ba4f0356b6396104", size = 240874, upload-time = "2026-07-06T10:45:43.414Z" }, + { url = "https://files.pythonhosted.org/packages/39/15/ce3ab5a1cd27ead25a5196e55a7284220f6ad6e316da494ffd900b2b600f/xxhash-3.8.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c4ed42965c2cd9081f011be22f69d0e65d3b6165fe7734072fd0c232840bbd4e", size = 300702, upload-time = "2026-07-06T10:45:45.135Z" }, + { url = "https://files.pythonhosted.org/packages/96/c0/2281a8ab5f2a62dbf57a23c58a01ccc1d98abf40f71193c8a81f59e759b5/xxhash-3.8.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:3557bec8fcb11738a8920eeb68974bc76b75262f6947998d3147954ce0a4b893", size = 443351, upload-time = "2026-07-06T10:45:47.188Z" }, + { url = "https://files.pythonhosted.org/packages/81/2e/071a58c1a53a52d4f7a3aa0987be0c396dffd40da8204805fe1b130a81f4/xxhash-3.8.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:00de40f3b42240db23a82a5c682b55d7263d84a26a953240c1aee463409660e3", size = 217396, upload-time = "2026-07-06T10:45:48.925Z" }, + { url = "https://files.pythonhosted.org/packages/68/44/36ab58134badd9d3433fc7b53c4ca8d113d8e807782885628640f8297a4d/xxhash-3.8.1-cp313-cp313-win32.whl", hash = "sha256:b5196cc2574cfec572a5f3fb7cfa5ade27305ae3d06516a082132441aff4c83a", size = 31974, upload-time = "2026-07-06T10:45:50.591Z" }, + { url = "https://files.pythonhosted.org/packages/96/2a/2a0b84798448e766f7b89ceed073cb0cb5a43fc9ebbacbdea74a38de18e3/xxhash-3.8.1-cp313-cp313-win_amd64.whl", hash = "sha256:538f5f865df6cd8c32dd63158a0e5b4f5dd08d732a7da8b7228a5a0776c8ce55", size = 32739, upload-time = "2026-07-06T10:45:52.221Z" }, + { url = "https://files.pythonhosted.org/packages/d4/60/bb51dbf7c363ff88a7cbd50b7959718219577ef44d7cf255929ffc4a2194/xxhash-3.8.1-cp313-cp313-win_arm64.whl", hash = "sha256:a6617f30641ba0d8baa1635fbefb1dffc5165ec36d26921bd5cee13497cd937a", size = 29239, upload-time = "2026-07-06T10:45:53.714Z" }, + { url = "https://files.pythonhosted.org/packages/56/d3/827ca123c2ee5443a6aaed3c5dd199237dc2f010e2bebd7ec09ef36f3a5f/xxhash-3.8.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:bfcd82852c62a60e314670a9602de354c4460f8adad916e2e42a20860c7870bc", size = 34964, upload-time = "2026-07-06T10:45:55.535Z" }, + { url = "https://files.pythonhosted.org/packages/05/67/67ae2a3ccdeb8b8ef025d35aee9edd1d26c3abe5051d47da9286232afbf8/xxhash-3.8.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:08ea2081f5e88615fec8622a9f87fbe21b8ea58d88cfc02163ca11026ee62a92", size = 32697, upload-time = "2026-07-06T10:45:57.288Z" }, + { url = "https://files.pythonhosted.org/packages/38/5a/3d3994346e1f45493679cb5c1ffc2bf454e410e9d1e8a662d253becee91e/xxhash-3.8.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:2e32855b6f9e5b18f449e59d45e3d5778bdeb660632ef2693cca267a11246c75", size = 225954, upload-time = "2026-07-06T10:45:58.897Z" }, + { url = "https://files.pythonhosted.org/packages/3f/2c/53169270309b7cd8e05504e07fe123bac053b89d00ac63617faacf0a2ec0/xxhash-3.8.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a6e088bd7870775624256a0d84c2a6714afd223b2eeb56b0ca58398e52a32fda", size = 249776, upload-time = "2026-07-06T10:46:00.977Z" }, + { url = "https://files.pythonhosted.org/packages/70/e0/5c551d8d592f944506f7c5185e210255c15e672a3c6008c156a1bd9b775e/xxhash-3.8.1-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:72eb5ae575cc7ae2b23f6f8064a8b10f638c7149819ae9cc6d20ebd4d37a1629", size = 274776, upload-time = "2026-07-06T10:46:02.869Z" }, + { url = "https://files.pythonhosted.org/packages/a0/2a/d3a762270cee2d7bcd0e25e28c623e5f3f5c0dc637b66e3e47dd5b0bb3f0/xxhash-3.8.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d0b48cdf690a64cedf7258c3dc9506cc41fc86edd7739c40e3098952265dc068", size = 252056, upload-time = "2026-07-06T10:46:04.688Z" }, + { url = "https://files.pythonhosted.org/packages/c1/8f/b78e4373b2cb6d1c42af60ea2d7e9146ad0710b239ac7f706d5d31d5bb98/xxhash-3.8.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fb9e256a357dfcede7818c6d34e70db2d6b664394803d1de4b6984d2de76c0f1", size = 482108, upload-time = "2026-07-06T10:46:06.498Z" }, + { url = "https://files.pythonhosted.org/packages/e6/0d/642d923336ea61a15f8ce64fc7e078729e6e06c3a026e517fa79b2c23b7a/xxhash-3.8.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:51f71a6e2ad071e70c937e41fcb6c19f82c3f9f49831eba850ed4a106ffbb647", size = 226739, upload-time = "2026-07-06T10:46:08.598Z" }, + { url = "https://files.pythonhosted.org/packages/a6/0a/a37d6da6427d45a8d23e3ee3a0ca9c9d4a90364849c6637fe2963a755f9b/xxhash-3.8.1-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e4a6443968c4e8dc69967e12776776a5952c119cc1bd94168ad1c5ad667c2be1", size = 319658, upload-time = "2026-07-06T10:46:10.504Z" }, + { url = "https://files.pythonhosted.org/packages/4a/51/ebbd40da8a3f1bc53b4b7a9a87f8e28bd95c5f21bc14b8a57860cf367d1b/xxhash-3.8.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:714503083a1f2065c9ad15340dd49ac8a8e948a505a705ffa1750cb951519113", size = 246059, upload-time = "2026-07-06T10:46:12.634Z" }, + { url = "https://files.pythonhosted.org/packages/24/4c/d9014030147e1f0bb26e7da47aa240dd9ec61c763c573e558111d869f8e1/xxhash-3.8.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:77f74e45a1e5574bbbf80181c8027b3a4c65c2248fffbd557bd596fff13102f9", size = 275535, upload-time = "2026-07-06T10:46:14.614Z" }, + { url = "https://files.pythonhosted.org/packages/84/86/caee2db41fadcd5a25aa4323213f9afec5a8586d4e419241e3d659362bd7/xxhash-3.8.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:4e0e1b0fb0259c1b75d1251ac0bb4d7ab675d36f7a6bf4ba6aa630dae94f9ffa", size = 231292, upload-time = "2026-07-06T10:46:16.452Z" }, + { url = "https://files.pythonhosted.org/packages/0b/60/f52f08bcdc904c4514ea5c25caa19e9f3214144434a6ff96dc82dc1cbddd/xxhash-3.8.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:10e4393ec33633c2f05ad01869e546ad080b1a18f2650503731f153774608b31", size = 250490, upload-time = "2026-07-06T10:46:18.318Z" }, + { url = "https://files.pythonhosted.org/packages/24/a0/94dc7ae310838f250669c6ad7168e6d6fca17d49dac1053f06dc232c4a56/xxhash-3.8.1-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:b3ba794c3d885803db6c3116686923f1ec13bc86e621e169a375282b63ea1cc6", size = 309861, upload-time = "2026-07-06T10:46:20.503Z" }, + { url = "https://files.pythonhosted.org/packages/8b/f9/adeead7d0eb28cdfc2832544ea639ffbc6749ccde47a8e228d667459182e/xxhash-3.8.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:57189a69c0891e4818853feaa521c972d22c880a001453addea015f48e3c3398", size = 448739, upload-time = "2026-07-06T10:46:22.79Z" }, + { url = "https://files.pythonhosted.org/packages/04/a4/22ec0e07db57d901c9298ae98aa3cf2be45bafded6f07c13131e85b89032/xxhash-3.8.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d59e71153fe9ff85648d00e18649b07e9b22c797291abb7e27274fa06df8b838", size = 223657, upload-time = "2026-07-06T10:46:24.831Z" }, + { url = "https://files.pythonhosted.org/packages/94/32/8a9531f37b59e5a013003db7cb7414baf4ce7e0e1268e0d5947cd3d6a2df/xxhash-3.8.1-cp313-cp313t-win32.whl", hash = "sha256:5b96f0024e9840f449bd91b2d005c921a4b666055a0d1b6492463799f32aae22", size = 32377, upload-time = "2026-07-06T10:46:26.86Z" }, + { url = "https://files.pythonhosted.org/packages/e7/ab/2ca45fd7f671de5f81fc297ef1c95080b40c86ec6be0cc6034b8f7707ac8/xxhash-3.8.1-cp313-cp313t-win_amd64.whl", hash = "sha256:37d5a56c36dcc0b9a87b814cd992598d33863ff683749de6c86081f278d5e629", size = 33274, upload-time = "2026-07-06T10:46:28.39Z" }, + { url = "https://files.pythonhosted.org/packages/5a/54/20d7163463ddb6438b73a427d1655a77a502cf9b9b0c3ada3599629d9c0a/xxhash-3.8.1-cp313-cp313t-win_arm64.whl", hash = "sha256:6696c8752aded28ff3b16f33ef28ce28fb5d209b80c206746f943199fcf5fd65", size = 29375, upload-time = "2026-07-06T10:46:29.962Z" }, + { url = "https://files.pythonhosted.org/packages/c2/8b/df2ba04f22a6cd6b39f96a6577329a8471a55c90ef8d8e2f7c102363613f/xxhash-3.8.1-cp314-cp314-android_24_arm64_v8a.whl", hash = "sha256:9db455cb649dcfe4504d6d68a6d83a7315a99a3ca59871dc3ff840671f99adba", size = 38430, upload-time = "2026-07-06T10:46:31.496Z" }, + { url = "https://files.pythonhosted.org/packages/b2/4f/6a059e8ad3ca8deedc91dfe335b211204900895152212c03ebbe721de68b/xxhash-3.8.1-cp314-cp314-android_24_x86_64.whl", hash = "sha256:affb37f152e55b5e4494bb9d0107f7bb08515c6704fbed82d9f61214d74adc17", size = 36558, upload-time = "2026-07-06T10:46:33.078Z" }, + { url = "https://files.pythonhosted.org/packages/cb/95/40be178205acce092ae418feb20ac737b32a02c7b864926ed0717354c9f8/xxhash-3.8.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:460261045936975193bfd20549a0de1cd52a33b405cbb972f0d80940c42266cd", size = 31181, upload-time = "2026-07-06T10:46:34.793Z" }, + { url = "https://files.pythonhosted.org/packages/3f/89/2da4dbf051bafa156c0e3f12012db2b0ac3b84ff37ca1f021f6bfffcdfbb/xxhash-3.8.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:38c887aedb696ef8bca19983206d270848558cfae4a91afa6a2fb05dde58ffc5", size = 32192, upload-time = "2026-07-06T10:46:36.393Z" }, + { url = "https://files.pythonhosted.org/packages/7c/4e/e000bbae3566bc8e0be771a8a0f294aa99075e3f0bc4ef43922ebffdebc8/xxhash-3.8.1-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:594131ce1aad18db3689781f806db1b065cdaa04f4df36b4c038d2013aefd0bf", size = 34691, upload-time = "2026-07-06T10:46:38.1Z" }, + { url = "https://files.pythonhosted.org/packages/b4/4a/ea954aacc7d1c8711880ac2b55da94429a9b4296b151c4fc0966549ca1ee/xxhash-3.8.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:78c794b643d214f1522e7a288bcf5a2de120d26cd170516749a4009dc92722c9", size = 34807, upload-time = "2026-07-06T10:46:39.647Z" }, + { url = "https://files.pythonhosted.org/packages/ca/29/df598e738ff37558ac627264deb2e560902d9bf7f46d3bd5175c9eee593e/xxhash-3.8.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:af0c9fedc4a2c24e8664953882fe8185f3790b8338c9c700f76f5ad660817711", size = 32410, upload-time = "2026-07-06T10:46:41.359Z" }, + { url = "https://files.pythonhosted.org/packages/59/9c/81ab40e7d33ada0b3df5d1bc884894d15dbf4f805cd645b685e4606bb8e0/xxhash-3.8.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:115772daeb71b2f3b9381177017f53e6cf3f3439c840737fdabd21aba6e54920", size = 220564, upload-time = "2026-07-06T10:46:43.463Z" }, + { url = "https://files.pythonhosted.org/packages/fd/6f/62ae6f5c8606320a0e2a41c2dc8c6d91cc5d63d0f84dd9582e9543779dd8/xxhash-3.8.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:000435984a0469b0f822fe76f35bddea0f96a4d6521b3339a60a6428cdee1edc", size = 241462, upload-time = "2026-07-06T10:46:45.509Z" }, + { url = "https://files.pythonhosted.org/packages/15/a1/9c3a0ec6cb524396f551eddd102a76690a795494eb9784fc67542b0daa37/xxhash-3.8.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2f1c68394818e0595569c2ff3cbc1e6d5a36a434e796f5c526b987b80c8a8c62", size = 264491, upload-time = "2026-07-06T10:46:47.655Z" }, + { url = "https://files.pythonhosted.org/packages/64/f2/700a4674e4308eb59d2fdb973977e82eae231bea5044753fee5c9eec0e0c/xxhash-3.8.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:46b39976d008e2a845758650f0ff7136bca004f40da0c8798bd37ac37860154f", size = 242905, upload-time = "2026-07-06T10:46:49.857Z" }, + { url = "https://files.pythonhosted.org/packages/f3/8a/72d9874375c8d4cbc64a8cd1d659d5695a8765c3db82efa82dc5bd9f14d0/xxhash-3.8.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d5006c65ec507a333479e76e00e2c368781f16c24ededa764763956b32a0e93e", size = 473873, upload-time = "2026-07-06T10:46:51.953Z" }, + { url = "https://files.pythonhosted.org/packages/03/f0/6db07590ed7e0a77f186ef0bcea8d52553bf1ba57833e09467a2411f0f2d/xxhash-3.8.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c31a2649bcf1fe97cf11c79848d761df33ac46b3896942d31b640557b486ff6b", size = 220765, upload-time = "2026-07-06T10:46:55.41Z" }, + { url = "https://files.pythonhosted.org/packages/8f/10/00d12d8b8beabbf49a8bbc626fb9f40445145a8887eb41a6acfb69149ac4/xxhash-3.8.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8f759eed402448c2bdbb492e4fba1f20668ffe29688605ea61f0f67f9e4e386d", size = 310478, upload-time = "2026-07-06T10:46:57.729Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f9/12a82394eefb0f185d15a7f7b9f627c61c475a72dd83718436a5b84b42ac/xxhash-3.8.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7b5f97ecfede10d5b2870383620e2d25c8561e217c7bf9081073802b54248d2b", size = 238393, upload-time = "2026-07-06T10:46:59.87Z" }, + { url = "https://files.pythonhosted.org/packages/20/f3/53f963e320b9ce678337aa7273f39ce692ded8b99e3d22a866ec722159ab/xxhash-3.8.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:1da930bbcac3e8fbe2191850e2abb57977a99348c12c4b385e1058ac1b0a9ecc", size = 268704, upload-time = "2026-07-06T10:47:01.806Z" }, + { url = "https://files.pythonhosted.org/packages/0a/50/5b5badbd87c82d9f9b5f58ac74a3f29ef08f6fc387b324b8fd482450b862/xxhash-3.8.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:747476436f6891b9773374ce8d48edcc8b12cb5b61b67c6fb6289633747d088f", size = 225015, upload-time = "2026-07-06T10:47:03.784Z" }, + { url = "https://files.pythonhosted.org/packages/30/93/3ca68265afe7b4e69435e08a7b6a1d9d0f2a071e889da1f8041ed00fe878/xxhash-3.8.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:4ef09bbc2519a93cd0f95f2ceb5f7b85919dffea643278e02362bf40e3c4bed1", size = 240951, upload-time = "2026-07-06T10:47:05.816Z" }, + { url = "https://files.pythonhosted.org/packages/dd/a6/27e19670c40f46b5e76e11f2f4713d21054804568425d870670e757172ad/xxhash-3.8.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:a5eed9d41995a83f3332b4e3396abb7f433cac584222bd7e305b606d8353861e", size = 300751, upload-time = "2026-07-06T10:47:07.95Z" }, + { url = "https://files.pythonhosted.org/packages/bc/fb/b33e27689959fe7ed2ae0b830af41560d65213943983afa9db3a8d481bce/xxhash-3.8.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:53f3ed9118397074ff63a79b66b7fec1c84c782eecde35c5bc94e420a971c231", size = 443480, upload-time = "2026-07-06T10:47:10Z" }, + { url = "https://files.pythonhosted.org/packages/26/60/0e0d973be5fe280753ef02fbc89349492ad6e903bf1dcb870b668f94b662/xxhash-3.8.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d247b34bf433c92b41689318fd25d246313cab2275a6a47e2efac178b80d6efe", size = 217657, upload-time = "2026-07-06T10:47:12.196Z" }, + { url = "https://files.pythonhosted.org/packages/ad/68/c9e3ecef4a9a417d464cb5bd200aa12f73192dee677901b9e08e0ad0d1bb/xxhash-3.8.1-cp314-cp314-win32.whl", hash = "sha256:d58ce8b6cfa9c4d2f230557f69caf7c06369e318015d0b19485095bc2c5963ab", size = 32690, upload-time = "2026-07-06T10:47:14.204Z" }, + { url = "https://files.pythonhosted.org/packages/d7/99/e9e44588c0b62837bbec5ba7927816de0afa03406b1a0b6c7a7e1d1a30a0/xxhash-3.8.1-cp314-cp314-win_amd64.whl", hash = "sha256:6cee733fe4ccb1737e0997135283c82341e5cfa9cf214b165f9087fb663aaf4f", size = 33460, upload-time = "2026-07-06T10:47:16.021Z" }, + { url = "https://files.pythonhosted.org/packages/45/2b/64f36d86380b3657ad9031967ab814f3ef31307174650853f69c18932ebc/xxhash-3.8.1-cp314-cp314-win_arm64.whl", hash = "sha256:58346024d47e84f7d8b3e7f5d6faa1d58acbbe49a8771497872059f58c1d8ea5", size = 30092, upload-time = "2026-07-06T10:47:17.81Z" }, + { url = "https://files.pythonhosted.org/packages/92/cb/18b64bff88c58a0ca209dc533e63cf02d7ae5aa6b1b9a9fd14e81b5dbd60/xxhash-3.8.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:01cab782f8a0a05ecad2c63d7ef10f7ab475f660e0d6419d069418c14d88de7c", size = 35024, upload-time = "2026-07-06T10:47:19.821Z" }, + { url = "https://files.pythonhosted.org/packages/af/1d/72d8a70520e5dcddb472ea0486d299da3240745a10658290cd7b5690ede2/xxhash-3.8.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:717b12fdc51819833704e85e6926d76981ffa3f780ef92e33ebb8b26d46bb230", size = 32697, upload-time = "2026-07-06T10:47:21.649Z" }, + { url = "https://files.pythonhosted.org/packages/9c/b8/e041f555903c56db3d0a731b3d72a6575d75e0ed868b1bd2e5176111ca44/xxhash-3.8.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ec55d80e9b8a519d742669e0b49e8ce9e6747be42bf3c138158b6543a9c8e489", size = 226044, upload-time = "2026-07-06T10:47:23.612Z" }, + { url = "https://files.pythonhosted.org/packages/3a/7e/5cdcf06bf6ec4b5d2ac073feb23432ec1d603fd438864cbd2c09c7cb45e1/xxhash-3.8.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98d8ac1129b4dd39098cffed94d1284aceb61c3aa396757ccc736ac392e4cee5", size = 249899, upload-time = "2026-07-06T10:47:25.812Z" }, + { url = "https://files.pythonhosted.org/packages/c0/c0/eb7e059cb5e1dba11fd30d2fdf882f56e5a417a3eaa43669d43623767f45/xxhash-3.8.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3bc0fa90830df1e1277f33cc6e55de9990b83c0319fd8c7412866cfde38b025e", size = 274892, upload-time = "2026-07-06T10:47:27.931Z" }, + { url = "https://files.pythonhosted.org/packages/66/74/a600aaf7cd39957fd1510adeedb1749c1e7eb82bd632a1153d9c664c3135/xxhash-3.8.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c73b6f652f0745425aa6378319c331293b5341756262e9408ed3d45f183375e6", size = 252243, upload-time = "2026-07-06T10:47:30.288Z" }, + { url = "https://files.pythonhosted.org/packages/ad/04/78d88fa75a6763e5d09bf1b947a392a27988903381b219006f92f3c68fc8/xxhash-3.8.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f6114692261eff4266386cdec0f7d87eee24e317ab397c218b7ae6a76b4c6339", size = 482191, upload-time = "2026-07-06T10:47:32.45Z" }, + { url = "https://files.pythonhosted.org/packages/7f/06/07a8aea1108d682de8791ce608cdf367d75ff4e7e57cd3c154bdc6f47b23/xxhash-3.8.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4df57c0b161ec1b3ed0526a67b0db0914b557e86ee8aae51887aec941b261542", size = 226877, upload-time = "2026-07-06T10:47:34.705Z" }, + { url = "https://files.pythonhosted.org/packages/ed/b5/86bade5618a524d2c06c4041aa2fe8e5749ce16e88afba60d67c1684a21f/xxhash-3.8.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9043877a917be88ccf230aa5667c1bd059bce80f4c2727e4defa1b29b7f48b08", size = 319794, upload-time = "2026-07-06T10:47:37.08Z" }, + { url = "https://files.pythonhosted.org/packages/23/69/9b1a2b89b1621bb740fbcb7beb512f60f99480c1bdc680c0c90e1f56ff75/xxhash-3.8.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:559e3cabe522231909f9de98ef06929edbd53782046bd21aae0c72db6f2a0775", size = 246202, upload-time = "2026-07-06T10:47:39.676Z" }, + { url = "https://files.pythonhosted.org/packages/08/ea/662ed6cb49f1d34078b6a3a3e0f3d29ff93fd7b5a03c0bc9ecfd9b2159c3/xxhash-3.8.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:264710bd335016f303763ce1275c6486df30bb57c2245c91b224c983d7ac39b8", size = 275628, upload-time = "2026-07-06T10:47:41.99Z" }, + { url = "https://files.pythonhosted.org/packages/13/f5/49fc9e4c6728a5a3bd8fe639199d2fa67609b3a84f938aff6e8568dd3e4f/xxhash-3.8.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:e14800b9b10bb39d7a60ad4a310e403164d7b8988a27ae933d4e40618a44088e", size = 231390, upload-time = "2026-07-06T10:47:44.233Z" }, + { url = "https://files.pythonhosted.org/packages/64/9d/3acaf8f599c0e0b30e910a3a11ba32929da53c86dc73c7c55fe6a010b4e9/xxhash-3.8.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:ea6a3e734b0fd41b82784a400be946821900daebe610c050a5e0760838a34f99", size = 250600, upload-time = "2026-07-06T10:47:47.611Z" }, + { url = "https://files.pythonhosted.org/packages/23/64/8acab4c5ec60dbe664b5b9858fd44c2413b07e535b09556a0a5022e78aa6/xxhash-3.8.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:cf399fac542a1c7a4734a435b93df2c55e858c7d31abf6c1bdf46f9ae67fbfd0", size = 310032, upload-time = "2026-07-06T10:47:49.88Z" }, + { url = "https://files.pythonhosted.org/packages/56/47/a0288d7329b1fe63e2734a32d19d444a96ae2b4810f545bc61e561224917/xxhash-3.8.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:44c89d915a75c11d2547eaee9098fcd80398987c4bff2974a0497a925bf92c07", size = 448882, upload-time = "2026-07-06T10:47:52.631Z" }, + { url = "https://files.pythonhosted.org/packages/01/e7/3071dfd3beb5c38204ce1cf56bf7749fce08de900fa92714b81d1d8ca1f2/xxhash-3.8.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:358650d5bda9c635da699c53adf4e8134af492ecc79c960f917eebf088bb6799", size = 223728, upload-time = "2026-07-06T10:47:55.093Z" }, + { url = "https://files.pythonhosted.org/packages/12/11/b99949f0ba2b07e9f9ffe83b9c86faa685f9080725dc21a916a607313be5/xxhash-3.8.1-cp314-cp314t-win32.whl", hash = "sha256:c240939e963653054fc7e4a17c382829cda4aa88a7daf0af841715dbded1b497", size = 33150, upload-time = "2026-07-06T10:47:57.274Z" }, + { url = "https://files.pythonhosted.org/packages/54/1c/09703eb341f8416e74e58d6c6732d4b5c46de59c942363203cb237cc95b0/xxhash-3.8.1-cp314-cp314t-win_amd64.whl", hash = "sha256:7258ee276e8772599bc19e14b36f6260306e21b637190cd7cb489a2449d48684", size = 34005, upload-time = "2026-07-06T10:47:59.434Z" }, + { url = "https://files.pythonhosted.org/packages/d6/f9/6ed7251bb6a8af10ac73b1821c60583d2826e5b2064e45a979c935287c98/xxhash-3.8.1-cp314-cp314t-win_arm64.whl", hash = "sha256:8f454166c2ffed45636c8d501741e649851ba2f346c4eb73a64c07ac00428f20", size = 30239, upload-time = "2026-07-06T10:48:01.874Z" }, + { url = "https://files.pythonhosted.org/packages/99/e4/4d8040435aeac814fc69ba63621565fbeb19229a138e2568324a26b2a45c/xxhash-3.8.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:39c9d5b61508b0bb68f29e54546de0ed2a74943c6a18585535a7e37356f1dd12", size = 32687, upload-time = "2026-07-06T10:49:42.803Z" }, + { url = "https://files.pythonhosted.org/packages/da/6a/975f1f2318c760e5bcec109ed379713ae645d8d856c2a3b9ec5d26857087/xxhash-3.8.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:83b9130b80b216d56fdf9e87131946b353c9627930c061955a101ea82b09fed9", size = 29879, upload-time = "2026-07-06T10:49:45.172Z" }, + { url = "https://files.pythonhosted.org/packages/08/0b/40a2a55ff52cf635bfdc5eae67a772bec85b4f44c6c737f73f6f528d51d1/xxhash-3.8.1-pp311-pypy311_pp73-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8304be0982130954b7fd3aad18e2c6f8ee40254bc3d2e635991c16d77c91e2bd", size = 43246, upload-time = "2026-07-06T10:49:47.905Z" }, + { url = "https://files.pythonhosted.org/packages/9c/6d/56ed2b6b200f26fb474f3fd387d95d0601efcd5bb33430c90c68924bdd77/xxhash-3.8.1-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4b512261801b1e5fde7b6ebf2fef7977339c620cbbca88a0040ad9ad134f4d02", size = 38202, upload-time = "2026-07-06T10:49:50.59Z" }, + { url = "https://files.pythonhosted.org/packages/0d/a3/56864d895d1161a9f17502088e9c1fb7c06bde2c2efdde620d22bb7a9c43/xxhash-3.8.1-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:49aa8692507835dcc1e8ad8021f20c74c2dc13d83b5112e87877faa2a0035b20", size = 34448, upload-time = "2026-07-06T10:49:53.242Z" }, + { url = "https://files.pythonhosted.org/packages/6b/57/5c6e0908a47f61dca96d01c8ee6fce01ed1050611eb779083ba8758fed81/xxhash-3.8.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:345b07b78e2bf583d71682aa34ae5b5fab575f7a1cb31e10263ebbc6f89f8c42", size = 32869, upload-time = "2026-07-06T10:49:55.972Z" }, ] [[package]] name = "zipp" -version = "3.23.1" +version = "4.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/30/21/093488dfc7cc8964ded15ab726fad40f25fd3d788fd741cc1c5a17d78ee8/zipp-3.23.1.tar.gz", hash = "sha256:32120e378d32cd9714ad503c1d024619063ec28aad2248dc6672ad13edfa5110", size = 25965, upload-time = "2026-04-13T23:21:46.6Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b9/d8/eab98a517c14134c0b2eb4e2387bc5f457334293ec5d2dd3857ec2966802/zipp-4.1.0.tar.gz", hash = "sha256:4cb57381f544315db7688e976e922a2b18cdb513d21cc194eb42232ba2a3e602", size = 26214, upload-time = "2026-05-18T20:08:57.967Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/08/8a/0861bec20485572fbddf3dfba2910e38fe249796cb73ecdeb74e07eeb8d3/zipp-3.23.1-py3-none-any.whl", hash = "sha256:0b3596c50a5c700c9cb40ba8d86d9f2cc4807e9bedb06bcdf7fac85633e444dc", size = 10378, upload-time = "2026-04-13T23:21:45.386Z" }, + { url = "https://files.pythonhosted.org/packages/3a/13/547360d81e6d88d58492968ffda9f9542854f11310ee556fef14260cc886/zipp-4.1.0-py3-none-any.whl", hash = "sha256:25ad4e16390cd314347dd8f1de67a2ac538ae658ed4ab9db16029c07c188e97f", size = 10238, upload-time = "2026-05-18T20:08:57.045Z" }, ] [[package]]