core: Add ruff rules FBT001 and FBT002 (#30695)

Add ruff rules
[FBT001](https://docs.astral.sh/ruff/rules/boolean-type-hint-positional-argument/)
and
[FBT002](https://docs.astral.sh/ruff/rules/boolean-default-value-positional-argument/).
Mostly `noqa`s to not introduce breaking changes and possible
non-breaking fixes have already been done in a [previous
PR](https://github.com/langchain-ai/langchain/pull/29424).
These rules will prevent new violations to happen.
This commit is contained in:
Christophe Bornet
2025-04-11 22:26:33 +02:00
committed by GitHub
parent 2803a48661
commit 913c896598
22 changed files with 96 additions and 47 deletions

View File

@@ -105,7 +105,7 @@ def _remove_additionalproperties_from_untyped_dicts(schema: dict) -> dict[str, A
"""
def _remove_dict_additional_props(
obj: Union[dict[str, Any], list[Any]], inside_properties: bool = False
obj: Union[dict[str, Any], list[Any]], *, inside_properties: bool = False
) -> None:
if isinstance(obj, dict):
if (
@@ -120,11 +120,13 @@ def _remove_additionalproperties_from_untyped_dicts(schema: dict) -> dict[str, A
# We are "inside_properties" if the *current* key is "properties",
# or if we were already inside properties in the caller.
next_inside_properties = inside_properties or (key == "properties")
_remove_dict_additional_props(value, next_inside_properties)
_remove_dict_additional_props(
value, inside_properties=next_inside_properties
)
elif isinstance(obj, list):
for item in obj:
_remove_dict_additional_props(item, inside_properties)
_remove_dict_additional_props(item, inside_properties=inside_properties)
_remove_dict_additional_props(schema, inside_properties=False)
return schema

View File

@@ -119,10 +119,10 @@ class _MockStructuredTool(BaseTool):
args_schema: type[BaseModel] = _MockSchema
description: str = "A Structured Tool"
def _run(self, arg1: int, arg2: bool, arg3: Optional[dict] = None) -> str:
def _run(self, *, arg1: int, arg2: bool, arg3: Optional[dict] = None) -> str:
return f"{arg1} {arg2} {arg3}"
async def _arun(self, arg1: int, arg2: bool, arg3: Optional[dict] = None) -> str:
async def _arun(self, *, arg1: int, arg2: bool, arg3: Optional[dict] = None) -> str:
raise NotImplementedError
@@ -146,11 +146,13 @@ def test_misannotated_base_tool_raises_error() -> None:
args_schema: BaseModel = _MockSchema # type: ignore[assignment]
description: str = "A Structured Tool"
def _run(self, arg1: int, arg2: bool, arg3: Optional[dict] = None) -> str:
def _run(
self, *, arg1: int, arg2: bool, arg3: Optional[dict] = None
) -> str:
return f"{arg1} {arg2} {arg3}"
async def _arun(
self, arg1: int, arg2: bool, arg3: Optional[dict] = None
self, *, arg1: int, arg2: bool, arg3: Optional[dict] = None
) -> str:
raise NotImplementedError
@@ -163,11 +165,11 @@ def test_forward_ref_annotated_base_tool_accepted() -> None:
args_schema: "type[BaseModel]" = _MockSchema
description: str = "A Structured Tool"
def _run(self, arg1: int, arg2: bool, arg3: Optional[dict] = None) -> str:
def _run(self, *, arg1: int, arg2: bool, arg3: Optional[dict] = None) -> str:
return f"{arg1} {arg2} {arg3}"
async def _arun(
self, arg1: int, arg2: bool, arg3: Optional[dict] = None
self, *, arg1: int, arg2: bool, arg3: Optional[dict] = None
) -> str:
raise NotImplementedError
@@ -180,11 +182,11 @@ def test_subclass_annotated_base_tool_accepted() -> None:
args_schema: type[_MockSchema] = _MockSchema
description: str = "A Structured Tool"
def _run(self, arg1: int, arg2: bool, arg3: Optional[dict] = None) -> str:
def _run(self, *, arg1: int, arg2: bool, arg3: Optional[dict] = None) -> str:
return f"{arg1} {arg2} {arg3}"
async def _arun(
self, arg1: int, arg2: bool, arg3: Optional[dict] = None
self, *, arg1: int, arg2: bool, arg3: Optional[dict] = None
) -> str:
raise NotImplementedError
@@ -197,14 +199,14 @@ def test_decorator_with_specified_schema() -> None:
"""Test that manually specified schemata are passed through to the tool."""
@tool(args_schema=_MockSchema)
def tool_func(arg1: int, arg2: bool, arg3: Optional[dict] = None) -> str:
def tool_func(*, arg1: int, arg2: bool, arg3: Optional[dict] = None) -> str:
return f"{arg1} {arg2} {arg3}"
assert isinstance(tool_func, BaseTool)
assert tool_func.args_schema == _MockSchema
@tool(args_schema=cast("ArgsSchema", _MockSchemaV1))
def tool_func_v1(arg1: int, arg2: bool, arg3: Optional[dict] = None) -> str:
def tool_func_v1(*, arg1: int, arg2: bool, arg3: Optional[dict] = None) -> str:
return f"{arg1} {arg2} {arg3}"
assert isinstance(tool_func_v1, BaseTool)
@@ -216,7 +218,7 @@ def test_decorated_function_schema_equivalent() -> None:
@tool
def structured_tool_input(
arg1: int, arg2: bool, arg3: Optional[dict] = None
*, arg1: int, arg2: bool, arg3: Optional[dict] = None
) -> str:
"""Return the arguments directly."""
return f"{arg1} {arg2} {arg3}"
@@ -1397,14 +1399,17 @@ class _MockStructuredToolWithRawOutput(BaseTool):
response_format: Literal["content_and_artifact"] = "content_and_artifact"
def _run(
self, arg1: int, arg2: bool, arg3: Optional[dict] = None
self,
arg1: int,
arg2: bool, # noqa: FBT001
arg3: Optional[dict] = None,
) -> tuple[str, dict]:
return f"{arg1} {arg2}", {"arg1": arg1, "arg2": arg2, "arg3": arg3}
@tool("structured_api", response_format="content_and_artifact")
def _mock_structured_tool_with_artifact(
arg1: int, arg2: bool, arg3: Optional[dict] = None
*, arg1: int, arg2: bool, arg3: Optional[dict] = None
) -> tuple[str, dict]:
"""A Structured Tool."""
return f"{arg1} {arg2}", {"arg1": arg1, "arg2": arg2, "arg3": arg3}