Bump Python version used for linters to 3.10

Change-Id: I6895cd7bf4f2872f6a0111eb55b1691bf23d9a14
Signed-off-by: Stephen Finucane <sfinucan@redhat.com>
This commit is contained in:
Stephen Finucane
2025-05-07 12:45:40 +01:00
parent adc5c6b81c
commit af17b57035
14 changed files with 48 additions and 61 deletions

View File

@@ -15,7 +15,7 @@ repos:
files: .*\.(yaml|yml)$
exclude: '^zuul.d/.*$'
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.6
rev: v0.11.8
hooks:
- id: ruff
args: ['--fix', '--unsafe-fixes']

View File

@@ -76,15 +76,14 @@ class App:
def __init__(
self,
description: ty.Optional[str],
version: ty.Optional[str],
description: str | None,
version: str | None,
command_manager: '_commandmanager.CommandManager',
stdin: ty.Optional[ty.TextIO] = None,
stdout: ty.Optional[ty.TextIO] = None,
stderr: ty.Optional[ty.TextIO] = None,
interactive_app_factory: ty.Optional[
type['_interactive.InteractiveApp']
] = None,
stdin: ty.TextIO | None = None,
stdout: ty.TextIO | None = None,
stderr: ty.TextIO | None = None,
interactive_app_factory: type['_interactive.InteractiveApp']
| None = None,
deferred_help: bool = False,
) -> None:
"""Initialize the application."""
@@ -96,13 +95,13 @@ class App:
self.deferred_help = deferred_help
self.parser = self.build_option_parser(description, version)
self.interactive_mode = False
self.interpreter: ty.Optional[_interactive.InteractiveApp] = None
self.interpreter: _interactive.InteractiveApp | None = None
def _set_streams(
self,
stdin: ty.Optional[ty.TextIO],
stdout: ty.Optional[ty.TextIO],
stderr: ty.Optional[ty.TextIO],
stdin: ty.TextIO | None,
stdout: ty.TextIO | None,
stderr: ty.TextIO | None,
) -> None:
try:
locale.setlocale(locale.LC_ALL, '')
@@ -141,9 +140,9 @@ class App:
def build_option_parser(
self,
description: ty.Optional[str],
version: ty.Optional[str],
argparse_kwargs: ty.Optional[dict[str, ty.Any]] = None,
description: str | None,
version: str | None,
argparse_kwargs: dict[str, ty.Any] | None = None,
) -> _argparse.ArgumentParser:
"""Return an argparse option parser for this application.
@@ -331,7 +330,7 @@ class App:
self,
cmd: '_command.Command',
result: int,
err: ty.Optional[BaseException],
err: BaseException | None,
) -> None:
"""Hook run after a command is done to shutdown the app.
@@ -434,7 +433,7 @@ class App:
kwargs['cmd_name'] = cmd_name
cmd = cmd_factory(self, self.options, **kwargs)
result = 1
err: ty.Optional[BaseException] = None
err: BaseException | None = None
try:
self.prepare_to_run_command(cmd)
full_name = (

View File

@@ -12,22 +12,15 @@
import abc
import argparse
from importlib.metadata import packages_distributions
import inspect
import types
import sys
import typing as ty
from stevedore import extension
from cliff import _argparse
if sys.version_info < (3, 10):
# Python 3.9 and older
from importlib_metadata import packages_distributions
else:
# Python 3.10 and later
from importlib.metadata import packages_distributions # type: ignore
if ty.TYPE_CHECKING:
from . import app as _app
@@ -52,8 +45,8 @@ def _get_distributions_by_modules() -> dict[str, str]:
def _get_distribution_for_module(
module: ty.Optional[types.ModuleType],
) -> ty.Optional[str]:
module: types.ModuleType | None,
) -> str | None:
"Return the distribution containing the module."
dist_name = None
if module:
@@ -77,7 +70,7 @@ class Command(metaclass=abc.ABCMeta):
:param cmd_name: The name of the command.
"""
app_dist_name: ty.Optional[str]
app_dist_name: str | None
deprecated = False
conflict_handler = 'ignore'
@@ -88,8 +81,8 @@ class Command(metaclass=abc.ABCMeta):
def __init__(
self,
app: '_app.App',
app_args: ty.Optional[argparse.Namespace],
cmd_name: ty.Optional[str] = None,
app_args: argparse.Namespace | None,
cmd_name: str | None = None,
) -> None:
self.app = app
self.app_args = app_args

View File

@@ -15,7 +15,6 @@
import collections.abc
import inspect
import logging
import typing as ty
import stevedore
@@ -158,7 +157,7 @@ class CommandManager:
return i
return len(argv)
def add_command_group(self, group: ty.Optional[str] = None) -> None:
def add_command_group(self, group: str | None = None) -> None:
"""Adds another group of command entrypoints"""
if group:
self.load_commands(group)
@@ -167,7 +166,7 @@ class CommandManager:
"""Returns a list of the loaded command groups"""
return self.group_list
def get_command_names(self, group: ty.Optional[str] = None) -> list[str]:
def get_command_names(self, group: str | None = None) -> list[str]:
"""Returns a list of commands loaded for the specified group"""
group_list: list[str] = []
if group is not None:

View File

@@ -196,7 +196,7 @@ class CompleteCommand(_command.Command):
self,
app: 'app.App',
app_args: argparse.Namespace,
cmd_name: ty.Optional[str] = None,
cmd_name: str | None = None,
) -> None:
super().__init__(app, app_args, cmd_name)
self._formatters = stevedore.ExtensionManager(

View File

@@ -33,8 +33,8 @@ class DisplayCommandBase(command.Command, metaclass=abc.ABCMeta):
def __init__(
self,
app: app.App,
app_args: ty.Optional[argparse.Namespace],
cmd_name: ty.Optional[str] = None,
app_args: argparse.Namespace | None,
cmd_name: str | None = None,
) -> None:
super().__init__(app, app_args, cmd_name=cmd_name)
self._formatter_plugins = self._load_formatter_plugins()
@@ -112,7 +112,7 @@ class DisplayCommandBase(command.Command, metaclass=abc.ABCMeta):
self,
parsed_args: argparse.Namespace,
column_names: collections.abc.Sequence[str],
) -> tuple[list[str], ty.Optional[list[bool]]]:
) -> tuple[list[str], list[bool] | None]:
"""Generate included columns and selector according to parsed args.
We normalize the column names so that someone can do e.g. '-c

