Skip to content

Commit

Permalink
feat(commit): implement questions 'filter' support with evaluations
Browse files Browse the repository at this point in the history
Supported APIs: Common Python, commitizen.cz.utils.* functions

Example YAML configurations:
---
commitizen:
  name: cz_customize
  customize:
    questions:
      - ...
      - type: input
        name: scope
        message: 'Scope of the change :'
        filter: 'lambda text: commitizen.cz.utils.required_validator(text, msg="! Error: Scope is required")'
        default: ''
      - type: input
        name: subject
        message: 'Title of the commit (starting in lower case and without period) :'
        filter: 'lambda text: commitizen.cz.utils.required_validator(text.strip(".").strip(), msg="! Error: Title is required")'
        default: ''
      - type: input
        name: body
        message: 'Additional contextual message (Empty to skip) :'
        default: 'Issue: #...'
        filter: 'commitizen.cz.utils.multiple_line_breaker'
---

Signed-off-by: Adrian DC <[email protected]>
  • Loading branch information
AdrianDC committed Aug 13, 2024
1 parent ef9dc84 commit 5a661cf
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 4 deletions.
19 changes: 18 additions & 1 deletion commitizen/commands/commit.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
from commitizen import factory, git, out
from commitizen.config import BaseConfig
from commitizen.cz.exceptions import CzException
from commitizen.cz.utils import get_backup_file_path
from commitizen.cz.utils import (
get_backup_file_path,
multiple_line_breaker,
)
from commitizen.exceptions import (
CommitError,
CommitMessageLengthExceededError,
Expand Down Expand Up @@ -49,8 +52,22 @@ def prompt_commit_questions(self) -> str:
# Prompt user for the commit message
cz = self.cz
questions = cz.questions()

for question in filter(lambda q: q["type"] == "list", questions):
question["use_shortcuts"] = self.config.settings["use_shortcuts"]

# Import allowed modules for 'filter'
global commitizen
import commitizen.cz.utils

for question in filter(
lambda q: isinstance(q.get("filter", None), str), questions
):
question_filter = [

Check warning on line 66 in commitizen/commands/commit.py

View check run for this annotation

Codecov / codecov/patch

commitizen/commands/commit.py#L66

Added line #L66 was not covered by tests
multiple_line_breaker(question["filter"].replace("\\n", "\n"))
]
question["filter"] = eval("\n".join(question_filter))

Check warning on line 69 in commitizen/commands/commit.py

View check run for this annotation

Codecov / codecov/patch

commitizen/commands/commit.py#L69

Added line #L69 was not covered by tests

try:
answers = questionary.prompt(questions, style=cz.style)
except ValueError as err:
Expand Down
2 changes: 1 addition & 1 deletion docs/customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ commitizen:
| `message` | `str` | `None` | Detail description for the question. |
| `choices` | `list` | `None` | (OPTIONAL) The choices when `type = list`. Either use a list of values or a list of dictionaries with `name` and `value` keys. Keyboard shortcuts can be defined via `key`. See examples above. |
| `default` | `Any` | `None` | (OPTIONAL) The default value for this question. |
| `filter` | `str` | `None` | (Optional) Validator for user's answer. **(Work in Progress)** |
| `filter` | `str` | `None` | (OPTIONAL) Validator for user's answer. The string is evaluated into a Python function, either use `commitizen.cz.utils.*` or lambda functions like `lambda text: text.strip(".").strip()` |
[different-question-types]: https://github.com/tmbo/questionary#different-question-types

#### Shortcut keys
Expand Down
40 changes: 38 additions & 2 deletions tests/test_cz_customize.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
type = "input"
name = "message"
message = "Body."
filter = "commitizen.cz.utils.multiple_line_breaker"
[[tool.commitizen.customize.questions]]
type = "confirm"
Expand Down Expand Up @@ -84,7 +85,8 @@
{
"type": "input",
"name": "message",
"message": "Body."
"message": "Body.",
"filter": "commitizen.cz.utils.multiple_line_breaker"
},
{
"type": "confirm",
Expand Down Expand Up @@ -134,6 +136,7 @@
- type: input
name: message
message: Body.
filter: 'commitizen.cz.utils.multiple_line_breaker'
- type: confirm
name: show_message
message: Do you want to add body message in commit?
Expand Down Expand Up @@ -442,7 +445,40 @@ def test_questions(config):
],
"message": "Select the type of change you are committing",
},
{"type": "input", "name": "message", "message": "Body."},
{
"type": "input",
"name": "message",
"message": "Body.",
"filter": "commitizen.cz.utils.multiple_line_breaker",
},
{
"type": "confirm",
"name": "show_message",
"message": "Do you want to add body message in commit?",
},
]
assert list(questions) == expected_questions


def test_questions_filter(config):
cz = CustomizeCommitsCz(config)
questions = cz.questions()
expected_questions = [
{
"type": "list",
"name": "change_type",
"choices": [
{"value": "feature", "name": "feature: A new feature."},
{"value": "bug fix", "name": "bug fix: A bug fix."},
],
"message": "Select the type of change you are committing",
},
{
"type": "input",
"name": "message",
"message": "Body.",
"filter": "commitizen.cz.utils.multiple_line_breaker",
},
{
"type": "confirm",
"name": "show_message",
Expand Down

0 comments on commit 5a661cf

Please sign in to comment.