Skip to content

Enable ruff ARG ruleset to warn about unused arguments #1425

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

Merged
merged 1 commit into from
May 25, 2025
Merged
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
4 changes: 2 additions & 2 deletions cmd2/argparse_custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ class CompletionItem(str): # noqa: SLOT000
See header of this file for more information
"""

def __new__(cls, value: object, *args: Any, **kwargs: Any) -> 'CompletionItem':
def __new__(cls, value: object, *_args: Any, **_kwargs: Any) -> 'CompletionItem':
return super().__new__(cls, value)

def __init__(self, value: object, description: str = '', *args: Any) -> None:
Expand Down Expand Up @@ -914,7 +914,7 @@ def _ArgumentParser_set_ap_completer_type(self: argparse.ArgumentParser, ap_comp
############################################################################################################
# Patch ArgumentParser._check_value to support CompletionItems as choices
############################################################################################################
def _ArgumentParser_check_value(self: argparse.ArgumentParser, action: argparse.Action, value: Any) -> None: # noqa: N802
def _ArgumentParser_check_value(_self: argparse.ArgumentParser, action: argparse.Action, value: Any) -> None: # noqa: N802
"""Custom override of ArgumentParser._check_value that supports CompletionItems as choices.
When evaluating choices, input is compared to CompletionItem.orig_value instead of the
CompletionItem instance.
Expand Down
26 changes: 16 additions & 10 deletions cmd2/cmd2.py
Original file line number Diff line number Diff line change
Expand Up @@ -1111,7 +1111,7 @@ def remove_settable(self, name: str) -> None:
def build_settables(self) -> None:
"""Create the dictionary of user-settable parameters."""

def get_allow_style_choices(cli_self: Cmd) -> list[str]:
def get_allow_style_choices(_cli_self: Cmd) -> list[str]:
"""Used to tab complete allow_style values."""
return [val.name.lower() for val in ansi.AllowStyle]

