mirror of
https://github.com/hwchase17/langchain.git
synced 2025-09-11 16:01:33 +00:00
chore(standard-tests): add mypy strict checking (#32384)
Co-authored-by: Mason Daugherty <mason@langchain.dev>
This commit is contained in:
committed by
GitHub
parent
0c3e8ccd0e
commit
323729915a
@@ -3,7 +3,7 @@
|
||||
import gzip
|
||||
from os import PathLike
|
||||
from pathlib import Path
|
||||
from typing import Union
|
||||
from typing import Any, Union
|
||||
|
||||
import pytest
|
||||
import yaml
|
||||
@@ -36,7 +36,7 @@ class CustomSerializer:
|
||||
def deserialize(data: bytes) -> dict:
|
||||
"""Decompress data and convert it from YAML."""
|
||||
text = gzip.decompress(data).decode("utf-8")
|
||||
cassette = yaml.safe_load(text)
|
||||
cassette: dict[str, Any] = yaml.safe_load(text)
|
||||
cassette["requests"] = [
|
||||
Request._from_dict(request) for request in cassette["requests"]
|
||||
]
|
||||
|
@@ -15,7 +15,6 @@ from langchain_core.messages import (
|
||||
AIMessage,
|
||||
AIMessageChunk,
|
||||
BaseMessage,
|
||||
BaseMessageChunk,
|
||||
HumanMessage,
|
||||
SystemMessage,
|
||||
ToolMessage,
|
||||
@@ -67,8 +66,6 @@ def _get_joke_class(
|
||||
|
||||
if schema_type == "json_schema":
|
||||
return Joke.model_json_schema(), validate_joke_dict
|
||||
msg = "Invalid schema type"
|
||||
raise ValueError(msg)
|
||||
|
||||
|
||||
class _TestCallbackHandler(BaseCallbackHandler):
|
||||
@@ -1381,7 +1378,7 @@ class ChatModelIntegrationTests(ChatModelTests):
|
||||
_validate_tool_call_message(result)
|
||||
|
||||
# Test stream
|
||||
full: Optional[BaseMessageChunk] = None
|
||||
full: Optional[BaseMessage] = None
|
||||
for chunk in model_with_tools.stream(query):
|
||||
full = chunk if full is None else full + chunk # type: ignore[assignment]
|
||||
assert isinstance(full, AIMessage)
|
||||
@@ -1443,7 +1440,7 @@ class ChatModelIntegrationTests(ChatModelTests):
|
||||
_validate_tool_call_message(result)
|
||||
|
||||
# Test astream
|
||||
full: Optional[BaseMessageChunk] = None
|
||||
full: Optional[BaseMessage] = None
|
||||
async for chunk in model_with_tools.astream(query):
|
||||
full = chunk if full is None else full + chunk # type: ignore[assignment]
|
||||
assert isinstance(full, AIMessage)
|
||||
@@ -1791,7 +1788,7 @@ class ChatModelIntegrationTests(ChatModelTests):
|
||||
result = model_with_tools.invoke(query)
|
||||
_validate_tool_call_message_no_args(result)
|
||||
|
||||
full: Optional[BaseMessageChunk] = None
|
||||
full: Optional[BaseMessage] = None
|
||||
for chunk in model_with_tools.stream(query):
|
||||
full = chunk if full is None else full + chunk # type: ignore[assignment]
|
||||
assert isinstance(full, AIMessage)
|
||||
@@ -1932,7 +1929,11 @@ class ChatModelIntegrationTests(ChatModelTests):
|
||||
assert isinstance(result, AIMessage)
|
||||
|
||||
@pytest.mark.parametrize("schema_type", ["pydantic", "typeddict", "json_schema"])
|
||||
def test_structured_output(self, model: BaseChatModel, schema_type: str) -> None:
|
||||
def test_structured_output(
|
||||
self,
|
||||
model: BaseChatModel,
|
||||
schema_type: Literal["pydantic", "typeddict", "json_schema"],
|
||||
) -> None:
|
||||
"""Test to verify structured output is generated both on invoke and stream.
|
||||
|
||||
This test is optional and should be skipped if the model does not support
|
||||
@@ -1968,7 +1969,7 @@ class ChatModelIntegrationTests(ChatModelTests):
|
||||
if not self.has_structured_output:
|
||||
pytest.skip("Test requires structured output.")
|
||||
|
||||
schema, validation_function = _get_joke_class(schema_type) # type: ignore[arg-type]
|
||||
schema, validation_function = _get_joke_class(schema_type)
|
||||
chat = model.with_structured_output(schema, **self.structured_output_kwargs)
|
||||
mock_callback = MagicMock()
|
||||
mock_callback.on_chat_model_start = MagicMock()
|
||||
@@ -2012,7 +2013,9 @@ class ChatModelIntegrationTests(ChatModelTests):
|
||||
|
||||
@pytest.mark.parametrize("schema_type", ["pydantic", "typeddict", "json_schema"])
|
||||
async def test_structured_output_async(
|
||||
self, model: BaseChatModel, schema_type: str
|
||||
self,
|
||||
model: BaseChatModel,
|
||||
schema_type: Literal["pydantic", "typeddict", "json_schema"],
|
||||
) -> None:
|
||||
"""Test to verify structured output is generated both on invoke and stream.
|
||||
|
||||
@@ -2049,7 +2052,7 @@ class ChatModelIntegrationTests(ChatModelTests):
|
||||
if not self.has_structured_output:
|
||||
pytest.skip("Test requires structured output.")
|
||||
|
||||
schema, validation_function = _get_joke_class(schema_type) # type: ignore[arg-type]
|
||||
schema, validation_function = _get_joke_class(schema_type)
|
||||
|
||||
chat = model.with_structured_output(schema, **self.structured_output_kwargs)
|
||||
ainvoke_callback = _TestCallbackHandler()
|
||||
@@ -2269,9 +2272,6 @@ class ChatModelIntegrationTests(ChatModelTests):
|
||||
punchline: str = FieldProper(description="answer to resolve the joke")
|
||||
|
||||
# Pydantic class
|
||||
# Type ignoring since the interface only officially supports pydantic 1
|
||||
# or pydantic.v1.BaseModel but not pydantic.BaseModel from pydantic 2.
|
||||
# We'll need to do a pass updating the type signatures.
|
||||
chat = model.with_structured_output(Joke, method="json_mode")
|
||||
msg = (
|
||||
"Tell me a joke about cats. Return the result as a JSON with 'setup' and "
|
||||
|
@@ -4,7 +4,7 @@ from abc import abstractmethod
|
||||
|
||||
import pytest
|
||||
from langchain_core.documents import Document
|
||||
from langchain_core.embeddings.fake import DeterministicFakeEmbedding, Embeddings
|
||||
from langchain_core.embeddings import DeterministicFakeEmbedding, Embeddings
|
||||
from langchain_core.vectorstores import VectorStore
|
||||
|
||||
from langchain_tests.base import BaseStandardTests
|
||||
|
@@ -1022,8 +1022,8 @@ class ChatModelUnitTests(ChatModelTests):
|
||||
|
||||
# Test optional params
|
||||
model = self.chat_model_class(
|
||||
max_tokens=10, # type: ignore[call-arg]
|
||||
stop=["test"], # type: ignore[call-arg]
|
||||
max_tokens=10,
|
||||
stop=["test"],
|
||||
**self.chat_model_params,
|
||||
)
|
||||
ls_params = model._get_ls_params()
|
||||
|
@@ -32,25 +32,29 @@ repository = "https://github.com/langchain-ai/langchain"
|
||||
[dependency-groups]
|
||||
test = ["langchain-core"]
|
||||
test_integration = []
|
||||
|
||||
lint = ["ruff<0.13,>=0.12.10"]
|
||||
typing = ["mypy<2,>=1.17.1", "langchain-core"]
|
||||
typing = [
|
||||
"mypy<1.18,>=1.17.1",
|
||||
"types-pyyaml<7.0.0.0,>=6.0.12.2",
|
||||
"langchain-core",
|
||||
]
|
||||
|
||||
[tool.uv.sources]
|
||||
langchain-core = { path = "../core", editable = true }
|
||||
|
||||
[tool.mypy]
|
||||
disallow_untyped_defs = "True"
|
||||
plugins = ["pydantic.mypy"]
|
||||
strict = true
|
||||
enable_error_code = "deprecated"
|
||||
warn_unreachable = true
|
||||
|
||||
# TODO: activate for 'strict' checking
|
||||
disallow_any_generics = false
|
||||
|
||||
[[tool.mypy.overrides]]
|
||||
module = "yaml"
|
||||
module = ["vcr.*",]
|
||||
ignore_missing_imports = true
|
||||
|
||||
[[tool.mypy.overrides]]
|
||||
module = "vcr.*"
|
||||
ignore_missing_imports = true
|
||||
|
||||
|
||||
[tool.ruff]
|
||||
target-version = "py39"
|
||||
|
||||
|
2141
libs/standard-tests/uv.lock
generated
2141
libs/standard-tests/uv.lock
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user