Skip to content

Commit c1d23cc

Browse files
committed
Provide better error messages about version mismatches
1 parent 74f7125 commit c1d23cc

File tree

3 files changed

+279
-218
lines changed

3 files changed

+279
-218
lines changed

get_releasenote.py

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ def parse_changes(
8585

8686
return _parse_changes(
8787
changes=changes,
88+
changes_file=changes_file,
8889
version=ctx.version,
8990
start_line=start_line,
9091
head_line=head_line,
@@ -96,6 +97,7 @@ def parse_changes(
9697
def _parse_changes(
9798
*,
9899
changes: str,
100+
changes_file: str,
99101
version: str,
100102
start_line: str,
101103
head_line: str,
@@ -105,7 +107,10 @@ def _parse_changes(
105107
) -> str:
106108
top, sep, msg = changes.partition(start_line)
107109
if not sep:
108-
raise ValueError(f"Cannot find TOWNCRIER start mark ({start_line!r})")
110+
raise ValueError(
111+
f"Cannot find TOWNCRIER start mark ({start_line!r}) "
112+
"in file '{changes_file}'"
113+
)
109114

110115
msg = msg.strip()
111116
head_re = re.compile(
@@ -119,11 +124,11 @@ def _parse_changes(
119124
match = head_re.match(msg)
120125
if match is None:
121126
raise ValueError(
122-
f"Cannot find TOWNCRIER version head mark ({head_re.pattern!r})"
127+
f"Cannot find TOWNCRIER version head mark ({head_re.pattern!r}) "
128+
f"in file '{changes_file}'"
123129
)
124130
found_version = match.group("version")
125-
if version != found_version:
126-
raise ValueError(f"Version check mismatch: {version} != {found_version}")
131+
check_changes_version(version, found_version, changes_file)
127132

128133
match2 = head_re.search(msg, match.end())
129134
if match2 is not None:
@@ -138,6 +143,29 @@ def _parse_changes(
138143
return msg.strip()
139144

140145

146+
def check_changes_version(
147+
declared_version: str, found_version: str, changes_file: str
148+
) -> None:
149+
if declared_version == found_version:
150+
return
151+
dver = parse_version(declared_version)
152+
fver = parse_version(found_version)
153+
154+
if dver < fver:
155+
raise ValueError(
156+
f"The distribution version {dver} is older than "
157+
f"{fver} (from '{changes_file}').\n"
158+
"Hint: push git tag with the latest version."
159+
)
160+
161+
else:
162+
raise ValueError(
163+
f"The distribution version {dver} is younger than "
164+
f"{fver} (from '{changes_file}').\n"
165+
"Hint: run 'towncrier' again."
166+
)
167+
168+
141169
VERSION_RE = re.compile(
142170
"^{version} *= *{spec}".format(
143171
version="(?:__version__|version)",

tests/test_parse_changes.py

Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
from textwrap import dedent
2+
3+
import pytest
4+
5+
from get_releasenote import _parse_changes
6+
7+
START_LINE = ".. towncrier release notes start"
8+
9+
10+
def test_parse_no_start_line() -> None:
11+
with pytest.raises(ValueError, match="Cannot find TOWNCRIER start mark"):
12+
_parse_changes(
13+
changes="text",
14+
changes_file="CHANGES.rst",
15+
version="1.2.3",
16+
start_line=START_LINE,
17+
head_line="{version} \\({date}\\)\n=====+\n?",
18+
fix_issue_regex="",
19+
fix_issue_repl="",
20+
name="name",
21+
)
22+
23+
24+
def test_parse_no_head_line() -> None:
25+
CHANGES = dedent(
26+
f"""\
27+
{START_LINE}
28+
NO-VERSION
29+
"""
30+
)
31+
with pytest.raises(ValueError, match="Cannot find TOWNCRIER version head mark"):
32+
_parse_changes(
33+
changes=CHANGES,
34+
changes_file="CHANGES.rst",
35+
version="1.2.3",
36+
start_line=START_LINE,
37+
head_line="{version} \\({date}\\)\n=====+\n?",
38+
fix_issue_regex="",
39+
fix_issue_repl="",
40+
name="name",
41+
)
42+
43+
44+
def test_parse_version_older() -> None:
45+
CHANGES = dedent(
46+
f"""\
47+
{START_LINE}
48+
49+
1.2.4 (2020-12-16)
50+
==================
51+
52+
"""
53+
)
54+
with pytest.raises(
55+
ValueError, match="The distribution version 1.2.3 is older than 1.2.4"
56+
):
57+
_parse_changes(
58+
changes=CHANGES,
59+
changes_file="CHANGES.rst",
60+
version="1.2.3",
61+
start_line=START_LINE,
62+
head_line="{version} \\({date}\\)\n=====+\n?",
63+
fix_issue_regex="",
64+
fix_issue_repl="",
65+
name="name",
66+
)
67+
68+
69+
def test_parse_version_younger() -> None:
70+
CHANGES = dedent(
71+
f"""\
72+
{START_LINE}
73+
74+
1.2.4 (2020-12-16)
75+
==================
76+
77+
"""
78+
)
79+
with pytest.raises(
80+
ValueError, match="The distribution version 1.2.5 is younger than 1.2.4"
81+
):
82+
_parse_changes(
83+
changes=CHANGES,
84+
changes_file="CHANGES.rst",
85+
version="1.2.5",
86+
start_line=START_LINE,
87+
head_line="{version} \\({date}\\)\n=====+\n?",
88+
fix_issue_regex="",
89+
fix_issue_repl="",
90+
name="name",
91+
)
92+
93+
94+
def test_parse_single_changes() -> None:
95+
CHANGES = dedent(
96+
f"""\
97+
Header
98+
{START_LINE}
99+
100+
1.2.3 (2020-12-16)
101+
==================
102+
103+
Features
104+
--------
105+
106+
- Feature 1 (#1024)
107+
108+
- Feature 2 (#1025)
109+
110+
"""
111+
)
112+
ret = _parse_changes(
113+
changes=CHANGES,
114+
changes_file="CHANGES.rst",
115+
version="1.2.3",
116+
start_line=START_LINE,
117+
head_line="{version} \\({date}\\)\n=====+\n?",
118+
fix_issue_regex="",
119+
fix_issue_repl="",
120+
name="name",
121+
)
122+
assert ret == dedent(
123+
"""\
124+
Features
125+
--------
126+
127+
- Feature 1 (#1024)
128+
129+
- Feature 2 (#1025)"""
130+
)
131+
132+
133+
def test_parse_multi_changes() -> None:
134+
CHANGES = dedent(
135+
f"""\
136+
Header
137+
{START_LINE}
138+
139+
1.2.3 (2020-12-16)
140+
==================
141+
142+
Features
143+
--------
144+
145+
- Feature 1 (#1024)
146+
147+
- Feature 2 (#1025)
148+
149+
150+
151+
1.2.2 (2020-12-15)
152+
==================
153+
154+
Bugfixes
155+
--------
156+
"""
157+
)
158+
ret = _parse_changes(
159+
changes=CHANGES,
160+
changes_file="CHANGES.rst",
161+
version="1.2.3",
162+
start_line=START_LINE,
163+
head_line="{version} \\({date}\\)\n=====+\n?",
164+
fix_issue_regex="",
165+
fix_issue_repl="",
166+
name="name",
167+
)
168+
assert ret == dedent(
169+
"""\
170+
Features
171+
--------
172+
173+
- Feature 1 (#1024)
174+
175+
- Feature 2 (#1025)"""
176+
)
177+
178+
179+
def test_parse_fix_issues() -> None:
180+
CHANGES = dedent(
181+
f"""\
182+
Header
183+
{START_LINE}
184+
185+
1.2.3 (2020-12-16)
186+
==================
187+
188+
Features
189+
--------
190+
191+
- Feature 1 `#4603 <https://github.com/aio-libs/aiohttp/issues/4603>`_
192+
"""
193+
)
194+
ret = _parse_changes(
195+
changes=CHANGES,
196+
changes_file="CHANGES.rst",
197+
version="1.2.3",
198+
start_line=START_LINE,
199+
head_line="{version} \\({date}\\)\n=====+\n?",
200+
fix_issue_regex=(
201+
"\n?\\s*`#(\\d+) <https://github.com/aio-libs/aiohttp/issues/\\1>`_"
202+
),
203+
fix_issue_repl=" (#\\1)",
204+
name="name",
205+
)
206+
assert ret == dedent(
207+
"""\
208+
Features
209+
--------
210+
211+
- Feature 1 (#4603)"""
212+
)
213+
214+
215+
def test_parse_with_name() -> None:
216+
CHANGES = dedent(
217+
f"""\
218+
Header
219+
{START_LINE}
220+
221+
Project 1.2.3 (2020-12-16)
222+
==========================
223+
224+
Features
225+
--------
226+
227+
- Feature 1 (#1024)
228+
229+
"""
230+
)
231+
ret = _parse_changes(
232+
changes=CHANGES,
233+
changes_file="CHANGES.rst",
234+
version="1.2.3",
235+
start_line=START_LINE,
236+
head_line="Project {version} \\({date}\\)\n=====+\n?",
237+
fix_issue_regex="",
238+
fix_issue_repl="",
239+
name="name",
240+
)
241+
assert ret == dedent(
242+
"""\
243+
Features
244+
--------
245+
246+
- Feature 1 (#1024)"""
247+
)

0 commit comments

Comments
 (0)