View File

@@ -29,9 +29,9 @@ _T = ty.TypeVar('_T')
def _format_row(
row: collections.abc.Iterable[
ty.Union[columns.FormattableColumn[ty.Any], str, _T]
columns.FormattableColumn[ty.Any] | str | _T
],
) -> list[ty.Union[_T, str]]:
) -> list[_T | str]:
new_row = []
for r in row:
if isinstance(r, columns.FormattableColumn):

View File

@@ -44,8 +44,8 @@ class HelpAction(argparse.Action):
self,
parser: argparse.ArgumentParser,
namespace: argparse.Namespace,
values: ty.Union[str, collections.abc.Sequence[ty.Any], None],
option_string: ty.Optional[str] = None,
values: str | collections.abc.Sequence[ty.Any] | None,
option_string: str | None = None,
) -> None:
app = self.default
pager = autopage.argparse.help_pager(app.stdout)
@@ -57,7 +57,7 @@ class HelpAction(argparse.Action):
out.write('\n{}Commands{}:\n'.format(*title_hl))
dists_by_module = command._get_distributions_by_modules()
def dist_for_obj(obj: object) -> ty.Optional[str]:
def dist_for_obj(obj: object) -> str | None:
mod = inspect.getmodule(obj)
if mod is None:
raise RuntimeError(f"failed to find app: {obj}")

View File

@@ -12,7 +12,6 @@
import abc
import argparse
import typing as ty
from cliff import _argparse
from cliff import command
@@ -37,7 +36,7 @@ class CommandHook(metaclass=abc.ABCMeta):
@abc.abstractmethod
def get_parser(
self, parser: _argparse.ArgumentParser
) -> ty.Optional[_argparse.ArgumentParser]:
) -> _argparse.ArgumentParser | None:
"""Modify the command :class:`argparse.ArgumentParser`.
The provided parser is modified in-place, and the return value is not
@@ -49,7 +48,7 @@ class CommandHook(metaclass=abc.ABCMeta):
return parser
@abc.abstractmethod
def get_epilog(self) -> ty.Optional[str]:
def get_epilog(self) -> str | None:
"""Return text to add to the command help epilog.
:returns: An epilog string or None.

