Skip to content

Commit 9658c69

Browse files
authored
Merge pull request #74 from Lee-W/enhance-customization
Enhance customization
2 parents e2c6e0c + 0286e7b commit 9658c69

File tree

9 files changed

+61
-19
lines changed

9 files changed

+61
-19
lines changed

commitizen/commands/bump.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ def __call__(self):
122122
bump.update_version_in_files(current_version, new_version.public, files)
123123
c = git.commit(message, args="-a")
124124
if c.err:
125-
out.error("git.commit errror: \"{}\"".format(c.err.strip()))
125+
out.error('git.commit errror: "{}"'.format(c.err.strip()))
126126
raise SystemExit(COMMIT_FAILED)
127127
c = git.tag(new_tag_version)
128128
if c.err:

commitizen/cz/conventional_commits/conventional_commits.py

+3-9
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,11 @@
22

33
from commitizen import defaults
44
from commitizen.cz.base import BaseCommitizen
5-
from commitizen.cz.exceptions import CzException
5+
from commitizen.cz.utils import multiple_line_breaker, required_validator
66

77
__all__ = ["ConventionalCommitsCz"]
88

99

10-
class NoSubjectException(CzException):
11-
...
12-
13-
1410
def parse_scope(text):
1511
if not text:
1612
return ""
@@ -26,10 +22,7 @@ def parse_subject(text):
2622
if isinstance(text, str):
2723
text = text.strip(".").strip()
2824

29-
if not text:
30-
raise NoSubjectException("Subject is required.")
31-
32-
return text
25+
return required_validator(text, msg="Subject is required.")
3326

3427

