3232from collections .abc import Iterable
3333from dataclasses import dataclass
3434from datetime import date
35- from typing import TYPE_CHECKING
35+ from typing import TYPE_CHECKING , Any
3636
3737from jinja2 import (
3838 BaseLoader ,
@@ -74,6 +74,23 @@ def get_commit_tag(commit: GitCommit, tags: list[GitTag]) -> GitTag | None:
7474 return next ((tag for tag in tags if tag .rev == commit .rev ), None )
7575
7676
77+ def _get_release_info (
78+ current_tag_name : str ,
79+ current_tag_date : str ,
80+ changes : dict [str | None , list ],
81+ changelog_release_hook : ChangelogReleaseHook | None ,
82+ commit_tag : GitTag | None ,
83+ ) -> dict [str , Any ]:
84+ release = {
85+ "version" : current_tag_name ,
86+ "date" : current_tag_date ,
87+ "changes" : changes ,
88+ }
89+ if changelog_release_hook :
90+ return changelog_release_hook (release , commit_tag )
91+ return release
92+
93+
7794def generate_tree_from_commits (
7895 commits : list [GitCommit ],
7996 tags : list [GitTag ],
@@ -90,19 +107,22 @@ def generate_tree_from_commits(
90107 body_map_pat = re .compile (commit_parser , re .MULTILINE | re .DOTALL )
91108 rules = rules or TagRules ()
92109
93- # Check if the latest commit is not tagged
94- current_tag = get_commit_tag (commits [0 ], tags ) if commits else None
95-
110+ used_tags : set [GitTag ] = set ()
96111 current_tag_name = unreleased_version or "Unreleased"
97112 current_tag_date = (
98113 date .today ().isoformat () if unreleased_version is not None else ""
99114 )
100- if current_tag is not None and current_tag .name :
101- current_tag_name = current_tag .name
102- current_tag_date = current_tag .date
115+
116+ # Check if the latest commit is not tagged
117+ current_tag = get_commit_tag (commits [0 ], tags ) if commits else None
118+ if current_tag is not None :
119+ used_tags .add (current_tag )
120+ if current_tag .name :
121+ current_tag_name = current_tag .name
122+ current_tag_date = current_tag .date
103123
104124 changes : defaultdict [str | None , list ] = defaultdict (list )
105- used_tags : set [ GitTag | None ] = set ([ current_tag ])
125+ commit_tag : GitTag | None = None
106126 for commit in commits :
107127 commit_tag = get_commit_tag (commit , tags )
108128
@@ -112,20 +132,20 @@ def generate_tree_from_commits(
112132 and rules .include_in_changelog (commit_tag )
113133 ):
114134 used_tags .add (commit_tag )
115- release = {
116- "version" : current_tag_name ,
117- "date" : current_tag_date ,
118- "changes" : changes ,
119- }
120- if changelog_release_hook :
121- release = changelog_release_hook (release , commit_tag )
122- yield release
135+
136+ yield _get_release_info (
137+ current_tag_name ,
138+ current_tag_date ,
139+ changes ,
140+ changelog_release_hook ,
141+ commit_tag ,
142+ )
143+
123144 current_tag_name = commit_tag .name
124145 current_tag_date = commit_tag .date
125146 changes = defaultdict (list )
126147
127- matches = pat .match (commit .message )
128- if not matches :
148+ if not pat .match (commit .message ):
129149 continue
130150
131151 # Process subject from commit message
@@ -150,14 +170,13 @@ def generate_tree_from_commits(
150170 change_type_map ,
151171 )
152172
153- release = {
154- "version" : current_tag_name ,
155- "date" : current_tag_date ,
156- "changes" : changes ,
157- }
158- if changelog_release_hook :
159- release = changelog_release_hook (release , commit_tag )
160- yield release
173+ yield _get_release_info (
174+ current_tag_name ,
175+ current_tag_date ,
176+ changes ,
177+ changelog_release_hook ,
178+ commit_tag ,
179+ )
161180
162181
163182def process_commit_message (
@@ -167,7 +186,7 @@ def process_commit_message(
167186 changes : dict [str | None , list ],
168187 change_type_map : dict [str , str ] | None = None ,
169188):
170- message = {
189+ message : dict [ str , str | list [ str ] | Any ] = {
171190 "sha1" : commit .rev ,
172191 "parents" : commit .parents ,
173192 "author" : commit .author ,
0 commit comments