GeezerVison is showing github.com — feat: add config option for line length warning · commitizen-tools/commitizen@e6bcb1a
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: commitizen/cli.py -2Lines changed: 0 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -160,7 +160,6 @@ def __call__( | 160 | 160 | { | 161 | 161 | "name": ["-l", "--message-length-limit"], | 162 | 162 | "type": int, | 163 | | - "default": 0, | 164 | 163 | "help": "length limit of the commit message; 0 for no limit", | 165 | 164 | }, | 166 | 165 | { | @@ -499,7 +498,6 @@ def __call__( | 499 | 498 | { | 500 | 499 | "name": ["-l", "--message-length-limit"], | 501 | 500 | "type": int, | 502 | | - "default": 0, | 503 | 501 | "help": "length limit of the commit message; 0 for no limit", | 504 | 502 | }, | 505 | 503 | ], | |
Collapse file Copy file name to clipboardExpand all lines: commitizen/commands/check.py +15-6Lines changed: 15 additions & 6 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 7 | 7 | from commitizen import factory, git, out | 8 | 8 | from commitizen.config import BaseConfig | 9 | 9 | from commitizen.exceptions import ( | | 10 | + CommitMessageLengthExceededError, | 10 | 11 | InvalidCommandArgumentError, | 11 | 12 | InvalidCommitMessageError, | 12 | 13 | NoCommitsFoundError, | @@ -18,7 +19,7 @@ class CheckArgs(TypedDict, total=False): | 18 | 19 | commit_msg: str | 19 | 20 | rev_range: str | 20 | 21 | allow_abort: bool | 21 | | - message_length_limit: int | | 22 | + message_length_limit: int | None | 22 | 23 | allowed_prefixes: list[str] | 23 | 24 | message: str | 24 | 25 | use_default_range: bool | @@ -41,8 +42,11 @@ def __init__(self, config: BaseConfig, arguments: CheckArgs, *args: object) -> N | 41 | 42 | self.allow_abort = bool( | 42 | 43 | arguments.get("allow_abort", config.settings["allow_abort"]) | 43 | 44 | ) | | 45 | + | 44 | 46 | self.use_default_range = bool(arguments.get("use_default_range")) | 45 | | - self.max_msg_length = arguments.get("message_length_limit", 0) | | 47 | + self.max_msg_length = arguments.get( | | 48 | + "message_length_limit", config.settings.get("message_length_limit", None) | | 49 | + ) | 46 | 50 |
| 47 | 51 | # we need to distinguish between None and [], which is a valid value | 48 | 52 | allowed_prefixes = arguments.get("allowed_prefixes") | @@ -88,7 +92,7 @@ def __call__(self) -> None: | 88 | 92 | invalid_msgs_content = "\n".join( | 89 | 93 | f'commit "{commit.rev}": "{commit.message}"' | 90 | 94 | for commit in commits | 91 | | - if not self._validate_commit_message(commit.message, pattern) | | 95 | + if not self._validate_commit_message(commit.message, pattern, commit.rev) | 92 | 96 | ) | 93 | 97 | if invalid_msgs_content: | 94 | 98 | # TODO: capitalize the first letter of the error message for consistency in v5 | @@ -153,17 +157,22 @@ def _filter_comments(msg: str) -> str: | 153 | 157 | return "\n".join(lines) | 154 | 158 |
| 155 | 159 | def _validate_commit_message( | 156 | | - self, commit_msg: str, pattern: re.Pattern[str] | | 160 | + self, commit_msg: str, pattern: re.Pattern[str], commit_hash: str | 157 | 161 | ) -> bool: | 158 | 162 | if not commit_msg: | 159 | 163 | return self.allow_abort | 160 | 164 |
| 161 | 165 | if any(map(commit_msg.startswith, self.allowed_prefixes)): | 162 | 166 | return True | 163 | 167 |
| 164 | | - if self.max_msg_length: | | 168 | + if self.max_msg_length is not None: | 165 | 169 | msg_len = len(commit_msg.partition("\n")[0].strip()) | 166 | 170 | if msg_len > self.max_msg_length: | 167 | | - return False | | 171 | + raise CommitMessageLengthExceededError( | | 172 | + f"commit validation: failed!\n" | | 173 | + f"commit message length exceeds the limit.\n" | | 174 | + f'commit "{commit_hash}": "{commit_msg}"\n' | | 175 | + f"message length limit: {self.max_msg_length} (actual: {msg_len})" | | 176 | + ) | 168 | 177 |
| 169 | 178 | return bool(pattern.match(commit_msg)) |
Collapse file Copy file name to clipboardExpand all lines: commitizen/commands/commit.py +5-2Lines changed: 5 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -33,7 +33,7 @@ class CommitArgs(TypedDict, total=False): | 33 | 33 | dry_run: bool | 34 | 34 | edit: bool | 35 | 35 | extra_cli_args: str | 36 | | - message_length_limit: int | | 36 | + message_length_limit: int | None | 37 | 37 | no_retry: bool | 38 | 38 | signoff: bool | 39 | 39 | write_message_to_file: Path | None | @@ -80,8 +80,11 @@ def _get_message_by_prompt_commit_questions(self) -> str: | 80 | 80 | raise NoAnswersError() | 81 | 81 |
| 82 | 82 | message = self.cz.message(answers) | 83 | | - if limit := self.arguments.get("message_length_limit", 0): | | 83 | + if limit := self.arguments.get( | | 84 | + "message_length_limit", self.config.settings.get("message_length_limit", 0) | | 85 | + ): | 84 | 86 | self._validate_subject_length(message=message, length_limit=limit) | | 87 | + | 85 | 88 | return message | 86 | 89 |
| 87 | 90 | def _validate_subject_length(self, *, message: str, length_limit: int) -> None: | |
Collapse file Copy file name to clipboardExpand all lines: commitizen/defaults.py +2Lines changed: 2 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -46,6 +46,7 @@ class Settings(TypedDict, total=False): | 46 | 46 | ignored_tag_formats: Sequence[str] | 47 | 47 | legacy_tag_formats: Sequence[str] | 48 | 48 | major_version_zero: bool | | 49 | + message_length_limit: int | None | 49 | 50 | name: str | 50 | 51 | post_bump_hooks: list[str] | None | 51 | 52 | pre_bump_hooks: list[str] | None | @@ -111,6 +112,7 @@ class Settings(TypedDict, total=False): | 111 | 112 | "template": None, # default provided by plugin | 112 | 113 | "extras": {}, | 113 | 114 | "breaking_change_exclamation_in_title": False, | | 115 | + "message_length_limit": None, # None for no limit | 114 | 116 | } | 115 | 117 |
| 116 | 118 | MAJOR = "MAJOR" | |
Collapse file Copy file name to clipboardExpand all lines: poetry.lock +1-1Lines changed: 1 addition & 1 deletion Collapse file Copy file name to clipboardExpand all lines: pyproject.toml +1-1Lines changed: 1 addition & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -18,7 +18,7 @@ dependencies = [ | 18 | 18 | "colorama (>=0.4.1,<1.0)", | 19 | 19 | "termcolor (>=1.1.0,<4.0.0)", | 20 | 20 | "packaging>=19", | 21 | | - "tomlkit (>=0.5.3,<1.0.0)", | | 21 | + "tomlkit (>=0.8.0,<1.0.0)", | 22 | 22 | "jinja2>=2.10.3", | 23 | 23 | "pyyaml>=3.08", | 24 | 24 | "argcomplete >=1.12.1,<3.7", | |
Collapse file Copy file name to clipboardExpand all lines: tests/commands/test_check_command.py +58-1Lines changed: 58 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
| 8 | 8 |
| 9 | 9 | from commitizen import cli, commands, git | 10 | 10 | from commitizen.exceptions import ( | | 11 | + CommitMessageLengthExceededError, | 11 | 12 | InvalidCommandArgumentError, | 12 | 13 | InvalidCommitMessageError, | 13 | 14 | NoCommitsFoundError, | @@ -449,7 +450,7 @@ def test_check_command_with_message_length_limit_exceeded(config, mocker: MockFi | 449 | 450 | arguments={"message": message, "message_length_limit": len(message) - 1}, | 450 | 451 | ) | 451 | 452 |
| 452 | | - with pytest.raises(InvalidCommitMessageError): | | 453 | + with pytest.raises(CommitMessageLengthExceededError): | 453 | 454 | check_cmd() | 454 | 455 | error_mock.assert_called_once() | 455 | 456 |
| @@ -460,3 +461,59 @@ def test_check_command_with_amend_prefix_default(config, mocker: MockFixture): | 460 | 461 |
| 461 | 462 | check_cmd() | 462 | 463 | success_mock.assert_called_once() | | 464 | + | | 465 | + | | 466 | +def test_check_command_with_config_message_length_limit(config, mocker: MockFixture): | | 467 | + success_mock = mocker.patch("commitizen.out.success") | | 468 | + message = "fix(scope): some commit message" | | 469 | + | | 470 | + config.settings["message_length_limit"] = len(message) + 1 | | 471 | + | | 472 | + check_cmd = commands.Check( | | 473 | + config=config, | | 474 | + arguments={"message": message}, | | 475 | + ) | | 476 | + | | 477 | + check_cmd() | | 478 | + success_mock.assert_called_once() | | 479 | + | | 480 | + | | 481 | +def test_check_command_with_config_message_length_limit_exceeded( | | 482 | + config, mocker: MockFixture | | 483 | +): | | 484 | + error_mock = mocker.patch("commitizen.out.error") | | 485 | + message = "fix(scope): some commit message" | | 486 | + | | 487 | + config.settings["message_length_limit"] = len(message) - 1 | | 488 | + | | 489 | + check_cmd = commands.Check( | | 490 | + config=config, | | 491 | + arguments={"message": message}, | | 492 | + ) | | 493 | + | | 494 | + with pytest.raises(CommitMessageLengthExceededError): | | 495 | + check_cmd() | | 496 | + error_mock.assert_called_once() | | 497 | + | | 498 | + | | 499 | +def test_check_command_cli_overrides_config_message_length_limit( | | 500 | + config, mocker: MockFixture | | 501 | +): | | 502 | + success_mock = mocker.patch("commitizen.out.success") | | 503 | + message = "fix(scope): some commit message" | | 504 | + | | 505 | + config.settings["message_length_limit"] = len(message) - 1 | | 506 | + | | 507 | + check_cmd = commands.Check( | | 508 | + config=config, | | 509 | + arguments={"message": message, "message_length_limit": len(message) + 1}, | | 510 | + ) | | 511 | + | | 512 | + check_cmd() | | 513 | + success_mock.assert_called_once() | | 514 | + | | 515 | + success_mock.reset_mock() | | 516 | + check_cmd = commands.Check( | | 517 | + config=config, | | 518 | + arguments={"message": message, "message_length_limit": None}, | | 519 | + ) |
Collapse file Copy file name to clipboardExpand all lines: tests/commands/test_commit_command.py +59Lines changed: 59 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -554,3 +554,62 @@ def test_commit_when_nothing_added_to_commit(config, mocker: MockFixture, out): | 554 | 554 |
| 555 | 555 | commit_mock.assert_called_once() | 556 | 556 | error_mock.assert_called_once_with(out) | | 557 | + | | 558 | + | | 559 | +@pytest.mark.usefixtures("staging_is_clean") | | 560 | +def test_commit_command_with_config_message_length_limit(config, mocker: MockFixture): | | 561 | + prompt_mock = mocker.patch("questionary.prompt") | | 562 | + prefix = "feat" | | 563 | + subject = "random subject" | | 564 | + message_length = len(prefix) + len(": ") + len(subject) | | 565 | + prompt_mock.return_value = { | | 566 | + "prefix": prefix, | | 567 | + "subject": subject, | | 568 | + "scope": "", | | 569 | + "is_breaking_change": False, | | 570 | + "body": "random body", | | 571 | + "footer": "random footer", | | 572 | + } | | 573 | + | | 574 | + commit_mock = mocker.patch("commitizen.git.commit") | | 575 | + commit_mock.return_value = cmd.Command("success", "", b"", b"", 0) | | 576 | + success_mock = mocker.patch("commitizen.out.success") | | 577 | + | | 578 | + config.settings["message_length_limit"] = message_length | | 579 | + commands.Commit(config, {})() | | 580 | + success_mock.assert_called_once() | | 581 | + | | 582 | + config.settings["message_length_limit"] = message_length - 1 | | 583 | + with pytest.raises(CommitMessageLengthExceededError): | | 584 | + commands.Commit(config, {})() | | 585 | + | | 586 | + | | 587 | +@pytest.mark.usefixtures("staging_is_clean") | | 588 | +def test_commit_command_cli_overrides_config_message_length_limit( | | 589 | + config, mocker: MockFixture | | 590 | +): | | 591 | + prompt_mock = mocker.patch("questionary.prompt") | | 592 | + prefix = "feat" | | 593 | + subject = "random subject" | | 594 | + message_length = len(prefix) + len(": ") + len(subject) | | 595 | + prompt_mock.return_value = { | | 596 | + "prefix": prefix, | | 597 | + "subject": subject, | | 598 | + "scope": "", | | 599 | + "is_breaking_change": False, | | 600 | + "body": "random body", | | 601 | + "footer": "random footer", | | 602 | + } | | 603 | + | | 604 | + commit_mock = mocker.patch("commitizen.git.commit") | | 605 | + commit_mock.return_value = cmd.Command("success", "", b"", b"", 0) | | 606 | + success_mock = mocker.patch("commitizen.out.success") | | 607 | + | | 608 | + config.settings["message_length_limit"] = message_length - 1 | | 609 | + | | 610 | + commands.Commit(config, {"message_length_limit": message_length})() | | 611 | + success_mock.assert_called_once() | | 612 | + | | 613 | + success_mock.reset_mock() | | 614 | + commands.Commit(config, {"message_length_limit": None})() | | 615 | + success_mock.assert_called_once() |
Collapse file Copy file name to clipboardExpand all lines: tests/test_conf.py +2Lines changed: 2 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 106 | 106 | "template": None, | 107 | 107 | "extras": {}, | 108 | 108 | "breaking_change_exclamation_in_title": False, | | 109 | + "message_length_limit": None, | 109 | 110 | } | 110 | 111 |
| 111 | 112 | _new_settings: dict[str, Any] = { | | 145 | 146 | "template": None, | 146 | 147 | "extras": {}, | 147 | 148 | "breaking_change_exclamation_in_title": False, | | 149 | + "message_length_limit": None, | 148 | 150 | } | 149 | 151 |
| 150 | 152 |
| |
|