Expand Down Expand Up @@ -1419,9 +1419,9 @@ def tokens_for_completion(self, line: str, begidx: int, endidx: int) -> tuple[li
def basic_complete(
self,
text: str,
line: str,
begidx: int,
endidx: int,
line: str, # noqa: ARG002
begidx: int, # noqa: ARG002
endidx: int, # noqa: ARG002
match_against: Iterable[str],
) -> list[str]:
"""Basic tab completion function that matches against a list of strings without considering line contents
Expand Down Expand Up @@ -1602,7 +1602,13 @@ def index_based_complete(
return matches

def path_complete(
self, text: str, line: str, begidx: int, endidx: int, *, path_filter: Optional[Callable[[str], bool]] = None
self,
text: str,
line: str,
begidx: int, # noqa: ARG002
endidx: int,
*,
path_filter: Optional[Callable[[str], bool]] = None,
) -> list[str]:
"""Performs completion of local file system paths.

Expand Down Expand Up @@ -2346,7 +2352,7 @@ def get_help_topics(self) -> list[str]:
# Filter out hidden and disabled commands
return [topic for topic in all_topics if topic not in self.hidden_commands and topic not in self.disabled_commands]

def sigint_handler(self, signum: int, _: Optional[FrameType]) -> None:
def sigint_handler(self, signum: int, _: Optional[FrameType]) -> None: # noqa: ARG002
"""Signal handler for SIGINTs which typically come from Ctrl-C events.

If you need custom SIGINT behavior, then override this method.
Expand Down Expand Up @@ -2402,7 +2408,7 @@ def precmd(self, statement: Union[Statement, str]) -> Statement:
"""
return Statement(statement) if not isinstance(statement, Statement) else statement

def postcmd(self, stop: bool, statement: Union[Statement, str]) -> bool:
def postcmd(self, stop: bool, statement: Union[Statement, str]) -> bool: # noqa: ARG002
"""Hook method executed just after a command is executed by
[cmd2.Cmd.onecmd][].

Expand Down Expand Up @@ -3087,7 +3093,7 @@ def configure_readline() -> None:
# Disable completion
if completion_mode == utils.CompletionMode.NONE:

def complete_none(text: str, state: int) -> Optional[str]: # pragma: no cover
def complete_none(text: str, state: int) -> Optional[str]: # pragma: no cover # noqa: ARG001
return None

complete_func = complete_none
Expand Down Expand Up @@ -3773,7 +3779,7 @@ def do_help(self, args: argparse.Namespace) -> None:
self.perror(err_msg, apply_style=False)
self.last_result = False

def print_topics(self, header: str, cmds: Optional[list[str]], cmdlen: int, maxcol: int) -> None:
def print_topics(self, header: str, cmds: Optional[list[str]], cmdlen: int, maxcol: int) -> None: # noqa: ARG002
"""Print groups of commands and topics in columns and an optional header
Override of cmd's print_topics() to handle headers with newlines, ANSI style sequences, and wide characters.

Expand Down Expand Up @@ -5379,7 +5385,7 @@ def disable_command(self, command: str, message_to_print: str) -> None:
setattr(self, help_func_name, new_func)

# Set the completer to a function that returns a blank list
setattr(self, completer_func_name, lambda *args, **kwargs: [])
setattr(self, completer_func_name, lambda *_args, **_kwargs: [])

def disable_category(self, category: str, message_to_print: str) -> None:
"""Disable an entire category of commands.
Expand Down
2 changes: 1 addition & 1 deletion cmd2/parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ class Statement(str): # type: ignore[override] # noqa: SLOT000
# Used in JSON dictionaries
_args_field = 'args'

def __new__(cls, value: object, *pos_args: Any, **kw_args: Any) -> 'Statement':
def __new__(cls, value: object, *_pos_args: Any, **_kw_args: Any) -> 'Statement':
"""Create a new instance of Statement.

We must override __new__ because we are subclassing `str` which is
Expand Down
2 changes: 1 addition & 1 deletion examples/basic_completion.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def do_raise_error(self, statement: cmd2.Statement) -> None:
"""Demonstrates effect of raising CompletionError."""
self.poutput(f"Args: {statement.args}")

def complete_raise_error(self, text, line, begidx, endidx) -> list[str]:
def complete_raise_error(self, _text, _line, _begidx, _endidx) -> list[str]:
"""CompletionErrors can be raised if an error occurs while tab completing.

Example use cases
Expand Down
2 changes: 1 addition & 1 deletion examples/default_categories.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class ExampleApp(cmd2.Cmd):
def __init__(self) -> None:
super().__init__()

def do_something(self, arg) -> None:
def do_something(self, _arg) -> None:
self.poutput('this is the something command')


Expand Down
2 changes: 1 addition & 1 deletion examples/dynamic_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def __init__(self) -> None:

super().__init__(include_ipy=True)

def send_text(self, args: cmd2.Statement, *, text: str) -> None:
def send_text(self, _args: cmd2.Statement, *, text: str) -> None:
"""Simulate sending text to a server and printing the response."""
self.poutput(text.capitalize())

Expand Down
4 changes: 2 additions & 2 deletions examples/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def __init__(self) -> None:
)
self.add_settable(cmd2.Settable('sunny', bool, 'Is it sunny outside?', self))

def do_sunbathe(self, arg) -> None:
def do_sunbathe(self, _arg) -> None:
"""Attempt to sunbathe."""
if self.degrees_c < 20:
result = f"It's {self.degrees_c} C - are you a penguin?"
Expand All @@ -26,7 +26,7 @@ def do_sunbathe(self, arg) -> None:
result = 'UV is bad for your skin.'
self.poutput(result)

def _onchange_degrees_c(self, param_name, old, new) -> None:
def _onchange_degrees_c(self, _param_name, _old, new) -> None:
# if it's over 40C, it's gotta be sunny, right?
if new > 40:
self.sunny = True
Expand Down
2 changes: 1 addition & 1 deletion examples/migrating.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class CmdLineApp(cmd.Cmd):
MUMBLE_FIRST = ('so', 'like', 'well')
MUMBLE_LAST = ('right?',)

def do_exit(self, line) -> bool:
def do_exit(self, _line) -> bool:
"""Exit the application."""
return True

Expand Down
4 changes: 2 additions & 2 deletions examples/modular_commands/commandset_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def do_raise_error(self, statement: Statement) -> None:
"""Demonstrates effect of raising CompletionError."""
self._cmd.poutput(f"Args: {statement.args}")

def complete_raise_error(self, text: str, line: str, begidx: int, endidx: int) -> list[str]:
def complete_raise_error(self, _text: str, _line: str, _begidx: int, _endidx: int) -> list[str]:
"""CompletionErrors can be raised if an error occurs while tab completing.

Example use cases
Expand All @@ -83,5 +83,5 @@ def complete_raise_error(self, text: str, line: str, begidx: int, endidx: int) -
raise CompletionError("This is how a CompletionError behaves")

@with_category('Not Basic Completion')
def do_custom_category(self, statement: Statement) -> None:
def do_custom_category(self, _statement: Statement) -> None:
self._cmd.poutput('Demonstrates a command that bypasses the default category')
4 changes: 2 additions & 2 deletions examples/modular_commands/commandset_complex.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

@cmd2.with_default_category('Fruits')
class CommandSetA(cmd2.CommandSet):
def do_apple(self, statement: cmd2.Statement) -> None:
def do_apple(self, _statement: cmd2.Statement) -> None:
self._cmd.poutput('Apple!')

def do_banana(self, statement: cmd2.Statement) -> None:
def do_banana(self, _statement: cmd2.Statement) -> None:
"""Banana Command."""
self._cmd.poutput('Banana!!')

Expand Down
4 changes: 2 additions & 2 deletions examples/modular_commands/commandset_custominit.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ def __init__(self, arg1, arg2) -> None:
self._arg1 = arg1
self._arg2 = arg2

def do_show_arg1(self, cmd: Cmd, _: Statement) -> None:
def do_show_arg1(self, _cmd: Cmd, _: Statement) -> None:
self._cmd.poutput('Arg1: ' + self._arg1)

def do_show_arg2(self, cmd: Cmd, _: Statement) -> None:
def do_show_arg2(self, _cmd: Cmd, _: Statement) -> None:
self._cmd.poutput('Arg2: ' + self._arg2)
2 changes: 1 addition & 1 deletion examples/modular_commands_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class ExampleApp(cmd2.Cmd):
def __init__(self) -> None:
super().__init__()

def do_something(self, arg) -> None:
def do_something(self, _arg) -> None:
self.poutput('this is the something command')


Expand Down
6 changes: 3 additions & 3 deletions examples/pirate.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def precmd(self, line):
self.initial_gold = self.gold
return line

def postcmd(self, stop, line):
def postcmd(self, stop, _line):
"""Runs right before a command is about to return."""
if self.gold != self.initial_gold:
self.poutput(f'Now we gots {self.gold} doubloons')
Expand All @@ -51,7 +51,7 @@ def postcmd(self, stop, line):
stop = True
return stop

def do_loot(self, arg) -> None:
def do_loot(self, _arg) -> None:
"""Seize booty from a passing ship."""
self.gold += 1

Expand All @@ -67,7 +67,7 @@ def do_drink(self, arg) -> None:
self.poutput(f'''What's "{arg}"? I'll take rrrum.''')
self.gold -= 1

def do_quit(self, arg) -> bool:
def do_quit(self, _arg) -> bool:
"""Quit the application gracefully."""
self.poutput("Quiterrr!")
return True
Expand Down
4 changes: 2 additions & 2 deletions examples/python_scripting.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def _set_prompt(self) -> None:
self.cwd = os.getcwd()
self.prompt = ansi.style(f'{self.cwd} $ ', fg=ansi.Fg.CYAN)

def postcmd(self, stop: bool, line: str) -> bool:
def postcmd(self, stop: bool, _line: str) -> bool:
"""Hook method executed just after a command dispatch is finished.

:param stop: if True, the command has indicated the application should exit
Expand Down Expand Up @@ -96,7 +96,7 @@ def complete_cd(self, text, line, begidx, endidx):
dir_parser.add_argument('-l', '--long', action='store_true', help="display in long format with one item per line")

@cmd2.with_argparser(dir_parser, with_unknown_args=True)
def do_dir(self, args, unknown) -> None:
def do_dir(self, _args, unknown) -> None:
"""List contents of current directory."""
# No arguments for this command
if unknown:
Expand Down
2 changes: 1 addition & 1 deletion plugins/ext_test/examples/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def __init__(self, *args, **kwargs):
# gotta have this or neither the plugin or cmd2 will initialize
super().__init__(*args, **kwargs)

def do_something(self, arg):
def do_something(self, _arg):
self.last_result = 5
self.poutput('this is the something command')

Expand Down
2 changes: 1 addition & 1 deletion plugins/template/examples/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)

@cmd2_myplugin.empty_decorator
def do_something(self, arg) -> None:
def do_something(self, _arg) -> None:
self.poutput('this is the something command')


Expand Down
8 changes: 4 additions & 4 deletions plugins/template/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def pylint_tests(context) -> None:


@invoke.task
def build_clean(context) -> None:
def build_clean(_context) -> None:
"""Remove the build directory."""
# pylint: disable=unused-argument
rmrf(BUILDDIR)
Expand All @@ -106,7 +106,7 @@ def build_clean(context) -> None:


@invoke.task
def dist_clean(context) -> None:
def dist_clean(_context) -> None:
"""Remove the dist directory."""
# pylint: disable=unused-argument
rmrf(DISTDIR)
Expand All @@ -116,7 +116,7 @@ def dist_clean(context) -> None:


@invoke.task
def eggs_clean(context) -> None:
def eggs_clean(_context) -> None:
"""Remove egg directories."""
# pylint: disable=unused-argument
dirs = set()
Expand All @@ -133,7 +133,7 @@ def eggs_clean(context) -> None:


@invoke.task
def bytecode_clean(context) -> None:
def bytecode_clean(_context) -> None:
"""Remove __pycache__ directories and *.pyc files."""
# pylint: disable=unused-argument
dirs = set()
Expand Down
2 changes: 1 addition & 1 deletion plugins/template/tests/test_myplugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)

@cmd2_myplugin.empty_decorator
def do_empty(self, args) -> None:
def do_empty(self, _args) -> None:
self.poutput("running the empty command")


Expand Down
6 changes: 4 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,8 @@ select = [
# https://docs.astral.sh/ruff/rules
"A", # flake8-builtins (variables or arguments shadowing built-ins)
# "AIR", # Airflow specific warnings
"ANN", # flake8-annotations (missing type annotations for arguments or return types)
# "ARG", # flake8-unused-arguments (functions or methods with arguments that are never used)
"ANN", # flake8-annotations (missing type annotations for arguments or return types)
"ARG", # flake8-unused-arguments (functions or methods with arguments that are never used)
"ASYNC", # flake8-async (async await bugs)
# "B", # flake8-bugbear (various likely bugs and design issues)
"BLE", # flake8-blind-except (force more specific exception types than just Exception)
Expand Down Expand Up @@ -279,6 +279,7 @@ per-file-ignores."plugins/*.py" = [

per-file-ignores."tests/*.py" = [
"ANN", # Ignore all type annotation rules in test folders
"ARG", # Ignore all unused argument warnings in test folders
"D", # Ignore all pydocstyle rules in test folders
"E501", # Line too long
"S", # Ignore all Security rules in test folders
Expand All @@ -292,6 +293,7 @@ per-file-ignores."tests/pyscript/*.py" = [

per-file-ignores."tests_isolated/*.py" = [
"ANN", # Ignore all type annotation rules in test folders
"ARG", # Ignore all unused argument warnings in test folders
"D", # Ignore all pydocstyle rules in test folders
"S", # Ignore all Security rules in test folders
"SLF", # Ignore all warnings about private or protected member access in test folders
Expand Down
2 changes: 1 addition & 1 deletion tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ def mypy_clean(context: Context) -> None:


@invoke.task()
def docs(context: Context, builder: str = 'html') -> None:
def docs(context: Context) -> None:
"""Build documentation using MkDocs."""
with context.cd(TASK_ROOT_STR):
context.run('mkdocs build', pty=True)
Expand Down
Loading