diff --git a/libs/standard-tests/langchain_tests/base.py b/libs/standard-tests/langchain_tests/base.py index c54b84055a7..0f9156673c1 100644 --- a/libs/standard-tests/langchain_tests/base.py +++ b/libs/standard-tests/langchain_tests/base.py @@ -1,8 +1,13 @@ +"""Standard tests.""" + from abc import ABC class BaseStandardTests(ABC): - """:private:""" + """Base class for standard tests. + + :private: + """ def test_no_overrides_DO_NOT_OVERRIDE(self) -> None: """Test that no standard tests are overridden. diff --git a/libs/standard-tests/langchain_tests/conftest.py b/libs/standard-tests/langchain_tests/conftest.py index f8536c39a79..b1674bc963d 100644 --- a/libs/standard-tests/langchain_tests/conftest.py +++ b/libs/standard-tests/langchain_tests/conftest.py @@ -1,3 +1,5 @@ +"""Pytest conftest.""" + import gzip from os import PathLike from pathlib import Path @@ -88,7 +90,7 @@ _BASE_FILTER_HEADERS = [ @pytest.fixture(scope="session") def _base_vcr_config() -> dict: - """Get configuration that every cassette will receive. + """Return VCR configuration that every cassette will receive. (Anything permitted by ``vcr.VCR(**kwargs)`` can be put here.) """ @@ -105,4 +107,5 @@ def _base_vcr_config() -> dict: @pytest.fixture(scope="session") def vcr_config(_base_vcr_config: dict) -> dict: + """VCR config fixture.""" return _base_vcr_config diff --git a/libs/standard-tests/langchain_tests/integration_tests/__init__.py b/libs/standard-tests/langchain_tests/integration_tests/__init__.py index fbe4888d1e5..2a311bb8c9d 100644 --- a/libs/standard-tests/langchain_tests/integration_tests/__init__.py +++ b/libs/standard-tests/langchain_tests/integration_tests/__init__.py @@ -1,3 +1,5 @@ +"""Integration tests for LangChain components.""" + # ruff: noqa: E402 import pytest diff --git a/libs/standard-tests/langchain_tests/integration_tests/base_store.py b/libs/standard-tests/langchain_tests/integration_tests/base_store.py index 31daa8c2307..cba4c245e1d 100644 --- a/libs/standard-tests/langchain_tests/integration_tests/base_store.py +++ b/libs/standard-tests/langchain_tests/integration_tests/base_store.py @@ -62,7 +62,9 @@ class BaseStoreSyncTests(BaseStandardTests, Generic[V]): assert kv_store.mget(["foo", "bar"]) == [foo, bar] def test_store_still_empty(self, kv_store: BaseStore[str, V]) -> None: - """This test should follow a test that sets values. + """Test that the store is still empty. + + This test should follow a test that sets values. This just verifies that the fixture is set up properly to be empty after each test. @@ -192,7 +194,9 @@ class BaseStoreAsyncTests(BaseStandardTests, Generic[V]): assert await kv_store.amget(["foo", "bar"]) == [foo, bar] async def test_store_still_empty(self, kv_store: BaseStore[str, V]) -> None: - """This test should follow a test that sets values. + """Test that the store is still empty. + + This test should follow a test that sets values. This just verifies that the fixture is set up properly to be empty after each test. diff --git a/libs/standard-tests/langchain_tests/integration_tests/cache.py b/libs/standard-tests/langchain_tests/integration_tests/cache.py index 8856ff3bf69..18088612afa 100644 --- a/libs/standard-tests/langchain_tests/integration_tests/cache.py +++ b/libs/standard-tests/langchain_tests/integration_tests/cache.py @@ -62,7 +62,9 @@ class SyncCacheTestSuite(BaseStandardTests): assert cache.lookup(prompt, llm_string) == [generation] def test_cache_still_empty(self, cache: BaseCache) -> None: - """This test should follow a test that updates the cache. + """Test that the cache is still empty. + + This test should follow a test that updates the cache. This just verifies that the fixture is set up properly to be empty after each test. @@ -153,7 +155,9 @@ class AsyncCacheTestSuite(BaseStandardTests): assert await cache.alookup(prompt, llm_string) == [generation] async def test_cache_still_empty(self, cache: BaseCache) -> None: - """This test should follow a test that updates the cache. + """Test that the cache is still empty. + + This test should follow a test that updates the cache. This just verifies that the fixture is set up properly to be empty after each test. diff --git a/libs/standard-tests/langchain_tests/integration_tests/chat_models.py b/libs/standard-tests/langchain_tests/integration_tests/chat_models.py index d6666ed55a6..1750e8bdefd 100644 --- a/libs/standard-tests/langchain_tests/integration_tests/chat_models.py +++ b/libs/standard-tests/langchain_tests/integration_tests/chat_models.py @@ -1,3 +1,5 @@ +"""Integration tests for chat models.""" + import base64 import inspect import json @@ -39,8 +41,6 @@ from langchain_tests.utils.pydantic import PYDANTIC_MAJOR_VERSION def _get_joke_class( schema_type: Literal["pydantic", "typeddict", "json_schema"], ) -> Any: - """:private:""" - class Joke(BaseModel): """Joke to tell user.""" @@ -95,13 +95,13 @@ class _MagicFunctionSchema(BaseModel): @tool(args_schema=_MagicFunctionSchema) def magic_function(_input: int) -> int: - """Applies a magic function to an input.""" + """Apply a magic function to an input.""" return _input + 2 @tool def magic_function_no_args() -> int: - """Calculates a magic function.""" + """Calculate a magic function.""" return 5 @@ -143,7 +143,7 @@ def unicode_customer(customer_name: str, description: str) -> str: class ChatModelIntegrationTests(ChatModelTests): - """Base class for chat model integration tests. + '''Base class for chat model integration tests. Test subclasses must implement the ``chat_model_class`` and ``chat_model_params`` properties to specify what model to test and its @@ -587,7 +587,7 @@ class ChatModelIntegrationTests(ChatModelTests): @pytest.fixture(scope="session") def vcr_config(_base_vcr_config: dict) -> dict: # noqa: F811 - \"\"\"Extend the default configuration from langchain_tests.\"\"\" + """Extend the default configuration from langchain_tests.""" config = _base_vcr_config.copy() config.setdefault("filter_headers", []).extend(_EXTRA_HEADERS) config["before_record_response"] = remove_response_headers @@ -623,7 +623,7 @@ class ChatModelIntegrationTests(ChatModelTests): @pytest.fixture(scope="session") def vcr_config(_base_vcr_config: dict) -> dict: # noqa: F811 - \"\"\"Extend the default configuration from langchain_tests.\"\"\" + """Extend the default configuration from langchain_tests.""" config = _base_vcr_config.copy() config.setdefault("filter_headers", []).extend(_EXTRA_HEADERS) config["before_record_response"] = remove_response_headers @@ -675,11 +675,14 @@ class ChatModelIntegrationTests(ChatModelTests): You can then commit the cassette to your repository. Subsequent test runs will use the cassette instead of making HTTP calls. - """ # noqa: E501 + ''' # noqa: E501,D214 @property def standard_chat_model_params(self) -> dict: - """:private:""" + """Standard parameters for chat model. + + :private: + """ return {} def test_invoke(self, model: BaseChatModel) -> None: @@ -1270,8 +1273,10 @@ class ChatModelIntegrationTests(ChatModelTests): ) def test_stop_sequence(self, model: BaseChatModel) -> None: - """Test that model does not fail when invoked with the ``stop`` parameter, - which is a standard parameter for stopping generation at a certain token. + """Test that model does not fail when invoked with the ``stop`` parameter. + + The ``stop`` parameter is a standard parameter for stopping generation at a + certain token. `More on standard parameters `__ @@ -1306,8 +1311,10 @@ class ChatModelIntegrationTests(ChatModelTests): assert isinstance(result, AIMessage) def test_tool_calling(self, model: BaseChatModel) -> None: - """Test that the model generates tool calls. This test is skipped if the - ``has_tool_calling`` property on the test class is set to False. + """Test that the model generates tool calls. + + This test is skipped if the ``has_tool_calling`` property on the test class is + set to False. This test is optional and should be skipped if the model does not support tool calling (see Configuration below). @@ -1381,8 +1388,10 @@ class ChatModelIntegrationTests(ChatModelTests): _validate_tool_call_message(full) async def test_tool_calling_async(self, model: BaseChatModel) -> None: - """Test that the model generates tool calls. This test is skipped if the - ``has_tool_calling`` property on the test class is set to False. + """Test that the model generates tool calls. + + This test is skipped if the ``has_tool_calling`` property on the test class is + set to False. This test is optional and should be skipped if the model does not support tool calling (see Configuration below). @@ -1441,7 +1450,9 @@ class ChatModelIntegrationTests(ChatModelTests): _validate_tool_call_message(full) def test_bind_runnables_as_tools(self, model: BaseChatModel) -> None: - """Test that the model generates tool calls for tools that are derived from + """Test bind runnables as tools. + + Test that the model generates tool calls for tools that are derived from LangChain runnables. This test is skipped if the ``has_tool_calling`` property on the test class is set to False. @@ -1509,8 +1520,10 @@ class ChatModelIntegrationTests(ChatModelTests): def test_tool_message_histories_string_content( self, model: BaseChatModel, my_adder_tool: BaseTool ) -> None: - """Test that message histories are compatible with string tool contents - (e.g. OpenAI format). If a model passes this test, it should be compatible + """Test that message histories are compatible with string tool contents. + + For instance with OpenAI format contents. + If a model passes this test, it should be compatible with messages generated from providers following OpenAI format. This test should be skipped if the model does not support tool calling @@ -1581,8 +1594,9 @@ class ChatModelIntegrationTests(ChatModelTests): model: BaseChatModel, my_adder_tool: BaseTool, ) -> None: - """Test that message histories are compatible with list tool contents - (e.g. Anthropic format). + """Test that message histories are compatible with list tool contents. + + For instance with Anthropic format contents. These message histories will include ``AIMessage`` objects with "tool use" and content blocks, e.g., @@ -1671,7 +1685,9 @@ class ChatModelIntegrationTests(ChatModelTests): assert isinstance(result_list_content, AIMessage) def test_tool_choice(self, model: BaseChatModel) -> None: - """Test that the model can force tool calling via the ``tool_choice`` + """Test ``tool_choice`` parameter. + + Test that the model can force tool calling via the ``tool_choice`` parameter. This test is skipped if the ``has_tool_choice`` property on the test class is set to False. @@ -1723,6 +1739,7 @@ class ChatModelIntegrationTests(ChatModelTests): def test_tool_calling_with_no_arguments(self, model: BaseChatModel) -> None: """Test that the model generates tool calls for tools with no arguments. + This test is skipped if the ``has_tool_calling`` property on the test class is set to False. @@ -2075,7 +2092,9 @@ class ChatModelIntegrationTests(ChatModelTests): @pytest.mark.skipif(PYDANTIC_MAJOR_VERSION != 2, reason="Test requires pydantic 2.") def test_structured_output_pydantic_2_v1(self, model: BaseChatModel) -> None: - """Test to verify we can generate structured output using ``pydantic.v1.BaseModel``. + """Test structured output using pydantic.v1.BaseModel. + + Verify we can generate structured output using ``pydantic.v1.BaseModel``. ``pydantic.v1.BaseModel`` is available in the Pydantic 2 package. @@ -2140,7 +2159,9 @@ class ChatModelIntegrationTests(ChatModelTests): assert set(chunk.keys()) == {"setup", "punchline"} def test_structured_output_optional_param(self, model: BaseChatModel) -> None: - """Test to verify we can generate structured output that includes optional + """Test structured output with optional parameters. + + Test to verify we can generate structured output that includes optional parameters. This test is optional and should be skipped if the model does not support @@ -2847,8 +2868,10 @@ class ChatModelIntegrationTests(ChatModelTests): assert len(result.content) > 0 def test_agent_loop(self, model: BaseChatModel) -> None: - """Test that the model supports a simple ReAct agent loop. This test is skipped - if the ``has_tool_calling`` property on the test class is set to False. + """Test that the model supports a simple ReAct agent loop. + + This test is skipped if the ``has_tool_calling`` property on the test class is + set to False. This test is optional and should be skipped if the model does not support tool calling (see Configuration below). @@ -2953,23 +2976,38 @@ class ChatModelIntegrationTests(ChatModelTests): benchmark(_run) def invoke_with_audio_input(self, *, stream: bool = False) -> AIMessage: - """:private:""" + """Invoke with audio input. + + :private: + """ raise NotImplementedError def invoke_with_audio_output(self, *, stream: bool = False) -> AIMessage: - """:private:""" + """Invoke with audio output. + + :private: + """ raise NotImplementedError def invoke_with_reasoning_output(self, *, stream: bool = False) -> AIMessage: - """:private:""" + """Invoke with reasoning output. + + :private: + """ raise NotImplementedError def invoke_with_cache_read_input(self, *, stream: bool = False) -> AIMessage: - """:private:""" + """Invoke with cache read input. + + :private: + """ raise NotImplementedError def invoke_with_cache_creation_input(self, *, stream: bool = False) -> AIMessage: - """:private:""" + """Invoke with cache creation input. + + :private: + """ raise NotImplementedError def test_unicode_tool_call_integration( @@ -2979,7 +3017,7 @@ class ChatModelIntegrationTests(ChatModelTests): tool_choice: Optional[str] = None, force_tool_call: bool = True, ) -> None: - """Generic integration test for Unicode characters in tool calls. + r"""Generic integration test for Unicode characters in tool calls. Args: model: The chat model to test diff --git a/libs/standard-tests/langchain_tests/integration_tests/embeddings.py b/libs/standard-tests/langchain_tests/integration_tests/embeddings.py index eb68a42eccc..9f35aa0bd5b 100644 --- a/libs/standard-tests/langchain_tests/integration_tests/embeddings.py +++ b/libs/standard-tests/langchain_tests/integration_tests/embeddings.py @@ -1,3 +1,5 @@ +"""Integration tests for embeddings.""" + from langchain_core.embeddings import Embeddings from langchain_tests.unit_tests.embeddings import EmbeddingsTests diff --git a/libs/standard-tests/langchain_tests/integration_tests/retrievers.py b/libs/standard-tests/langchain_tests/integration_tests/retrievers.py index 3c024016097..204134e31a4 100644 --- a/libs/standard-tests/langchain_tests/integration_tests/retrievers.py +++ b/libs/standard-tests/langchain_tests/integration_tests/retrievers.py @@ -1,3 +1,5 @@ +"""Integration tests for retrievers.""" + from abc import abstractmethod import pytest @@ -37,7 +39,10 @@ class RetrieversIntegrationTests(BaseStandardTests): @pytest.fixture def retriever(self) -> BaseRetriever: - """:private:""" + """Return retriever fixture. + + :private: + """ return self.retriever_constructor(**self.retriever_constructor_params) def test_k_constructor_param(self) -> None: @@ -148,7 +153,9 @@ class RetrieversIntegrationTests(BaseStandardTests): assert all(isinstance(doc, Document) for doc in result_3) def test_invoke_returns_documents(self, retriever: BaseRetriever) -> None: - """If invoked with the example params, the retriever should return a list of + """Test invoke returns documents. + + If invoked with the example params, the retriever should return a list of Documents. .. dropdown:: Troubleshooting @@ -163,7 +170,9 @@ class RetrieversIntegrationTests(BaseStandardTests): assert all(isinstance(doc, Document) for doc in result) async def test_ainvoke_returns_documents(self, retriever: BaseRetriever) -> None: - """If ainvoked with the example params, the retriever should return a list of + """Test ainvoke returns documents. + + If ainvoked with the example params, the retriever should return a list of Documents. See :meth:`test_invoke_returns_documents` for more information on diff --git a/libs/standard-tests/langchain_tests/integration_tests/tools.py b/libs/standard-tests/langchain_tests/integration_tests/tools.py index e21772b8928..03915105e5f 100644 --- a/libs/standard-tests/langchain_tests/integration_tests/tools.py +++ b/libs/standard-tests/langchain_tests/integration_tests/tools.py @@ -1,3 +1,5 @@ +"""Integration tests for tools.""" + from langchain_core.messages import ToolCall from langchain_core.tools import BaseTool @@ -66,7 +68,9 @@ class ToolsIntegrationTests(ToolsTests): assert all(isinstance(c, (str, dict)) for c in tool_message.content) def test_invoke_no_tool_call(self, tool: BaseTool) -> None: - """If invoked without a ToolCall, the tool can return anything + """Test invoke without ToolCall. + + If invoked without a ToolCall, the tool can return anything but it shouldn't throw an error. If this test fails, your tool may not be handling the input you defined @@ -78,7 +82,9 @@ class ToolsIntegrationTests(ToolsTests): tool.invoke(self.tool_invoke_params_example) async def test_async_invoke_no_tool_call(self, tool: BaseTool) -> None: - """If ainvoked without a ToolCall, the tool can return anything + """Test async invoke without ToolCall. + + If ainvoked without a ToolCall, the tool can return anything but it shouldn't throw an error. For debugging tips, see :meth:`test_invoke_no_tool_call`. diff --git a/libs/standard-tests/langchain_tests/integration_tests/vectorstores.py b/libs/standard-tests/langchain_tests/integration_tests/vectorstores.py index acb6960d5c0..96088a552cb 100644 --- a/libs/standard-tests/langchain_tests/integration_tests/vectorstores.py +++ b/libs/standard-tests/langchain_tests/integration_tests/vectorstores.py @@ -116,7 +116,9 @@ class VectorStoreIntegrationTests(BaseStandardTests): @staticmethod def get_embeddings() -> Embeddings: - """A pre-defined embeddings model that should be used for this test. + """Get embeddings. + + A pre-defined embeddings model that should be used for this test. This currently uses ``DeterministicFakeEmbedding`` from ``langchain-core``, which uses numpy to generate random numbers based on a hash of the input text. @@ -173,7 +175,9 @@ class VectorStoreIntegrationTests(BaseStandardTests): ] def test_vectorstore_still_empty(self, vectorstore: VectorStore) -> None: - """This test should follow a test that adds documents. + """Test that the vectorstore is still empty. + + This test should follow a test that adds documents. This just verifies that the fixture is set up properly to be empty after each test. @@ -499,7 +503,9 @@ class VectorStoreIntegrationTests(BaseStandardTests): async def test_vectorstore_still_empty_async( self, vectorstore: VectorStore ) -> None: - """This test should follow a test that adds documents. + """Test that the vectorstore is still empty. + + This test should follow a test that adds documents. This just verifies that the fixture is set up properly to be empty after each test. diff --git a/libs/standard-tests/langchain_tests/unit_tests/__init__.py b/libs/standard-tests/langchain_tests/unit_tests/__init__.py index ee4a1700eda..5ba211de31e 100644 --- a/libs/standard-tests/langchain_tests/unit_tests/__init__.py +++ b/libs/standard-tests/langchain_tests/unit_tests/__init__.py @@ -1,3 +1,5 @@ +"""Unit tests for LangChain components.""" + # ruff: noqa: E402 import pytest diff --git a/libs/standard-tests/langchain_tests/unit_tests/chat_models.py b/libs/standard-tests/langchain_tests/unit_tests/chat_models.py index a42201f2bce..0c3b038df8d 100644 --- a/libs/standard-tests/langchain_tests/unit_tests/chat_models.py +++ b/libs/standard-tests/langchain_tests/unit_tests/chat_models.py @@ -83,7 +83,10 @@ class ChatModelTests(BaseStandardTests): @property def standard_chat_model_params(self) -> dict: - """:private:""" + """Standard chat model parameters. + + :private: + """ return { "temperature": 0, "max_tokens": 100, @@ -94,7 +97,10 @@ class ChatModelTests(BaseStandardTests): @pytest.fixture def model(self) -> BaseChatModel: - """:private:""" + """Model fixture. + + :private: + """ return self.chat_model_class( **{ **self.standard_chat_model_params, @@ -104,11 +110,17 @@ class ChatModelTests(BaseStandardTests): @pytest.fixture def my_adder_tool(self) -> BaseTool: - """:private:""" + """Adder tool fixture. + + :private: + """ @tool def my_adder_tool(a: int, b: int) -> int: - """Takes two integers, a and b, and returns their sum.""" + """Tool that adds two integers. + + Takes two integers, a and b, and returns their sum. + """ return a + b return my_adder_tool @@ -151,12 +163,22 @@ class ChatModelTests(BaseStandardTests): @property def supports_image_inputs(self) -> bool: - """(bool) whether the chat model supports image inputs, defaults to ``False``.""" # noqa: E501 + """Supports image inputs. + + (bool) whether the chat model supports image inputs, defaults to + ``False``. + + """ return False @property def supports_image_urls(self) -> bool: - """(bool) whether the chat model supports image inputs from URLs, defaults to ``False``.""" # noqa: E501 + """Supports image inputs from URLs. + + (bool) whether the chat model supports image inputs from URLs, defaults to + ``False``. + + """ return False @property @@ -166,12 +188,18 @@ class ChatModelTests(BaseStandardTests): @property def supports_audio_inputs(self) -> bool: - """(bool) whether the chat model supports audio inputs, defaults to ``False``.""" # noqa: E501 + """Supports audio inputs. + + (bool) whether the chat model supports audio inputs, defaults to ``False``. + + """ return False @property def supports_video_inputs(self) -> bool: - """(bool) whether the chat model supports video inputs, defaults to ``False``. + """Supports video inputs. + + (bool) whether the chat model supports video inputs, defaults to ``False``. No current tests are written for this feature. @@ -180,7 +208,12 @@ class ChatModelTests(BaseStandardTests): @property def returns_usage_metadata(self) -> bool: - """(bool) whether the chat model returns usage metadata on invoke and streaming responses.""" # noqa: E501 + """Returns usage metadata. + + (bool) whether the chat model returns usage metadata on invoke and streaming + responses. + + """ return True @property @@ -190,7 +223,12 @@ class ChatModelTests(BaseStandardTests): @property def supports_image_tool_message(self) -> bool: - """(bool) whether the chat model supports ``ToolMessage``s that include image content.""" # noqa: E501 + """Supports image ToolMessages. + + (bool) whether the chat model supports ToolMessages that include image + content. + + """ return False @property @@ -219,14 +257,16 @@ class ChatModelTests(BaseStandardTests): ] ], ]: - """(dict) what usage metadata details are emitted in invoke and stream. Only + """Supported usage metadata details. + + (dict) what usage metadata details are emitted in invoke and stream. Only needs to be overridden if these details are returned by the model. """ return {"invoke": [], "stream": []} class ChatModelUnitTests(ChatModelTests): - """Base class for chat model unit tests. + '''Base class for chat model unit tests. Test subclasses must implement the ``chat_model_class`` and ``chat_model_params`` properties to specify what model to test and its @@ -669,7 +709,7 @@ class ChatModelUnitTests(ChatModelTests): @pytest.fixture(scope="session") def vcr_config(_base_vcr_config: dict) -> dict: # noqa: F811 - \"\"\"Extend the default configuration from langchain_tests.\"\"\" + """Extend the default configuration from langchain_tests.""" config = _base_vcr_config.copy() config.setdefault("filter_headers", []).extend(_EXTRA_HEADERS) config["before_record_response"] = remove_response_headers @@ -705,7 +745,7 @@ class ChatModelUnitTests(ChatModelTests): @pytest.fixture(scope="session") def vcr_config(_base_vcr_config: dict) -> dict: # noqa: F811 - \"\"\"Extend the default configuration from langchain_tests.\"\"\" + """Extend the default configuration from langchain_tests.""" config = _base_vcr_config.copy() config.setdefault("filter_headers", []).extend(_EXTRA_HEADERS) config["before_record_response"] = remove_response_headers @@ -789,18 +829,23 @@ class ChatModelUnitTests(ChatModelTests): }, ) - """ # noqa: E501 + ''' # noqa: E501,D214 @property def standard_chat_model_params(self) -> dict: - """:private:""" + """Standard chat model parameters. + + :private: + """ params = super().standard_chat_model_params params["api_key"] = "test" return params @property def init_from_env_params(self) -> tuple[dict, dict, dict]: - """(tuple) environment variables, additional initialization args, and expected + """Init from env params. + + (tuple) environment variables, additional initialization args, and expected instance attributes for testing initialization from environment variables. """ @@ -826,9 +871,10 @@ class ChatModelUnitTests(ChatModelTests): assert model is not None def test_init_from_env(self) -> None: - """Test initialization from environment variables. Relies on the - ``init_from_env_params`` property. Test is skipped if that property is not - set. + """Test initialization from environment variables. + + Relies on the ``init_from_env_params`` property. Test is skipped if that + property is not set. .. dropdown:: Troubleshooting @@ -853,8 +899,9 @@ class ChatModelUnitTests(ChatModelTests): def test_init_streaming( self, ) -> None: - """Test that model can be initialized with ``streaming=True``. This is for - backward-compatibility purposes. + """Test that model can be initialized with ``streaming=True``. + + This is for backward-compatibility purposes. .. dropdown:: Troubleshooting @@ -876,7 +923,9 @@ class ChatModelUnitTests(ChatModelTests): model: BaseChatModel, my_adder_tool: BaseTool, ) -> None: - """Test that chat model correctly handles Pydantic models that are passed + """Test bind tools with Pydantic models. + + Test that chat model correctly handles Pydantic models that are passed into ``bind_tools``. Test is skipped if the ``has_tool_calling`` property on the test class is False. @@ -893,7 +942,7 @@ class ChatModelUnitTests(ChatModelTests): return def my_adder(a: int, b: int) -> int: - """Takes two integers, a and b, and returns their sum.""" + """Return the sum of two integers.""" return a + b tools = [my_adder_tool, my_adder] @@ -918,8 +967,10 @@ class ChatModelUnitTests(ChatModelTests): model: BaseChatModel, schema: Any, ) -> None: - """Test ``with_structured_output`` method. Test is skipped if the - ``has_structured_output`` property on the test class is False. + """Test ``with_structured_output`` method. + + Test is skipped if the ``has_structured_output`` property on the test class is + False. .. dropdown:: Troubleshooting @@ -942,8 +993,9 @@ class ChatModelUnitTests(ChatModelTests): ) def test_standard_params(self, model: BaseChatModel) -> None: - """Test that model properly generates standard parameters. These are used - for tracing purposes. + """Test that model properly generates standard parameters. + + These are used for tracing purposes. .. dropdown:: Troubleshooting @@ -981,9 +1033,10 @@ class ChatModelUnitTests(ChatModelTests): pytest.fail(f"Validation error: {e}") def test_serdes(self, model: BaseChatModel, snapshot: SnapshotAssertion) -> None: - """Test serialization and deserialization of the model. Test is skipped if the - ``is_lc_serializable`` property on the chat model class is not overwritten - to return ``True``. + """Test serialization and deserialization of the model. + + Test is skipped if the ``is_lc_serializable`` property on the chat model class + is not overwritten to return ``True``. .. dropdown:: Troubleshooting @@ -1007,7 +1060,9 @@ class ChatModelUnitTests(ChatModelTests): @pytest.mark.benchmark def test_init_time(self, benchmark: BenchmarkFixture) -> None: - """Test initialization time of the chat model. If this test fails, check that + """Test initialization time of the chat model. + + If this test fails, check that we are not introducing undue overhead in the model's initialization. """ diff --git a/libs/standard-tests/langchain_tests/unit_tests/embeddings.py b/libs/standard-tests/langchain_tests/unit_tests/embeddings.py index 0df698ee8bd..a1693b497a3 100644 --- a/libs/standard-tests/langchain_tests/unit_tests/embeddings.py +++ b/libs/standard-tests/langchain_tests/unit_tests/embeddings.py @@ -1,3 +1,5 @@ +"""Embeddings unit tests.""" + import os from abc import abstractmethod from unittest import mock @@ -10,18 +12,24 @@ from langchain_tests.base import BaseStandardTests class EmbeddingsTests(BaseStandardTests): - """:private:""" + """Embeddings tests base class. + + :private: + """ @property @abstractmethod - def embeddings_class(self) -> type[Embeddings]: ... + def embeddings_class(self) -> type[Embeddings]: + """Embeddings class.""" @property def embedding_model_params(self) -> dict: + """Embeddings model parameters.""" return {} @pytest.fixture def model(self) -> Embeddings: + """Embeddings model fixture.""" return self.embeddings_class(**self.embedding_model_params) @@ -87,7 +95,7 @@ class EmbeddingsUnitTests(EmbeddingsTests): }, ) - """ + """ # noqa: D214 def test_init(self) -> None: """Test model initialization. @@ -102,7 +110,9 @@ class EmbeddingsUnitTests(EmbeddingsTests): @property def init_from_env_params(self) -> tuple[dict, dict, dict]: - """This property is used in unit tests to test initialization from environment + """Init from env params. + + This property is used in unit tests to test initialization from environment variables. It should return a tuple of three dictionaries that specify the environment variables, additional initialization args, and expected instance attributes to check. @@ -110,9 +120,10 @@ class EmbeddingsUnitTests(EmbeddingsTests): return {}, {}, {} def test_init_from_env(self) -> None: - """Test initialization from environment variables. Relies on the - ``init_from_env_params`` property. Test is skipped if that property is not - set. + """Test initialization from environment variables. + + Relies on the ``init_from_env_params`` property. + Test is skipped if that property is not set. .. dropdown:: Troubleshooting diff --git a/libs/standard-tests/langchain_tests/unit_tests/tools.py b/libs/standard-tests/langchain_tests/unit_tests/tools.py index cbc40dc4121..fb59a2065c6 100644 --- a/libs/standard-tests/langchain_tests/unit_tests/tools.py +++ b/libs/standard-tests/langchain_tests/unit_tests/tools.py @@ -1,3 +1,5 @@ +"""Tools unit tests.""" + import os from abc import abstractmethod from typing import Union @@ -11,9 +13,11 @@ from langchain_tests.base import BaseStandardTests class ToolsTests(BaseStandardTests): - """:private: - Base class for testing tools. This won't show in the documentation, but - the docstrings will be inherited by subclasses. + """Base class for testing tools. + + :private: + This won't show in the documentation, but the docstrings will be inherited by + subclasses. """ @property @@ -38,7 +42,10 @@ class ToolsTests(BaseStandardTests): @pytest.fixture def tool(self) -> BaseTool: - """:private:""" + """Tool fixture. + + :private: + """ if isinstance(self.tool_constructor, BaseTool): if self.tool_constructor_params != {}: msg = ( @@ -55,13 +62,17 @@ class ToolsUnitTests(ToolsTests): @property def init_from_env_params(self) -> tuple[dict, dict, dict]: - """Return env vars, init args, and expected instance attrs for initializing + """Init from env params. + + Return env vars, init args, and expected instance attrs for initializing from env vars. """ return {}, {}, {} def test_init(self) -> None: - """Test that the tool can be initialized with :attr:`tool_constructor` and + """Test init. + + Test that the tool can be initialized with :attr:`tool_constructor` and :attr:`tool_constructor_params`. If this fails, check that the keyword args defined in :attr:`tool_constructor_params` are valid. """ @@ -72,6 +83,7 @@ class ToolsUnitTests(ToolsTests): assert tool is not None def test_init_from_env(self) -> None: + """Test that the tool can be initialized from environment variables.""" env_params, tools_params, expected_attrs = self.init_from_env_params if env_params: with mock.patch.dict(os.environ, env_params): diff --git a/libs/standard-tests/langchain_tests/utils/__init__.py b/libs/standard-tests/langchain_tests/utils/__init__.py index e69de29bb2d..a320431fc87 100644 --- a/libs/standard-tests/langchain_tests/utils/__init__.py +++ b/libs/standard-tests/langchain_tests/utils/__init__.py @@ -0,0 +1 @@ +"""Langchain tests utilities.""" diff --git a/libs/standard-tests/pyproject.toml b/libs/standard-tests/pyproject.toml index f30b8b37c71..2c50bd11c09 100644 --- a/libs/standard-tests/pyproject.toml +++ b/libs/standard-tests/pyproject.toml @@ -55,9 +55,12 @@ ignore_missing_imports = true target-version = "py39" [tool.ruff.lint] -select = ["E", "F", "I", "PGH", "T201", "UP",] +select = ["D", "E", "F", "I", "PGH", "T201", "UP",] pyupgrade.keep-runtime-typing = true +[tool.ruff.lint.per-file-ignores] +"tests/**" = [ "D1",] + [tool.coverage.run] omit = ["tests/*"] diff --git a/libs/standard-tests/scripts/check_imports.py b/libs/standard-tests/scripts/check_imports.py index fb5a5641fef..47360d73bb2 100644 --- a/libs/standard-tests/scripts/check_imports.py +++ b/libs/standard-tests/scripts/check_imports.py @@ -1,3 +1,5 @@ +"""Check imports script.""" + import secrets import string import sys diff --git a/libs/standard-tests/tests/unit_tests/custom_chat_model.py b/libs/standard-tests/tests/unit_tests/custom_chat_model.py index 737745ec27e..d8f9f7c668f 100644 --- a/libs/standard-tests/tests/unit_tests/custom_chat_model.py +++ b/libs/standard-tests/tests/unit_tests/custom_chat_model.py @@ -10,7 +10,9 @@ from pydantic import Field class ChatParrotLink(BaseChatModel): - """A custom chat model that echoes the first `parrot_buffer_length` characters + """Chat Parrot Link. + + A custom chat model that echoes the first `parrot_buffer_length` characters of the input. When contributing an implementation to LangChain, carefully document @@ -60,6 +62,8 @@ class ChatParrotLink(BaseChatModel): it makes it much easier to parse the output of the model downstream and understand why generation stopped. run_manager: A run manager with callbacks for the LLM. + **kwargs: Additional keyword arguments. + """ # Replace this with actual logic to generate a response from a list # of messages. @@ -111,6 +115,8 @@ class ChatParrotLink(BaseChatModel): it makes it much easier to parse the output of the model downstream and understand why generation stopped. run_manager: A run manager with callbacks for the LLM. + **kwargs: Additional keyword arguments. + """ _ = stop # Mark as used to avoid unused variable warning _ = kwargs # Mark as used to avoid unused variable warning