Skip to content

Commit ac64612

Browse files
committed
refactor(Init): make project_info a module and remove self.project_info
1 parent cc981fc commit ac64612

File tree

3 files changed

+84
-87
lines changed

3 files changed

+84
-87
lines changed

commitizen/commands/init.py

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

3-
import os
4-
import shutil
53
from typing import Any, NamedTuple
64

75
import questionary
86
import yaml
97

10-
from commitizen import cmd, factory, out
8+
from commitizen import cmd, factory, out, project_info
119
from commitizen.__version__ import __version__
1210
from commitizen.config import BaseConfig, JsonConfig, TomlConfig, YAMLConfig
1311
from commitizen.cz import registry
@@ -65,65 +63,13 @@ def title(self) -> str:
6563
)
6664

6765

68-
class ProjectInfo:
69-
"""Discover information about the current folder."""
70-
71-
@property
72-
def has_pyproject(self) -> bool:
73-
return os.path.isfile("pyproject.toml")
74-
75-
@property
76-
def has_uv_lock(self) -> bool:
77-
return os.path.isfile("uv.lock")
78-
79-
@property
80-
def has_setup(self) -> bool:
81-
return os.path.isfile("setup.py")
82-
83-
@property
84-
def has_pre_commit_config(self) -> bool:
85-
return os.path.isfile(".pre-commit-config.yaml")
86-
87-
@property
88-
def is_python_uv(self) -> bool:
89-
return self.has_pyproject and self.has_uv_lock
90-
91-
@property
92-
def is_python_poetry(self) -> bool:
93-
if not self.has_pyproject:
94-
return False
95-
with open("pyproject.toml") as f:
96-
return "[tool.poetry]" in f.read()
97-
98-
@property
99-
def is_python(self) -> bool:
100-
return self.has_pyproject or self.has_setup
101-
102-
@property
103-
def is_rust_cargo(self) -> bool:
104-
return os.path.isfile("Cargo.toml")
105-
106-
@property
107-
def is_npm_package(self) -> bool:
108-
return os.path.isfile("package.json")
109-
110-
@property
111-
def is_php_composer(self) -> bool:
112-
return os.path.isfile("composer.json")
113-
114-
@property
115-
def is_pre_commit_installed(self) -> bool:
116-
return bool(shutil.which("pre-commit"))
117-
118-
11966
class Init:
12067
_PRE_COMMIT_CONFIG_PATH = ".pre-commit-config.yaml"
12168

12269
def __init__(self, config: BaseConfig, *args: object) -> None:
12370
self.config: BaseConfig = config
12471
self.encoding = config.settings["encoding"]
12572
self.cz = factory.committer_factory(self.config)
126-
self.project_info = ProjectInfo()
12773

12874
def __call__(self) -> None:
12975
if self.config.path:
@@ -195,14 +141,10 @@ def __call__(self) -> None:
195141
out.success("Configuration complete 🚀")
196142

197143
def _ask_config_path(self) -> str:
198-
default_path = (
199-
"pyproject.toml" if self.project_info.has_pyproject else ".cz.toml"
200-
)
201-
202144
name: str = questionary.select(
203145
"Please choose a supported config file: ",
204146
choices=CONFIG_FILES,
205-
default=default_path,
147+
default=project_info.get_default_config_path(),
206148
style=self.cz.style,
207149
).unsafe_ask()
208150
return name
@@ -267,37 +209,17 @@ def _ask_version_provider(self) -> str:
267209
"Choose the source of the version:",
268210
choices=_VERSION_PROVIDER_CHOICES,
269211
style=self.cz.style,
270-
default=self._default_version_provider,
212+
default=project_info.get_default_version_provider(),
271213
).unsafe_ask()
272214
return version_provider
273215

274-
@property
275-
def _default_version_provider(self) -> str:
276-
if self.project_info.is_python:
277-
if self.project_info.is_python_poetry:
278-
return "poetry"
279-
if self.project_info.is_python_uv:
280-
return "uv"
281-
return "pep621"
282-
283-
if self.project_info.is_rust_cargo:
284-
return "cargo"
285-
if self.project_info.is_npm_package:
286-
return "npm"
287-
if self.project_info.is_php_composer:
288-
return "composer"
289-
290-
return "commitizen"
291-
292216
def _ask_version_scheme(self) -> str:
293217
"""Ask for setting: version_scheme"""
294-
default_scheme = "pep440" if self.project_info.is_python else "semver"
295-
296218
scheme: str = questionary.select(
297219
"Choose version scheme: ",
298220
choices=KNOWN_SCHEMES,
299221
style=self.cz.style,
300-
default=default_scheme,
222+
default=project_info.get_default_version_scheme(),
301223
).unsafe_ask()
302224
return scheme
303225

