From b0ffb9a951abe3d4ddd0ac82b492993570c9634f Mon Sep 17 00:00:00 2001 From: Yu-Ting Hsiung Date: Thu, 12 Jun 2025 22:17:06 +0800 Subject: [PATCH] fix(ExitCode): add from_str in ExitCode and replace parse_no_raise with it Warn if a given decimal string is not in range --- commitizen/cli.py | 21 ++++++--------------- commitizen/exceptions.py | 23 +++++++++++++++++++++-- tests/test_exceptions.py | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 17 deletions(-) create mode 100644 tests/test_exceptions.py diff --git a/commitizen/cli.py b/commitizen/cli.py index 6f7556df4..03bce13a8 100644 --- a/commitizen/cli.py +++ b/commitizen/cli.py @@ -12,7 +12,7 @@ import argcomplete from decli import cli -from commitizen import commands, config, out, version_schemes +from commitizen import commands, config, version_schemes from commitizen.exceptions import ( CommitizenException, ExitCode, @@ -583,20 +583,11 @@ def parse_no_raise(comma_separated_no_raise: str) -> list[int]: Receives digits and strings and outputs the parsed integer which represents the exit code found in exceptions. """ - no_raise_items: list[str] = comma_separated_no_raise.split(",") - no_raise_codes: list[int] = [] - for item in no_raise_items: - if item.isdecimal(): - no_raise_codes.append(int(item)) - continue - try: - exit_code = ExitCode[item.strip()] - except KeyError: - out.warn(f"WARN: no_raise key `{item}` does not exist. Skipping.") - continue - else: - no_raise_codes.append(exit_code.value) - return no_raise_codes + return [ + code.value + for s in comma_separated_no_raise.split(",") + if (code := ExitCode.from_str(s)) is not None + ] if TYPE_CHECKING: diff --git a/commitizen/exceptions.py b/commitizen/exceptions.py index 8c0956be5..2e452b42c 100644 --- a/commitizen/exceptions.py +++ b/commitizen/exceptions.py @@ -1,10 +1,12 @@ -import enum +from __future__ import annotations + +from enum import IntEnum from typing import Any from commitizen import out -class ExitCode(enum.IntEnum): +class ExitCode(IntEnum): EXPECTED_EXIT = 0 NO_COMMITIZEN_FOUND = 1 NOT_A_GIT_PROJECT = 2 @@ -39,6 +41,23 @@ class ExitCode(enum.IntEnum): CONFIG_FILE_IS_EMPTY = 31 COMMIT_MESSAGE_LENGTH_LIMIT_EXCEEDED = 32 + @classmethod + def from_str(cls, value: str) -> ExitCode | None: + if value.isdecimal(): + try: + return cls(int(value)) + except ValueError: + out.warn( + f"WARN: no_raise value `{value}` is not a valid exit code. Skipping." + ) + return None + + try: + return cls[value.strip()] + except KeyError: + out.warn(f"WARN: no_raise key `{value}` does not exist. Skipping.") + return None + class CommitizenException(Exception): def __init__(self, *args: str, **kwargs: Any) -> None: diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py new file mode 100644 index 000000000..285131442 --- /dev/null +++ b/tests/test_exceptions.py @@ -0,0 +1,32 @@ +from commitizen.exceptions import ExitCode + + +def test_from_str_with_decimal(): + """Test from_str with decimal values.""" + assert ExitCode.from_str("0") == ExitCode.EXPECTED_EXIT + assert ExitCode.from_str("1") == ExitCode.NO_COMMITIZEN_FOUND + assert ExitCode.from_str("32") == ExitCode.COMMIT_MESSAGE_LENGTH_LIMIT_EXCEEDED + + +def test_from_str_with_enum_name(): + """Test from_str with enum names.""" + assert ExitCode.from_str("EXPECTED_EXIT") == ExitCode.EXPECTED_EXIT + assert ExitCode.from_str("NO_COMMITIZEN_FOUND") == ExitCode.NO_COMMITIZEN_FOUND + assert ( + ExitCode.from_str("COMMIT_MESSAGE_LENGTH_LIMIT_EXCEEDED") + == ExitCode.COMMIT_MESSAGE_LENGTH_LIMIT_EXCEEDED + ) + + +def test_from_str_with_whitespace(): + """Test from_str with whitespace in enum names.""" + assert ExitCode.from_str(" EXPECTED_EXIT ") == ExitCode.EXPECTED_EXIT + assert ExitCode.from_str("\tNO_COMMITIZEN_FOUND\t") == ExitCode.NO_COMMITIZEN_FOUND + + +def test_from_str_with_invalid_values(): + """Test from_str with invalid values.""" + assert ExitCode.from_str("invalid_name") is None + assert ExitCode.from_str("999") is None # Out of range decimal + assert ExitCode.from_str("") is None + assert ExitCode.from_str(" ") is None