Skip to content

Commit 61a1f85

Browse files
committed
refactor(BaseConfig): update docstring, extract factory method and remove unnecessary variable assignment
1 parent a472bea commit 61a1f85

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
@@ -187,45 +191,33 @@ def __call__(self) -> None:
187191
)
188192
out.write("commitizen pre-commit hook is now installed in your '.git'\n")
189193

190-
# Initialize configuration
191-
if "toml" in config_path:
192-
self.config = TomlConfig(data="", path=config_path)
193-
elif "json" in config_path:
194-
self.config = JsonConfig(data="{}", path=config_path)
195-
elif "yaml" in config_path:
196-
self.config = YAMLConfig(data="", path=config_path)
197-
198-
# Create and initialize config
199-
self.config.init_empty_config_content()
200-
201-
self.config.set_key("name", cz_name)
202-
self.config.set_key("tag_format", tag_format)
203-
self.config.set_key("version_scheme", version_scheme)
204-
if version_provider == "commitizen":
205-
self.config.set_key("version", version.public)
206-
else:
207-
self.config.set_key("version_provider", version_provider)
208-
if update_changelog_on_bump:
209-
self.config.set_key("update_changelog_on_bump", update_changelog_on_bump)
210-
if major_version_zero:
211-
self.config.set_key("major_version_zero", major_version_zero)
194+
_write_config_to_file(
195+
path=config_path,
196+
cz_name=cz_name,
197+
version_provider=version_provider,
198+
version_scheme=version_scheme,
199+
version=version,
200+
tag_format=tag_format,
201+
update_changelog_on_bump=update_changelog_on_bump,
202+
major_version_zero=major_version_zero,
203+
)
212204

213205
out.write("\nYou can bump the version running:\n")
214206
out.info("\tcz bump\n")
215207
out.success("Configuration complete 🚀")
216208

217-
def _ask_config_path(self) -> str:
209+
def _ask_config_path(self) -> Path:
218210
default_path = (
219211
"pyproject.toml" if self.project_info.has_pyproject else ".cz.toml"
220212
)
221213

222-
name: str = questionary.select(
214+
filename: str = questionary.select(
223215
"Please choose a supported config file: ",
224216
choices=CONFIG_FILES,
225217
default=default_path,
226218
style=self.cz.style,
227219
).unsafe_ask()
228-
return name
220+
return Path(filename)
229221

230222
def _ask_name(self) -> str:
231223
name: str = questionary.select(
@@ -369,3 +361,30 @@ def _get_config_data(self) -> dict[str, Any]:
369361
else:
370362
repos.append(CZ_HOOK_CONFIG)
371363
return config_data
364+
365+
366+
def _write_config_to_file(
367+
*,
368+
path: Path,
369+
cz_name: str,
370+
version_provider: str,
371+
version_scheme: str,
372+
version: Version,
373+
tag_format: str,
374+
update_changelog_on_bump: bool,
375+
major_version_zero: bool,
376+
) -> None:
377+
out_config = create_config(path=path)
378+
out_config.init_empty_config_content()
379+
380+
out_config.set_key("name", cz_name)
381+
out_config.set_key("tag_format", tag_format)
382+
out_config.set_key("version_scheme", version_scheme)
383+
if version_provider == "commitizen":
384+
out_config.set_key("version", version.public)
385+
else:
386+
out_config.set_key("version_provider", version_provider)
387+
if update_changelog_on_bump:
388+
out_config.set_key("update_changelog_on_bump", update_changelog_on_bump)
389+
if major_version_zero:
390+
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)