@@ -351,7 +273,7 @@ def _get_config_data(self) -> dict[str, Any]:
351273
],
352274
}
353275

354-
if not self.project_info.has_pre_commit_config:
276+
if not project_info.has_pre_commit_config():
355277
# .pre-commit-config.yaml does not exist
356278
return {"repos": [CZ_HOOK_CONFIG]}
357279

@@ -377,7 +299,7 @@ def _install_pre_commit_hook(self, hook_types: list[str] | None = None) -> None:
377299
) as config_file:
378300
yaml.safe_dump(config_data, stream=config_file)
379301

380-
if not self.project_info.is_pre_commit_installed:
302+
if not project_info.is_pre_commit_installed():
381303
raise InitFailedError("pre-commit is not installed in current environment.")
382304
if hook_types is None:
383305
hook_types = ["commit-msg", "pre-push"]

commitizen/project_info.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
"""Resolves project information about the current working directory."""
2+
3+
import shutil
4+
from pathlib import Path
5+
from typing import Literal
6+
7+
8+
def has_pyproject() -> bool:
9+
return Path("pyproject.toml").is_file()
10+
11+
12+
def has_uv_lock() -> bool:
13+
return Path("uv.lock").is_file()
14+
15+
16+
def has_setup() -> bool:
17+
return Path("setup.py").is_file()
18+
19+
20+
def has_pre_commit_config() -> bool:
21+
return Path(".pre-commit-config.yaml").is_file()
22+
23+
24+
def is_python_uv() -> bool:
25+
return has_pyproject() and has_uv_lock()
26+
27+
28+
def is_python_poetry() -> bool:
29+
return has_pyproject() and "[tool.poetry]" in Path("pyproject.toml").read_text()
30+
31+
32+
def is_python() -> bool:
33+
return has_pyproject() or has_setup()
34+
35+
36+
def is_rust_cargo() -> bool:
37+
return Path("Cargo.toml").is_file()
38+
39+
40+
def is_npm_package() -> bool:
41+
return Path("package.json").is_file()
42+
43+
44+
def is_php_composer() -> bool:
45+
return Path("composer.json").is_file()
46+
47+
48+
def is_pre_commit_installed() -> bool:
49+
return bool(shutil.which("pre-commit"))
50+
51+
52+
def get_default_version_provider() -> Literal[
53+
"commitizen", "cargo", "composer", "npm", "pep621", "poetry", "uv"
54+
]:
55+
if is_python():
56+
if is_python_poetry():
57+
return "poetry"
58+
if is_python_uv():
59+
return "uv"
60+
return "pep621"
61+
if is_rust_cargo():
62+
return "cargo"
63+
if is_npm_package():
64+
return "npm"
65+
if is_php_composer():
66+
return "composer"
67+
return "commitizen"
68+
69+
70+
def get_default_config_path() -> Literal["pyproject.toml", ".cz.toml"]:
71+
return "pyproject.toml" if has_pyproject() else ".cz.toml"
72+
73+
74+
def get_default_version_scheme() -> Literal["pep440", "semver"]:
75+
return "pep440" if is_python() else "semver"

tests/commands/test_init_command.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ def test_executed_pre_commit_command(config):
125125
def pre_commit_installed(mocker: MockFixture):
126126
# Assume the `pre-commit` is installed
127127
mocker.patch(
128-
"commitizen.commands.init.ProjectInfo.is_pre_commit_installed",
128+
"commitizen.project_info.is_pre_commit_installed",
129129
return_value=True,
130130
)
131131
# And installation success (i.e. no exception raised)
@@ -230,7 +230,7 @@ def test_pre_commit_not_installed(
230230
):
231231
# Assume `pre-commit` is not installed
232232
mocker.patch(
233-
"commitizen.commands.init.ProjectInfo.is_pre_commit_installed",
233+
"commitizen.project_info.is_pre_commit_installed",
234234
return_value=False,
235235
)
236236
with tmpdir.as_cwd():
@@ -242,7 +242,7 @@ def test_pre_commit_exec_failed(
242242
):
243243
# Assume `pre-commit` is installed
244244
mocker.patch(
245-
"commitizen.commands.init.ProjectInfo.is_pre_commit_installed",
245+
"commitizen.project_info.is_pre_commit_installed",
246246
return_value=True,
247247
)
248248
# But pre-commit installation will fail

0 commit comments

Comments
 (0)