View File

@@ -50,8 +50,8 @@ class InteractiveApp(cmd2.Cmd):
self,
parent_app: '_app.App',
command_manager: '_commandmanager.CommandManager',
stdin: ty.Optional[ty.TextIO],
stdout: ty.Optional[ty.TextIO],
stdin: ty.TextIO | None,
stdout: ty.TextIO | None,
errexit: bool = False,
):
self.parent_app = parent_app
@@ -65,7 +65,7 @@ class InteractiveApp(cmd2.Cmd):
cmd2.Cmd.__init__(self, 'tab', stdin=stdin, stdout=stdout)
# def _split_line(self, line: cmd2.Statement) -> list[str]:
def _split_line(self, line: ty.Union[str, cmd2.Statement]) -> list[str]:
def _split_line(self, line: str | cmd2.Statement) -> list[str]:
# cmd2 >= 0.9.1 gives us a Statement not a PyParsing parse
# result.
parts = shlex.split(line)
@@ -73,7 +73,7 @@ class InteractiveApp(cmd2.Cmd):
parts.insert(0, line.command)
return parts
def default(self, line: str) -> ty.Optional[bool]: # type: ignore[override]
def default(self, line: str) -> bool | None: # type: ignore[override]
# Tie in the default command processor to
# dispatch commands known to the command manager.
# We send the message through our parent app,
@@ -120,7 +120,7 @@ class InteractiveApp(cmd2.Cmd):
# Use the command manager to get instructions for "help"
self.default('help help')
def do_help(self, arg: ty.Optional[str]) -> None:
def do_help(self, arg: str | None) -> None:
if arg:
# Check if the arg is a builtin command or something
# coming from the command manager
@@ -167,9 +167,7 @@ class InteractiveApp(cmd2.Cmd):
n for n in cmd2.Cmd.get_names(self) if not n.startswith('do__')
]
def precmd(
self, statement: ty.Union[cmd2.Statement, str]
) -> cmd2.Statement:
def precmd(self, statement: cmd2.Statement | str) -> cmd2.Statement:
"""Hook method executed just before the command is executed by
:meth:`~cmd2.Cmd.onecmd` and after adding it to history.
@@ -207,7 +205,7 @@ class InteractiveApp(cmd2.Cmd):
)
return statement
def cmdloop(self, intro: ty.Optional[str] = None) -> None: # type: ignore[override]
def cmdloop(self, intro: str | None = None) -> None: # type: ignore[override]
# We don't want the cmd2 cmdloop() behaviour, just call the old one
# directly. In part this is because cmd2.cmdloop() doe not return
# anything useful and we want to have a useful exit code.

View File

@@ -279,7 +279,7 @@ class AutoprogramCliffDirective(rst.Directive):
del parser._actions[parser._actions.index(action)]
break
def _load_app(self) -> ty.Optional[app.App]:
def _load_app(self) -> app.App | None:
mod_str, _sep, class_str = self.arguments[0].rpartition('.')
if not mod_str:
return None

View File

@@ -10,13 +10,12 @@
# License for the specific language governing permissions and limitations
# under the License.
import typing as ty
import unittest
from cliff import columns
class FauxColumn(columns.FormattableColumn[ty.Union[str, list[str]]]):
class FauxColumn(columns.FormattableColumn[str | list[str]]):
def human_readable(self):
return f'I made this string myself: {self._value}'

View File

@@ -12,7 +12,6 @@
# limitations under the License.
import os
import typing as ty
# Each edit operation is assigned different cost, such as:
# 'w' means swap operation, the cost is 0;
@@ -91,7 +90,7 @@ def damerau_levenshtein(s1: str, s2: str, cost: dict[str, int]) -> int:
return row1[-1]
def terminal_width() -> ty.Optional[int]:
def terminal_width() -> int | None:
"""Return terminal width in columns
Uses `os.get_terminal_size` function

View File

@@ -1,5 +1,5 @@
[tool.mypy]
python_version = "3.9"
python_version = "3.10"
show_column_numbers = true
show_error_context = true
ignore_missing_imports = true
@@ -35,6 +35,7 @@ disallow_subclassing_any = false
[tool.ruff]
line-length = 79
target-version = "py310"
[tool.ruff.format]
quote-style = "preserve"