From d57216c295d7bc496391782ad0abfa33086dd8c6 Mon Sep 17 00:00:00 2001 From: Christophe Bornet Date: Mon, 14 Jul 2025 16:42:03 +0200 Subject: [PATCH] feat(core): add ruff rules D to tests except D1 (#32000) Docs are not required for tests but when there are docstrings, they shall be correctly formatted. See https://docs.astral.sh/ruff/rules/#pydocstyle-d --- libs/core/pyproject.toml | 2 +- .../test_deterministic_embedding.py | 4 +- .../unit_tests/indexing/test_indexing.py | 3 +- .../language_models/llms/test_base.py | 2 +- .../output_parsers/test_list_parser.py | 8 +++- .../tests/unit_tests/prompts/test_prompt.py | 5 ++- .../unit_tests/runnables/test_runnable.py | 39 +++++++++++++------ .../runnables/test_runnable_events_v2.py | 1 - libs/core/tests/unit_tests/test_messages.py | 2 +- .../tests/unit_tests/test_pydantic_serde.py | 4 +- libs/core/tests/unit_tests/test_tools.py | 15 +++---- .../vectorstores/test_vectorstore.py | 4 +- libs/core/uv.lock | 6 +-- 13 files changed, 61 insertions(+), 34 deletions(-) diff --git a/libs/core/pyproject.toml b/libs/core/pyproject.toml index 5d1f0e62fce..c48e9f553c2 100644 --- a/libs/core/pyproject.toml +++ b/libs/core/pyproject.toml @@ -124,5 +124,5 @@ asyncio_default_fixture_loop_scope = "function" [tool.ruff.lint.per-file-ignores] "langchain_core/utils/mustache.py" = [ "PLW0603",] "tests/unit_tests/test_tools.py" = [ "ARG",] -"tests/**" = [ "D", "S", "SLF",] +"tests/**" = [ "D1", "S", "SLF",] "scripts/**" = [ "INP", "S",] diff --git a/libs/core/tests/unit_tests/embeddings/test_deterministic_embedding.py b/libs/core/tests/unit_tests/embeddings/test_deterministic_embedding.py index f4eb128a607..94b948d973f 100644 --- a/libs/core/tests/unit_tests/embeddings/test_deterministic_embedding.py +++ b/libs/core/tests/unit_tests/embeddings/test_deterministic_embedding.py @@ -2,7 +2,9 @@ from langchain_core.embeddings import DeterministicFakeEmbedding def test_deterministic_fake_embeddings() -> None: - """Test that the deterministic fake embeddings return the same + """Test that DeterministicFakeEmbedding is deterministic. + + Test that the deterministic fake embeddings return the same embedding vector for the same text. """ fake = DeterministicFakeEmbedding(size=10) diff --git a/libs/core/tests/unit_tests/indexing/test_indexing.py b/libs/core/tests/unit_tests/indexing/test_indexing.py index 1f6ca8671e9..2343f630b6f 100644 --- a/libs/core/tests/unit_tests/indexing/test_indexing.py +++ b/libs/core/tests/unit_tests/indexing/test_indexing.py @@ -905,7 +905,7 @@ async def test_ascoped_full_fails_with_bad_source_ids( def test_index_empty_doc_scoped_full( record_manager: InMemoryRecordManager, vector_store: InMemoryVectorStore ) -> None: - """Test Indexing with scoped_full strategy""" + """Test Indexing with scoped_full strategy.""" loader = ToyLoader( documents=[ Document( @@ -1927,7 +1927,6 @@ def test_incremental_cleanup_with_different_batchsize( record_manager: InMemoryRecordManager, vector_store: VectorStore ) -> None: """Check that we can clean up with different batch size.""" - docs = [ Document( page_content="This is a test document.", diff --git a/libs/core/tests/unit_tests/language_models/llms/test_base.py b/libs/core/tests/unit_tests/language_models/llms/test_base.py index b81f98d07be..438580eafbc 100644 --- a/libs/core/tests/unit_tests/language_models/llms/test_base.py +++ b/libs/core/tests/unit_tests/language_models/llms/test_base.py @@ -99,7 +99,7 @@ async def test_async_batch_size() -> None: async def test_error_callback() -> None: class FailingLLMError(Exception): - """FailingLLMError""" + """FailingLLMError.""" class FailingLLM(LLM): @property diff --git a/libs/core/tests/unit_tests/output_parsers/test_list_parser.py b/libs/core/tests/unit_tests/output_parsers/test_list_parser.py index c49d80fae8e..85d24088ea1 100644 --- a/libs/core/tests/unit_tests/output_parsers/test_list_parser.py +++ b/libs/core/tests/unit_tests/output_parsers/test_list_parser.py @@ -28,7 +28,9 @@ def test_single_item() -> None: def test_multiple_items_with_spaces() -> None: - """Test that a string with multiple comma-separated items + """Test multiple items with spaces. + + Test that a string with multiple comma-separated items with spaces is parsed to a list. """ parser = CommaSeparatedListOutputParser() @@ -66,7 +68,9 @@ def test_multiple_items() -> None: def test_multiple_items_with_comma() -> None: - """Test that a string with multiple comma-separated items with 1 item containing a + """Test multiple items with a comma. + + Test that a string with multiple comma-separated items with 1 item containing a comma is parsed to a list. """ parser = CommaSeparatedListOutputParser() diff --git a/libs/core/tests/unit_tests/prompts/test_prompt.py b/libs/core/tests/unit_tests/prompts/test_prompt.py index 50e23981776..e092eb66581 100644 --- a/libs/core/tests/unit_tests/prompts/test_prompt.py +++ b/libs/core/tests/unit_tests/prompts/test_prompt.py @@ -361,8 +361,9 @@ def test_prompt_from_file() -> None: def test_prompt_from_file_with_partial_variables() -> None: - """Test prompt can be successfully constructed from a file - with partial variables. + """Test prompt from file with partial variables. + + Test prompt can be successfully constructed from a file with partial variables. """ # given template = "This is a {foo} test {bar}." diff --git a/libs/core/tests/unit_tests/runnables/test_runnable.py b/libs/core/tests/unit_tests/runnables/test_runnable.py index 98a8ae09eb0..4b63fb50ae2 100644 --- a/libs/core/tests/unit_tests/runnables/test_runnable.py +++ b/libs/core/tests/unit_tests/runnables/test_runnable.py @@ -102,6 +102,7 @@ PYDANTIC_VERSION_AT_LEAST_210 = version.parse("2.10") <= PYDANTIC_VERSION class FakeTracer(BaseTracer): """Fake tracer that records LangChain execution. + It replaces run ids with deterministic UUIDs for snapshotting. """ @@ -4867,7 +4868,9 @@ async def test_runnable_gen_async() -> None: def test_runnable_gen_context_config() -> None: - """Test that a generator can call other runnables with config + """Test generator runnable config propagation. + + Test that a generator can call other runnables with config propagated from the context. """ fake = RunnableLambda(len) @@ -4942,9 +4945,11 @@ def test_runnable_gen_context_config() -> None: "async tasks in a specific context", ) async def test_runnable_gen_context_config_async() -> None: - """Test that a generator can call other runnables with config - propagated from the context.""" + """Test generator runnable config propagation. + Test that a generator can call other runnables with config + propagated from the context. + """ fake = RunnableLambda(len) async def agen(_: AsyncIterator[Any]) -> AsyncIterator[int]: @@ -5010,7 +5015,9 @@ async def test_runnable_gen_context_config_async() -> None: def test_runnable_iter_context_config() -> None: - """Test that a generator can call other runnables with config + """Test generator runnable config propagation. + + Test that a generator can call other runnables with config propagated from the context. """ fake = RunnableLambda(len) @@ -5069,9 +5076,11 @@ def test_runnable_iter_context_config() -> None: "async tasks in a specific context", ) async def test_runnable_iter_context_config_async() -> None: - """Test that a generator can call other runnables with config - propagated from the context.""" + """Test generator runnable config propagation. + Test that a generator can call other runnables with config + propagated from the context. + """ fake = RunnableLambda(len) @chain @@ -5135,7 +5144,9 @@ async def test_runnable_iter_context_config_async() -> None: def test_runnable_lambda_context_config() -> None: - """Test that a function can call other runnables with config + """Test function runnable config propagation. + + Test that a function can call other runnables with config propagated from the context. """ fake = RunnableLambda(len) @@ -5192,9 +5203,11 @@ def test_runnable_lambda_context_config() -> None: "async tasks in a specific context", ) async def test_runnable_lambda_context_config_async() -> None: - """Test that a function can call other runnables with config - propagated from the context.""" + """Test function runnable config propagation. + Test that a function can call other runnables with config + propagated from the context. + """ fake = RunnableLambda(len) @chain @@ -5295,7 +5308,9 @@ def test_with_config_callbacks() -> None: async def test_ainvoke_on_returned_runnable() -> None: - """Verify that a runnable returned by a sync runnable in the async path will + """Test ainvoke on a returned runnable. + + Verify that a runnable returned by a sync runnable in the async path will be runthroughaasync path (issue #13407). """ @@ -5637,7 +5652,9 @@ def test_pydantic_protected_namespaces() -> None: def test_schema_for_prompt_and_chat_model() -> None: - """Testing that schema is generated properly when using variable names + """Test schema generation for prompt and chat model. + + Testing that schema is generated properly when using variable names that collide with pydantic attributes. """ prompt = ChatPromptTemplate([("system", "{model_json_schema}, {_private}, {json}")]) diff --git a/libs/core/tests/unit_tests/runnables/test_runnable_events_v2.py b/libs/core/tests/unit_tests/runnables/test_runnable_events_v2.py index ea7fe95ba5b..a7731053032 100644 --- a/libs/core/tests/unit_tests/runnables/test_runnable_events_v2.py +++ b/libs/core/tests/unit_tests/runnables/test_runnable_events_v2.py @@ -2797,6 +2797,5 @@ async def test_custom_event_root_dispatch_with_in_tool() -> None: def test_default_is_v2() -> None: """Test that we default to version="v2".""" - signature = inspect.signature(Runnable.astream_events) assert signature.parameters["version"].default == "v2" diff --git a/libs/core/tests/unit_tests/test_messages.py b/libs/core/tests/unit_tests/test_messages.py index e6cc725cfca..58822433d7a 100644 --- a/libs/core/tests/unit_tests/test_messages.py +++ b/libs/core/tests/unit_tests/test_messages.py @@ -940,7 +940,7 @@ def test_tool_message_serdes() -> None: class BadObject: - """""" + pass def test_tool_message_ser_non_serializable() -> None: diff --git a/libs/core/tests/unit_tests/test_pydantic_serde.py b/libs/core/tests/unit_tests/test_pydantic_serde.py index 32ac6447315..1d98ecaedcd 100644 --- a/libs/core/tests/unit_tests/test_pydantic_serde.py +++ b/libs/core/tests/unit_tests/test_pydantic_serde.py @@ -1,4 +1,6 @@ -"""A set of tests that verifies that Union discrimination works correctly with +"""Test pydantic SerDe. + +A set of tests that verifies that Union discrimination works correctly with the various pydantic base models. These tests can uncover issues that will also arise during regular instantiation diff --git a/libs/core/tests/unit_tests/test_tools.py b/libs/core/tests/unit_tests/test_tools.py index e163ca15ba4..f5cc42e1b4d 100644 --- a/libs/core/tests/unit_tests/test_tools.py +++ b/libs/core/tests/unit_tests/test_tools.py @@ -544,8 +544,9 @@ def test_empty_args_decorator() -> None: def test_tool_from_function_with_run_manager() -> None: """Test run of tool when using run_manager.""" - def foo(bar: str, callbacks: Optional[CallbackManagerForToolRun] = None) -> str: - """Docstring + def foo(bar: str, callbacks: Optional[CallbackManagerForToolRun] = None) -> str: # noqa: D417 + """Docstring. + Args: bar: str. """ @@ -562,7 +563,7 @@ def test_tool_from_function_with_run_manager() -> None: def test_structured_tool_from_function_with_run_manager() -> None: """Test args and schema of structured tool when using callbacks.""" - def foo( + def foo( # noqa: D417 bar: int, baz: str, callbacks: Optional[CallbackManagerForToolRun] = None ) -> str: """Docstring. @@ -1193,7 +1194,7 @@ def test_tool_arg_descriptions() -> None: assert args_schema == expected # Test parsing with run_manager does not raise error - def foo3( + def foo3( # noqa: D417 bar: str, baz: int, run_manager: Optional[CallbackManagerForToolRun] = None ) -> str: """The foo. @@ -1310,7 +1311,7 @@ def test_docstring_parsing() -> None: def test_tool_invalid_docstrings() -> None: - """Test invalid docstrings""" + """Test invalid docstrings.""" def foo3(bar: str, baz: int) -> str: """The foo.""" @@ -1321,14 +1322,14 @@ def test_tool_invalid_docstrings() -> None: Args: bar: The bar. baz: The baz. - """ + """ # noqa: D205,D411 return bar for func in {foo3, foo4}: with pytest.raises(ValueError, match="Found invalid Google-Style docstring."): _ = tool(func, parse_docstring=True) - def foo5(bar: str, baz: int) -> str: + def foo5(bar: str, baz: int) -> str: # noqa: D417 """The foo. Args: diff --git a/libs/core/tests/unit_tests/vectorstores/test_vectorstore.py b/libs/core/tests/unit_tests/vectorstores/test_vectorstore.py index 172e441055f..75fed8fea84 100644 --- a/libs/core/tests/unit_tests/vectorstores/test_vectorstore.py +++ b/libs/core/tests/unit_tests/vectorstores/test_vectorstore.py @@ -121,7 +121,9 @@ class CustomAddDocumentsVectorstore(VectorStore): "vs_class", [CustomAddTextsVectorstore, CustomAddDocumentsVectorstore] ) def test_default_add_documents(vs_class: type[VectorStore]) -> None: - """Test that we can implement the upsert method of the CustomVectorStore + """Test default implementation of add_documents. + + Test that we can implement the upsert method of the CustomVectorStore class without violating the Liskov Substitution Principle. """ store = vs_class() diff --git a/libs/core/uv.lock b/libs/core/uv.lock index ac765240b1a..de302c3dabe 100644 --- a/libs/core/uv.lock +++ b/libs/core/uv.lock @@ -1008,7 +1008,7 @@ dev = [ { name = "jupyter", specifier = ">=1.0.0,<2.0.0" }, { name = "setuptools", specifier = ">=67.6.1,<68.0.0" }, ] -lint = [{ name = "ruff", specifier = ">=0.12.2,<0.13.0" }] +lint = [{ name = "ruff", specifier = ">=0.12.2,<0.13" }] test = [ { name = "blockbuster", specifier = "~=1.5.18" }, { name = "freezegun", specifier = ">=1.2.2,<2.0.0" }, @@ -1072,7 +1072,7 @@ requires-dist = [ [package.metadata.requires-dev] codespell = [{ name = "codespell", specifier = ">=2.2.0,<3.0.0" }] -lint = [{ name = "ruff", specifier = ">=0.9.2,<1.0.0" }] +lint = [{ name = "ruff", specifier = ">=0.12.2,<0.13" }] test = [{ name = "langchain-core", editable = "." }] test-integration = [] typing = [ @@ -1098,7 +1098,7 @@ dev = [ ] lint = [ { name = "langchain-core", editable = "." }, - { name = "ruff", specifier = ">=0.9.2,<1.0.0" }, + { name = "ruff", specifier = ">=0.12.2,<0.13" }, ] test = [ { name = "freezegun", specifier = ">=1.2.2,<2.0.0" },