Skip to content

Commit 90c1ad5

Browse files
committed
fix: add explicit UTF-8 encoding to all file read/write operations
On Windows, Path.read_text() and Path.write_text() use the system default encoding (e.g. CP1251) instead of UTF-8. This causes UnicodeDecodeError when config files contain non-ASCII characters such as Cyrillic text in commitizen customization options. Fixes #1636
1 parent a03739f commit 90c1ad5

File tree

6 files changed

+37
-23
lines changed

6 files changed

+37
-23
lines changed

commitizen/commands/changelog.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,8 @@ def _export_template(self, dist: str) -> None:
183183
if filename is None:
184184
raise NotAllowed("Template filename is not set")
185185

186-
text = Path(filename).read_text()
187-
Path(dist).write_text(text)
186+
text = Path(filename).read_text(encoding="utf-8")
187+
Path(dist).write_text(text, encoding="utf-8")
188188

189189
def __call__(self) -> None:
190190
commit_parser = self.cz.commit_parser

commitizen/project_info.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def get_default_version_provider() -> Literal[
1414
]:
1515
pyproject_path = Path("pyproject.toml")
1616
if pyproject_path.is_file():
17-
if "[tool.poetry]" in pyproject_path.read_text():
17+
if "[tool.poetry]" in pyproject_path.read_text(encoding="utf-8"):
1818
return "poetry"
1919
if Path("uv.lock").is_file():
2020
return "uv"

commitizen/providers/base_provider.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,15 @@ class JsonProvider(FileProvider):
5858
indent: ClassVar[int] = 2
5959

6060
def get_version(self) -> str:
61-
document = json.loads(self.file.read_text())
61+
document = json.loads(self.file.read_text(encoding="utf-8"))
6262
return self.get(document)
6363

6464
def set_version(self, version: str) -> None:
65-
document = json.loads(self.file.read_text())
65+
document = json.loads(self.file.read_text(encoding="utf-8"))
6666
self.set(document, version)
67-
self.file.write_text(json.dumps(document, indent=self.indent) + "\n")
67+
self.file.write_text(
68+
json.dumps(document, indent=self.indent) + "\n", encoding="utf-8"
69+
)
6870

6971
def get(self, document: Mapping[str, str]) -> str:
7072
return document["version"]
@@ -79,13 +81,13 @@ class TomlProvider(FileProvider):
7981
"""
8082

8183
def get_version(self) -> str:
82-
document = tomlkit.parse(self.file.read_text())
84+
document = tomlkit.parse(self.file.read_text(encoding="utf-8"))
8385
return self.get(document)
8486

8587
def set_version(self, version: str) -> None:
86-
document = tomlkit.parse(self.file.read_text())
88+
document = tomlkit.parse(self.file.read_text(encoding="utf-8"))
8789
self.set(document, version)
88-
self.file.write_text(tomlkit.dumps(document))
90+
self.file.write_text(tomlkit.dumps(document), encoding="utf-8")
8991

9092
def get(self, document: tomlkit.TOMLDocument) -> str:
9193
return document["project"]["version"] # type: ignore[index,return-value]

commitizen/providers/cargo_provider.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ def set_version(self, version: str) -> None:
4343
self.set_lock_version(version)
4444

4545
def set_lock_version(self, version: str) -> None:
46-
cargo_toml_content = parse(self.file.read_text())
47-
cargo_lock_content = parse(self.lock_file.read_text())
46+
cargo_toml_content = parse(self.file.read_text(encoding="utf-8"))
47+
cargo_lock_content = parse(self.lock_file.read_text(encoding="utf-8"))
4848
packages = cargo_lock_content["package"]
4949

5050
if TYPE_CHECKING:
@@ -75,7 +75,9 @@ def set_lock_version(self, version: str) -> None:
7575
continue
7676

7777
cargo_file = Path(path) / "Cargo.toml"
78-
package_content = parse(cargo_file.read_text()).get("package", {})
78+
package_content = parse(
79+
cargo_file.read_text(encoding="utf-8")
80+
).get("package", {})
7981
if TYPE_CHECKING:
8082
assert isinstance(package_content, dict)
8183
try:
@@ -92,7 +94,7 @@ def set_lock_version(self, version: str) -> None:
9294
if package["name"] in members_inheriting:
9395
cargo_lock_content["package"][i]["version"] = version # type: ignore[index]
9496

95-
self.lock_file.write_text(dumps(cargo_lock_content))
97+
self.lock_file.write_text(dumps(cargo_lock_content), encoding="utf-8")
9698

9799

98100
def _try_get_workspace(document: TOMLDocument) -> dict:

commitizen/providers/npm_provider.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,29 +36,37 @@ def get_version(self) -> str:
3636
"""
3737
Get the current version from package.json
3838
"""
39-
package_document = json.loads(self.package_file.read_text())
39+
package_document = json.loads(
40+
self.package_file.read_text(encoding="utf-8")
41+
)
4042
return self.get_package_version(package_document)
4143

4244
def set_version(self, version: str) -> None:
4345
package_document = self.set_package_version(
44-
json.loads(self.package_file.read_text()), version
46+
json.loads(self.package_file.read_text(encoding="utf-8")), version
4547
)
4648
self.package_file.write_text(
47-
json.dumps(package_document, indent=self.indent) + "\n"
49+
json.dumps(package_document, indent=self.indent) + "\n",
50+
encoding="utf-8",
4851
)
4952
if self.lock_file.is_file():
5053
lock_document = self.set_lock_version(
51-
json.loads(self.lock_file.read_text()), version
54+
json.loads(self.lock_file.read_text(encoding="utf-8")), version
5255
)
5356
self.lock_file.write_text(
54-
json.dumps(lock_document, indent=self.indent) + "\n"
57+
json.dumps(lock_document, indent=self.indent) + "\n",
58+
encoding="utf-8",
5559
)
5660
if self.shrinkwrap_file.is_file():
5761
shrinkwrap_document = self.set_shrinkwrap_version(
58-
json.loads(self.shrinkwrap_file.read_text()), version
62+
json.loads(
63+
self.shrinkwrap_file.read_text(encoding="utf-8")
64+
),
65+
version,
5966
)
6067
self.shrinkwrap_file.write_text(
61-
json.dumps(shrinkwrap_document, indent=self.indent) + "\n"
68+
json.dumps(shrinkwrap_document, indent=self.indent) + "\n",
69+
encoding="utf-8",
6270
)
6371

6472
def get_package_version(self, document: Mapping[str, str]) -> str:

commitizen/providers/uv_provider.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,17 @@ def set_version(self, version: str) -> None:
2626
self.set_lock_version(version)
2727

2828
def set_lock_version(self, version: str) -> None:
29-
pyproject_toml_content = tomlkit.parse(self.file.read_text())
29+
pyproject_toml_content = tomlkit.parse(
30+
self.file.read_text(encoding="utf-8")
31+
)
3032
project_name = pyproject_toml_content["project"]["name"] # type: ignore[index]
3133
normalized_project_name = canonicalize_name(str(project_name))
3234

33-
document = tomlkit.parse(self.lock_file.read_text())
35+
document = tomlkit.parse(self.lock_file.read_text(encoding="utf-8"))
3436

3537
packages: tomlkit.items.AoT = document["package"] # type: ignore[assignment]
3638
for i, package in enumerate(packages):
3739
if package["name"] == normalized_project_name:
3840
document["package"][i]["version"] = version # type: ignore[index]
3941
break
40-
self.lock_file.write_text(tomlkit.dumps(document))
42+
self.lock_file.write_text(tomlkit.dumps(document), encoding="utf-8")

0 commit comments

Comments
 (0)