diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 909ad4e1..df51ba5b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,12 +22,12 @@ repos: - id: check-docstring-first - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.15.4 + rev: v0.17.0 hooks: - id: ruff-check - id: ruff-format - repo: https://github.com/woodruffw/zizmor-pre-commit - rev: v1.22.0 + rev: v1.31.0 hooks: - id: zizmor diff --git a/README.md b/README.md index 19b5be8b..28a8d4df 100644 --- a/README.md +++ b/README.md @@ -24,22 +24,19 @@ To make a command that greets you from the command line, create from cleo.commands.command import Command from cleo.helpers import argument, option + class GreetCommand(Command): name = "greet" description = "Greets someone" arguments = [ - argument( - "name", - description="Who do you want to greet?", - optional=True - ) + argument("name", description="Who do you want to greet?", optional=True) ] options = [ option( "yell", "y", description="If set, the task will yell in uppercase letters", - flag=True + flag=True, ) ] @@ -204,18 +201,14 @@ class GreetCommand(Command): "name", description="Who do you want to greet?", ), - argument( - "last_name", - description="Your last name?", - optional=True - ) + argument("last_name", description="Your last name?", optional=True), ] options = [ option( "yell", "y", description="If set, the task will yell in uppercase letters", - flag=True + flag=True, ) ] ``` @@ -244,18 +237,14 @@ class GreetCommand(Command): name = "greet" description = "Greets someone" arguments = [ - argument( - "names", - description="Who do you want to greet?", - multiple=True - ) + argument("names", description="Who do you want to greet?", multiple=True) ] options = [ option( "yell", "y", description="If set, the task will yell in uppercase letters", - flag=True + flag=True, ) ] ``` @@ -296,24 +285,20 @@ class GreetCommand(Command): name = "greet" description = "Greets someone" arguments = [ - argument( - "name", - description="Who do you want to greet?", - optional=True - ) + argument("name", description="Who do you want to greet?", optional=True) ] options = [ option( "yell", "y", description="If set, the task will yell in uppercase letters", - flag=True + flag=True, ), option( "iterations", description="How many times should the message be printed?", - default=1 - ) + default=1, + ), ] ``` diff --git a/pyproject.toml b/pyproject.toml index 6274f380..042ed569 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -97,6 +97,9 @@ lines-after-imports = 2 known-first-party = ["cleo"] required-imports = ["from __future__ import annotations"] +[tool.ruff.lint.per-file-ignores] +"tests/*" = ["BLE001"] # ignore bare Exception in test fixtures + [tool.mypy] strict = true files = ["src", "tests"] diff --git a/src/cleo/application.py b/src/cleo/application.py index b02e0d00..a816ce34 100644 --- a/src/cleo/application.py +++ b/src/cleo/application.py @@ -444,7 +444,7 @@ def _run_command(self, command: Command, io: IO) -> int: exit_code = command.run(io) else: exit_code = ConsoleCommandEvent.RETURN_CODE_DISABLED - except Exception as e: + except Exception as e: # TODO: make proper error out of this # noqa: BLE001 error_event = ConsoleErrorEvent(command, io, e) self._event_dispatcher.dispatch(error_event, ERROR) error = error_event.error @@ -499,7 +499,7 @@ def _configure_io(self, io: IO) -> None: ): io.interactive(False) - shell_verbosity = int(os.getenv("SHELL_VERBOSITY", 0)) + shell_verbosity = int(os.getenv("SHELL_VERBOSITY", "0")) if shell_verbosity == -1: io.set_verbosity(Verbosity.QUIET) elif shell_verbosity == 1: diff --git a/src/cleo/events/event_dispatcher.py b/src/cleo/events/event_dispatcher.py index 45b64e86..f41c8033 100644 --- a/src/cleo/events/event_dispatcher.py +++ b/src/cleo/events/event_dispatcher.py @@ -38,9 +38,9 @@ def get_listeners( return self._sorted[event_name] - for event_name in self._listeners: - if event_name not in self._sorted: - self._sort_listeners(event_name) + for event_listener in self._listeners: + if event_listener not in self._sorted: + self._sort_listeners(event_listener) return self._sorted diff --git a/src/cleo/io/inputs/option.py b/src/cleo/io/inputs/option.py index 2fcc4c43..b5df39f5 100644 --- a/src/cleo/io/inputs/option.py +++ b/src/cleo/io/inputs/option.py @@ -23,8 +23,7 @@ def __init__( description: str | None = None, default: Any | None = None, ) -> None: - if name.startswith("--"): - name = name[2:] + name = name.removeprefix("--") if not name: raise CleoValueError("An option name cannot be empty") diff --git a/src/cleo/io/outputs/stream_output.py b/src/cleo/io/outputs/stream_output.py index 5a824b4b..1974c31c 100644 --- a/src/cleo/io/outputs/stream_output.py +++ b/src/cleo/io/outputs/stream_output.py @@ -59,7 +59,7 @@ def _get_utf8_support_info(self) -> bool: try: return codecs.lookup(encoding).name == "utf-8" - except Exception: + except LookupError: return True def flush(self) -> None: diff --git a/src/cleo/ui/question.py b/src/cleo/ui/question.py index b0c1a364..d6b0badb 100644 --- a/src/cleo/ui/question.py +++ b/src/cleo/ui/question.py @@ -244,7 +244,7 @@ def _validate_attempts(self, interviewer: Callable[[], Any], io: IO) -> Any: try: return self._validator(interviewer()) - except Exception as e: + except Exception as e: # noqa: BLE001 error = e if attempts is not None: @@ -267,8 +267,9 @@ def _read_from_input(self, io: IO) -> str: def _has_stty_available(self) -> bool: with Path(os.devnull).open("w", encoding="utf-8") as devnull: try: + # TODO: replace with subprocess.run exit_code = subprocess.call(["stty"], stdout=devnull, stderr=devnull) - except Exception: + except Exception: # noqa: BLE001 exit_code = 2 return exit_code == 0 diff --git a/src/cleo/ui/table.py b/src/cleo/ui/table.py index 2651bb51..7865b34a 100644 --- a/src/cleo/ui/table.py +++ b/src/cleo/ui/table.py @@ -519,7 +519,7 @@ def _fill_next_rows(self, rows: Rows, line: int) -> Rows: } for k, v in unmerged_rows.items(): if k in placeholder: - for l, m in unmerged_rows[k].items(): # noqa: E741 + for l, m in v.items(): placeholder[k][l] = m else: placeholder[k] = v @@ -547,9 +547,7 @@ def _fill_next_rows(self, rows: Rows, line: int) -> Rows: and ( ( self._get_number_of_columns(this_row) - + self._get_number_of_columns( - list(unmerged_rows[unmerged_row_key].values()) - ) + + self._get_number_of_columns(list(unmerged_row.values())) ) <= self._number_of_columns ) @@ -561,7 +559,7 @@ def _fill_next_rows(self, rows: Rows, line: int) -> Rows: row = self._copy_row(rows, unmerged_row_key - 1) for column, cell in unmerged_row.items(): if len(cell): - row[column] = unmerged_row[column] + row[column] = cell rows.insert(unmerged_row_key, row) diff --git a/src/cleo/ui/table_cell.py b/src/cleo/ui/table_cell.py index c066260c..3e22b073 100644 --- a/src/cleo/ui/table_cell.py +++ b/src/cleo/ui/table_cell.py @@ -4,6 +4,8 @@ if TYPE_CHECKING: + from typing_extensions import Self + from cleo.ui.table_cell_style import TableCellStyle @@ -14,7 +16,7 @@ def __new__( rowspan: int = 1, colspan: int = 1, style: TableCellStyle | None = None, - ) -> TableCell: + ) -> Self: return super().__new__(cls, value) def __init__( diff --git a/tests/ui/test_question.py b/tests/ui/test_question.py index a505ed3c..71c4c993 100644 --- a/tests/ui/test_question.py +++ b/tests/ui/test_question.py @@ -54,7 +54,7 @@ def test_ask_and_validate(io: BufferedIO) -> None: def validator(color: str) -> str: if color not in ["white", "black"]: - raise Exception(error) + raise Exception(error) # noqa: TRY002 return color