Skip to content

Commit 514ff61

Browse files
authored
Merge pull request #315 from danvergara/add-yaml-support-for-config
Add yaml support for config
2 parents 57fe0ea + c09f377 commit 514ff61

File tree

9 files changed

+224
-17
lines changed

9 files changed

+224
-17
lines changed

commitizen/commands/init.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from commitizen import cmd, factory, out
88
from commitizen.__version__ import __version__
9-
from commitizen.config import BaseConfig, JsonConfig, TomlConfig
9+
from commitizen.config import BaseConfig, JsonConfig, TomlConfig, YAMLConfig
1010
from commitizen.cz import registry
1111
from commitizen.defaults import config_files
1212
from commitizen.exceptions import NoAnswersError
@@ -28,6 +28,8 @@ def __call__(self):
2828
self.config = TomlConfig(data="", path=config_path)
2929
elif "json" in config_path:
3030
self.config = JsonConfig(data="{}", path=config_path)
31+
elif "yaml" in config_path:
32+
self.config = YAMLConfig(data="", path=config_path)
3133

3234
self.config.init_empty_config_content()
3335

commitizen/config/__init__.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from .base_config import BaseConfig
77
from .json_config import JsonConfig
88
from .toml_config import TomlConfig
9+
from .yaml_config import YAMLConfig
910

1011

1112
def read_cfg() -> BaseConfig:
@@ -25,15 +26,17 @@ def read_cfg() -> BaseConfig:
2526
if not filename.exists():
2627
continue
2728

29+
_conf: Union[TomlConfig, JsonConfig, YAMLConfig]
30+
2831
with open(filename, "r") as f:
2932
data: str = f.read()
3033

31-
_conf: Union[TomlConfig, JsonConfig]
3234
if "toml" in filename.suffix:
3335
_conf = TomlConfig(data=data, path=filename)
34-
35-
if "json" in filename.suffix:
36+
elif "json" in filename.suffix:
3637
_conf = JsonConfig(data=data, path=filename)
38+
elif "yaml" in filename.suffix:
39+
_conf = YAMLConfig(data=data, path=filename)
3740

3841
if _conf.is_empty_config:
3942
continue

commitizen/config/yaml_config.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
from pathlib import Path
2+
from typing import Union
3+
4+
import yaml
5+
6+
from .base_config import BaseConfig
7+
8+
9+
class YAMLConfig(BaseConfig):
10+
def __init__(self, *, data: str, path: Union[Path, str]):
11+
super(YAMLConfig, self).__init__()
12+
self.is_empty_config = False
13+
self._parse_setting(data)
14+
self.add_path(path)
15+
16+
def init_empty_config_content(self):
17+
with open(self.path, "a") as json_file:
18+
yaml.dump({"commitizen": {}}, json_file)
19+
20+
def _parse_setting(self, data: str):
21+
"""We expect to have a section in cz.yaml looking like
22+
23+
```
24+
commitizen:
25+
name: cz_conventional_commits
26+
```
27+
"""
28+
doc = yaml.safe_load(data)
29+
try:
30+
self.settings.update(doc["commitizen"])
31+
except (KeyError, TypeError):
32+
self.is_empty_config = True
33+
34+
def set_key(self, key, value):
35+
"""Set or update a key in the conf.
36+
37+
For now only strings are supported.
38+
We use to update the version number.
39+
"""
40+
with open(self.path, "r") as yaml_file:
41+
parser = yaml.load(yaml_file)
42+
43+
parser["commitizen"][key] = value
44+
with open(self.path, "w") as yaml_file:
45+
yaml.dump(parser, yaml_file)
46+
47+
return self

commitizen/defaults.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,14 @@
22
from typing import Any, Dict, List
33

44
name: str = "cz_conventional_commits"
5-
config_files: List[str] = ["pyproject.toml", ".cz.toml", ".cz.json", "cz.json"]
5+
config_files: List[str] = [
6+
"pyproject.toml",
7+
".cz.toml",
8+
".cz.json",
9+
"cz.json",
10+
".cz.yaml",
11+
"cz.yaml",
12+
]
613

