mirror of
https://github.com/hwchase17/langchain.git
synced 2025-09-12 00:11:17 +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
|
import gzip
|
||||||
from os import PathLike
|
from os import PathLike
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Union
|
from typing import Any, Union
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
import yaml
|
import yaml
|
||||||
@@ -36,7 +36,7 @@ class CustomSerializer:
|
|||||||
def deserialize(data: bytes) -> dict:
|
def deserialize(data: bytes) -> dict:
|
||||||
"""Decompress data and convert it from YAML."""
|
"""Decompress data and convert it from YAML."""
|
||||||
text = gzip.decompress(data).decode("utf-8")
|
text = gzip.decompress(data).decode("utf-8")
|
||||||
cassette = yaml.safe_load(text)
|
cassette: dict[str, Any] = yaml.safe_load(text)
|
||||||
cassette["requests"] = [
|
cassette["requests"] = [
|
||||||
Request._from_dict(request) for request in cassette["requests"]
|
Request._from_dict(request) for request in cassette["requests"]
|
||||||
]
|
]
|
||||||
|
@@ -15,7 +15,6 @@ from langchain_core.messages import (
|
|||||||
AIMessage,
|
AIMessage,
|
||||||
AIMessageChunk,
|
AIMessageChunk,
|
||||||
BaseMessage,
|
BaseMessage,
|
||||||
BaseMessageChunk,
|
|
||||||
HumanMessage,
|
HumanMessage,
|
||||||
SystemMessage,
|
SystemMessage,
|
||||||
ToolMessage,
|
ToolMessage,
|
||||||
@@ -67,8 +66,6 @@ def _get_joke_class(
|
|||||||
|
|
||||||
if schema_type == "json_schema":
|
if schema_type == "json_schema":
|
||||||
return Joke.model_json_schema(), validate_joke_dict
|
return Joke.model_json_schema(), validate_joke_dict
|
||||||
msg = "Invalid schema type"
|
|
||||||
raise ValueError(msg)
|
|
||||||
|
|
||||||
|
|
||||||
class _TestCallbackHandler(BaseCallbackHandler):
|
class _TestCallbackHandler(BaseCallbackHandler):
|
||||||
@@ -1381,7 +1378,7 @@ class ChatModelIntegrationTests(ChatModelTests):
|
|||||||
_validate_tool_call_message(result)
|
_validate_tool_call_message(result)
|
||||||
|
|
||||||
# Test stream
|
# Test stream
|
||||||
full: Optional[BaseMessageChunk] = None
|
full: Optional[BaseMessage] = None
|
||||||
for chunk in model_with_tools.stream(query):
|
for chunk in model_with_tools.stream(query):
|
||||||
full = chunk if full is None else full + chunk # type: ignore[assignment]
|
full = chunk if full is None else full + chunk # type: ignore[assignment]
|
||||||
assert isinstance(full, AIMessage)
|
assert isinstance(full, AIMessage)
|
||||||
@@ -1443,7 +1440,7 @@ class ChatModelIntegrationTests(ChatModelTests):
|
|||||||
_validate_tool_call_message(result)
|
_validate_tool_call_message(result)
|
||||||
|
|
||||||
# Test astream
|
# Test astream
|
||||||
full: Optional[BaseMessageChunk] = None
|
full: Optional[BaseMessage] = None
|
||||||
async for chunk in model_with_tools.astream(query):
|
async for chunk in model_with_tools.astream(query):
|
||||||
full = chunk if full is None else full + chunk # type: ignore[assignment]
|
full = chunk if full is None else full + chunk # type: ignore[assignment]
|
||||||
assert isinstance(full, AIMessage)
|
assert isinstance(full, AIMessage)
|
||||||
@@ -1791,7 +1788,7 @@ class ChatModelIntegrationTests(ChatModelTests):
|
|||||||
result = model_with_tools.invoke(query)
|
result = model_with_tools.invoke(query)
|
||||||
_validate_tool_call_message_no_args(result)
|
_validate_tool_call_message_no_args(result)
|
||||||
|
|
||||||
full: Optional[BaseMessageChunk] = None
|
full: Optional[BaseMessage] = None
|
||||||
for chunk in model_with_tools.stream(query):
|
for chunk in model_with_tools.stream(query):
|
||||||
full = chunk if full is None else full + chunk # type: ignore[assignment]
|
full = chunk if full is None else full + chunk # type: ignore[assignment]
|
||||||
assert isinstance(full, AIMessage)
|
assert isinstance(full, AIMessage)
|
||||||
@@ -1932,7 +1929,11 @@ class ChatModelIntegrationTests(ChatModelTests):
|
|||||||
assert isinstance(result, AIMessage)
|
assert isinstance(result, AIMessage)
|
||||||
|
|
||||||
@pytest.mark.parametrize("schema_type", ["pydantic", "typeddict", "json_schema"])
|
@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.
|
"""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
|
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:
|
if not self.has_structured_output:
|
||||||
pytest.skip("Test requires 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)
|
chat = model.with_structured_output(schema, **self.structured_output_kwargs)
|
||||||
mock_callback = MagicMock()
|
mock_callback = MagicMock()
|
||||||
mock_callback.on_chat_model_start = MagicMock()
|
mock_callback.on_chat_model_start = MagicMock()
|
||||||
@@ -2012,7 +2013,9 @@ class ChatModelIntegrationTests(ChatModelTests):
|
|||||||
|
|
||||||
@pytest.mark.parametrize("schema_type", ["pydantic", "typeddict", "json_schema"])
|
@pytest.mark.parametrize("schema_type", ["pydantic", "typeddict", "json_schema"])
|
||||||
async def test_structured_output_async(
|
async def test_structured_output_async(
|
||||||
self, model: BaseChatModel, schema_type: str
|
self,
|
||||||
|
model: BaseChatModel,
|
||||||
|
schema_type: Literal["pydantic", "typeddict", "json_schema"],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test to verify structured output is generated both on invoke and stream.
|
"""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:
|
if not self.has_structured_output:
|
||||||
pytest.skip("Test requires 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)
|
chat = model.with_structured_output(schema, **self.structured_output_kwargs)
|
||||||
ainvoke_callback = _TestCallbackHandler()
|
ainvoke_callback = _TestCallbackHandler()
|
||||||
@@ -2269,9 +2272,6 @@ class ChatModelIntegrationTests(ChatModelTests):
|
|||||||
punchline: str = FieldProper(description="answer to resolve the joke")
|
punchline: str = FieldProper(description="answer to resolve the joke")
|
||||||
|
|
||||||
# Pydantic class
|
# 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")
|
chat = model.with_structured_output(Joke, method="json_mode")
|
||||||
msg = (
|
msg = (
|
||||||
"Tell me a joke about cats. Return the result as a JSON with 'setup' and "
|
"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
|
import pytest
|
||||||
from langchain_core.documents import Document
|
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_core.vectorstores import VectorStore
|
||||||
|
|
||||||
from langchain_tests.base import BaseStandardTests
|
from langchain_tests.base import BaseStandardTests
|
||||||
|
@@ -1022,8 +1022,8 @@ class ChatModelUnitTests(ChatModelTests):
|
|||||||
|
|
||||||
# Test optional params
|
# Test optional params
|
||||||
model = self.chat_model_class(
|
model = self.chat_model_class(
|
||||||
max_tokens=10, # type: ignore[call-arg]
|
max_tokens=10,
|
||||||
stop=["test"], # type: ignore[call-arg]
|
stop=["test"],
|
||||||
**self.chat_model_params,
|
**self.chat_model_params,
|
||||||
)
|
)
|
||||||
ls_params = model._get_ls_params()
|
ls_params = model._get_ls_params()
|
||||||
|
@@ -32,25 +32,29 @@ repository = "https://github.com/langchain-ai/langchain"
|
|||||||
[dependency-groups]
|
[dependency-groups]
|
||||||
test = ["langchain-core"]
|
test = ["langchain-core"]
|
||||||
test_integration = []
|
test_integration = []
|
||||||
|
|
||||||
lint = ["ruff<0.13,>=0.12.10"]
|
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]
|
[tool.uv.sources]
|
||||||
langchain-core = { path = "../core", editable = true }
|
langchain-core = { path = "../core", editable = true }
|
||||||
|
|
||||||
[tool.mypy]
|
[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]]
|
[[tool.mypy.overrides]]
|
||||||
module = "yaml"
|
module = ["vcr.*",]
|
||||||
ignore_missing_imports = true
|
ignore_missing_imports = true
|
||||||
|
|
||||||
[[tool.mypy.overrides]]
|
|
||||||
module = "vcr.*"
|
|
||||||
ignore_missing_imports = true
|
|
||||||
|
|
||||||
|
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
target-version = "py39"
|
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