Coverage for tests / test_prepare_release.py: 100%
88 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-06-10 09:40 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2026-06-10 09:40 +0000
1from datetime import date 1abcdefgh
2from pathlib import Path 1abcdefgh
4import pytest 1abcdefgh
5from typer.testing import CliRunner 1abcdefgh
7from scripts.prepare_release import ( 1abcdefgh
8 BumpType,
9 app,
10 bump_version,
11 get_release_notes_body,
12 update_release_notes,
13 update_version_file,
14)
16runner = CliRunner() 1abcdefgh
19@pytest.mark.parametrize( 1abcdefgh
20 ("current_version", "bump", "new_version"),
21 [
22 ("0.0.38", "major", "1.0.0"),
23 ("0.0.38", "minor", "0.1.0"),
24 ("0.0.38", "patch", "0.0.39"),
25 ],
26)
27def test_bump_version(current_version: str, bump: BumpType, new_version: str) -> None: 1abcdefgh
28 assert bump_version(current_version, bump) == new_version 2xbybzbAbBbCbDbEb
31def test_update_version_file() -> None: 1abcdefgh
32 content = '__version__ = "0.0.38"\n\nfrom sqlalchemy.engine import create_engine\n' 1OPQRSTUV
34 new_content = update_version_file(content, "0.0.39", Path("sqlmodel/__init__.py")) 1OPQRSTUV
36 assert ( 1OPQRSTUV
37 new_content
38 == '__version__ = "0.0.39"\n\nfrom sqlalchemy.engine import create_engine\n'
39 )
42def test_update_version_file_requires_newer_version() -> None: 1abcdefgh
43 content = '__version__ = "0.0.38"\n' 1WXYZ0123
45 with pytest.raises(RuntimeError, match="must be greater"): 1WXYZ0123
46 update_version_file(content, "0.0.38", Path("sqlmodel/__init__.py")) 1WXYZ0123
49def test_update_release_notes() -> None: 1abcdefgh
50 content = """# Release Notes 1456789!#
52## Latest Changes
54### Fixes
56* Fix something.
58## 0.0.38 (2026-04-02)
60### Fixes
62* Previous fix.
63"""
65 new_content = update_release_notes( 1456789!#
66 content, "0.0.39", date(2026, 5, 30), Path("docs/release-notes.md")
67 )
69 assert ( 1456789!#
70 new_content
71 == """# Release Notes
73## Latest Changes
75## 0.0.39 (2026-05-30)
77### Fixes
79* Fix something.
81## 0.0.38 (2026-04-02)
83### Fixes
85* Previous fix.
86"""
87 )
90def test_update_release_notes_rejects_existing_version() -> None: 1abcdefgh
91 content = """# Release Notes 1$%'()*+,
93## Latest Changes
95## 0.0.39 (2026-05-30)
96"""
98 with pytest.raises(RuntimeError, match="already contain"): 1$%'()*+,
99 update_release_notes( 1$%'()*+,
100 content, "0.0.39", date(2026, 5, 30), Path("docs/release-notes.md")
101 )
104def test_get_release_notes_body_with_dated_heading() -> None: 1abcdefgh
105 content = """# Release Notes 1-./:;=?@
107## Latest Changes
109## 0.0.39 (2026-05-30)
111### Fixes
113* Fix something.
115## 0.0.38 (2026-04-02)
117### Fixes
119* Previous fix.
120"""
122 body = get_release_notes_body(content, "0.0.39", Path("docs/release-notes.md")) 1-./:;=?@
124 assert ( 1-./:;=?@
125 body
126 == """### Fixes
128* Fix something.
129"""
130 )
133def test_get_release_notes_body_with_plain_heading() -> None: 1abcdefgh
134 content = """# Release Notes 1[]^_`{|}
136## Latest Changes
138## 0.0.39
140### Fixes
142* Fix something.
143"""
145 body = get_release_notes_body(content, "0.0.39", Path("docs/release-notes.md")) 1[]^_`{|}
147 assert body == "### Fixes\n\n* Fix something.\n" 1[]^_`{|}
150def test_get_release_notes_body_allows_non_version_h2_content() -> None: 1abcdefgh
151 content = """# Release Notes 2~ abbbcbdbebfbgb
153## Latest Changes
155## 0.0.39
157## Highlights
159* Fix something.
161## 0.0.38
163* Previous fix.
164"""
166 body = get_release_notes_body(content, "0.0.39", Path("docs/release-notes.md")) 2~ abbbcbdbebfbgb
168 assert body == "## Highlights\n\n* Fix something.\n" 2~ abbbcbdbebfbgb
171def test_get_release_notes_body_requires_version_section() -> None: 1abcdefgh
172 content = "# Release Notes\n\n## Latest Changes\n" 2hbibjbkblbmbnbob
174 with pytest.raises(RuntimeError, match="Could not find"): 2hbibjbkblbmbnbob
175 get_release_notes_body(content, "0.0.39", Path("docs/release-notes.md")) 2hbibjbkblbmbnbob
178def test_get_release_notes_body_requires_non_empty_section() -> None: 1abcdefgh
179 content = """# Release Notes 2pbqbrbsbtbubvbwb
181## Latest Changes
183## 0.0.39
185## 0.0.38
187* Previous fix.
188"""
190 with pytest.raises(RuntimeError, match="is empty"): 2pbqbrbsbtbubvbwb
191 get_release_notes_body(content, "0.0.39", Path("docs/release-notes.md")) 2pbqbrbsbtbubvbwb
194def test_cli_updates_configured_files(tmp_path: Path) -> None: 1abcdefgh
195 version_file = tmp_path / "sqlmodel" / "__init__.py" 1qrstuvwx
196 version_file.parent.mkdir() 1qrstuvwx
197 version_file.write_text('__version__ = "0.0.38"\n') 1qrstuvwx
198 release_notes_file = tmp_path / "release-notes.md" 1qrstuvwx
199 release_notes_file.write_text( 1qrstuvwx
200 """# Release Notes
202## Latest Changes
204### Fixes
206* Fix something.
207"""
208 )
210 result = runner.invoke( 1qrstuvwx
211 app,
212 [
213 "prepare",
214 "patch",
215 "--version-file",
216 str(version_file),
217 "--release-notes-file",
218 str(release_notes_file),
219 "--date",
220 "2026-05-30",
221 ],
222 )
224 assert result.exit_code == 0, result.output 1qrstuvwx
225 assert "Prepared release 0.0.39 (2026-05-30)" in result.output 1qrstuvwx
226 assert version_file.read_text() == '__version__ = "0.0.39"\n' 1qrstuvwx
227 assert "## 0.0.39 (2026-05-30)" in release_notes_file.read_text() 1qrstuvwx
230def test_cli_accepts_env_vars(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: 1abcdefgh
231 version_file = tmp_path / "sqlmodel" / "__init__.py" 1ijklmnop
232 version_file.parent.mkdir() 1ijklmnop
233 version_file.write_text('__version__ = "0.0.38"\n') 1ijklmnop
234 release_notes_file = tmp_path / "docs" / "release-notes.md" 1ijklmnop
235 release_notes_file.parent.mkdir() 1ijklmnop
236 release_notes_file.write_text("# Release Notes\n\n## Latest Changes\n") 1ijklmnop
237 monkeypatch.setenv("PREPARE_RELEASE_BUMP", "minor") 1ijklmnop
238 monkeypatch.setenv("PREPARE_RELEASE_VERSION_FILE", str(version_file)) 1ijklmnop
239 monkeypatch.setenv("PREPARE_RELEASE_RELEASE_NOTES_FILE", str(release_notes_file)) 1ijklmnop
240 monkeypatch.setenv("PREPARE_RELEASE_DATE", "2026-05-30") 1ijklmnop
242 result = runner.invoke(app, ["prepare"]) 1ijklmnop
244 assert result.exit_code == 0, result.output 1ijklmnop
245 assert "Prepared release 0.1.0 (2026-05-30)" in result.output 1ijklmnop
246 assert version_file.read_text() == '__version__ = "0.1.0"\n' 1ijklmnop
247 assert "## 0.1.0 (2026-05-30)" in release_notes_file.read_text() 1ijklmnop
250def test_cli_prints_current_version(tmp_path: Path) -> None: 1abcdefgh
251 version_file = tmp_path / "sqlmodel" / "__init__.py" 1GHIJKLMN
252 version_file.parent.mkdir() 1GHIJKLMN
253 version_file.write_text('__version__ = "0.0.39"\n') 1GHIJKLMN
255 result = runner.invoke( 1GHIJKLMN
256 app,
257 [
258 "current-version",
259 "--version-file",
260 str(version_file),
261 ],
262 )
264 assert result.exit_code == 0, result.output 1GHIJKLMN
265 assert result.output == "0.0.39\n" 1GHIJKLMN
268def test_cli_prints_release_notes(tmp_path: Path) -> None: 1abcdefgh
269 version_file = tmp_path / "sqlmodel" / "__init__.py" 1yzABCDEF
270 version_file.parent.mkdir() 1yzABCDEF
271 version_file.write_text('__version__ = "0.0.39"\n') 1yzABCDEF
272 release_notes_file = tmp_path / "release-notes.md" 1yzABCDEF
273 release_notes_file.write_text( 1yzABCDEF
274 """# Release Notes
276## Latest Changes
278## 0.0.39 (2026-05-30)
280### Fixes
282* Fix something.
283"""
284 )
286 result = runner.invoke( 1yzABCDEF
287 app,
288 [
289 "release-notes",
290 "--version-file",
291 str(version_file),
292 "--release-notes-file",
293 str(release_notes_file),
294 ],
295 )
297 assert result.exit_code == 0, result.output 1yzABCDEF
298 assert result.output == "### Fixes\n\n* Fix something.\n" 1yzABCDEF