mirror of
https://github.com/hwchase17/langchain.git
synced 2025-08-09 21:08:59 +00:00
chore(core): bump mypy version to 1.17 (#32390)
Co-authored-by: Mason Daugherty <mason@langchain.dev>
This commit is contained in:
parent
42c1159991
commit
499dc35cfb
@ -144,7 +144,7 @@ def beta(
|
||||
obj.__init__ = functools.wraps(obj.__init__)( # type: ignore[misc]
|
||||
warn_if_direct_instance
|
||||
)
|
||||
return cast("T", obj)
|
||||
return obj
|
||||
|
||||
elif isinstance(obj, property):
|
||||
# note(erick): this block doesn't seem to be used?
|
||||
|
@ -225,7 +225,7 @@ def deprecated(
|
||||
obj.__init__ = functools.wraps(obj.__init__)( # type: ignore[misc]
|
||||
warn_if_direct_instance
|
||||
)
|
||||
return cast("T", obj)
|
||||
return obj
|
||||
|
||||
elif isinstance(obj, FieldInfoV1):
|
||||
wrapped = None
|
||||
|
@ -107,23 +107,27 @@ class _StreamingParser:
|
||||
self.buffer = ""
|
||||
# yield all events
|
||||
try:
|
||||
for event, elem in self.pull_parser.read_events():
|
||||
if event == "start":
|
||||
# update current path
|
||||
self.current_path.append(elem.tag)
|
||||
self.current_path_has_children = False
|
||||
elif event == "end":
|
||||
# remove last element from current path
|
||||
#
|
||||
self.current_path.pop()
|
||||
# yield element
|
||||
if not self.current_path_has_children:
|
||||
yield nested_element(self.current_path, elem)
|
||||
# prevent yielding of parent element
|
||||
if self.current_path:
|
||||
self.current_path_has_children = True
|
||||
else:
|
||||
self.xml_started = False
|
||||
for raw_event in self.pull_parser.read_events():
|
||||
if len(raw_event) <= 1:
|
||||
continue
|
||||
event, elem = raw_event
|
||||
if isinstance(elem, ET.Element):
|
||||
if event == "start":
|
||||
# update current path
|
||||
self.current_path.append(elem.tag)
|
||||
self.current_path_has_children = False
|
||||
elif event == "end":
|
||||
# remove last element from current path
|
||||
#
|
||||
self.current_path.pop()
|
||||
# yield element
|
||||
if not self.current_path_has_children:
|
||||
yield nested_element(self.current_path, elem)
|
||||
# prevent yielding of parent element
|
||||
if self.current_path:
|
||||
self.current_path_has_children = True
|
||||
else:
|
||||
self.xml_started = False
|
||||
except xml.etree.ElementTree.ParseError:
|
||||
# This might be junk at the end of the XML input.
|
||||
# Let's check whether the current path is empty.
|
||||
|
@ -5300,7 +5300,7 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]):
|
||||
kwargs.
|
||||
"""
|
||||
|
||||
config: RunnableConfig = Field(default_factory=RunnableConfig) # type: ignore[arg-type]
|
||||
config: RunnableConfig = Field(default_factory=RunnableConfig)
|
||||
"""The config to bind to the underlying Runnable."""
|
||||
|
||||
config_factories: list[Callable[[RunnableConfig], RunnableConfig]] = Field(
|
||||
|
@ -5,7 +5,7 @@ import inspect
|
||||
import typing
|
||||
from collections.abc import AsyncIterator, Iterator, Sequence
|
||||
from functools import wraps
|
||||
from typing import TYPE_CHECKING, Any, Optional, Union
|
||||
from typing import TYPE_CHECKING, Any, Optional, Union, cast
|
||||
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
from typing_extensions import override
|
||||
@ -397,7 +397,7 @@ class RunnableWithFallbacks(RunnableSerializable[Input, Output]):
|
||||
)
|
||||
)
|
||||
|
||||
to_return = {}
|
||||
to_return: dict[int, Union[Output, BaseException]] = {}
|
||||
run_again = dict(enumerate(inputs))
|
||||
handled_exceptions: dict[int, BaseException] = {}
|
||||
first_to_raise = None
|
||||
@ -447,7 +447,7 @@ class RunnableWithFallbacks(RunnableSerializable[Input, Output]):
|
||||
if not return_exceptions and sorted_handled_exceptions:
|
||||
raise sorted_handled_exceptions[0][1]
|
||||
to_return.update(handled_exceptions)
|
||||
return [output for _, output in sorted(to_return.items())] # type: ignore[misc]
|
||||
return [cast("Output", output) for _, output in sorted(to_return.items())]
|
||||
|
||||
@override
|
||||
def stream(
|
||||
@ -569,7 +569,7 @@ class RunnableWithFallbacks(RunnableSerializable[Input, Output]):
|
||||
async for chunk in stream:
|
||||
yield chunk
|
||||
try:
|
||||
output = output + chunk
|
||||
output = output + chunk # type: ignore[operator]
|
||||
except TypeError:
|
||||
output = None
|
||||
except BaseException as e:
|
||||
|
@ -177,7 +177,7 @@ class RunLog(RunLogPatch):
|
||||
# Then compare that the ops are the same
|
||||
return super().__eq__(other)
|
||||
|
||||
__hash__ = None # type: ignore[assignment]
|
||||
__hash__ = None
|
||||
|
||||
|
||||
T = TypeVar("T")
|
||||
|
@ -277,7 +277,7 @@ def _convert_any_typed_dicts_to_pydantic(
|
||||
)
|
||||
fields: dict = {}
|
||||
for arg, arg_type in annotations_.items():
|
||||
if get_origin(arg_type) is Annotated:
|
||||
if get_origin(arg_type) is Annotated: # type: ignore[comparison-overlap]
|
||||
annotated_args = get_args(arg_type)
|
||||
new_arg_type = _convert_any_typed_dicts_to_pydantic(
|
||||
annotated_args[0], depth=depth + 1, visited=visited
|
||||
|
@ -417,7 +417,7 @@ class AIMessageChunk(AIMessage):
|
||||
self._tool_call_chunks = [
|
||||
block for block in self.content if types.is_tool_call_chunk(block)
|
||||
]
|
||||
return cast("list[types.ToolCallChunk]", self._tool_call_chunks)
|
||||
return self._tool_call_chunks
|
||||
|
||||
@property
|
||||
def tool_calls(self) -> list[types.ToolCall]:
|
||||
|
@ -28,7 +28,7 @@ repository = "https://github.com/langchain-ai/langchain"
|
||||
[dependency-groups]
|
||||
lint = ["ruff<0.13,>=0.12.2"]
|
||||
typing = [
|
||||
"mypy<1.16,>=1.15",
|
||||
"mypy<1.18,>=1.17.1",
|
||||
"types-pyyaml<7.0.0.0,>=6.0.12.2",
|
||||
"types-requests<3.0.0.0,>=2.28.11.5",
|
||||
"langchain-text-splitters",
|
||||
|
@ -479,28 +479,12 @@ class TestFactoryTypeConsistency:
|
||||
|
||||
|
||||
class TestExtraItems:
|
||||
"""Test that content blocks support extra items via __extra_items__ field."""
|
||||
|
||||
def test_text_block_extra_items(self) -> None:
|
||||
"""Test that TextContentBlock can store extra provider-specific fields."""
|
||||
block = create_text_block("Hello world")
|
||||
|
||||
block["openai_metadata"] = {"model": "gpt-4", "temperature": 0.7} # type: ignore[typeddict-unknown-key]
|
||||
block["anthropic_usage"] = {"input_tokens": 10, "output_tokens": 20} # type: ignore[typeddict-unknown-key]
|
||||
block["custom_field"] = "any value" # type: ignore[typeddict-unknown-key]
|
||||
|
||||
assert block["type"] == "text"
|
||||
assert block["text"] == "Hello world"
|
||||
assert "id" in block
|
||||
assert block.get("openai_metadata") == {"model": "gpt-4", "temperature": 0.7}
|
||||
assert block.get("anthropic_usage") == {"input_tokens": 10, "output_tokens": 20}
|
||||
assert block.get("custom_field") == "any value"
|
||||
"""Test that content blocks support extra items."""
|
||||
|
||||
def test_text_block_extras_field(self) -> None:
|
||||
"""Test that TextContentBlock properly supports the explicit extras field."""
|
||||
"""Test that TextContentBlock properly supports the extras field."""
|
||||
block = create_text_block("Hello world")
|
||||
|
||||
# Test direct assignment to extras field
|
||||
block["extras"] = {
|
||||
"openai_metadata": {"model": "gpt-4", "temperature": 0.7},
|
||||
"anthropic_usage": {"input_tokens": 10, "output_tokens": 20},
|
||||
@ -518,32 +502,6 @@ class TestExtraItems:
|
||||
assert extras.get("anthropic_usage") == expected_usage
|
||||
assert extras.get("custom_field") == "any value"
|
||||
|
||||
def test_mixed_extra_items_types(self) -> None:
|
||||
"""Test that extra items can be various types (str, int, bool, dict, list)."""
|
||||
block = create_text_block("Test content")
|
||||
|
||||
# Add various types of extra fields
|
||||
block["string_field"] = "string value" # type: ignore[typeddict-unknown-key]
|
||||
block["int_field"] = 42 # type: ignore[typeddict-unknown-key]
|
||||
block["float_field"] = 3.14 # type: ignore[typeddict-unknown-key]
|
||||
block["bool_field"] = True # type: ignore[typeddict-unknown-key]
|
||||
block["list_field"] = ["item1", "item2", "item3"] # type: ignore[typeddict-unknown-key]
|
||||
block["dict_field"] = {"nested": {"deeply": "nested value"}} # type: ignore[typeddict-unknown-key]
|
||||
block["none_field"] = None # type: ignore[typeddict-unknown-key]
|
||||
|
||||
# Verify all types are preserved
|
||||
assert block.get("string_field") == "string value"
|
||||
assert block.get("int_field") == 42
|
||||
assert block.get("float_field") == 3.14
|
||||
assert block.get("bool_field") is True
|
||||
assert block.get("list_field") == ["item1", "item2", "item3"]
|
||||
dict_field = block.get("dict_field", {})
|
||||
assert isinstance(dict_field, dict)
|
||||
nested = dict_field.get("nested", {})
|
||||
assert isinstance(nested, dict)
|
||||
assert nested.get("deeply") == "nested value"
|
||||
assert block.get("none_field") is None
|
||||
|
||||
def test_extra_items_do_not_interfere_with_standard_fields(self) -> None:
|
||||
"""Test that extra items don't interfere with standard field access."""
|
||||
block = create_text_block("Original text", index=1)
|
||||
@ -567,22 +525,21 @@ class TestExtraItems:
|
||||
block = create_image_block(url="https://example.com/image.jpg")
|
||||
|
||||
# Add an extra field
|
||||
block["status"] = "pending" # type: ignore[typeddict-unknown-key]
|
||||
assert block.get("status") == "pending"
|
||||
block["extras"] = {"status": "pending"}
|
||||
assert block["extras"].get("status") == "pending"
|
||||
|
||||
# Modify the extra field
|
||||
block["status"] = "processed" # type: ignore[typeddict-unknown-key]
|
||||
assert block.get("status") == "processed"
|
||||
block["extras"] = {"status": "processed"}
|
||||
assert block["extras"].get("status") == "processed"
|
||||
|
||||
# Add more fields
|
||||
block["metadata"] = {"version": 1} # type: ignore[typeddict-unknown-key]
|
||||
metadata = block.get("metadata", {})
|
||||
block["extras"] = {"metadata": {"version": 1}}
|
||||
metadata = block["extras"].get("metadata", {})
|
||||
assert isinstance(metadata, dict)
|
||||
assert metadata.get("version") == 1
|
||||
|
||||
# Modify nested extra field
|
||||
block["metadata"]["version"] = 2 # type: ignore[typeddict-item]
|
||||
metadata = block.get("metadata", {})
|
||||
metadata["version"] = 2
|
||||
assert isinstance(metadata, dict)
|
||||
assert metadata.get("version") == 2
|
||||
|
||||
@ -590,40 +547,36 @@ class TestExtraItems:
|
||||
"""Test that all content block types support extra items."""
|
||||
# Test each content block type
|
||||
text_block = create_text_block("test")
|
||||
text_block["extra"] = "text_extra" # type: ignore[typeddict-unknown-key]
|
||||
assert text_block.get("extra") == "text_extra"
|
||||
text_block["extras"] = {"text_extra": "a"}
|
||||
assert text_block.get("extras") == {"text_extra": "a"}
|
||||
|
||||
image_block = create_image_block(url="https://example.com/image.jpg")
|
||||
image_block["extra"] = "image_extra" # type: ignore[typeddict-unknown-key]
|
||||
assert image_block.get("extra") == "image_extra"
|
||||
image_block["extras"] = {"image_extra": "a"}
|
||||
assert image_block.get("extras") == {"image_extra": "a"}
|
||||
|
||||
video_block = create_video_block(url="https://example.com/video.mp4")
|
||||
video_block["extra"] = "video_extra" # type: ignore[typeddict-unknown-key]
|
||||
assert video_block.get("extra") == "video_extra"
|
||||
video_block["extras"] = {"video_extra": "a"}
|
||||
assert video_block.get("extras") == {"video_extra": "a"}
|
||||
|
||||
audio_block = create_audio_block(url="https://example.com/audio.mp3")
|
||||
audio_block["extra"] = "audio_extra" # type: ignore[typeddict-unknown-key]
|
||||
assert audio_block.get("extra") == "audio_extra"
|
||||
audio_block["extras"] = {"audio_extra": "a"}
|
||||
assert audio_block.get("extras") == {"audio_extra": "a"}
|
||||
|
||||
file_block = create_file_block(url="https://example.com/file.pdf")
|
||||
file_block["extra"] = "file_extra" # type: ignore[typeddict-unknown-key]
|
||||
assert file_block.get("extra") == "file_extra"
|
||||
file_block["extras"] = {"file_extra": "a"}
|
||||
assert file_block.get("extras") == {"file_extra": "a"}
|
||||
|
||||
plain_text_block = create_plaintext_block("content")
|
||||
plain_text_block["extra"] = "plaintext_extra" # type: ignore[typeddict-unknown-key]
|
||||
assert plain_text_block.get("extra") == "plaintext_extra"
|
||||
plain_text_block["extras"] = {"plaintext_extra": "a"}
|
||||
assert plain_text_block.get("extras") == {"plaintext_extra": "a"}
|
||||
|
||||
tool_call = create_tool_call("tool", {"arg": "value"})
|
||||
tool_call["extra"] = "tool_extra" # type: ignore[typeddict-unknown-key]
|
||||
assert tool_call.get("extra") == "tool_extra"
|
||||
tool_call["extras"] = {"tool_extra": "a"}
|
||||
assert tool_call.get("extras") == {"tool_extra": "a"}
|
||||
|
||||
reasoning_block = create_reasoning_block("reasoning")
|
||||
reasoning_block["extra"] = "reasoning_extra" # type: ignore[typeddict-unknown-key]
|
||||
assert reasoning_block.get("extra") == "reasoning_extra"
|
||||
|
||||
non_standard_block = create_non_standard_block({"data": "value"})
|
||||
non_standard_block["extra"] = "non_standard_extra" # type: ignore[typeddict-unknown-key]
|
||||
assert non_standard_block.get("extra") == "non_standard_extra"
|
||||
reasoning_block["extras"] = {"reasoning_extra": "a"}
|
||||
assert reasoning_block.get("extras") == {"reasoning_extra": "a"}
|
||||
|
||||
|
||||
class TestExtrasField:
|
||||
|
@ -81,7 +81,7 @@ def test_structured_prompt_dict() -> None:
|
||||
|
||||
chain = loads(dumps(prompt)) | model
|
||||
|
||||
assert chain.invoke({"hello": "there"}) == {"name": 1, "value": 42} # type: ignore[comparison-overlap]
|
||||
assert chain.invoke({"hello": "there"}) == {"name": 1, "value": 42}
|
||||
|
||||
|
||||
def test_structured_prompt_kwargs() -> None:
|
||||
@ -104,7 +104,7 @@ def test_structured_prompt_kwargs() -> None:
|
||||
assert chain.invoke({"hello": "there"}) == {"name": 1, "value": 7} # type: ignore[comparison-overlap]
|
||||
assert loads(dumps(prompt)).model_dump() == prompt.model_dump()
|
||||
chain = loads(dumps(prompt)) | model
|
||||
assert chain.invoke({"hello": "there"}) == {"name": 1, "value": 7} # type: ignore[comparison-overlap]
|
||||
assert chain.invoke({"hello": "there"}) == {"name": 1, "value": 7}
|
||||
|
||||
class OutputSchema(BaseModel):
|
||||
name: str
|
||||
|
1081
libs/core/uv.lock
1081
libs/core/uv.lock
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user