3528
class ConventionalCommitsCz(BaseCommitizen):
@@ -124,6 +117,7 @@ def questions(self) -> list:
124117
"Body. Motivation for the change and contrast this "
125118
"with previous behavior:\n"
126119
),
120+
"filter": multiple_line_breaker,
127121
},
128122
{
129123
"type": "input",

commitizen/cz/customize/customize.py

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
try:
2+
from jinja2 import Template
3+
except ImportError:
4+
from string import Template
5+
16
from commitizen import defaults
27
from commitizen.cz.base import BaseCommitizen
38

@@ -24,8 +29,11 @@ def questions(self) -> list:
2429
return self.custom_config.get("questions")
2530

2631
def message(self, answers: dict) -> str:
27-
message_template = self.custom_config.get("message_template")
28-
return message_template.format(**answers)
32+
message_template = Template(self.custom_config.get("message_template"))
33+
if getattr(Template, "substitute", None):
34+
return message_template.substitute(**answers)
35+
else:
36+
return message_template.render(**answers)
2937

3038
def example(self) -> str:
3139
return self.custom_config.get("example")

commitizen/cz/exceptions.py

+4
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
class CzException(Exception):
22
...
3+
4+
5+
class AnswerRequiredError(Exception):
6+
...

commitizen/cz/utils.py

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from commitizen.cz import exceptions
2+
3+
4+
def required_validator(ans, msg=None):
5+
if not ans:
6+
raise exceptions.AnswerRequiredError(msg)
7+
return ans
8+
9+
10+
def multiple_line_breaker(ans, sep="|"):
11+
return "\n".join(line.strip() for line in ans.split(sep) if line)

docs/customization.md

+7-2
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ Example:
151151
name = "cz_customize"
152152

153153
[tool.commitizen.customize]
154-
message_template = "{change_type}: {message}"
154+
message_template = "{{change_type}}:{% if show_message %} {{message}}{% endif %}"
155155
example = "feature: this feature eanable customize through config file"
156156
schema = "<type>: <body>"
157157
bump_pattern = "^(break|new|fix|hotfix)"
@@ -171,14 +171,19 @@ message = "Select the type of change you are committing"
171171
type = "input"
172172
name = "message"
173173
message = "Body."
174+
175+
[[tool.commitizen.customize.questions]]
176+
type = "confirm"
177+
name = "show_message"
178+
message = "Do you want to add body message in commit?"
174179
```
175180

176181
### Customize configuration
177182

178183
| Parameter | Type | Default | Description |
179184
| --------- | ---- | ------- | ----------- |
180185
| `question` | `dict` | `None` | Questions regarding the commit message. Detatiled below. |
181-
| `message_template` | `str` | `None` | The template for generating message from the given answers. `message_template` should follow the python string formatting specification, and all the variables in this template should be defined in `name` in `questions`. |
186+
| `message_template` | `str` | `None` | The template for generating message from the given answers. `message_template` should either follow the [string.Template](https://docs.python.org/3/library/string.html#template-strings) or [Jinja2](https://jinja.palletsprojects.com/en/2.10.x/) formatting specification, and all the variables in this template should be defined in `name` in `questions`. Note that `Jinja2` is not installed by default. If not installed, commitizen will use `string.Template` formatting. |
182187
| `example` | `str` | `None` | (OPTIONAL) Provide an example to help understand the style. Used by `cz example`. |
183188
| `schema` | `str` | `None` | (OPTIONAL) Show the schema used. Used by `cz schema`. |
184189
| `info_path` | `str` | `None` | (OPTIONAL) The path to the file that contains explanation of the commit rules. Used by `cz info`. If not provided `cz info`, will load `info` instead. |

pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ colorama = "^0.4.1"
5151
termcolor = "^1.1"
5252
packaging = "^19.0"
5353
tomlkit = "^0.5.3"
54+
jinja2 = {version = "^2.10.3", optional = true}
5455

5556
[tool.poetry.dev-dependencies]
5657
ipython = "^7.2"

tests/test_cz_conventional_commits.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
from commitizen import defaults
44
from commitizen.cz.conventional_commits.conventional_commits import (
55
ConventionalCommitsCz,
6-
NoSubjectException,
76
parse_scope,
87
parse_subject,
98
)
9+
from commitizen.cz.exceptions import AnswerRequiredError
1010

1111
config = {"name": defaults.name}
1212

@@ -39,7 +39,7 @@ def test_parse_subject_valid_values():
3939

4040
def test_parse_subject_invalid_values():
4141
for valid_subject in invalid_subjects:
42-
with pytest.raises(NoSubjectException):
42+
with pytest.raises(AnswerRequiredError):
4343
parse_subject(valid_subject)
4444

4545

tests/test_cz_customize.py

+22-3
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@
88
@pytest.fixture(scope="module")
99
def config():
1010
_conf = Config()
11-
toml_str = """
11+
toml_str = r"""
1212
[tool.commitizen.customize]
13-
# message_template should follow the python string formatting spec
14-
message_template = "{change_type}: {message}"
13+
message_template = "{{change_type}}:{% if show_message %} {{message}}{% endif %}"
1514
example = "feature: this feature eanable customize through config file"
1615
schema = "<type>: <body>"
1716
bump_pattern = "^(break|new|fix|hotfix)"
@@ -31,6 +30,11 @@ def config():
3130
type = "input"
3231
name = "message"
3332
message = "Body."
33+
34+
[[tool.commitizen.customize.questions]]
35+
type = "confirm"
36+
name = "show_message"
37+
message = "Do you want to add body message in commit?"
3438
"""
3539
_conf.update(parse(toml_str)["tool"]["commitizen"])
3640
return _conf.config
@@ -65,6 +69,11 @@ def test_questions(config):
6569
"message": "Select the type of change you are committing",
6670
},
6771
{"type": "input", "name": "message", "message": "Body."},
72+
{
73+
"type": "confirm",
74+
"name": "show_message",
75+
"message": "Do you want to add body message in commit?",
76+
},
6877
]
6978
assert list(questions) == expected_questions
7079

@@ -74,10 +83,20 @@ def test_answer(config):
7483
answers = {
7584
"change_type": "feature",
7685
"message": "this feature eanable customize through config file",
86+
"show_message": True,
7787
}
7888
message = cz.message(answers)
7989
assert message == "feature: this feature eanable customize through config file"
8090

91+
cz = CustomizeCommitsCz(config)
92+
answers = {
93+
"change_type": "feature",
94+
"message": "this feature eanable customize through config file",
95+
"show_message": False,
96+
}
97+
message = cz.message(answers)
98+
assert message == "feature:"
99+
81100

82101
def test_example(config):
83102
cz = CustomizeCommitsCz(config)

0 commit comments

Comments
 (0)