Python: Fix Python pyright package scoping and typing remediation (#4426)

* Fix Python pyright package scoping and typing remediation

Implements issue #4407 by removing the root pyright include, adding package-level pyright includes, and resolving pyright/mypy typing issues across Python packages. Also cleans unnecessary casts and applies line-level, rule-specific ignores where external libraries are too dynamic.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Reduce pyright cost in handoff cloning

Simplify cloned_options construction in HandoffAgentExecutor to avoid expensive TypedDict narrowing/inference in _handoff.py, which was causing pyright to spend a long time in orchestrations.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix types

* Fix lint and type-check regressions

Resolve current Python package check failures across lint, pyright, and mypy after recent code changes, including purview/declarative pyright issues and multiple ruff simplification findings.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fixed hooks

* Stabilize package tests and test tasks

Resolve cross-package non-integration test failures, simplify streaming type flow, harden locale/culture handling, and standardize package test poe tasks to exclude integration tests where applicable.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* lots of small fixes

* Fix current Python test regressions

Address current failing unit tests in azure-ai, bedrock, and azure-cosmos while keeping Bedrock parsing logic inline (no new static helper methods).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* small fixes

* small fixes

* removed pydantic from json

* final updates

* fix core

* fix tests

* fix obser

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Eduard van Valkenburg
2026-03-05 16:32:24 +01:00
committed by GitHub
Unverified
parent 4a043c6c66
commit 55ddd841b7
122 changed files with 2328 additions and 2407 deletions
@@ -12,7 +12,7 @@ import json
import sys
from functools import reduce
from operator import and_
from typing import TYPE_CHECKING, Any, ClassVar, Literal, cast
from typing import TYPE_CHECKING, Any, ClassVar, Literal
import numpy as np
from agent_framework import Message
@@ -107,9 +107,10 @@ class RedisContextProvider(BaseContextProvider):
self._token_escaper: TokenEscaper = TokenEscaper()
self._index_initialized: bool = False
self._schema_dict: dict[str, Any] | None = None
self.redis_index = redis_index or AsyncSearchIndex.from_dict(
index = redis_index or AsyncSearchIndex.from_dict( # pyright: ignore[reportUnknownMemberType]
self.schema_dict, redis_url=self.redis_url, validate_on_load=True
)
self.redis_index: Any = index
# -- Hooks pattern ---------------------------------------------------------
@@ -189,7 +190,7 @@ class RedisContextProvider(BaseContextProvider):
def _build_filter_from_dict(self, filters: dict[str, str | None]) -> Any | None:
"""Builds a combined filter expression from simple equality tags."""
parts = [Tag(k) == v for k, v in filters.items() if v]
parts: list[FilterExpression] = [Tag(k) == v for k, v in filters.items() if v]
return reduce(and_, parts) if parts else None
def _build_schema_dict(
@@ -278,7 +279,9 @@ class RedisContextProvider(BaseContextProvider):
sig["fields"][name] = {"type": ftype}
return sig
existing_index = await AsyncSearchIndex.from_existing(self.index_name, redis_url=self.redis_url)
existing_index: Any = await AsyncSearchIndex.from_existing( # pyright: ignore[reportUnknownMemberType]
self.index_name, redis_url=self.redis_url
)
existing_schema = existing_index.schema.to_dict()
current_schema = self.schema_dict
existing_sig = _schema_signature(existing_schema)
@@ -319,7 +322,9 @@ class RedisContextProvider(BaseContextProvider):
if self.redis_vectorizer and self.vector_field_name:
text_list = [d["content"] for d in prepared]
embeddings = await self.redis_vectorizer.aembed_many(text_list, batch_size=len(text_list))
embeddings = await self.redis_vectorizer.aembed_many( # pyright: ignore[reportUnknownMemberType]
text_list, batch_size=len(text_list)
)
for i, d in enumerate(prepared):
vec = np.asarray(embeddings[i], dtype=np.float32).tobytes()
field_name: str = self.vector_field_name
@@ -365,7 +370,7 @@ class RedisContextProvider(BaseContextProvider):
try:
if self.redis_vectorizer and self.vector_field_name:
vector = await self.redis_vectorizer.aembed(q)
vector = await self.redis_vectorizer.aembed(q) # pyright: ignore[reportUnknownMemberType]
query = HybridQuery(
text=q,
text_field_name="content",
@@ -374,13 +379,12 @@ class RedisContextProvider(BaseContextProvider):
text_scorer=text_scorer,
filter_expression=combined_filter,
linear_alpha=linear_alpha,
dtype=self.redis_vectorizer.dtype,
dtype=self.redis_vectorizer.dtype, # pyright: ignore[reportUnknownMemberType]
num_results=num_results,
return_fields=return_fields,
stopwords=None,
)
hybrid_results = await self.redis_index.query(query)
return cast(list[dict[str, Any]], hybrid_results)
return await self.redis_index.query(query) # type: ignore[no-any-return]
query = TextQuery(
text=q,
text_field_name="content",
@@ -390,8 +394,7 @@ class RedisContextProvider(BaseContextProvider):
return_fields=return_fields,
stopwords=None,
)
text_results = await self.redis_index.query(query)
return cast(list[dict[str, Any]], text_results)
return await self.redis_index.query(query) # type: ignore[no-any-return]
except Exception as exc: # pragma: no cover
raise IntegrationInvalidRequestException(f"Redis text search failed: {exc}") from exc
@@ -118,11 +118,11 @@ class RedisHistoryProvider(BaseHistoryProvider):
List of stored Message objects in chronological order.
"""
key = self._redis_key(session_id)
redis_messages = await self._redis_client.lrange(key, 0, -1) # type: ignore[misc]
redis_messages: list[str] = await self._redis_client.lrange(key, 0, -1) # type: ignore[misc]
messages: list[Message] = []
if redis_messages:
for serialized in redis_messages:
messages.append(Message.from_dict(self._deserialize_json(serialized)))
for serialized in redis_messages: # type: ignore[union-attr]
messages.append(Message.from_dict(self._deserialize_json(serialized))) # type: ignore[union-attr]
return messages
async def save_messages(self, session_id: str | None, messages: Sequence[Message], **kwargs: Any) -> None: