Skip to content

fix: Add linting rule to enforce unused parameter rule #190

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ select = [
"G", # logging format
"I", # isort
"LOG", # logging
"ARG", # flake8-unused-arguments
]

[tool.ruff.lint.per-file-ignores]
Expand Down
2 changes: 1 addition & 1 deletion src/strands/event_loop/event_loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ def _handle_tool_execution(
handler=tool_handler_process,
tool_uses=tool_uses,
event_loop_metrics=event_loop_metrics,
request_state=cast(Any, kwargs["request_state"]),
_request_state=cast(Any, kwargs["request_state"]),
invalid_tool_use_ids=invalid_tool_use_ids,
tool_results=tool_results,
cycle_trace=cycle_trace,
Expand Down
2 changes: 1 addition & 1 deletion src/strands/tools/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def run_tools(
handler: Callable[[ToolUse], ToolResult],
tool_uses: List[ToolUse],
event_loop_metrics: EventLoopMetrics,
request_state: Any,
_request_state: Any,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should just remove this parameter I think? No need to pass it if it's not used

invalid_tool_use_ids: List[str],
tool_results: List[ToolResult],
cycle_trace: Trace,
Expand Down
2 changes: 1 addition & 1 deletion src/strands/tools/mcp/mcp_agent_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def tool_type(self) -> str:
"""
return "python"

def invoke(self, tool: ToolUse, *args: Any, **kwargs: dict[str, Any]) -> ToolResult:
def invoke(self, tool: ToolUse, *_args: Any, **_kwargs: dict[str, Any]) -> ToolResult:
"""Invoke the MCP tool.

This method delegates the tool invocation to the MCP server connection,
Expand Down
2 changes: 1 addition & 1 deletion src/strands/tools/mcp/mcp_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def start(self) -> "MCPClient":
return self

def stop(
self, exc_type: Optional[BaseException], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType]
self, _exc_type: Optional[BaseException], _exc_val: Optional[BaseException], _exc_tb: Optional[TracebackType]
) -> None:
"""Signals the background thread to stop and waits for it to complete, ensuring proper cleanup of all resources.

Expand Down
2 changes: 1 addition & 1 deletion src/strands/tools/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ def supports_hot_reload(self) -> bool:
"""
return True

def invoke(self, tool: ToolUse, *args: Any, **kwargs: Any) -> ToolResult:
def invoke(self, tool: ToolUse, *_args: Any, **kwargs: Any) -> ToolResult:
"""Execute the function with the given tool use request.

Args:
Expand Down
20 changes: 9 additions & 11 deletions tests/strands/agent/test_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def tool(tool_decorated, tool_registry):


@pytest.fixture
def tools(request, tool):
def tools(request):
return request.param if hasattr(request, "param") else [tool_decorated]


Expand All @@ -140,8 +140,6 @@ def agent(
callback_handler,
messages,
tools,
tool,
tool_registry,
tool_decorated,
request,
):
Expand Down Expand Up @@ -321,7 +319,7 @@ def test_agent__call__(
conversation_manager_spy.apply_management.assert_called_with(agent)


def test_agent__call__passes_kwargs(mock_model, system_prompt, callback_handler, agent, tool, mock_event_loop_cycle):
def test_agent__call__passes_kwargs(mock_model, agent, tool, mock_event_loop_cycle):
mock_model.mock_converse.side_effect = [
[
{
Expand Down Expand Up @@ -381,7 +379,7 @@ def check_kwargs(some_value, **kwargs):
mock_event_loop_cycle.assert_called_once()


def test_agent__call__retry_with_reduced_context(mock_model, agent, tool):
def test_agent__call__retry_with_reduced_context(mock_model, agent):
conversation_manager_spy = unittest.mock.Mock(wraps=agent.conversation_manager)
agent.conversation_manager = conversation_manager_spy

Expand Down Expand Up @@ -437,7 +435,7 @@ def test_agent__call__retry_with_reduced_context(mock_model, agent, tool):
assert conversation_manager_spy.apply_management.call_count == 1


def test_agent__call__always_sliding_window_conversation_manager_doesnt_infinite_loop(mock_model, agent, tool):
def test_agent__call__always_sliding_window_conversation_manager_doesnt_infinite_loop(mock_model, agent):
conversation_manager = SlidingWindowConversationManager(window_size=500)
conversation_manager_spy = unittest.mock.Mock(wraps=conversation_manager)
agent.conversation_manager = conversation_manager_spy
Expand All @@ -463,7 +461,7 @@ def test_agent__call__always_sliding_window_conversation_manager_doesnt_infinite
assert conversation_manager_spy.apply_management.call_count == 1


def test_agent__call__null_conversation_window_manager__doesnt_infinite_loop(mock_model, agent, tool):
def test_agent__call__null_conversation_window_manager__doesnt_infinite_loop(mock_model, agent):
agent.conversation_manager = NullConversationManager()

messages: Messages = [
Expand Down Expand Up @@ -626,7 +624,7 @@ def test_agent_tool_tool_does_not_exist(agent):


@pytest.mark.parametrize("tools", [None, [tool_decorated]], indirect=True)
def test_agent_tool_names(tools, agent):
def test_agent_tool_names(agent):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pytest parametrize attribute still references tools here - is that expected?

Is it still doing what it should be doing in that case?

actual = agent.tool_names
expected = list(agent.tool_registry.get_all_tools_config().keys())

Expand All @@ -643,7 +641,7 @@ def test_agent_init_with_no_model_or_model_id():
assert agent.model.get_config().get("model_id") == DEFAULT_BEDROCK_MODEL_ID


def test_agent_tool_no_parameter_conflict(agent, tool_registry, mock_randint):
def test_agent_tool_no_parameter_conflict(agent, mock_randint):
agent.tool_handler = unittest.mock.Mock()

@strands.tools.tool(name="system_prompter")
Expand Down Expand Up @@ -722,7 +720,7 @@ async def test_stream_async_returns_all_events(mock_event_loop_cycle):
agent = Agent()

# Define the side effect to simulate callback handler being called multiple times
def call_callback_handler(*args, **kwargs):
def call_callback_handler(**kwargs):
# Extract the callback handler from kwargs
callback_handler = kwargs.get("callback_handler")
# Call the callback handler with different data values
Expand Down Expand Up @@ -993,7 +991,7 @@ async def test_agent_stream_async_creates_and_ends_span_on_success(mock_get_trac
mock_get_tracer.return_value = mock_tracer

# Define the side effect to simulate callback handler being called multiple times
def call_callback_handler(*args, **kwargs):
def call_callback_handler(*_args, **kwargs):
# Extract the callback handler from kwargs
callback_handler = kwargs.get("callback_handler")
# Call the callback handler with different data values
Expand Down
3 changes: 3 additions & 0 deletions tests/strands/models/test_bedrock.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ def test__init__with_region_and_session_raises_value_error():

def test__init__default_user_agent(bedrock_client):
"""Set user agent when no boto_client_config is provided."""
_ = bedrock_client
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we turn this into an autofixture instead or use usefixtures? E.g. is there a reason we need to have it as a parameter or use

with unittest.mock.patch("strands.models.bedrock.boto3.Session") as mock_session_cls:
mock_session = mock_session_cls.return_value
_ = BedrockModel()
Expand All @@ -133,6 +134,7 @@ def test__init__default_user_agent(bedrock_client):

def test__init__with_custom_boto_client_config_no_user_agent(bedrock_client):
"""Set user agent when boto_client_config is provided without user_agent_extra."""
_ = bedrock_client
custom_config = BotocoreConfig(read_timeout=900)

with unittest.mock.patch("strands.models.bedrock.boto3.Session") as mock_session_cls:
Expand All @@ -150,6 +152,7 @@ def test__init__with_custom_boto_client_config_no_user_agent(bedrock_client):

def test__init__with_custom_boto_client_config_with_user_agent(bedrock_client):
"""Append to existing user agent when boto_client_config is provided with user_agent_extra."""
_ = bedrock_client
custom_config = BotocoreConfig(user_agent_extra="existing-agent", read_timeout=900)

with unittest.mock.patch("strands.models.bedrock.boto3.Session") as mock_session_cls:
Expand Down
16 changes: 8 additions & 8 deletions tests/strands/telemetry/test_tracer.py
Original file line number Diff line number Diff line change
Expand Up @@ -726,8 +726,8 @@ def test_serialize_vs_json_dumps():
assert japanese_text in custom_result
assert "\\u" not in custom_result


def test_init_with_no_env_or_param(clean_env):
@pytest.mark.usefixtures("clean_env")
def test_init_with_no_env_or_param():
"""Test initializing with neither environment variable nor constructor parameter."""
tracer = Tracer()
assert tracer.otlp_endpoint is None
Expand All @@ -739,8 +739,8 @@ def test_init_with_no_env_or_param(clean_env):
tracer = Tracer(enable_console_export=True)
assert tracer.enable_console_export is True


def test_constructor_params_with_otlp_env(env_with_otlp):
@pytest.mark.usefixtures("env_with_otlp")
def test_constructor_params_with_otlp_env():
"""Test constructor parameters precedence over OTLP environment variable."""
# Constructor parameter should take precedence
tracer = Tracer(otlp_endpoint="http://constructor-endpoint")
Expand All @@ -750,8 +750,8 @@ def test_constructor_params_with_otlp_env(env_with_otlp):
tracer = Tracer()
assert tracer.otlp_endpoint == "http://env-endpoint"


def test_constructor_params_with_console_env(env_with_console):
@pytest.mark.usefixtures("env_with_console")
def test_constructor_params_with_console_env():
"""Test constructor parameters precedence over console environment variable."""
# Constructor parameter should take precedence
tracer = Tracer(enable_console_export=False)
Expand All @@ -761,8 +761,8 @@ def test_constructor_params_with_console_env(env_with_console):
tracer = Tracer()
assert tracer.enable_console_export is True


def test_fallback_to_env_vars(env_with_both):
@pytest.mark.usefixtures("env_with_both")
def test_fallback_to_env_vars():
"""Test fallback to environment variables when no constructor parameters."""
tracer = Tracer()
assert tracer.otlp_endpoint == "http://env-endpoint"
Expand Down
2 changes: 1 addition & 1 deletion tests/strands/tools/mcp/test_mcp_agent_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def test_tool_type(mcp_agent_tool):
assert mcp_agent_tool.tool_type == "python"


def test_tool_spec_with_description(mcp_agent_tool, mock_mcp_tool):
def test_tool_spec_with_description(mcp_agent_tool):
tool_spec = mcp_agent_tool.tool_spec

assert tool_spec["name"] == "test_tool"
Expand Down
2 changes: 1 addition & 1 deletion tests/strands/tools/mcp/test_mcp_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def mock_session():


@pytest.fixture
def mcp_client(mock_transport, mock_session):
def mcp_client(mock_transport):
with MCPClient(mock_transport["transport_callable"]) as client:
yield client

Expand Down
4 changes: 2 additions & 2 deletions tests/strands/tools/test_decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ def test_tool(
bool_param: bool,
) -> str:
"""Test basic types."""
return "Success"
return f"Successfully used parameters: {str_param}, {int_param}, {float_param}, {bool_param}"

spec = test_tool.TOOL_SPEC
schema = spec["inputSchema"]["json"]
Expand Down Expand Up @@ -570,7 +570,7 @@ def validation_tool(str_param: str, int_param: int, bool_param: bool) -> str:
int_param: Integer parameter
bool_param: Boolean parameter
"""
return "Valid"
return f"Valid parameters: String argument{str_param}, Int arguemnt {int_param}, Bool argument {bool_param}"

# Test wrong type for int
tool_use = {
Expand Down
8 changes: 3 additions & 5 deletions tests/strands/tools/test_executor.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import concurrent
import functools
import unittest.mock
import uuid

import pytest

Expand Down Expand Up @@ -59,9 +58,9 @@ def invalid_tool_use_ids(request):


@pytest.fixture
def cycle_trace():
with unittest.mock.patch.object(uuid, "uuid4", return_value="trace1"):
return strands.telemetry.metrics.Trace(name="test trace", raw_name="raw_name")
def cycle_trace(mocker):
mocker.patch.object(strands.telemetry.metrics, "id", return_value="trace1")
return strands.telemetry.metrics.Trace(name="test trace", raw_name="raw_name")


@pytest.fixture
Expand Down Expand Up @@ -395,7 +394,6 @@ def test_run_tools_creates_and_ends_span_on_failure(
@unittest.mock.patch("strands.tools.executor.get_tracer")
def test_run_tools_handles_exception_in_tool_execution(
mock_get_tracer,
tool_handler,
tool_uses,
event_loop_metrics,
request_state,
Expand Down
Loading