From bc47278d195f3bf825f60f35f0385edfdda38239 Mon Sep 17 00:00:00 2001 From: Christophe Bornet Date: Wed, 22 Jan 2025 15:23:58 +0100 Subject: [PATCH] core: Add ruff rules RUF --- libs/core/langchain_core/_api/__init__.py | 6 +-- .../core/langchain_core/callbacks/__init__.py | 50 +++++++++---------- .../document_loaders/__init__.py | 2 +- .../core/langchain_core/documents/__init__.py | 2 +- libs/core/langchain_core/indexing/__init__.py | 6 +-- .../language_models/__init__.py | 20 ++++---- .../langchain_core/language_models/llms.py | 4 +- libs/core/langchain_core/load/__init__.py | 2 +- libs/core/langchain_core/memory.py | 2 +- libs/core/langchain_core/messages/__init__.py | 8 +-- libs/core/langchain_core/messages/base.py | 2 +- libs/core/langchain_core/messages/utils.py | 2 +- .../langchain_core/output_parsers/__init__.py | 22 ++++---- .../core/langchain_core/output_parsers/xml.py | 2 +- libs/core/langchain_core/prompts/__init__.py | 6 +-- libs/core/langchain_core/prompts/chat.py | 6 +-- libs/core/langchain_core/prompts/loading.py | 10 ++-- libs/core/langchain_core/prompts/string.py | 2 +- .../core/langchain_core/prompts/structured.py | 6 +-- .../core/langchain_core/runnables/__init__.py | 16 +++--- libs/core/langchain_core/runnables/base.py | 6 +-- .../langchain_core/runnables/configurable.py | 2 +- libs/core/langchain_core/runnables/history.py | 4 +- libs/core/langchain_core/runnables/utils.py | 12 ++--- libs/core/langchain_core/sys_info.py | 2 +- libs/core/langchain_core/tools/base.py | 8 ++- libs/core/langchain_core/tracers/__init__.py | 4 +- .../langchain_core/tracers/event_stream.py | 2 +- .../core/langchain_core/tracers/log_stream.py | 2 +- libs/core/langchain_core/tracers/stdout.py | 4 +- libs/core/langchain_core/utils/__init__.py | 24 ++++----- libs/core/langchain_core/utils/_merge.py | 4 +- libs/core/langchain_core/utils/aiter.py | 2 +- libs/core/langchain_core/utils/env.py | 8 +-- libs/core/langchain_core/utils/iter.py | 2 +- libs/core/langchain_core/utils/mustache.py | 4 +- .../langchain_core/vectorstores/__init__.py | 4 +- libs/core/langchain_core/vectorstores/base.py | 2 +- .../langchain_core/vectorstores/in_memory.py | 2 +- libs/core/pyproject.toml | 4 +- libs/core/scripts/check_imports.py | 3 +- .../test_length_based_example_selector.py | 2 +- .../unit_tests/indexing/test_public_api.py | 2 +- .../output_parsers/test_pydantic_parser.py | 4 +- .../tests/unit_tests/prompts/test_chat.py | 2 +- .../unit_tests/runnables/test_runnable.py | 2 +- .../runnables/test_tracing_interops.py | 2 +- .../unit_tests/tracers/test_memory_stream.py | 4 +- .../unit_tests/utils/test_function_calling.py | 17 +++---- 49 files changed, 152 insertions(+), 164 deletions(-) diff --git a/libs/core/langchain_core/_api/__init__.py b/libs/core/langchain_core/_api/__init__.py index 2251973d6b5ae..aa48d31f3bd53 100644 --- a/libs/core/langchain_core/_api/__init__.py +++ b/libs/core/langchain_core/_api/__init__.py @@ -25,15 +25,15 @@ from .path import as_import_path, get_relative_path __all__ = [ + "LangChainBetaWarning", + "LangChainDeprecationWarning", "as_import_path", "beta", "deprecated", "get_relative_path", - "LangChainBetaWarning", - "LangChainDeprecationWarning", "suppress_langchain_beta_warning", - "surface_langchain_beta_warnings", "suppress_langchain_deprecation_warning", + "surface_langchain_beta_warnings", "surface_langchain_deprecation_warnings", "warn_deprecated", ] diff --git a/libs/core/langchain_core/callbacks/__init__.py b/libs/core/langchain_core/callbacks/__init__.py index a55f41ce34407..5d06f45d1d252 100644 --- a/libs/core/langchain_core/callbacks/__init__.py +++ b/libs/core/langchain_core/callbacks/__init__.py @@ -45,36 +45,36 @@ from langchain_core.callbacks.streaming_stdout import StreamingStdOutCallbackHandler __all__ = [ - "dispatch_custom_event", - "adispatch_custom_event", - "RetrieverManagerMixin", - "LLMManagerMixin", - "ChainManagerMixin", - "ToolManagerMixin", - "Callbacks", - "CallbackManagerMixin", - "RunManagerMixin", - "BaseCallbackHandler", "AsyncCallbackHandler", - "BaseCallbackManager", - "BaseRunManager", - "RunManager", - "ParentRunManager", - "AsyncRunManager", - "AsyncParentRunManager", - "CallbackManagerForLLMRun", - "AsyncCallbackManagerForLLMRun", - "CallbackManagerForChainRun", + "AsyncCallbackManager", + "AsyncCallbackManagerForChainGroup", "AsyncCallbackManagerForChainRun", - "CallbackManagerForToolRun", - "AsyncCallbackManagerForToolRun", - "CallbackManagerForRetrieverRun", + "AsyncCallbackManagerForLLMRun", "AsyncCallbackManagerForRetrieverRun", + "AsyncCallbackManagerForToolRun", + "AsyncParentRunManager", + "AsyncRunManager", + "BaseCallbackHandler", + "BaseCallbackManager", + "BaseRunManager", "CallbackManager", "CallbackManagerForChainGroup", - "AsyncCallbackManager", - "AsyncCallbackManagerForChainGroup", + "CallbackManagerForChainRun", + "CallbackManagerForLLMRun", + "CallbackManagerForRetrieverRun", + "CallbackManagerForToolRun", + "CallbackManagerMixin", + "Callbacks", + "ChainManagerMixin", + "FileCallbackHandler", + "LLMManagerMixin", + "ParentRunManager", + "RetrieverManagerMixin", + "RunManager", + "RunManagerMixin", "StdOutCallbackHandler", "StreamingStdOutCallbackHandler", - "FileCallbackHandler", + "ToolManagerMixin", + "adispatch_custom_event", + "dispatch_custom_event", ] diff --git a/libs/core/langchain_core/document_loaders/__init__.py b/libs/core/langchain_core/document_loaders/__init__.py index e8b6fde5be89b..e1a20a6f17c86 100644 --- a/libs/core/langchain_core/document_loaders/__init__.py +++ b/libs/core/langchain_core/document_loaders/__init__.py @@ -7,6 +7,6 @@ "BaseLoader", "Blob", "BlobLoader", - "PathLike", "LangSmithLoader", + "PathLike", ] diff --git a/libs/core/langchain_core/documents/__init__.py b/libs/core/langchain_core/documents/__init__.py index 5430d24f54fe5..9a4db7114ac4e 100644 --- a/libs/core/langchain_core/documents/__init__.py +++ b/libs/core/langchain_core/documents/__init__.py @@ -7,4 +7,4 @@ from langchain_core.documents.compressor import BaseDocumentCompressor from langchain_core.documents.transformers import BaseDocumentTransformer -__all__ = ["Document", "BaseDocumentTransformer", "BaseDocumentCompressor"] +__all__ = ["BaseDocumentCompressor", "BaseDocumentTransformer", "Document"] diff --git a/libs/core/langchain_core/indexing/__init__.py b/libs/core/langchain_core/indexing/__init__.py index 472f41e11a846..dc9e954e829c5 100644 --- a/libs/core/langchain_core/indexing/__init__.py +++ b/libs/core/langchain_core/indexing/__init__.py @@ -15,12 +15,12 @@ ) __all__ = [ - "aindex", "DeleteResponse", "DocumentIndex", - "index", - "IndexingResult", "InMemoryRecordManager", + "IndexingResult", "RecordManager", "UpsertResponse", + "aindex", + "index", ] diff --git a/libs/core/langchain_core/language_models/__init__.py b/libs/core/langchain_core/language_models/__init__.py index 2b3c6b40ef827..8de1597bd727a 100644 --- a/libs/core/langchain_core/language_models/__init__.py +++ b/libs/core/langchain_core/language_models/__init__.py @@ -58,20 +58,20 @@ from langchain_core.language_models.llms import LLM, BaseLLM __all__ = [ - "BaseLanguageModel", + "LLM", "BaseChatModel", - "SimpleChatModel", "BaseLLM", - "LLM", - "LanguageModelInput", - "get_tokenizer", - "LangSmithParams", - "LanguageModelOutput", - "LanguageModelLike", - "FakeListLLM", - "FakeStreamingListLLM", + "BaseLanguageModel", "FakeListChatModel", + "FakeListLLM", "FakeMessagesListChatModel", + "FakeStreamingListLLM", "GenericFakeChatModel", + "LangSmithParams", + "LanguageModelInput", + "LanguageModelLike", + "LanguageModelOutput", "ParrotFakeChatModel", + "SimpleChatModel", + "get_tokenizer", ] diff --git a/libs/core/langchain_core/language_models/llms.py b/libs/core/langchain_core/language_models/llms.py index 4ba16f516965d..a8a3398c8f8be 100644 --- a/libs/core/langchain_core/language_models/llms.py +++ b/libs/core/langchain_core/language_models/llms.py @@ -101,7 +101,9 @@ def _before_sleep(retry_state: RetryCallState) -> None: try: loop = asyncio.get_event_loop() if loop.is_running(): - loop.create_task(coro) + # TODO: Fix RUF006 - this task should have a reference + # and be awaited somewhere + loop.create_task(coro) # noqa: RUF006 else: asyncio.run(coro) except Exception as e: diff --git a/libs/core/langchain_core/load/__init__.py b/libs/core/langchain_core/load/__init__.py index 913bd39260478..0692673e65f70 100644 --- a/libs/core/langchain_core/load/__init__.py +++ b/libs/core/langchain_core/load/__init__.py @@ -4,4 +4,4 @@ from langchain_core.load.load import load, loads from langchain_core.load.serializable import Serializable -__all__ = ["dumpd", "dumps", "load", "loads", "Serializable"] +__all__ = ["Serializable", "dumpd", "dumps", "load", "loads"] diff --git a/libs/core/langchain_core/memory.py b/libs/core/langchain_core/memory.py index 0313f74e1220e..afb99311dfc02 100644 --- a/libs/core/langchain_core/memory.py +++ b/libs/core/langchain_core/memory.py @@ -3,7 +3,7 @@ This module contains memory abstractions from LangChain v0.0.x. These abstractions are now deprecated and will be removed in LangChain v1.0.0. -""" # noqa: E501 +""" from __future__ import annotations diff --git a/libs/core/langchain_core/messages/__init__.py b/libs/core/langchain_core/messages/__init__.py index f8fdf4d4a3bed..d38bfa90d18a2 100644 --- a/libs/core/langchain_core/messages/__init__.py +++ b/libs/core/langchain_core/messages/__init__.py @@ -66,23 +66,23 @@ "HumanMessageChunk", "InvalidToolCall", "MessageLikeRepresentation", + "RemoveMessage", "SystemMessage", "SystemMessageChunk", "ToolCall", "ToolCallChunk", "ToolMessage", "ToolMessageChunk", - "RemoveMessage", "_message_from_dict", "convert_to_messages", + "convert_to_openai_messages", + "filter_messages", "get_buffer_string", "merge_content", + "merge_message_runs", "message_chunk_to_message", "message_to_dict", "messages_from_dict", "messages_to_dict", - "filter_messages", - "merge_message_runs", "trim_messages", - "convert_to_openai_messages", ] diff --git a/libs/core/langchain_core/messages/base.py b/libs/core/langchain_core/messages/base.py index 9eab1ed431af2..919e9c51bd9bd 100644 --- a/libs/core/langchain_core/messages/base.py +++ b/libs/core/langchain_core/messages/base.py @@ -141,7 +141,7 @@ def merge_content( merged = cast(str, merged) + content # If the next chunk is a list, add the current to the start of the list else: - merged = [merged] + content # type: ignore + merged = [merged, *content] elif isinstance(content, list): # If both are lists merged = merge_lists(cast(list, merged), content) # type: ignore diff --git a/libs/core/langchain_core/messages/utils.py b/libs/core/langchain_core/messages/utils.py index f7d823bf80a11..6fc0ca8427df7 100644 --- a/libs/core/langchain_core/messages/utils.py +++ b/libs/core/langchain_core/messages/utils.py @@ -826,7 +826,7 @@ def dummy_token_counter(messages: list[BaseMessage]) -> int: list_token_counter = token_counter.get_num_tokens_from_messages elif callable(token_counter): if ( - list(inspect.signature(token_counter).parameters.values())[0].annotation + next(iter(inspect.signature(token_counter).parameters.values())).annotation is BaseMessage ): diff --git a/libs/core/langchain_core/output_parsers/__init__.py b/libs/core/langchain_core/output_parsers/__init__.py index a1bbdeb4f9db9..6b6115fbbde7e 100644 --- a/libs/core/langchain_core/output_parsers/__init__.py +++ b/libs/core/langchain_core/output_parsers/__init__.py @@ -39,21 +39,21 @@ from langchain_core.output_parsers.xml import XMLOutputParser __all__ = [ - "BaseLLMOutputParser", + "BaseCumulativeTransformOutputParser", "BaseGenerationOutputParser", + "BaseLLMOutputParser", "BaseOutputParser", - "ListOutputParser", - "CommaSeparatedListOutputParser", - "NumberedListOutputParser", - "MarkdownListOutputParser", - "StrOutputParser", "BaseTransformOutputParser", - "BaseCumulativeTransformOutputParser", - "SimpleJsonOutputParser", - "XMLOutputParser", + "CommaSeparatedListOutputParser", + "JsonOutputKeyToolsParser", "JsonOutputParser", - "PydanticOutputParser", "JsonOutputToolsParser", - "JsonOutputKeyToolsParser", + "ListOutputParser", + "MarkdownListOutputParser", + "NumberedListOutputParser", + "PydanticOutputParser", "PydanticToolsParser", + "SimpleJsonOutputParser", + "StrOutputParser", + "XMLOutputParser", ] diff --git a/libs/core/langchain_core/output_parsers/xml.py b/libs/core/langchain_core/output_parsers/xml.py index 4fef349c498fc..6d9771af893af 100644 --- a/libs/core/langchain_core/output_parsers/xml.py +++ b/libs/core/langchain_core/output_parsers/xml.py @@ -1,7 +1,7 @@ import contextlib import re import xml -import xml.etree.ElementTree as ET # noqa: N817 +import xml.etree.ElementTree as ET from collections.abc import AsyncIterator, Iterator from typing import Any, Literal, Optional, Union from xml.etree.ElementTree import TreeBuilder diff --git a/libs/core/langchain_core/prompts/__init__.py b/libs/core/langchain_core/prompts/__init__.py index 4565018b6a30a..8be905bc36a71 100644 --- a/libs/core/langchain_core/prompts/__init__.py +++ b/libs/core/langchain_core/prompts/__init__.py @@ -61,20 +61,20 @@ "BasePromptTemplate", "ChatMessagePromptTemplate", "ChatPromptTemplate", + "FewShotChatMessagePromptTemplate", "FewShotPromptTemplate", "FewShotPromptWithTemplates", - "FewShotChatMessagePromptTemplate", "HumanMessagePromptTemplate", "MessagesPlaceholder", "PipelinePromptTemplate", "PromptTemplate", "StringPromptTemplate", "SystemMessagePromptTemplate", - "load_prompt", - "format_document", "aformat_document", "check_valid_template", + "format_document", "get_template_variables", "jinja2_formatter", + "load_prompt", "validate_jinja2", ] diff --git a/libs/core/langchain_core/prompts/chat.py b/libs/core/langchain_core/prompts/chat.py index 11924e3328d68..eef15834db46b 100644 --- a/libs/core/langchain_core/prompts/chat.py +++ b/libs/core/langchain_core/prompts/chat.py @@ -523,7 +523,7 @@ def from_template( raise ValueError(msg) prompt = [] for tmpl in template: - if isinstance(tmpl, str) or isinstance(tmpl, dict) and "text" in tmpl: + if isinstance(tmpl, str) or (isinstance(tmpl, dict) and "text" in tmpl): if isinstance(tmpl, str): text: str = tmpl else: @@ -1043,13 +1043,13 @@ def __add__(self, other: Any) -> ChatPromptTemplate: elif isinstance( other, (BaseMessagePromptTemplate, BaseMessage, BaseChatPromptTemplate) ): - return ChatPromptTemplate(messages=self.messages + [other]) # type: ignore[call-arg] + return ChatPromptTemplate(messages=[*self.messages, other]) # type: ignore[call-arg] elif isinstance(other, (list, tuple)): _other = ChatPromptTemplate.from_messages(other) return ChatPromptTemplate(messages=self.messages + _other.messages) # type: ignore[call-arg] elif isinstance(other, str): prompt = HumanMessagePromptTemplate.from_template(other) - return ChatPromptTemplate(messages=self.messages + [prompt]) # type: ignore[call-arg] + return ChatPromptTemplate(messages=[*self.messages, prompt]) # type: ignore[call-arg] else: msg = f"Unsupported operand type for +: {type(other)}" raise NotImplementedError(msg) diff --git a/libs/core/langchain_core/prompts/loading.py b/libs/core/langchain_core/prompts/loading.py index da89972e7579a..8b1ab3f3bd035 100644 --- a/libs/core/langchain_core/prompts/loading.py +++ b/libs/core/langchain_core/prompts/loading.py @@ -84,15 +84,11 @@ def _load_examples(config: dict) -> dict: def _load_output_parser(config: dict) -> dict: """Load output parser.""" - if "output_parser" in config and config["output_parser"]: - _config = config.pop("output_parser") - output_parser_type = _config.pop("_type") - if output_parser_type == "default": - output_parser = StrOutputParser(**_config) - else: + if _config := config.get("output_parser"): + if output_parser_type := _config.get("_type") != "default": msg = f"Unsupported output parser {output_parser_type}" raise ValueError(msg) - config["output_parser"] = output_parser + config["output_parser"] = StrOutputParser(**_config) return config diff --git a/libs/core/langchain_core/prompts/string.py b/libs/core/langchain_core/prompts/string.py index 61fc1d35d4f0b..80dc8dd5c9726 100644 --- a/libs/core/langchain_core/prompts/string.py +++ b/libs/core/langchain_core/prompts/string.py @@ -96,7 +96,7 @@ def _get_jinja2_variables_from_template(template: str) -> set[str]: "Please install it with `pip install jinja2`." ) raise ImportError(msg) from e - # noqa for insecure warning elsewhere + env = Environment() # noqa: S701 ast = env.parse(template) variables = meta.find_undeclared_variables(ast) diff --git a/libs/core/langchain_core/prompts/structured.py b/libs/core/langchain_core/prompts/structured.py index 1f38695760be6..d053fac63fbb3 100644 --- a/libs/core/langchain_core/prompts/structured.py +++ b/libs/core/langchain_core/prompts/structured.py @@ -141,10 +141,8 @@ def pipe( NotImplementedError: If the first element of `others` is not a language model. """ - if ( - others - and isinstance(others[0], BaseLanguageModel) - or hasattr(others[0], "with_structured_output") + if (others and isinstance(others[0], BaseLanguageModel)) or hasattr( + others[0], "with_structured_output" ): return RunnableSequence( self, diff --git a/libs/core/langchain_core/runnables/__init__.py b/libs/core/langchain_core/runnables/__init__.py index 44c95519c0808..692d0024f9adf 100644 --- a/libs/core/langchain_core/runnables/__init__.py +++ b/libs/core/langchain_core/runnables/__init__.py @@ -55,19 +55,15 @@ ) __all__ = [ - "chain", "AddableDict", "ConfigurableField", - "ConfigurableFieldSingleOption", "ConfigurableFieldMultiOption", + "ConfigurableFieldSingleOption", "ConfigurableFieldSpec", - "ensure_config", - "run_in_executor", - "patch_config", "RouterInput", "RouterRunnable", "Runnable", - "RunnableSerializable", + "RunnableAssign", "RunnableBinding", "RunnableBranch", "RunnableConfig", @@ -76,12 +72,16 @@ "RunnableMap", "RunnableParallel", "RunnablePassthrough", - "RunnableAssign", "RunnablePick", "RunnableSequence", + "RunnableSerializable", "RunnableWithFallbacks", "RunnableWithMessageHistory", - "get_config_list", "aadd", "add", + "chain", + "ensure_config", + "get_config_list", + "patch_config", + "run_in_executor", ] diff --git a/libs/core/langchain_core/runnables/base.py b/libs/core/langchain_core/runnables/base.py index bf805c3a4f07c..5bd991337d28f 100644 --- a/libs/core/langchain_core/runnables/base.py +++ b/libs/core/langchain_core/runnables/base.py @@ -2787,7 +2787,7 @@ def steps(self) -> list[Runnable[Any, Any]]: Returns: A list of Runnables. """ - return [self.first] + self.middle + [self.last] + return [self.first, *self.middle, self.last] @classmethod def is_lc_serializable(cls) -> bool: @@ -3332,7 +3332,7 @@ def _transform( ) -> Iterator[Output]: from langchain_core.beta.runnables.context import config_with_context - steps = [self.first] + self.middle + [self.last] + steps = [self.first, *self.middle, self.last] config = config_with_context(config, self.steps) # transform the input stream of each step with the next @@ -3359,7 +3359,7 @@ async def _atransform( ) -> AsyncIterator[Output]: from langchain_core.beta.runnables.context import aconfig_with_context - steps = [self.first] + self.middle + [self.last] + steps = [self.first, *self.middle, self.last] config = aconfig_with_context(config, self.steps) # stream the last steps diff --git a/libs/core/langchain_core/runnables/configurable.py b/libs/core/langchain_core/runnables/configurable.py index b59d0239fb1f3..5cb75414c456c 100644 --- a/libs/core/langchain_core/runnables/configurable.py +++ b/libs/core/langchain_core/runnables/configurable.py @@ -557,7 +557,7 @@ def config_specs(self) -> list[ConfigurableFieldSpec]: self.which.name or self.which.id, ( (v, v) - for v in list(self.alternatives.keys()) + [self.default_key] + for v in [*list(self.alternatives.keys()), self.default_key] ), ) _enums_for_spec[self.which] = cast(type[StrEnum], which_enum) diff --git a/libs/core/langchain_core/runnables/history.py b/libs/core/langchain_core/runnables/history.py index d2040a3f3fb6f..fb023a3d8c8ea 100644 --- a/libs/core/langchain_core/runnables/history.py +++ b/libs/core/langchain_core/runnables/history.py @@ -450,7 +450,7 @@ def _get_input_messages( if self.input_messages_key: key = self.input_messages_key elif len(input_val) == 1: - key = list(input_val.keys())[0] + key = next(iter(input_val.keys())) else: key = "input" input_val = input_val[key] @@ -493,7 +493,7 @@ def _get_output_messages( if self.output_messages_key: key = self.output_messages_key elif len(output_val) == 1: - key = list(output_val.keys())[0] + key = next(iter(output_val.keys())) else: key = "output" # If you are wrapping a chat model directly diff --git a/libs/core/langchain_core/runnables/utils.py b/libs/core/langchain_core/runnables/utils.py index 75063c7db58bb..2cbf7e3e9faff 100644 --- a/libs/core/langchain_core/runnables/utils.py +++ b/libs/core/langchain_core/runnables/utils.py @@ -659,7 +659,7 @@ def get_unique_config_specs( else: msg = ( "RunnableSequence contains conflicting config specs" - f"for {id}: {[first] + others}" + f"for {id}: {[first, *others]}" ) raise ValueError(msg) return unique @@ -732,9 +732,8 @@ def is_async_generator( TypeGuard[Callable[..., AsyncIterator]: True if the function is an async generator, False otherwise. """ - return ( - inspect.isasyncgenfunction(func) - or hasattr(func, "__call__") # noqa: B004 + return inspect.isasyncgenfunction(func) or ( + hasattr(func, "__call__") # noqa: B004 and inspect.isasyncgenfunction(func.__call__) ) @@ -751,8 +750,7 @@ def is_async_callable( TypeGuard[Callable[..., Awaitable]: True if the function is async, False otherwise. """ - return ( - asyncio.iscoroutinefunction(func) - or hasattr(func, "__call__") # noqa: B004 + return asyncio.iscoroutinefunction(func) or ( + hasattr(func, "__call__") # noqa: B004 and asyncio.iscoroutinefunction(func.__call__) ) diff --git a/libs/core/langchain_core/sys_info.py b/libs/core/langchain_core/sys_info.py index 532b4e63802ed..1936a4206c5eb 100644 --- a/libs/core/langchain_core/sys_info.py +++ b/libs/core/langchain_core/sys_info.py @@ -73,7 +73,7 @@ def print_sys_info(*, additional_pkgs: Sequence[str] = ()) -> None: for pkg in reversed(order_by): if pkg in all_packages: all_packages.remove(pkg) - all_packages = [pkg] + list(all_packages) + all_packages = [pkg, *list(all_packages)] system_info = { "OS": platform.system(), diff --git a/libs/core/langchain_core/tools/base.py b/libs/core/langchain_core/tools/base.py index f0833cdc24a14..eb20e43509857 100644 --- a/libs/core/langchain_core/tools/base.py +++ b/libs/core/langchain_core/tools/base.py @@ -269,7 +269,7 @@ def create_schema_from_function( # Handle classmethods and instance methods existing_params: list[str] = list(sig.parameters.keys()) if existing_params and existing_params[0] in ("self", "cls") and in_class: - filter_args_ = [existing_params[0]] + list(FILTERED_ARGS) + filter_args_ = [existing_params[0], *list(FILTERED_ARGS)] else: filter_args_ = list(FILTERED_ARGS) @@ -946,10 +946,8 @@ def _format_output( def _is_message_content_type(obj: Any) -> bool: """Check for OpenAI or Anthropic format tool message content.""" - return ( - isinstance(obj, str) - or isinstance(obj, list) - and all(_is_message_content_block(e) for e in obj) + return isinstance(obj, str) or ( + isinstance(obj, list) and all(_is_message_content_block(e) for e in obj) ) diff --git a/libs/core/langchain_core/tracers/__init__.py b/libs/core/langchain_core/tracers/__init__.py index 05440d395a702..d67bed5de0ed1 100644 --- a/libs/core/langchain_core/tracers/__init__.py +++ b/libs/core/langchain_core/tracers/__init__.py @@ -10,13 +10,13 @@ __all__ = [ "BaseTracer", + "ConsoleCallbackHandler", "EvaluatorCallbackHandler", "LangChainTracer", - "ConsoleCallbackHandler", + "LogStreamCallbackHandler", "Run", "RunLog", "RunLogPatch", - "LogStreamCallbackHandler", ] from langchain_core.tracers.base import BaseTracer diff --git a/libs/core/langchain_core/tracers/event_stream.py b/libs/core/langchain_core/tracers/event_stream.py index b7f3db8595d61..2bee33f8c1db0 100644 --- a/libs/core/langchain_core/tracers/event_stream.py +++ b/libs/core/langchain_core/tracers/event_stream.py @@ -946,7 +946,7 @@ async def _astream_events_implementation_v2( if callbacks is None: config["callbacks"] = [event_streamer] elif isinstance(callbacks, list): - config["callbacks"] = callbacks + [event_streamer] + config["callbacks"] = [*callbacks, event_streamer] elif isinstance(callbacks, BaseCallbackManager): callbacks = callbacks.copy() callbacks.add_handler(event_streamer, inherit=True) diff --git a/libs/core/langchain_core/tracers/log_stream.py b/libs/core/langchain_core/tracers/log_stream.py index 2284ff7022f42..9a17cbac51f63 100644 --- a/libs/core/langchain_core/tracers/log_stream.py +++ b/libs/core/langchain_core/tracers/log_stream.py @@ -607,7 +607,7 @@ async def _astream_log_implementation( if callbacks is None: config["callbacks"] = [stream] elif isinstance(callbacks, list): - config["callbacks"] = callbacks + [stream] + config["callbacks"] = [*callbacks, stream] elif isinstance(callbacks, BaseCallbackManager): callbacks = callbacks.copy() callbacks.add_handler(stream, inherit=True) diff --git a/libs/core/langchain_core/tracers/stdout.py b/libs/core/langchain_core/tracers/stdout.py index 3643724f9e2b4..c2ce64e9b43df 100644 --- a/libs/core/langchain_core/tracers/stdout.py +++ b/libs/core/langchain_core/tracers/stdout.py @@ -86,9 +86,7 @@ def get_breadcrumbs(self, run: Run) -> str: parents = self.get_parents(run)[::-1] string = " > ".join( f"{parent.run_type}:{parent.name}" - if i != len(parents) - 1 - else f"{parent.run_type}:{parent.name}" - for i, parent in enumerate(parents + [run]) + for i, parent in enumerate([*parents, run]) ) return string diff --git a/libs/core/langchain_core/utils/__init__.py b/libs/core/langchain_core/utils/__init__.py index 1af695b4fb696..9245b5ce47e13 100644 --- a/libs/core/langchain_core/utils/__init__.py +++ b/libs/core/langchain_core/utils/__init__.py @@ -31,30 +31,30 @@ ) __all__ = [ - "build_extra_kwargs", "StrictFormatter", + "abatch_iterate", + "batch_iterate", + "build_extra_kwargs", "check_package_version", + "comma_list", "convert_to_secret_str", "formatter", + "from_env", "get_bolded_text", "get_color_mapping", "get_colored_text", + "get_from_dict_or_env", + "get_from_env", "get_pydantic_field_names", "guard_import", + "image", "mock_now", + "pre_init", "print_text", "raise_for_status_with_text", - "xor_args", - "try_load_from_hub", - "image", - "get_from_env", - "get_from_dict_or_env", + "secret_from_env", "stringify_dict", - "comma_list", "stringify_value", - "pre_init", - "batch_iterate", - "abatch_iterate", - "from_env", - "secret_from_env", + "try_load_from_hub", + "xor_args", ] diff --git a/libs/core/langchain_core/utils/_merge.py b/libs/core/langchain_core/utils/_merge.py index be8f829387454..0b8232457771c 100644 --- a/libs/core/langchain_core/utils/_merge.py +++ b/libs/core/langchain_core/utils/_merge.py @@ -29,7 +29,9 @@ def merge_dicts(left: dict[str, Any], *others: dict[str, Any]) -> dict[str, Any] merged = left.copy() for right in others: for right_k, right_v in right.items(): - if right_k not in merged or right_v is not None and merged[right_k] is None: + if right_k not in merged or ( + right_v is not None and merged[right_k] is None + ): merged[right_k] = right_v elif right_v is None: continue diff --git a/libs/core/langchain_core/utils/aiter.py b/libs/core/langchain_core/utils/aiter.py index b4e26915a39dc..36e6f2ce0de55 100644 --- a/libs/core/langchain_core/utils/aiter.py +++ b/libs/core/langchain_core/utils/aiter.py @@ -134,7 +134,7 @@ async def tee_peer( yield buffer.popleft() finally: async with lock: - # this peer is done – remove its buffer + # this peer is done - remove its buffer for idx, peer_buffer in enumerate(peers): # pragma: no branch if peer_buffer is buffer: peers.pop(idx) diff --git a/libs/core/langchain_core/utils/env.py b/libs/core/langchain_core/utils/env.py index ac018b0208a70..a331f2fa3aad8 100644 --- a/libs/core/langchain_core/utils/env.py +++ b/libs/core/langchain_core/utils/env.py @@ -40,8 +40,8 @@ def get_from_dict_or_env( """ if isinstance(key, (list, tuple)): for k in key: - if k in data and data[k]: - return data[k] + if value := data.get(k): + return value if isinstance(key, str) and key in data and data[key]: return data[key] @@ -68,8 +68,8 @@ def get_from_env(key: str, env_key: str, default: Optional[str] = None) -> str: ValueError: If the key is not in the dictionary and no default value is provided or if the environment variable is not set. """ - if env_key in os.environ and os.environ[env_key]: - return os.environ[env_key] + if env_value := os.getenv(env_key): + return env_value elif default is not None: return default else: diff --git a/libs/core/langchain_core/utils/iter.py b/libs/core/langchain_core/utils/iter.py index 7868119caedd2..0b905069197c4 100644 --- a/libs/core/langchain_core/utils/iter.py +++ b/libs/core/langchain_core/utils/iter.py @@ -72,7 +72,7 @@ def tee_peer( yield buffer.popleft() finally: with lock: - # this peer is done – remove its buffer + # this peer is done - remove its buffer for idx, peer_buffer in enumerate(peers): # pragma: no branch if peer_buffer is buffer: peers.pop(idx) diff --git a/libs/core/langchain_core/utils/mustache.py b/libs/core/langchain_core/utils/mustache.py index ee2ed8f2528f8..b34ba8a96f833 100644 --- a/libs/core/langchain_core/utils/mustache.py +++ b/libs/core/langchain_core/utils/mustache.py @@ -563,7 +563,7 @@ def render( padding=padding, def_ldel=def_ldel, def_rdel=def_rdel, - scopes=data and [data] + scopes or scopes, + scopes=(data and [data, *scopes]) or scopes, warn=warn, keep=keep, ), @@ -593,7 +593,7 @@ def render( # For every item in the scope for thing in scope: # Append it as the most recent scope and render - new_scope = [thing] + scopes + new_scope = [thing, *scopes] rend = render( template=tags, scopes=new_scope, diff --git a/libs/core/langchain_core/vectorstores/__init__.py b/libs/core/langchain_core/vectorstores/__init__.py index c80958679f1f6..135cf536814e5 100644 --- a/libs/core/langchain_core/vectorstores/__init__.py +++ b/libs/core/langchain_core/vectorstores/__init__.py @@ -2,8 +2,8 @@ from langchain_core.vectorstores.in_memory import InMemoryVectorStore __all__ = [ - "VectorStore", "VST", - "VectorStoreRetriever", "InMemoryVectorStore", + "VectorStore", + "VectorStoreRetriever", ] diff --git a/libs/core/langchain_core/vectorstores/base.py b/libs/core/langchain_core/vectorstores/base.py index b154a14b98191..e0b0ea3966f59 100644 --- a/libs/core/langchain_core/vectorstores/base.py +++ b/libs/core/langchain_core/vectorstores/base.py @@ -990,7 +990,7 @@ def as_retriever(self, **kwargs: Any) -> VectorStoreRetriever: search_kwargs={'filter': {'paper_title':'GPT-4 Technical Report'}} ) """ - tags = kwargs.pop("tags", None) or [] + self._get_retriever_tags() + tags = kwargs.pop("tags", None) or [*self._get_retriever_tags()] return VectorStoreRetriever(vectorstore=self, tags=tags, **kwargs) diff --git a/libs/core/langchain_core/vectorstores/in_memory.py b/libs/core/langchain_core/vectorstores/in_memory.py index ab32c7cdacbe9..d98dc616c51ed 100644 --- a/libs/core/langchain_core/vectorstores/in_memory.py +++ b/libs/core/langchain_core/vectorstores/in_memory.py @@ -139,7 +139,7 @@ def _filter_function(doc: Document) -> bool: [Document(id='2', metadata={'bar': 'baz'}, page_content='thud')] - """ # noqa: E501 + """ def __init__(self, embedding: Embeddings) -> None: """Initialize with the given embedding function. diff --git a/libs/core/pyproject.toml b/libs/core/pyproject.toml index f9b731c730163..4d1a5fcbbe6af 100644 --- a/libs/core/pyproject.toml +++ b/libs/core/pyproject.toml @@ -44,8 +44,8 @@ python = ">=3.12.4" [tool.poetry.extras] [tool.ruff.lint] -select = [ "ASYNC", "B", "C4", "COM", "DJ", "E", "EM", "EXE", "F", "FLY", "FURB", "I", "ICN", "INT", "LOG", "N", "NPY", "PD", "PIE", "Q", "RSE", "S", "SIM", "SLOT", "T10", "T201", "TID", "TRY", "UP", "W", "YTT",] -ignore = [ "COM812", "UP007", "S110", "S112",] +select = [ "ASYNC", "B", "C4", "COM", "DJ", "E", "EM", "EXE", "F", "FLY", "FURB", "I", "ICN", "INT", "LOG", "N", "NPY", "PD", "PIE", "Q", "RSE", "RUF", "S", "SIM", "SLOT", "T10", "T201", "TID", "TRY", "UP", "W", "YTT",] +ignore = [ "COM812", "UP007", "RUF010", "RUF012", "S110", "S112",] [tool.coverage.run] omit = [ "tests/*",] diff --git a/libs/core/scripts/check_imports.py b/libs/core/scripts/check_imports.py index fa189a7117534..825bea5b48737 100644 --- a/libs/core/scripts/check_imports.py +++ b/libs/core/scripts/check_imports.py @@ -10,8 +10,7 @@ for file in files: try: module_name = "".join( - random.choice(string.ascii_letters) - for _ in range(20) # noqa: S311 + random.choice(string.ascii_letters) for _ in range(20) ) SourceFileLoader(module_name, file).load_module() except Exception: diff --git a/libs/core/tests/unit_tests/example_selectors/test_length_based_example_selector.py b/libs/core/tests/unit_tests/example_selectors/test_length_based_example_selector.py index db3a88160dbbd..4c4e216be9372 100644 --- a/libs/core/tests/unit_tests/example_selectors/test_length_based_example_selector.py +++ b/libs/core/tests/unit_tests/example_selectors/test_length_based_example_selector.py @@ -38,7 +38,7 @@ def test_selector_add_example(selector: LengthBasedExampleSelector) -> None: selector.add_example(new_example) short_question = "Short question?" output = selector.select_examples({"question": short_question}) - assert output == EXAMPLES + [new_example] + assert output == [*EXAMPLES, new_example] def test_selector_trims_one_example(selector: LengthBasedExampleSelector) -> None: diff --git a/libs/core/tests/unit_tests/indexing/test_public_api.py b/libs/core/tests/unit_tests/indexing/test_public_api.py index 24ac092eb2d4a..361a450ab4431 100644 --- a/libs/core/tests/unit_tests/indexing/test_public_api.py +++ b/libs/core/tests/unit_tests/indexing/test_public_api.py @@ -3,7 +3,7 @@ def test_all() -> None: """Use to catch obvious breaking changes.""" - assert __all__ == sorted(__all__, key=str.lower) + assert __all__ == sorted(__all__) assert set(__all__) == { "aindex", "DeleteResponse", diff --git a/libs/core/tests/unit_tests/output_parsers/test_pydantic_parser.py b/libs/core/tests/unit_tests/output_parsers/test_pydantic_parser.py index 4d152e34fd9ca..884ec8cf4e558 100644 --- a/libs/core/tests/unit_tests/output_parsers/test_pydantic_parser.py +++ b/libs/core/tests/unit_tests/output_parsers/test_pydantic_parser.py @@ -191,14 +191,14 @@ def test_format_instructions_preserves_language() -> None: description = ( "你好, こんにちは, नमस्ते, Bonjour, Hola, " - "Olá, 안녕하세요, Jambo, Merhaba, Γειά σου" + "Olá, 안녕하세요, Jambo, Merhaba, Γειά σου" # noqa: RUF001 ) class Foo(BaseModel): hello: str = Field( description=( "你好, こんにちは, नमस्ते, Bonjour, Hola, " - "Olá, 안녕하세요, Jambo, Merhaba, Γειά σου" + "Olá, 안녕하세요, Jambo, Merhaba, Γειά σου" # noqa: RUF001 ) ) diff --git a/libs/core/tests/unit_tests/prompts/test_chat.py b/libs/core/tests/unit_tests/prompts/test_chat.py index cad31d03ef929..1e5850f5e59d2 100644 --- a/libs/core/tests/unit_tests/prompts/test_chat.py +++ b/libs/core/tests/unit_tests/prompts/test_chat.py @@ -376,7 +376,7 @@ def test_chat_prompt_template_with_messages( messages: list[BaseMessagePromptTemplate], ) -> None: chat_prompt_template = ChatPromptTemplate.from_messages( - messages + [HumanMessage(content="foo")] + [*messages, HumanMessage(content="foo")] ) assert sorted(chat_prompt_template.input_variables) == sorted( [ diff --git a/libs/core/tests/unit_tests/runnables/test_runnable.py b/libs/core/tests/unit_tests/runnables/test_runnable.py index 1bd21b9d5605a..dd4d335709a4c 100644 --- a/libs/core/tests/unit_tests/runnables/test_runnable.py +++ b/libs/core/tests/unit_tests/runnables/test_runnable.py @@ -162,7 +162,7 @@ def _persist_run(self, run: Run) -> None: self.runs.append(self._copy_run(run)) def flattened_runs(self) -> list[Run]: - q = [] + self.runs + q = [*self.runs] result = [] while q: parent = q.pop() diff --git a/libs/core/tests/unit_tests/runnables/test_tracing_interops.py b/libs/core/tests/unit_tests/runnables/test_tracing_interops.py index 3409d04f23401..abf4721bacc40 100644 --- a/libs/core/tests/unit_tests/runnables/test_tracing_interops.py +++ b/libs/core/tests/unit_tests/runnables/test_tracing_interops.py @@ -412,7 +412,7 @@ def child(x: str) -> str: tags=["afoo"], ): if parent_type == "ls": - collected: dict[str, RunTree] = {} # noqa + collected: dict[str, RunTree] = {} def collect_run(run: RunTree) -> None: collected[str(run.id)] = run diff --git a/libs/core/tests/unit_tests/tracers/test_memory_stream.py b/libs/core/tests/unit_tests/tracers/test_memory_stream.py index 74541f42adb0c..2dbec5aa79e8b 100644 --- a/libs/core/tests/unit_tests/tracers/test_memory_stream.py +++ b/libs/core/tests/unit_tests/tracers/test_memory_stream.py @@ -40,7 +40,7 @@ async def consumer() -> AsyncIterator[dict]: **item, } - asyncio.create_task(producer()) + producer_task = asyncio.create_task(producer()) items = [item async for item in consumer()] @@ -58,6 +58,8 @@ async def consumer() -> AsyncIterator[dict]: f"delta_time: {delta_time}" ) + await producer_task + async def test_queue_for_streaming_via_sync_call() -> None: """Test via async -> sync -> async path.""" diff --git a/libs/core/tests/unit_tests/utils/test_function_calling.py b/libs/core/tests/unit_tests/utils/test_function_calling.py index d7a90635e3627..a0c8011c084b5 100644 --- a/libs/core/tests/unit_tests/utils/test_function_calling.py +++ b/libs/core/tests/unit_tests/utils/test_function_calling.py @@ -2,7 +2,7 @@ import sys import typing from collections.abc import Iterable, Mapping, MutableMapping, Sequence -from typing import Annotated as ExtensionsAnnotated +from typing import Annotated as TypingAnnotated from typing import ( Any, Callable, @@ -13,19 +13,14 @@ from typing import TypedDict as TypingTypedDict import pytest +from pydantic import BaseModel, Field from pydantic import BaseModel as BaseModelV2Maybe # pydantic: ignore from pydantic import Field as FieldV2Maybe # pydantic: ignore +from typing_extensions import Annotated as ExtensionsAnnotated # noqa: UP035 from typing_extensions import ( TypedDict as ExtensionsTypedDict, ) -try: - from typing import Annotated as TypingAnnotated # type: ignore[attr-defined] -except ImportError: - TypingAnnotated = ExtensionsAnnotated - -from pydantic import BaseModel, Field - from langchain_core.messages import AIMessage, HumanMessage, ToolMessage from langchain_core.runnables import Runnable, RunnableLambda from langchain_core.tools import BaseTool, StructuredTool, Tool, tool @@ -156,8 +151,8 @@ def dummy_typing_typed_dict() -> type: class dummy_function(TypingTypedDict): # noqa: N801 """Dummy function.""" - arg1: TypingAnnotated[int, ..., "foo"] # noqa: F821 - arg2: TypingAnnotated[Literal["bar", "baz"], ..., "one of 'bar', 'baz'"] # noqa: F722 + arg1: TypingAnnotated[int, ..., "foo"] + arg2: TypingAnnotated[Literal["bar", "baz"], ..., "one of 'bar', 'baz'"] return dummy_function @@ -719,7 +714,7 @@ def test__convert_typed_dict_to_openai_function( use_extension_typed_dict: bool, use_extension_annotated: bool ) -> None: typed_dict = ExtensionsTypedDict if use_extension_typed_dict else TypingTypedDict - annotated = TypingAnnotated if use_extension_annotated else TypingAnnotated + annotated = ExtensionsAnnotated if use_extension_annotated else TypingAnnotated class SubTool(typed_dict): """Subtool docstring."""