Skip to content

Commit 407af3a

Browse files
adam-grant-hendryLee-W
authored andcommitted
feat(unicode): add unicode support
This will allow commiting, e.g., emoji's and parsing commit messages for unicode characters when creating change logs.
1 parent 114501d commit 407af3a

25 files changed

+205
-107
lines changed

commitizen/bump.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from commitizen.defaults import MAJOR, MINOR, PATCH, bump_message
99
from commitizen.exceptions import CurrentVersionNotFoundError
1010
from commitizen.git import GitCommit, smart_open
11-
from commitizen.version_schemes import DEFAULT_SCHEME, VersionScheme, Version
11+
from commitizen.version_schemes import DEFAULT_SCHEME, Version, VersionScheme
1212

1313

1414
def find_increment(
@@ -45,7 +45,12 @@ def find_increment(
4545

4646

4747
def update_version_in_files(
48-
current_version: str, new_version: str, files: list[str], *, check_consistency=False
48+
current_version: str,
49+
new_version: str,
50+
files: List[str],
51+
encoding: str,
52+
*,
53+
check_consistency=False,
4954
) -> None:
5055
"""Change old version to the new one in every file given.
5156
@@ -62,7 +67,11 @@ def update_version_in_files(
6267
regex = _version_to_regex(current_version)
6368

6469
current_version_found, version_file = _bump_with_regex(
65-
filepath, current_version, new_version, regex
70+
filepath,
71+
current_version,
72+
new_version,
73+
regex,
74+
encoding,
6675
)
6776

6877
if check_consistency and not current_version_found:
@@ -73,17 +82,21 @@ def update_version_in_files(
7382
)
7483

7584
# Write the file out again
76-
with smart_open(filepath, "w") as file:
85+
with smart_open(filepath, "w", encoding=encoding) as file:
7786
file.write(version_file)
7887

7988

8089
def _bump_with_regex(
81-
version_filepath: str, current_version: str, new_version: str, regex: str
82-
) -> tuple[bool, str]:
90+
version_filepath: str,
91+
current_version: str,
92+
new_version: str,
93+
regex: str,
94+
encoding: str,
95+
) -> Tuple[bool, str]:
8396
current_version_found = False
8497
lines = []
8598
pattern = re.compile(regex)
86-
with open(version_filepath, "r") as f:
99+
with open(version_filepath, "r", encoding=encoding) as f:
87100
for line in f:
88101
if pattern.search(line):
89102
bumped_line = line.replace(current_version, new_version)

commitizen/changelog.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ def get_metadata(filepath: str, scheme: VersionScheme = Pep440) -> dict:
227227
"latest_version_position": None,
228228
}
229229

230-
with open(filepath, "r") as changelog_file:
230+
with open(filepath, "r", encoding=encoding) as changelog_file:
231231
for index, line in enumerate(changelog_file):
232232
line = line.strip().lower()
233233

commitizen/changelog_parser.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
]
3737

3838

39-
def find_version_blocks(filepath: str) -> Generator:
39+
def find_version_blocks(filepath: str, encoding: str) -> Generator:
4040
"""Find version block (version block: contains all the information about a version.)
4141
4242
E.g:
@@ -53,7 +53,7 @@ def find_version_blocks(filepath: str) -> Generator:
5353
5454
```
5555
"""
56-
with open(filepath, "r") as f:
56+
with open(filepath, "r", encoding=encoding) as f:
5757
block: list = []
5858
for line in f:
5959
line = line.strip("\n")

commitizen/commands/bump.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ def __init__(self, config: BaseConfig, arguments: dict):
3636
raise NotAGitProjectError()
3737

3838
self.config: BaseConfig = config
39+
self.encoding = config.settings["encoding"]
3940
self.arguments: dict = arguments
4041
self.bump_settings: dict = {
4142
**config.settings,
@@ -297,6 +298,7 @@ def __call__(self): # noqa: C901
297298
str(current_version),
298299
str(new_version),
299300
version_files,
301+
self.encoding,
300302
check_consistency=self.check_consistency,
301303
)
302304

commitizen/commands/changelog.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ def __init__(self, config: BaseConfig, args):
2727
raise NotAGitProjectError()
2828

2929
self.config: BaseConfig = config
30+
self.encoding = self.config.settings["encoding"]
3031
self.cz = factory.commiter_factory(self.config)
3132

3233
self.start_rev = args.get("start_rev") or self.config.settings.get(
@@ -100,9 +101,9 @@ def write_changelog(
100101
f"or the setting `changelog_file` in {self.config.path}"
101102
)
102103

103-
changelog_hook: Callable | None = self.cz.changelog_hook
104-
with smart_open(self.file_name, "w") as changelog_file:
105-
partial_changelog: str | None = None
104+
changelog_hook: Optional[Callable] = self.cz.changelog_hook
105+
with smart_open(self.file_name, "w", encoding=self.encoding) as changelog_file:
106+
partial_changelog: Optional[str] = None
106107
if self.incremental:
107108
new_lines = changelog.incremental_build(
108109
changelog_out, lines, changelog_meta
@@ -141,7 +142,9 @@ def __call__(self):
141142

142143
end_rev = ""
143144
if self.incremental:
144-
changelog_meta = changelog.get_metadata(self.file_name, self.scheme)
145+
changelog_meta = changelog.get_metadata(
146+
self.file_name, self.scheme, self.encoding
147+
)
145148
latest_version = changelog_meta.get("latest_version")
146149
if latest_version:
147150
latest_tag_version: str = bump.normalize_tag(
@@ -187,7 +190,7 @@ def __call__(self):
187190

188191
lines = []
189192
if self.incremental and os.path.isfile(self.file_name):
190-
with open(self.file_name, "r") as changelog_file:
193+
with open(self.file_name, "r", encoding=self.encoding) as changelog_file:
191194
lines = changelog_file.readlines()
192195

193196
self.write_changelog(changelog_out, lines, changelog_meta)

commitizen/commands/check.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ def __init__(self, config: BaseConfig, arguments: dict[str, Any], cwd=os.getcwd(
4444
self._valid_command_argument()
4545

4646
self.config: BaseConfig = config
47+
self.encoding = config.settings["encoding"]
4748
self.cz = factory.commiter_factory(self.config)
4849

4950
def _valid_command_argument(self):
@@ -97,7 +98,7 @@ def _get_commits(self):
9798
# Get commit message from file (--commit-msg-file)
9899
if self.commit_msg_file is not None:
99100
# Enter this branch if commit_msg_file is "".
100-
with open(self.commit_msg_file, "r", encoding="utf-8") as commit_file:
101+
with open(self.commit_msg_file, "r", encoding=self.encoding) as commit_file:
101102
msg = commit_file.read()
102103
# Get commit message from command line (--message)
103104
elif self.commit_msg is not None:

commitizen/commands/commit.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ def __init__(self, config: BaseConfig, arguments: dict):
2828
raise NotAGitProjectError()
2929

3030
self.config: BaseConfig = config
31+
self.encoding = config.settings["encoding"]
3132
self.cz = factory.commiter_factory(self.config)
3233
self.arguments = arguments
3334
self.temp_file: str = os.path.join(
@@ -41,7 +42,7 @@ def read_backup_message(self) -> str:
4142
raise NoCommitBackupError()
4243

4344
# Read commit message from backup
44-
with open(self.temp_file, "r") as f:
45+
with open(self.temp_file, "r", encoding=self.encoding) as f:
4546
return f.read().strip()
4647

4748
def prompt_commit_questions(self) -> str:
@@ -99,7 +100,7 @@ def __call__(self):
99100
out.error(c.err)
100101

101102
# Create commit backup
102-
with smart_open(self.temp_file, "w") as f:
103+
with smart_open(self.temp_file, "w", encoding=self.encoding) as f:
103104
f.write(m)
104105

105106
raise CommitError()

commitizen/commands/init.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ def is_pre_commit_installed(self) -> bool:
7272
class Init:
7373
def __init__(self, config: BaseConfig, *args):
7474
self.config: BaseConfig = config
75+
self.encoding = config.settings["encoding"]
7576
self.cz = factory.commiter_factory(self.config)
7677
self.project_info = ProjectInfo()
7778

@@ -324,7 +325,9 @@ def _install_pre_commit_hook(self, hook_types: list[str] | None = None):
324325
# .pre-commit-config.yaml does not exist
325326
config_data["repos"] = [cz_hook_config]
326327
else:
327-
with open(pre_commit_config_filename) as config_file:
328+
with open(
329+
pre_commit_config_filename, encoding=self.encoding
330+
) as config_file:
328331
yaml_data = yaml.safe_load(config_file)
329332
if yaml_data:
330333
config_data = yaml_data
@@ -340,7 +343,9 @@ def _install_pre_commit_hook(self, hook_types: list[str] | None = None):
340343
# .pre-commit-config.yaml exists but there's no "repos" key
341344
config_data["repos"] = [cz_hook_config]
342345

343-
with smart_open(pre_commit_config_filename, "w") as config_file:
346+
with smart_open(
347+
pre_commit_config_filename, "w", encoding=self.encoding
348+
) as config_file:
344349
yaml.safe_dump(config_data, stream=config_file)
345350

346351
if not self.project_info.is_pre_commit_installed:

commitizen/config/json_config.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@
1212
class JsonConfig(BaseConfig):
1313
def __init__(self, *, data: bytes | str, path: Path | str):
1414
super(JsonConfig, self).__init__()
15+
self.encoding = self.settings["encoding"]
1516
self.is_empty_config = False
1617
self.add_path(path)
1718
self._parse_setting(data)
1819

1920
def init_empty_config_content(self):
20-
with smart_open(self.path, "a") as json_file:
21+
with smart_open(self.path, "a", encoding=self.encoding) as json_file:
2122
json.dump({"commitizen": {}}, json_file)
2223

2324
def set_key(self, key, value):
@@ -30,7 +31,7 @@ def set_key(self, key, value):
3031
parser = json.load(f)
3132

3233
parser["commitizen"][key] = value
33-
with smart_open(self.path, "w") as f:
34+
with smart_open(self.path, "w", encoding=self.encoding) as f:
3435
json.dump(parser, f, indent=2)
3536
return self
3637

commitizen/config/toml_config.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
class TomlConfig(BaseConfig):
1212
def __init__(self, *, data: bytes | str, path: Path | str):
1313
super(TomlConfig, self).__init__()
14+
self.encoding = self.settings["encoding"]
1415
self.is_empty_config = False
1516
self._parse_setting(data)
1617
self.add_path(path)
@@ -26,7 +27,7 @@ def init_empty_config_content(self):
2627
if parser.get("tool") is None:
2728
parser["tool"] = table()
2829
parser["tool"]["commitizen"] = table()
29-
output_toml_file.write(parser.as_string().encode("utf-8"))
30+
output_toml_file.write(parser.as_string().encode(self.encoding))
3031

3132
def set_key(self, key, value):
3233
"""Set or update a key in the conf.
@@ -39,7 +40,7 @@ def set_key(self, key, value):
3940

4041
parser["tool"]["commitizen"][key] = value
4142
with open(self.path, "wb") as f:
42-
f.write(parser.as_string().encode("utf-8"))
43+
f.write(parser.as_string().encode(self.encoding))
4344
return self
4445

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

commitizen/config/yaml_config.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@
1212
class YAMLConfig(BaseConfig):
1313
def __init__(self, *, data: bytes | str, path: Path | str):
1414
super(YAMLConfig, self).__init__()
15+
self.encoding = self.settings["encoding"]
1516
self.is_empty_config = False
1617
self._parse_setting(data)
1718
self.add_path(path)
1819

1920
def init_empty_config_content(self):
20-
with smart_open(self.path, "a") as json_file:
21+
with smart_open(self.path, "a", encoding=self.encoding) as json_file:
2122
yaml.dump({"commitizen": {}}, json_file, explicit_start=True)
2223

2324
def _parse_setting(self, data: bytes | str) -> None:
@@ -44,7 +45,7 @@ def set_key(self, key, value):
4445
parser = yaml.load(yaml_file, Loader=yaml.FullLoader)
4546

4647
parser["commitizen"][key] = value
47-
with smart_open(self.path, "w") as yaml_file:
48+
with smart_open(self.path, "w", encoding=self.encoding) as yaml_file:
4849
yaml.dump(parser, yaml_file, explicit_start=True)
4950

5051
return self

commitizen/cz/conventional_commits/conventional_commits.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ def schema_pattern(self) -> str:
202202
def info(self) -> str:
203203
dir_path = os.path.dirname(os.path.realpath(__file__))
204204
filepath = os.path.join(dir_path, "conventional_commits_info.txt")
205-
with open(filepath, "r") as f:
205+
with open(filepath, "r", encoding=self.config.settings["encoding"]) as f:
206206
content = f.read()
207207
return content
208208

commitizen/cz/customize/customize.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def info(self) -> str | None:
8181
info_path = self.custom_settings.get("info_path")
8282
info = self.custom_settings.get("info")
8383
if info_path:
84-
with open(info_path, "r") as f:
84+
with open(info_path, "r", encoding=self.config.settings["encoding"]) as f:
8585
content = f.read()
8686
return content
8787
elif info:

commitizen/cz/jira/jira.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,6 @@ def schema_pattern(self) -> str:
7676
def info(self) -> str:
7777
dir_path = os.path.dirname(os.path.realpath(__file__))
7878
filepath = os.path.join(dir_path, "jira_info.txt")
79-
with open(filepath, "r") as f:
79+
with open(filepath, "r", encoding=self.config.settings["encoding"]) as f:
8080
content = f.read()
8181
return content

commitizen/defaults.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class Settings(TypedDict, total=False):
5555
pre_bump_hooks: list[str] | None
5656
post_bump_hooks: list[str] | None
5757
prerelease_offset: int
58+
encoding: str
5859

5960

6061
name: str = "cz_conventional_commits"
@@ -66,6 +67,7 @@ class Settings(TypedDict, total=False):
6667
".cz.yaml",
6768
"cz.yaml",
6869
]
70+
encoding: str = "utf-8"
6971

7072
DEFAULT_SETTINGS: Settings = {
7173
"name": "cz_conventional_commits",
@@ -93,6 +95,7 @@ class Settings(TypedDict, total=False):
9395
"pre_bump_hooks": [],
9496
"post_bump_hooks": [],
9597
"prerelease_offset": 0,
98+
"encoding": "utf-8",
9699
}
97100

98101
MAJOR = "MAJOR"

0 commit comments

Comments
 (0)