714
DEFAULT_SETTINGS: Dict[str, Any] = {
815
"name": "cz_conventional_commits",

docs/config.md

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ style = [
3030

3131
## .cz.json or cz.json
3232

33-
JSON may be a more commong configuration format for non-python projects, so Commitizen supports JSON config files, now.
33+
JSON might be a more common configuration format for non-python projects, so Commitizen supports JSON config files, now.
3434

3535
```json
3636
{
@@ -87,6 +87,39 @@ JSON may be a more commong configuration format for non-python projects, so Comm
8787
}
8888
```
8989

90+
## .cz.yaml or cz.yaml
91+
YAML is another format for **non-python** proyects as well, supported by Commitizen:
92+
93+
```yaml
94+
commitizen:
95+
name: cz_conventional_commits
96+
version: 0.1.0
97+
version_files:
98+
- src/__version__.py
99+
- pyproject.toml:version
100+
style:
101+
- - qmark
102+
- fg:#ff9d00 bold
103+
- - question
104+
- bold
105+
- - answer
106+
- fg:#ff9d00 bold
107+
- - pointer
108+
- fg:#ff9d00 bold
109+
- - highlighted
110+
- fg:#ff9d00 bold
111+
- - selected
112+
- fg:#cc5454
113+
- - separator
114+
- fg:#cc5454
115+
- - instruction
116+
- ''
117+
- - text
118+
- ''
119+
- - disabled
120+
- fg:#858585 italic
121+
```
122+
90123
## Settings
91124
92125
| Variable | Type | Default | Description |

docs/customization.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,41 @@ The equivalent example for a json config file:
9898
}
9999
```
100100

101+
And the correspondent example for a yaml json file:
102+
103+
```yaml
104+
commitizen:
105+
name: cz_customize
106+
customize:
107+
message_template: "{{change_type}}:{% if show_message %} {{message}}{% endif %}"
108+
example: 'feature: this feature enable customize through config file'
109+
schema: "<type>: <body>"
110+
schema_pattern: "(feature|bug fix):(\\s.*)"
111+
bump_pattern: "^(break|new|fix|hotfix)"
112+
bump_map:
113+
break: MAJOR
114+
new: MINOR
115+
fix: PATCH
116+
hotfix: PATCH
117+
info_path: cz_customize_info.txt
118+
info: This is customized info
119+
questions:
120+
- type: list
121+
name: change_type
122+
choices:
123+
- value: feature
124+
name: 'feature: A new feature.'
125+
- value: bug fix
126+
name: 'bug fix: A bug fix.'
127+
message: Select the type of change you are committing
128+
- type: input
129+
name: message
130+
message: Body.
131+
- type: confirm
132+
name: show_message
133+
message: Do you want to add body message in commit?
134+
```
135+
101136
### Customize configuration
102137
103138
| Parameter | Type | Default | Description |

tests/commands/test_init_command.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def ask(self):
3131
'tag_format = "$version"\n'
3232
)
3333

34-
EXPECTED_JSON_CONFIG = {
34+
EXPECTED_DICT_CONFIG = {
3535
"commitizen": {
3636
"name": "cz_conventional_commits",
3737
"version": "0.0.1",
@@ -94,7 +94,7 @@ def test_init_without_choosing_tag(config, mocker, tmpdir):
9494

9595

9696
class TestPreCommitCases:
97-
@pytest.fixture(scope="function", params=["pyproject.toml", ".cz.json"])
97+
@pytest.fixture(scope="function", params=["pyproject.toml", ".cz.json", ".cz.yaml"])
9898
def default_choice(_, request, mocker):
9999
mocker.patch(
100100
"questionary.select",
@@ -108,13 +108,15 @@ def default_choice(_, request, mocker):
108108
mocker.patch("questionary.confirm", return_value=FakeQuestion(True))
109109
return request.param
110110

111-
def test_no_existing_pre_commit_json_conifg(_, default_choice, tmpdir, config):
111+
def test_no_existing_pre_commit_conifg(_, default_choice, tmpdir, config):
112112
with tmpdir.as_cwd():
113113
commands.Init(config)()
114114

115115
with open(default_choice, "r") as file:
116116
if "json" in default_choice:
117-
assert json.load(file) == EXPECTED_JSON_CONFIG
117+
assert json.load(file) == EXPECTED_DICT_CONFIG
118+
elif "yaml" in default_choice:
119+
assert yaml.load(file) == EXPECTED_DICT_CONFIG
118120
else:
119121
config_data = file.read()
120122
assert config_data == expected_config
@@ -132,7 +134,9 @@ def test_empty_pre_commit_config(_, default_choice, tmpdir, config):
132134

133135
with open(default_choice, "r") as file:
134136
if "json" in default_choice:
135-
assert json.load(file) == EXPECTED_JSON_CONFIG
137+
assert json.load(file) == EXPECTED_DICT_CONFIG
138+
elif "yaml" in default_choice:
139+
assert yaml.load(file) == EXPECTED_DICT_CONFIG
136140
else:
137141
config_data = file.read()
138142
assert config_data == expected_config
@@ -156,7 +160,9 @@ def test_pre_commit_config_without_cz_hook(_, default_choice, tmpdir, config):
156160

157161
with open(default_choice, "r") as file:
158162
if "json" in default_choice:
159-
assert json.load(file) == EXPECTED_JSON_CONFIG
163+
assert json.load(file) == EXPECTED_DICT_CONFIG
164+
elif "yaml" in default_choice:
165+
assert yaml.load(file) == EXPECTED_DICT_CONFIG
160166
else:
161167
config_data = file.read()
162168
assert config_data == expected_config
@@ -176,7 +182,9 @@ def test_cz_hook_exists_in_pre_commit_config(_, default_choice, tmpdir, config):
176182

177183
with open(default_choice, "r") as file:
178184
if "json" in default_choice:
179-
assert json.load(file) == EXPECTED_JSON_CONFIG
185+
assert json.load(file) == EXPECTED_DICT_CONFIG
186+
elif "yaml" in default_choice:
187+
assert yaml.load(file) == EXPECTED_DICT_CONFIG
180188
else:
181189
config_data = file.read()
182190
assert config_data == expected_config

tests/test_conf.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from pathlib import Path
44

55
import pytest
6+
import yaml
67

78
from commitizen import config, defaults, git
89

@@ -24,7 +25,7 @@
2425
target-version = ['py36', 'py37', 'py38']
2526
"""
2627

27-
JSON_CONFIG = {
28+
DICT_CONFIG = {
2829
"commitizen": {
2930
"name": "cz_jira",
3031
"version": "1.0.0",
@@ -33,6 +34,7 @@
3334
}
3435
}
3536

37+
3638
_settings = {
3739
"name": "cz_jira",
3840
"version": "1.0.0",
@@ -75,8 +77,10 @@ def config_files_manager(request, tmpdir):
7577
with open(filename, "w") as f:
7678
if "toml" in filename:
7779
f.write(PYPROJECT)
78-
if "json" in filename:
79-
json.dump(JSON_CONFIG, f)
80+
elif "json" in filename:
81+
json.dump(DICT_CONFIG, f)
82+
elif "yaml" in filename:
83+
yaml.dump(DICT_CONFIG, f)
8084
yield
8185

8286

0 commit comments

Comments
 (0)