Skip to content

Commit a8be6cc

Browse files
committed
refactor(changelog): some cleanup and adjust test cases
1 parent 391501f commit a8be6cc

File tree

2 files changed

+64
-58
lines changed

2 files changed

+64
-58
lines changed

commitizen/changelog.py

Lines changed: 58 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
from collections.abc import Iterable
3333
from dataclasses import dataclass
3434
from datetime import date
35+
from itertools import islice
3536
from typing import TYPE_CHECKING
3637

3738
from jinja2 import (
@@ -88,24 +89,21 @@ def generate_tree_from_commits(
8889
pat = re.compile(changelog_pattern)
8990
map_pat = re.compile(commit_parser, re.MULTILINE)
9091
body_map_pat = re.compile(commit_parser, re.MULTILINE | re.DOTALL)
91-
current_tag: GitTag | None = None
9292
rules = rules or TagRules()
9393

9494
# Check if the latest commit is not tagged
95-
if commits:
96-
latest_commit = commits[0]
97-
current_tag = get_commit_tag(latest_commit, tags)
98-
99-
current_tag_name: str = unreleased_version or "Unreleased"
100-
current_tag_date: str = ""
101-
if unreleased_version is not None:
102-
current_tag_date = date.today().isoformat()
95+
current_tag = get_commit_tag(commits[0], tags) if commits else None
96+
97+
current_tag_name = unreleased_version or "Unreleased"
98+
current_tag_date = (
99+
date.today().isoformat() if unreleased_version is not None else ""
100+
)
103101
if current_tag is not None and current_tag.name:
104102
current_tag_name = current_tag.name
105103
current_tag_date = current_tag.date
106104

107-
changes: dict = defaultdict(list)
108-
used_tags: list = [current_tag]
105+
changes: defaultdict[str | None, list] = defaultdict(list)
106+
used_tags = [current_tag]
109107
for commit in commits:
110108
commit_tag = get_commit_tag(commit, tags)
111109

@@ -170,21 +168,23 @@ def process_commit_message(
170168
changes: dict[str | None, list],
171169
change_type_map: dict[str, str] | None = None,
172170
):
173-
message: dict = {
171+
message = {
174172
"sha1": commit.rev,
175173
"parents": commit.parents,
176174
"author": commit.author,
177175
"author_email": commit.author_email,
178176
**parsed.groupdict(),
179177
}
178+
processed = hook(message, commit) if hook else message
179+
if not processed:
180+
return
180181

181-
if processed := hook(message, commit) if hook else message:
182-
messages = [processed] if isinstance(processed, dict) else processed
183-
for msg in messages:
184-
change_type = msg.pop("change_type", None)
185-
if change_type_map:
186-
change_type = change_type_map.get(change_type, change_type)
187-
changes[change_type].append(msg)
182+
processed_messages = [processed] if isinstance(processed, dict) else processed
183+
for msg in processed_messages:
184+
change_type = msg.pop("change_type", None)
185+
if change_type_map:
186+
change_type = change_type_map.get(change_type, change_type)
187+
changes[change_type].append(msg)
188188

189189

190190
def order_changelog_tree(tree: Iterable, change_type_order: list[str]) -> Iterable:
@@ -225,8 +225,7 @@ def render_changelog(
225225
**kwargs,
226226
) -> str:
227227
jinja_template = get_changelog_template(loader, template)
228-
changelog: str = jinja_template.render(tree=tree, **kwargs)
229-
return changelog
228+
return jinja_template.render(tree=tree, **kwargs)
230229

231230

232231
def incremental_build(
@@ -253,7 +252,9 @@ def incremental_build(
253252
for index, line in enumerate(lines):
254253
if index == unreleased_start:
255254
skip = True
256-
elif index == unreleased_end:
255+
continue
256+
257+
if index == unreleased_end:
257258
skip = False
258259
if (
259260
latest_version_position is None
@@ -268,13 +269,15 @@ def incremental_build(
268269

269270
if index == latest_version_position:
270271
output_lines.extend([new_content, "\n"])
271-
272272
output_lines.append(line)
273-
if not isinstance(latest_version_position, int):
274-
if output_lines and output_lines[-1].strip():
275-
# Ensure at least one blank line between existing and new content.
276-
output_lines.append("\n")
277-
output_lines.append(new_content)
273+
274+
if isinstance(latest_version_position, int):
275+
return output_lines
276+
277+
if output_lines and output_lines[-1].strip():
278+
# Ensure at least one blank line between existing and new content.
279+
output_lines.append("\n")
280+
output_lines.append(new_content)
278281
return output_lines
279282

280283

@@ -285,23 +288,26 @@ def get_smart_tag_range(
285288
286289
This is because we need to find until the next tag
287290
"""
288-
accumulator = []
289-
keep = False
290291
if not oldest:
291292
oldest = newest
292-
for index, tag in enumerate(tags):
293-
if tag.name == newest:
294-
keep = True
295-
if keep:
296-
accumulator.append(tag)
297-
if tag.name == oldest:
298-
keep = False
299-
try:
300-
accumulator.append(tags[index + 1])
301-
except IndexError:
302-
pass
303-
break
304-
return accumulator
293+
294+
# Find indices of newest and oldest tags
295+
try:
296+
newest_idx = next((i for i, tag in enumerate(tags) if tag.name == newest))
297+
oldest_idx = newest_idx + (
298+
next(
299+
i
300+
for i, tag in enumerate(islice(tags, newest_idx, None))
301+
if tag.name == oldest
302+
)
303+
)
304+
except StopIteration:
305+
# Should not reach here
306+
raise NoCommitsFoundError(f"Could not find the tags {newest=} and {oldest=}.")
307+
308+
# Get the range of tags including the next tag after oldest if it exists
309+
end_idx = min(oldest_idx + 2, len(tags))
310+
return tags[newest_idx:end_idx]
305311

306312

307313
def get_oldest_and_newest_rev(
@@ -337,17 +343,17 @@ def get_oldest_and_newest_rev(
337343
if not tags_range:
338344
raise NoCommitsFoundError("Could not find a valid revision range.")
339345

340-
oldest_rev: str | None = tags_range[-1].name
346+
oldest_rev = tags_range[-1].name
341347
newest_rev = newest_tag.name
342348

343-
# check if it's the first tag created
344-
# and it's also being requested as part of the range
345-
if oldest_rev == tags[-1].name and oldest_rev == oldest_tag_name:
346-
return None, newest_rev
347-
348-
# when they are the same, and it's also the
349-
# first tag created
350-
if oldest_rev == newest_rev:
349+
# Return None for oldest_rev if:
350+
# 1. The oldest tag is the last tag in the list and matches the requested oldest tag, or
351+
# 2. The oldest and newest tags are the same
352+
if (
353+
oldest_rev == tags[-1].name
354+
and oldest_rev == oldest_tag_name
355+
or oldest_rev == newest_rev
356+
):
351357
return None, newest_rev
352358

353359
return oldest_rev, newest_rev

tests/test_changelog.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1539,21 +1539,21 @@ def test_get_smart_tag_range_returns_an_extra_for_a_single_tag(tags):
15391539

15401540
def test_get_smart_tag_range_returns_an_empty_list_for_nonexistent_end_tag(tags):
15411541
start = tags[0]
1542-
res = changelog.get_smart_tag_range(tags, start.name, "nonexistent")
1543-
assert len(tags) == len(res)
1542+
with pytest.raises(changelog.NoCommitsFoundError):
1543+
changelog.get_smart_tag_range(tags, start.name, "nonexistent")
15441544

15451545

15461546
def test_get_smart_tag_range_returns_an_empty_list_for_nonexistent_start_tag(tags):
15471547
end = tags[0]
1548-
res = changelog.get_smart_tag_range(tags, "nonexistent", end.name)
1549-
assert 1 == len(res)
1548+
with pytest.raises(changelog.NoCommitsFoundError):
1549+
changelog.get_smart_tag_range(tags, "nonexistent", end.name)
15501550

15511551

15521552
def test_get_smart_tag_range_returns_an_empty_list_for_nonexistent_start_and_end_tags(
15531553
tags,
15541554
):
1555-
res = changelog.get_smart_tag_range(tags, "nonexistent", "nonexistent")
1556-
assert 0 == len(res)
1555+
with pytest.raises(changelog.NoCommitsFoundError):
1556+
changelog.get_smart_tag_range(tags, "nonexistent", "nonexistent")
15571557

15581558

15591559
@dataclass

0 commit comments

Comments
 (0)