Skip to content

Commit 94b34ee

Browse files
committed
refactor(BaseConfig): update docstring, extract factory method and remove unnecessary variable assignment
1 parent cc981fc commit 94b34ee

File tree

6 files changed

+103
-67
lines changed

6 files changed

+103
-67
lines changed

commitizen/commands/init.py

Lines changed: 45 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@
22

33
import os
44
import shutil
5+
from pathlib import Path
56
from typing import Any, NamedTuple
67

78
import questionary
89
import yaml
910

1011
from commitizen import cmd, factory, out
1112
from commitizen.__version__ import __version__
12-
from commitizen.config import BaseConfig, JsonConfig, TomlConfig, YAMLConfig
13+
from commitizen.config import (
14+
BaseConfig,
15+
create_config,
16+
)
1317
from commitizen.cz import registry
1418
from commitizen.defaults import CONFIG_FILES, DEFAULT_SETTINGS
1519
from commitizen.exceptions import InitFailedError, NoAnswersError
@@ -153,14 +157,6 @@ def __call__(self) -> None:
153157
except KeyboardInterrupt:
154158
raise InitFailedError("Stopped by user")
155159

156-
# Initialize configuration
157-
if "toml" in config_path:
158-
self.config = TomlConfig(data="", path=config_path)
159-
elif "json" in config_path:
160-
self.config = JsonConfig(data="{}", path=config_path)
161-
elif "yaml" in config_path:
162-
self.config = YAMLConfig(data="", path=config_path)
163-
164160
# Collect hook data
165161
hook_types = questionary.checkbox(
166162
"What types of pre-commit hook you want to install? (Leave blank if you don't want to install)",
@@ -175,37 +171,33 @@ def __call__(self) -> None:
175171
except InitFailedError as e:
176172
raise InitFailedError(f"Failed to install pre-commit hook.\n{e}")
177173

178-
# Create and initialize config
179-
self.config.init_empty_config_content()
180-
181-
self.config.set_key("name", cz_name)
182-
self.config.set_key("tag_format", tag_format)
183-
self.config.set_key("version_scheme", version_scheme)
184-
if version_provider == "commitizen":
185-
self.config.set_key("version", version.public)
186-
else:
187-
self.config.set_key("version_provider", version_provider)
188-
if update_changelog_on_bump:
189-
self.config.set_key("update_changelog_on_bump", update_changelog_on_bump)
190-
if major_version_zero:
191-
self.config.set_key("major_version_zero", major_version_zero)
174+
_write_config_to_file(
175+
path=config_path,
176+
cz_name=cz_name,
177+
version_provider=version_provider,
178+
version_scheme=version_scheme,
179+
version=version,
180+
tag_format=tag_format,
181+
update_changelog_on_bump=update_changelog_on_bump,
182+
major_version_zero=major_version_zero,
183+
)
192184

193185
out.write("\nYou can bump the version running:\n")
194186
out.info("\tcz bump\n")
195187
out.success("Configuration complete 🚀")
196188

197-
def _ask_config_path(self) -> str:
189+
def _ask_config_path(self) -> Path:
198190
default_path = (
199191
"pyproject.toml" if self.project_info.has_pyproject else ".cz.toml"
200192
)
201193

202-
name: str = questionary.select(
194+
filename: str = questionary.select(
203195
"Please choose a supported config file: ",
204196
choices=CONFIG_FILES,
205197
default=default_path,
206198
style=self.cz.style,
207199
).unsafe_ask()
208-
return name
200+
return Path(filename)
209201

210202
def _ask_name(self) -> str:
211203
name: str = questionary.select(
@@ -383,3 +375,30 @@ def _install_pre_commit_hook(self, hook_types: list[str] | None = None) -> None:
383375
hook_types = ["commit-msg", "pre-push"]
384376
self._exec_install_pre_commit_hook(hook_types)
385377
out.write("commitizen pre-commit hook is now installed in your '.git'\n")
378+
379+
380+
def _write_config_to_file(
381+
*,
382+
path: Path,
383+
cz_name: str,
384+
version_provider: str,
385+
version_scheme: str,
386+
version: Version,
387+
tag_format: str,
388+
update_changelog_on_bump: bool,
389+
major_version_zero: bool,
390+
) -> None:
391+
out_config = create_config(path=path)
392+
out_config.init_empty_config_content()
393+
394+
out_config.set_key("name", cz_name)
395+
out_config.set_key("tag_format", tag_format)
396+
out_config.set_key("version_scheme", version_scheme)
397+
if version_provider == "commitizen":
398+
out_config.set_key("version", version.public)
399+
else:
400+
out_config.set_key("version_provider", version_provider)
401+
if update_changelog_on_bump:
402+
out_config.set_key("update_changelog_on_bump", update_changelog_on_bump)
403+
if major_version_zero:
404+
out_config.set_key("major_version_zero", major_version_zero)

commitizen/config/__init__.py

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
from collections.abc import Generator
34
from pathlib import Path
45

56
from commitizen import defaults, git
@@ -11,48 +12,55 @@
1112
from .yaml_config import YAMLConfig
1213

1314

14-
def read_cfg(filepath: str | None = None) -> BaseConfig:
15-
conf = BaseConfig()
16-
15+
def _resolve_config_paths(filepath: str | None = None) -> Generator[Path, None, None]:
1716
if filepath is not None:
18-
if not Path(filepath).exists():
17+
out_path = Path(filepath)
18+
if not out_path.exists():
1919
raise ConfigFileNotFound()
2020

21-
cfg_paths = (path for path in (Path(filepath),))
22-
else:
23-
git_project_root = git.find_git_project_root()
24-
cfg_search_paths = [Path(".")]
25-
if git_project_root:
26-
cfg_search_paths.append(git_project_root)
21+
yield out_path
22+
return
23+
24+
git_project_root = git.find_git_project_root()
25+
cfg_search_paths = [Path(".")]
26+
if git_project_root:
27+
cfg_search_paths.append(git_project_root)
2728

28-
cfg_paths = (
29-
path / Path(filename)
30-
for path in cfg_search_paths
31-
for filename in defaults.CONFIG_FILES
32-
)
29+
for path in cfg_search_paths:
30+
for filename in defaults.CONFIG_FILES:
31+
yield path / Path(filename)
32+
return
3333

34-
for filename in cfg_paths:
34+
35+
def read_cfg(filepath: str | None = None) -> BaseConfig:
36+
for filename in _resolve_config_paths(filepath):
3537
if not filename.exists():
3638
continue
3739

38-
_conf: TomlConfig | JsonConfig | YAMLConfig
39-
4040
with open(filename, "rb") as f:
4141
data: bytes = f.read()
4242

43-
if "toml" in filename.suffix:
44-
_conf = TomlConfig(data=data, path=filename)
45-
elif "json" in filename.suffix:
46-
_conf = JsonConfig(data=data, path=filename)
47-
elif "yaml" in filename.suffix:
48-
_conf = YAMLConfig(data=data, path=filename)
43+
conf = create_config(data=data, path=filename)
44+
if not conf.is_empty_config:
45+
return conf
4946

50-
if filepath is not None and _conf.is_empty_config:
47+
if filepath is not None:
5148
raise ConfigFileIsEmpty()
52-
elif _conf.is_empty_config:
53-
continue
54-
else:
55-
conf = _conf
56-
break
5749

58-
return conf
50+
return BaseConfig()
51+
52+
53+
# TODO: consider moving this to some factory class?
54+
def create_config(*, data: bytes | str | None = None, path: Path) -> BaseConfig:
55+
if "toml" in path.suffix:
56+
return TomlConfig(data=data or "", path=path)
57+
if "json" in path.suffix:
58+
return JsonConfig(data=data or "{}", path=path)
59+
if "yaml" in path.suffix:
60+
return YAMLConfig(data=data or "", path=path)
61+
62+
# TODO: adjust the exception type
63+
# Should be unreachable. See the constant CONFIG_FILES.
64+
raise ValueError(
65+
f"Unsupported config file: {path.name} due to unknown file extension"
66+
)

commitizen/config/base_config.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717

1818
class BaseConfig:
1919
def __init__(self) -> None:
20+
self.is_empty_config = False
2021
self._settings: Settings = DEFAULT_SETTINGS.copy()
21-
self.encoding = self.settings["encoding"]
2222
self._path: Path | None = None
2323

2424
@property
@@ -48,4 +48,8 @@ def _parse_setting(self, data: bytes | str) -> None:
4848
raise NotImplementedError()
4949

5050
def init_empty_config_content(self) -> None:
51+
"""Create a config file with the empty config content.
52+
53+
The implementation is different for each config file type.
54+
"""
5155
raise NotImplementedError()

commitizen/config/json_config.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,13 @@
2222
class JsonConfig(BaseConfig):
2323
def __init__(self, *, data: bytes | str, path: Path | str) -> None:
2424
super().__init__()
25-
self.is_empty_config = False
2625
self.path = path
2726
self._parse_setting(data)
2827

2928
def init_empty_config_content(self) -> None:
30-
with smart_open(self.path, "a", encoding=self.encoding) as json_file:
29+
with smart_open(
30+
self.path, "a", encoding=self._settings["encoding"]
31+
) as json_file:
3132
json.dump({"commitizen": {}}, json_file)
3233

3334
def set_key(self, key: str, value: Any) -> Self:
@@ -40,7 +41,7 @@ def set_key(self, key: str, value: Any) -> Self:
4041
parser = json.load(f)
4142

4243
parser["commitizen"][key] = value
43-
with smart_open(self.path, "w", encoding=self.encoding) as f:
44+
with smart_open(self.path, "w", encoding=self._settings["encoding"]) as f:
4445
json.dump(parser, f, indent=2)
4546
return self
4647

commitizen/config/toml_config.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
class TomlConfig(BaseConfig):
2424
def __init__(self, *, data: bytes | str, path: Path | str) -> None:
2525
super().__init__()
26-
self.is_empty_config = False
2726
self.path = path
2827
self._parse_setting(data)
2928

@@ -38,7 +37,9 @@ def init_empty_config_content(self) -> None:
3837
if parser.get("tool") is None:
3938
parser["tool"] = table()
4039
parser["tool"]["commitizen"] = table() # type: ignore[index]
41-
output_toml_file.write(parser.as_string().encode(self.encoding))
40+
output_toml_file.write(
41+
parser.as_string().encode(self._settings["encoding"])
42+
)
4243

4344
def set_key(self, key: str, value: Any) -> Self:
4445
"""Set or update a key in the conf.
@@ -51,7 +52,7 @@ def set_key(self, key: str, value: Any) -> Self:
5152

5253
parser["tool"]["commitizen"][key] = value # type: ignore[index]
5354
with open(self.path, "wb") as f:
54-
f.write(parser.as_string().encode(self.encoding))
55+
f.write(parser.as_string().encode(self._settings["encoding"]))
5556
return self
5657

5758
def _parse_setting(self, data: bytes | str) -> None:

commitizen/config/yaml_config.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,13 @@
2323
class YAMLConfig(BaseConfig):
2424
def __init__(self, *, data: bytes | str, path: Path | str) -> None:
2525
super().__init__()
26-
self.is_empty_config = False
2726
self.path = path
2827
self._parse_setting(data)
2928

3029
def init_empty_config_content(self) -> None:
31-
with smart_open(self.path, "a", encoding=self.encoding) as json_file:
30+
with smart_open(
31+
self.path, "a", encoding=self._settings["encoding"]
32+
) as json_file:
3233
yaml.dump({"commitizen": {}}, json_file, explicit_start=True)
3334

3435
def _parse_setting(self, data: bytes | str) -> None:
@@ -61,7 +62,9 @@ def set_key(self, key: str, value: Any) -> Self:
6162
parser = yaml.load(yaml_file, Loader=yaml.FullLoader)
6263

6364
parser["commitizen"][key] = value
64-
with smart_open(self.path, "w", encoding=self.encoding) as yaml_file:
65+
with smart_open(
66+
self.path, "w", encoding=self._settings["encoding"]
67+
) as yaml_file:
6568
yaml.dump(parser, yaml_file, explicit_start=True)
6669

6770
return self

0 commit comments

Comments
 (0)