From 861027e67ac684147aab13d3c429e0ae384880e4 Mon Sep 17 00:00:00 2001 From: cbornet Date: Wed, 23 Jul 2025 17:01:36 +0200 Subject: [PATCH] feat(langchain): add ruff rules N --- libs/langchain/langchain/agents/__init__.py | 4 ++-- .../langchain/agents/agent_toolkits/csv/__init__.py | 13 +++---------- .../agents/agent_toolkits/pandas/__init__.py | 13 +++---------- .../agents/agent_toolkits/python/__init__.py | 13 +++---------- .../agents/agent_toolkits/spark/__init__.py | 13 +++---------- .../agents/agent_toolkits/xorbits/__init__.py | 13 +++---------- .../langchain/callbacks/streamlit/__init__.py | 2 +- libs/langchain/langchain/chains/llm.py | 2 +- libs/langchain/langchain/chat_models/base.py | 1 + .../langchain/retrievers/self_query/base.py | 6 +++--- .../langchain/smith/evaluation/runner_utils.py | 2 +- libs/langchain/langchain/tools/__init__.py | 8 ++++---- libs/langchain/pyproject.toml | 4 +++- .../integration_tests/chat_models/test_base.py | 4 ++-- .../tests/unit_tests/chains/test_sequential.py | 8 +++++--- .../evaluation/comparison/test_eval_chain.py | 2 +- .../evaluation/criteria/test_eval_chain.py | 2 +- .../evaluation/scoring/test_eval_chain.py | 2 +- 18 files changed, 41 insertions(+), 71 deletions(-) diff --git a/libs/langchain/langchain/agents/__init__.py b/libs/langchain/langchain/agents/__init__.py index f919f5fbdf4..f182b3b6b73 100644 --- a/libs/langchain/langchain/agents/__init__.py +++ b/libs/langchain/langchain/agents/__init__.py @@ -120,11 +120,11 @@ def __getattr__(name: str) -> Any: """Get attr name.""" if name in DEPRECATED_CODE: # Get directory of langchain package - HERE = Path(__file__).parents[1] + here = Path(__file__).parents[1] relative_path = as_import_path( Path(__file__).parent, suffix=name, - relative_to=HERE, + relative_to=here, ) old_path = "langchain." + relative_path new_path = "langchain_experimental." + relative_path diff --git a/libs/langchain/langchain/agents/agent_toolkits/csv/__init__.py b/libs/langchain/langchain/agents/agent_toolkits/csv/__init__.py index 82c49e246a6..c877de12572 100644 --- a/libs/langchain/langchain/agents/agent_toolkits/csv/__init__.py +++ b/libs/langchain/langchain/agents/agent_toolkits/csv/__init__.py @@ -1,19 +1,10 @@ -from pathlib import Path from typing import Any -from langchain_core._api.path import as_import_path - def __getattr__(name: str) -> Any: """Get attr name.""" if name == "create_csv_agent": - # Get directory of langchain package - HERE = Path(__file__).parents[3] - here = as_import_path(Path(__file__).parent, relative_to=HERE) - - old_path = "langchain." + here + "." + name - new_path = "langchain_experimental." + here + "." + name msg = ( "This agent has been moved to langchain experiment. " "This agent relies on python REPL tool under the hood, so to use it " @@ -21,7 +12,9 @@ def __getattr__(name: str) -> Any: "Read https://github.com/langchain-ai/langchain/blob/master/SECURITY.md " "and https://github.com/langchain-ai/langchain/discussions/11680" "To keep using this code as is, install langchain experimental and " - f"update your import statement from:\n `{old_path}` to `{new_path}`." + "update your import statement from:\n " + f"`langchain.agents.agent_toolkits.csv.{name}` to " + f"`langchain_experimental.agents.agent_toolkits.{name}`." ) raise ImportError(msg) msg = f"{name} does not exist" diff --git a/libs/langchain/langchain/agents/agent_toolkits/pandas/__init__.py b/libs/langchain/langchain/agents/agent_toolkits/pandas/__init__.py index edb90f5a7c0..4ed1ad4a196 100644 --- a/libs/langchain/langchain/agents/agent_toolkits/pandas/__init__.py +++ b/libs/langchain/langchain/agents/agent_toolkits/pandas/__init__.py @@ -1,19 +1,10 @@ -from pathlib import Path from typing import Any -from langchain_core._api.path import as_import_path - def __getattr__(name: str) -> Any: """Get attr name.""" if name == "create_pandas_dataframe_agent": - # Get directory of langchain package - HERE = Path(__file__).parents[3] - here = as_import_path(Path(__file__).parent, relative_to=HERE) - - old_path = "langchain." + here + "." + name - new_path = "langchain_experimental." + here + "." + name msg = ( "This agent has been moved to langchain experiment. " "This agent relies on python REPL tool under the hood, so to use it " @@ -21,7 +12,9 @@ def __getattr__(name: str) -> Any: "Read https://github.com/langchain-ai/langchain/blob/master/SECURITY.md " "and https://github.com/langchain-ai/langchain/discussions/11680" "To keep using this code as is, install langchain experimental and " - f"update your import statement from:\n `{old_path}` to `{new_path}`." + "update your import statement from:\n" + f"`langchain.agents.agent_toolkits.pandas.{name}` to " + f"`langchain_experimental.agents.agent_toolkits.{name}`." ) raise ImportError(msg) msg = f"{name} does not exist" diff --git a/libs/langchain/langchain/agents/agent_toolkits/python/__init__.py b/libs/langchain/langchain/agents/agent_toolkits/python/__init__.py index 0ce36303edc..674f38e96cf 100644 --- a/libs/langchain/langchain/agents/agent_toolkits/python/__init__.py +++ b/libs/langchain/langchain/agents/agent_toolkits/python/__init__.py @@ -1,19 +1,10 @@ -from pathlib import Path from typing import Any -from langchain_core._api.path import as_import_path - def __getattr__(name: str) -> Any: """Get attr name.""" if name == "create_python_agent": - # Get directory of langchain package - HERE = Path(__file__).parents[3] - here = as_import_path(Path(__file__).parent, relative_to=HERE) - - old_path = "langchain." + here + "." + name - new_path = "langchain_experimental." + here + "." + name msg = ( "This agent has been moved to langchain experiment. " "This agent relies on python REPL tool under the hood, so to use it " @@ -21,7 +12,9 @@ def __getattr__(name: str) -> Any: "Read https://github.com/langchain-ai/langchain/blob/master/SECURITY.md " "and https://github.com/langchain-ai/langchain/discussions/11680" "To keep using this code as is, install langchain experimental and " - f"update your import statement from:\n `{old_path}` to `{new_path}`." + "update your import statement from:\n" + f"`langchain.agents.agent_toolkits.python.{name}` to " + f"`langchain_experimental.agents.agent_toolkits.{name}`." ) raise ImportError(msg) msg = f"{name} does not exist" diff --git a/libs/langchain/langchain/agents/agent_toolkits/spark/__init__.py b/libs/langchain/langchain/agents/agent_toolkits/spark/__init__.py index 76f96cc3352..5be92f2379c 100644 --- a/libs/langchain/langchain/agents/agent_toolkits/spark/__init__.py +++ b/libs/langchain/langchain/agents/agent_toolkits/spark/__init__.py @@ -1,19 +1,10 @@ -from pathlib import Path from typing import Any -from langchain_core._api.path import as_import_path - def __getattr__(name: str) -> Any: """Get attr name.""" if name == "create_spark_dataframe_agent": - # Get directory of langchain package - HERE = Path(__file__).parents[3] - here = as_import_path(Path(__file__).parent, relative_to=HERE) - - old_path = "langchain." + here + "." + name - new_path = "langchain_experimental." + here + "." + name msg = ( "This agent has been moved to langchain experiment. " "This agent relies on python REPL tool under the hood, so to use it " @@ -21,7 +12,9 @@ def __getattr__(name: str) -> Any: "Read https://github.com/langchain-ai/langchain/blob/master/SECURITY.md " "and https://github.com/langchain-ai/langchain/discussions/11680" "To keep using this code as is, install langchain experimental and " - f"update your import statement from:\n `{old_path}` to `{new_path}`." + "update your import statement from:\n" + f"`langchain.agents.agent_toolkits.spark.{name}` to " + f"`langchain_experimental.agents.agent_toolkits.{name}`." ) raise ImportError(msg) msg = f"{name} does not exist" diff --git a/libs/langchain/langchain/agents/agent_toolkits/xorbits/__init__.py b/libs/langchain/langchain/agents/agent_toolkits/xorbits/__init__.py index 7f23f48262d..04c235e9bd6 100644 --- a/libs/langchain/langchain/agents/agent_toolkits/xorbits/__init__.py +++ b/libs/langchain/langchain/agents/agent_toolkits/xorbits/__init__.py @@ -1,19 +1,10 @@ -from pathlib import Path from typing import Any -from langchain_core._api.path import as_import_path - def __getattr__(name: str) -> Any: """Get attr name.""" if name == "create_xorbits_agent": - # Get directory of langchain package - HERE = Path(__file__).parents[3] - here = as_import_path(Path(__file__).parent, relative_to=HERE) - - old_path = "langchain." + here + "." + name - new_path = "langchain_experimental." + here + "." + name msg = ( "This agent has been moved to langchain experiment. " "This agent relies on python REPL tool under the hood, so to use it " @@ -21,7 +12,9 @@ def __getattr__(name: str) -> Any: "Read https://github.com/langchain-ai/langchain/blob/master/SECURITY.md " "and https://github.com/langchain-ai/langchain/discussions/11680" "To keep using this code as is, install langchain experimental and " - f"update your import statement from:\n `{old_path}` to `{new_path}`." + "update your import statement from:\n" + f"`langchain.agents.agent_toolkits.xorbits.{name}` to " + f"`langchain_experimental.agents.agent_toolkits.{name}`." ) raise ImportError(msg) msg = f"{name} does not exist" diff --git a/libs/langchain/langchain/callbacks/streamlit/__init__.py b/libs/langchain/langchain/callbacks/streamlit/__init__.py index 21f33436120..90319bb3107 100644 --- a/libs/langchain/langchain/callbacks/streamlit/__init__.py +++ b/libs/langchain/langchain/callbacks/streamlit/__init__.py @@ -9,7 +9,7 @@ if TYPE_CHECKING: from streamlit.delta_generator import DeltaGenerator -def StreamlitCallbackHandler( +def StreamlitCallbackHandler( # noqa: N802 parent_container: DeltaGenerator, *, max_thought_containers: int = 4, diff --git a/libs/langchain/langchain/chains/llm.py b/libs/langchain/langchain/chains/llm.py index ca43d7a9e84..405dd50d1f7 100644 --- a/libs/langchain/langchain/chains/llm.py +++ b/libs/langchain/langchain/chains/llm.py @@ -78,7 +78,7 @@ class LLMChain(Chain): @classmethod @override - def is_lc_serializable(self) -> bool: + def is_lc_serializable(cls) -> bool: return True prompt: BasePromptTemplate diff --git a/libs/langchain/langchain/chat_models/base.py b/libs/langchain/langchain/chat_models/base.py index 01e51c5b845..95ecc3c247d 100644 --- a/libs/langchain/langchain/chat_models/base.py +++ b/libs/langchain/langchain/chat_models/base.py @@ -659,6 +659,7 @@ class _ConfigurableModel(Runnable[LanguageModelInput, Any]): ) @property + @override def InputType(self) -> TypeAlias: """Get the input type for this runnable.""" from langchain_core.prompt_values import ( diff --git a/libs/langchain/langchain/retrievers/self_query/base.py b/libs/langchain/langchain/retrievers/self_query/base.py index ba15288307c..b00dec8276e 100644 --- a/libs/langchain/langchain/retrievers/self_query/base.py +++ b/libs/langchain/langchain/retrievers/self_query/base.py @@ -97,7 +97,7 @@ def _get_builtin_translator(vectorstore: VectorStore) -> Visitor: Pinecone as CommunityPinecone, ) - BUILTIN_TRANSLATORS: dict[type[VectorStore], type[Visitor]] = { + builtin_translators: dict[type[VectorStore], type[Visitor]] = { AstraDB: AstraDBTranslator, PGVector: PGVectorTranslator, CommunityPinecone: PineconeTranslator, @@ -128,8 +128,8 @@ def _get_builtin_translator(vectorstore: VectorStore) -> Visitor: field.name for field in (vectorstore.meta_fields or []) if field.index ] return TencentVectorDBTranslator(fields) - if vectorstore.__class__ in BUILTIN_TRANSLATORS: - return BUILTIN_TRANSLATORS[vectorstore.__class__]() + if vectorstore.__class__ in builtin_translators: + return builtin_translators[vectorstore.__class__]() try: from langchain_astradb.vectorstores import AstraDBVectorStore except ImportError: diff --git a/libs/langchain/langchain/smith/evaluation/runner_utils.py b/libs/langchain/langchain/smith/evaluation/runner_utils.py index 89096c01794..676ed3636e3 100644 --- a/libs/langchain/langchain/smith/evaluation/runner_utils.py +++ b/libs/langchain/langchain/smith/evaluation/runner_utils.py @@ -154,7 +154,7 @@ class TestResult(dict): class EvalError(dict): """Your architecture raised an error.""" - def __init__(self, Error: BaseException, **kwargs: Any) -> None: + def __init__(self, Error: BaseException, **kwargs: Any) -> None: # noqa: N803 """Initialize the EvalError with an error and additional attributes. Args: diff --git a/libs/langchain/langchain/tools/__init__.py b/libs/langchain/langchain/tools/__init__.py index 0934636ac2b..6bfdb26f4a9 100644 --- a/libs/langchain/langchain/tools/__init__.py +++ b/libs/langchain/langchain/tools/__init__.py @@ -38,7 +38,7 @@ from langchain._api.interactive_env import is_interactive_env _DEPRECATED_TOOLS = {"PythonAstREPLTool", "PythonREPLTool"} -def _import_python_tool_PythonAstREPLTool() -> Any: +def _import_python_tool_python_ast_repl_tool() -> Any: msg = ( "This tool has been moved to langchain experiment. " "This tool has access to a python REPL. " @@ -50,7 +50,7 @@ def _import_python_tool_PythonAstREPLTool() -> Any: raise ImportError(msg) -def _import_python_tool_PythonREPLTool() -> Any: +def _import_python_tool_python_repl_tool() -> Any: msg = ( "This tool has been moved to langchain experiment. " "This tool has access to a python REPL. " @@ -64,9 +64,9 @@ def _import_python_tool_PythonREPLTool() -> Any: def __getattr__(name: str) -> Any: if name == "PythonAstREPLTool": - return _import_python_tool_PythonAstREPLTool() + return _import_python_tool_python_ast_repl_tool() if name == "PythonREPLTool": - return _import_python_tool_PythonREPLTool() + return _import_python_tool_python_repl_tool() from langchain_community import tools # If not in interactive env, raise warning. diff --git a/libs/langchain/pyproject.toml b/libs/langchain/pyproject.toml index f558488669d..0ec06e18cbb 100644 --- a/libs/langchain/pyproject.toml +++ b/libs/langchain/pyproject.toml @@ -145,8 +145,8 @@ ignore-words-list = "momento,collison,ned,foor,reworkd,parth,whats,aapply,mysogy [tool.ruff.lint] select = [ "A", # flake8-builtins - "B", # flake8-bugbear "ASYNC", # flake8-async + "B", # flake8-bugbear "C4", # flake8-comprehensions "COM", # flake8-commas "D1", # pydocstyle: missing docstring @@ -162,6 +162,7 @@ select = [ "ICN", # flake8-import-conventions "INT", # flake8-gettext "ISC", # isort-comprehensions + "N", # pep8-naming "PERF", # flake8-perf "PGH", # pygrep-hooks "PIE", # flake8-pie @@ -202,6 +203,7 @@ ignore = [ ] unfixable = ["B028"] # People should intentionally tune the stacklevel +pep8-naming.classmethod-decorators = [ "classmethod", "langchain_core.utils.pre_init", "pydantic.field_validator", "pydantic.v1.root_validator",] pydocstyle.convention = "google" pyupgrade.keep-runtime-typing = true diff --git a/libs/langchain/tests/integration_tests/chat_models/test_base.py b/libs/langchain/tests/integration_tests/chat_models/test_base.py index 1c915f7f588..8a2923a3545 100644 --- a/libs/langchain/tests/integration_tests/chat_models/test_base.py +++ b/libs/langchain/tests/integration_tests/chat_models/test_base.py @@ -11,7 +11,7 @@ from pydantic import BaseModel from langchain.chat_models import init_chat_model -class multiply(BaseModel): +class Multiply(BaseModel): """Product of two ints.""" x: int @@ -21,7 +21,7 @@ class multiply(BaseModel): @pytest.mark.requires("langchain_openai", "langchain_anthropic") async def test_init_chat_model_chain() -> None: model = init_chat_model("gpt-4o", configurable_fields="any", config_prefix="bar") - model_with_tools = model.bind_tools([multiply]) + model_with_tools = model.bind_tools([Multiply]) model_with_config = model_with_tools.with_config( RunnableConfig(tags=["foo"]), diff --git a/libs/langchain/tests/unit_tests/chains/test_sequential.py b/libs/langchain/tests/unit_tests/chains/test_sequential.py index f3313e9139f..d65148fe24b 100644 --- a/libs/langchain/tests/unit_tests/chains/test_sequential.py +++ b/libs/langchain/tests/unit_tests/chains/test_sequential.py @@ -200,8 +200,10 @@ def test_simple_sequential_functionality() -> None: assert output == expected_output -@pytest.mark.parametrize("isAsync", [False, True]) -async def test_simple_sequential_functionality_with_callbacks(*, isAsync: bool) -> None: +@pytest.mark.parametrize("is_async", [False, True]) +async def test_simple_sequential_functionality_with_callbacks( + *, is_async: bool +) -> None: """Test simple sequential functionality.""" handler_1 = FakeCallbackHandler() handler_2 = FakeCallbackHandler() @@ -222,7 +224,7 @@ async def test_simple_sequential_functionality_with_callbacks(*, isAsync: bool) callbacks=[handler_3], ) chain = SimpleSequentialChain(chains=[chain_1, chain_2, chain_3]) - if isAsync: + if is_async: output = await chain.ainvoke({"input": "123"}) else: output = chain({"input": "123"}) diff --git a/libs/langchain/tests/unit_tests/evaluation/comparison/test_eval_chain.py b/libs/langchain/tests/unit_tests/evaluation/comparison/test_eval_chain.py index cf1df2509b7..369d88b56f6 100644 --- a/libs/langchain/tests/unit_tests/evaluation/comparison/test_eval_chain.py +++ b/libs/langchain/tests/unit_tests/evaluation/comparison/test_eval_chain.py @@ -27,7 +27,7 @@ def test_resolve_criteria_list_enum() -> None: assert set(val.keys()) == {c.value for c in list(Criteria)} -def test_PairwiseStringResultOutputParser_parse() -> None: +def test_pairwise_string_result_output_parser_parse() -> None: output_parser = PairwiseStringResultOutputParser() text = """I like pie better than cake. [[A]]""" diff --git a/libs/langchain/tests/unit_tests/evaluation/criteria/test_eval_chain.py b/libs/langchain/tests/unit_tests/evaluation/criteria/test_eval_chain.py index 9a8dc153bc3..1401723d491 100644 --- a/libs/langchain/tests/unit_tests/evaluation/criteria/test_eval_chain.py +++ b/libs/langchain/tests/unit_tests/evaluation/criteria/test_eval_chain.py @@ -51,7 +51,7 @@ The criterion is: "Do you like cake?" I like cake.""", # noqa: E501 ), ], ) -def test_CriteriaResultOutputParser_parse(text: str, want: dict) -> None: +def test_criteria_result_output_parser_parse(text: str, want: dict) -> None: output_parser = CriteriaResultOutputParser() got = output_parser.parse(text) assert got.get("reasoning") == want["reasoning"] diff --git a/libs/langchain/tests/unit_tests/evaluation/scoring/test_eval_chain.py b/libs/langchain/tests/unit_tests/evaluation/scoring/test_eval_chain.py index 932b708c41c..67fd54d5862 100644 --- a/libs/langchain/tests/unit_tests/evaluation/scoring/test_eval_chain.py +++ b/libs/langchain/tests/unit_tests/evaluation/scoring/test_eval_chain.py @@ -12,7 +12,7 @@ from langchain.evaluation.scoring.eval_chain import ( from tests.unit_tests.llms.fake_llm import FakeLLM -def test_PairwiseStringResultOutputParser_parse() -> None: +def test_pairwise_string_result_output_parser_parse() -> None: output_parser = ScoreStringResultOutputParser() text = """This answer is really good. Rating: [[10]]"""