Skip to content

Commit 28729a2

Browse files
authored
Fix: Remove unused mypy ignores and fix type errors (#1481)
Fix: Remove unused mypy ignores and fix type errors (#1481) Also: - Fix a typo in comment in argparse_completer.py - Add draft GEMINI.md file for use with Gemini CLI
1 parent 8bbe688 commit 28729a2

File tree

9 files changed

+76
-33
lines changed

9 files changed

+76
-33
lines changed

GEMINI.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Instructions for Gemini CLI in a `uv` Python project
2+
3+
This `GEMINI.md` file provides context and instructions for the Gemini CLI when working with this
4+
Python project, which utilizes `uv` for environment and package management.
5+
6+
## General Instructions
7+
8+
- **Environment Management:** Prefer using `uv` for all Python environment management tasks.
9+
- **Package Installation:** Always use `uv` to install packages and ensure they are installed within
10+
the project's virtual environment.
11+
- **Running Scripts/Commands:**
12+
- To run Python scripts within the project's virtual environment, use `uv run ...`.
13+
- To run programs directly from a PyPI package (installing it on the fly if necessary), use
14+
`uvx ...` (shortcut for `uv tool run`).
15+
- **New Dependencies:** If a new dependency is required, please state the reason for its inclusion.
16+
17+
## Python Code Standards
18+
19+
To ensure Python code adheres to required standards, the following commands **must** be run before
20+
creating or modifying any `.py` files:
21+
22+
```bash
23+
make check
24+
```
25+
26+
To run unit tests use the following command:
27+
28+
```bash
29+
make test
30+
```
31+
32+
To make sure the documentation builds properly, use the following command:
33+
34+
```bash
35+
make docs-test
36+
```
37+
38+
All 3 of the above commands should be run prior to committing code.

cmd2/argparse_completer.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""Module efines the ArgparseCompleter class which provides argparse-based tab completion to cmd2 apps.
1+
"""Module defines the ArgparseCompleter class which provides argparse-based tab completion to cmd2 apps.
22
33
See the header of argparse_custom.py for instructions on how to use these features.
44
"""
@@ -533,7 +533,7 @@ def _format_completions(self, arg_state: _ArgumentState, completions: list[str]
533533
if not self._cmd2_app.matches_sorted:
534534
# If all orig_value types are numbers, then sort by that value
535535
if all_nums:
536-
completion_items.sort(key=lambda c: c.orig_value) # type: ignore[no-any-return]
536+
completion_items.sort(key=lambda c: c.orig_value)
537537

538538
# Otherwise sort as strings
539539
else:
@@ -726,12 +726,12 @@ def _complete_arg(
726726
if not arg_choices.is_completer:
727727
choices_func = arg_choices.choices_provider
728728
if isinstance(choices_func, ChoicesProviderFuncWithTokens):
729-
completion_items = choices_func(*args, **kwargs) # type: ignore[arg-type]
729+
completion_items = choices_func(*args, **kwargs)
730730
else: # pragma: no cover
731731
# This won't hit because runtime checking doesn't check function argument types and will always
732732
# resolve true above. Mypy, however, does see the difference and gives an error that can't be
733733
# ignored. Mypy issue #5485 discusses this problem
734-
completion_items = choices_func(*args) # type: ignore[arg-type]
734+
completion_items = choices_func(*args)
735735
# else case is already covered above
736736
else:
737737
completion_items = arg_choices

cmd2/argparse_custom.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1433,7 +1433,7 @@ def __init__(
14331433
description=description, # type: ignore[arg-type]
14341434
epilog=epilog, # type: ignore[arg-type]
14351435
parents=parents if parents else [],
1436-
formatter_class=formatter_class, # type: ignore[arg-type]
1436+
formatter_class=formatter_class,
14371437
prefix_chars=prefix_chars,
14381438
fromfile_prefix_chars=fromfile_prefix_chars,
14391439
argument_default=argument_default,
@@ -1498,7 +1498,7 @@ def format_help(self) -> str:
14981498
formatter = self._get_formatter()
14991499

15001500
# usage
1501-
formatter.add_usage(self.usage, self._actions, self._mutually_exclusive_groups) # type: ignore[arg-type]
1501+
formatter.add_usage(self.usage, self._actions, self._mutually_exclusive_groups)
15021502

15031503
# description
15041504
formatter.add_text(self.description)

cmd2/clipboard.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import typing
44

5-
import pyperclip # type: ignore[import]
5+
import pyperclip # type: ignore[import-untyped]
66

77

88
def get_paste_buffer() -> str:

cmd2/cmd2.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@
137137

138138
# NOTE: When using gnureadline with Python 3.13, start_ipython needs to be imported before any readline-related stuff
139139
with contextlib.suppress(ImportError):
140-
from IPython import start_ipython # type: ignore[import]
140+
from IPython import start_ipython
141141

142142
from .rl_utils import (
143143
RlType,
@@ -163,7 +163,7 @@
163163
if rl_type == RlType.NONE: # pragma: no cover
164164
Cmd2Console(sys.stderr).print(rl_warning, style=Cmd2Style.WARNING)
165165
else:
166-
from .rl_utils import ( # type: ignore[attr-defined]
166+
from .rl_utils import (
167167
readline,
168168
rl_force_redisplay,
169169
)
@@ -1068,7 +1068,7 @@ def _unregister_subcommands(self, cmdset: Union[CommandSet, 'Cmd']) -> None:
10681068

10691069
for action in command_parser._actions:
10701070
if isinstance(action, argparse._SubParsersAction):
1071-
action.remove_parser(subcommand_name) # type: ignore[arg-type,attr-defined]
1071+
action.remove_parser(subcommand_name) # type: ignore[attr-defined]
10721072
break
10731073

10741074
@property
@@ -3094,11 +3094,11 @@ def _redirect_output(self, statement: Statement) -> utils.RedirectionSavedState:
30943094
kwargs['executable'] = shell
30953095

30963096
# For any stream that is a StdSim, we will use a pipe so we can capture its output
3097-
proc = subprocess.Popen( # type: ignore[call-overload] # noqa: S602
3097+
proc = subprocess.Popen( # noqa: S602
30983098
statement.pipe_to,
30993099
stdin=subproc_stdin,
31003100
stdout=subprocess.PIPE if isinstance(self.stdout, utils.StdSim) else self.stdout, # type: ignore[unreachable]
3101-
stderr=subprocess.PIPE if isinstance(sys.stderr, utils.StdSim) else sys.stderr, # type: ignore[unreachable]
3101+
stderr=subprocess.PIPE if isinstance(sys.stderr, utils.StdSim) else sys.stderr,
31023102
shell=True,
31033103
**kwargs,
31043104
)
@@ -3115,7 +3115,7 @@ def _redirect_output(self, statement: Statement) -> utils.RedirectionSavedState:
31153115
subproc_stdin.close()
31163116
new_stdout.close()
31173117
raise RedirectionError(f'Pipe process exited with code {proc.returncode} before command could run')
3118-
redir_saved_state.redirecting = True # type: ignore[unreachable]
3118+
redir_saved_state.redirecting = True
31193119
cmd_pipe_proc_reader = utils.ProcReader(proc, cast(TextIO, self.stdout), sys.stderr)
31203120

31213121
self.stdout = new_stdout
@@ -3351,7 +3351,7 @@ def complete_none(text: str, state: int) -> str | None: # pragma: no cover # n
33513351
parser.add_argument(
33523352
'arg',
33533353
suppress_tab_hint=True,
3354-
choices=choices, # type: ignore[arg-type]
3354+
choices=choices,
33553355
choices_provider=choices_provider,
33563356
completer=completer,
33573357
)
@@ -4435,7 +4435,7 @@ def complete_set_value(
44354435
arg_name,
44364436
metavar=arg_name,
44374437
help=settable.description,
4438-
choices=settable.choices, # type: ignore[arg-type]
4438+
choices=settable.choices,
44394439
choices_provider=settable.choices_provider,
44404440
completer=settable.completer,
44414441
)
@@ -4566,15 +4566,15 @@ def do_shell(self, args: argparse.Namespace) -> None:
45664566
# still receive the SIGINT since it is in the same process group as us.
45674567
with self.sigint_protection:
45684568
# For any stream that is a StdSim, we will use a pipe so we can capture its output
4569-
proc = subprocess.Popen( # type: ignore[call-overload] # noqa: S602
4569+
proc = subprocess.Popen( # noqa: S602
45704570
expanded_command,
45714571
stdout=subprocess.PIPE if isinstance(self.stdout, utils.StdSim) else self.stdout, # type: ignore[unreachable]
4572-
stderr=subprocess.PIPE if isinstance(sys.stderr, utils.StdSim) else sys.stderr, # type: ignore[unreachable]
4572+
stderr=subprocess.PIPE if isinstance(sys.stderr, utils.StdSim) else sys.stderr,
45734573
shell=True,
45744574
**kwargs,
45754575
)
45764576

4577-
proc_reader = utils.ProcReader(proc, cast(TextIO, self.stdout), sys.stderr) # type: ignore[arg-type]
4577+
proc_reader = utils.ProcReader(proc, cast(TextIO, self.stdout), sys.stderr)
45784578
proc_reader.wait()
45794579

45804580
# Save the return code of the application for use in a pyscript
@@ -4656,9 +4656,9 @@ def _set_up_py_shell_env(self, interp: InteractiveConsole) -> _SavedCmd2Env:
46564656
# Save off the current completer and set a new one in the Python console
46574657
# Make sure it tab completes from its locals() dictionary
46584658
cmd2_env.readline_settings.completer = readline.get_completer()
4659-
interp.runcode("from rlcompleter import Completer") # type: ignore[arg-type]
4660-
interp.runcode("import readline") # type: ignore[arg-type]
4661-
interp.runcode("readline.set_completer(Completer(locals()).complete)") # type: ignore[arg-type]
4659+
interp.runcode(compile("from rlcompleter import Completer", "<stdin>", "exec"))
4660+
interp.runcode(compile("import readline", "<stdin>", "exec"))
4661+
interp.runcode(compile("readline.set_completer(Completer(locals()).complete)", "<stdin>", "exec"))
46624662

46634663
# Set up sys module for the Python console
46644664
self._reset_py_display()
@@ -4889,18 +4889,18 @@ def do_ipy(self, _: argparse.Namespace) -> bool | None: # pragma: no cover
48894889

48904890
# Detect whether IPython is installed
48914891
try:
4892-
import traitlets.config.loader as traitlets_loader # type: ignore[import]
4892+
import traitlets.config.loader as traitlets_loader
48934893

48944894
# Allow users to install ipython from a cmd2 prompt when needed and still have ipy command work
48954895
try:
48964896
_dummy = start_ipython # noqa: F823
48974897
except NameError:
4898-
from IPython import start_ipython # type: ignore[import]
4898+
from IPython import start_ipython
48994899

4900-
from IPython.terminal.interactiveshell import ( # type: ignore[import]
4900+
from IPython.terminal.interactiveshell import (
49014901
TerminalInteractiveShell,
49024902
)
4903-
from IPython.terminal.ipapp import ( # type: ignore[import]
4903+
from IPython.terminal.ipapp import (
49044904
TerminalIPythonApp,
49054905
)
49064906
except ImportError:

cmd2/decorators.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ def cmd_wrapper(*args: Any, **kwargs: Any) -> bool | None:
180180
cmd2_app, statement = _parse_positionals(args)
181181
_, parsed_arglist = cmd2_app.statement_parser.get_command_arg_list(command_name, statement, preserve_quotes)
182182
args_list = _arg_swap(args, statement, parsed_arglist)
183-
return func(*args_list, **kwargs) # type: ignore[call-arg]
183+
return func(*args_list, **kwargs)
184184

185185
command_name = func.__name__[len(constants.COMMAND_FUNC_PREFIX) :]
186186
cmd_wrapper.__doc__ = func.__doc__
@@ -336,7 +336,7 @@ def cmd_wrapper(*args: Any, **kwargs: dict[str, Any]) -> bool | None:
336336
delattr(ns, constants.NS_ATTR_SUBCMD_HANDLER)
337337

338338
args_list = _arg_swap(args, statement_arg, *new_args)
339-
return func(*args_list, **kwargs) # type: ignore[call-arg]
339+
return func(*args_list, **kwargs)
340340

341341
command_name = func.__name__[len(constants.COMMAND_FUNC_PREFIX) :]
342342

cmd2/parsing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ class Macro:
8181

8282

8383
@dataclass(frozen=True)
84-
class Statement(str): # type: ignore[override] # noqa: SLOT000
84+
class Statement(str): # noqa: SLOT000
8585
"""String subclass with additional attributes to store the results of parsing.
8686
8787
The ``cmd`` module in the standard library passes commands around as a

cmd2/rl_utils.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@
2424

2525
# Prefer statically linked gnureadline if installed due to compatibility issues with libedit
2626
try:
27-
import gnureadline as readline # type: ignore[import]
27+
import gnureadline as readline # type: ignore[import-not-found]
2828
except ImportError:
2929
# Note: If this actually fails, you should install gnureadline on Linux/Mac or pyreadline3 on Windows.
3030
with contextlib.suppress(ImportError):
31-
import readline # type: ignore[no-redef]
31+
import readline
3232

3333

3434
class RlType(Enum):
@@ -279,7 +279,7 @@ def rl_in_search_mode() -> bool: # pragma: no cover
279279
readline_state = ctypes.c_int.in_dll(readline_lib, "rl_readline_state").value
280280
return bool(in_search_mode & readline_state)
281281
if rl_type == RlType.PYREADLINE:
282-
from pyreadline3.modes.emacs import ( # type: ignore[import]
282+
from pyreadline3.modes.emacs import ( # type: ignore[import-not-found]
283283
EmacsMode,
284284
)
285285

@@ -294,3 +294,8 @@ def rl_in_search_mode() -> bool: # pragma: no cover
294294
)
295295
return readline.rl.mode.process_keyevent_queue[-1] in search_funcs
296296
return False
297+
298+
299+
__all__ = [
300+
'readline',
301+
]

cmd2/utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,7 @@ def do_echo(self, arglist):
697697
for item in func:
698698
setattr(item, constants.CMD_ATTR_HELP_CATEGORY, category)
699699
elif inspect.ismethod(func):
700-
setattr(func.__func__, constants.CMD_ATTR_HELP_CATEGORY, category) # type: ignore[attr-defined]
700+
setattr(func.__func__, constants.CMD_ATTR_HELP_CATEGORY, category)
701701
else:
702702
setattr(func, constants.CMD_ATTR_HELP_CATEGORY, category)
703703

@@ -716,7 +716,7 @@ def get_defining_class(meth: Callable[..., Any]) -> type[Any] | None:
716716
if inspect.ismethod(meth) or (
717717
inspect.isbuiltin(meth) and hasattr(meth, '__self__') and hasattr(meth.__self__, '__class__')
718718
):
719-
for cls in inspect.getmro(meth.__self__.__class__): # type: ignore[attr-defined]
719+
for cls in inspect.getmro(meth.__self__.__class__):
720720
if meth.__name__ in cls.__dict__:
721721
return cls
722722
meth = getattr(meth, '__func__', meth) # fallback to __qualname__ parsing

0 commit comments

Comments
 (0)