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

1from datetime import date 1abcdefgh

2from pathlib import Path 1abcdefgh

3 

4import pytest 1abcdefgh

5from typer.testing import CliRunner 1abcdefgh

6 

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) 

15 

16runner = CliRunner() 1abcdefgh

17 

18 

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

29 

30 

31def test_update_version_file() -> None: 1abcdefgh

32 content = '__version__ = "0.0.38"\n\nfrom sqlalchemy.engine import create_engine\n' 1OPQRSTUV

33 

34 new_content = update_version_file(content, "0.0.39", Path("sqlmodel/__init__.py")) 1OPQRSTUV

35 

36 assert ( 1OPQRSTUV

37 new_content 

38 == '__version__ = "0.0.39"\n\nfrom sqlalchemy.engine import create_engine\n' 

39 ) 

40 

41 

42def test_update_version_file_requires_newer_version() -> None: 1abcdefgh

43 content = '__version__ = "0.0.38"\n' 1WXYZ0123

44 

45 with pytest.raises(RuntimeError, match="must be greater"): 1WXYZ0123

46 update_version_file(content, "0.0.38", Path("sqlmodel/__init__.py")) 1WXYZ0123

47 

48 

49def test_update_release_notes() -> None: 1abcdefgh

50 content = """# Release Notes 1456789!#

51 

52## Latest Changes 

53 

54### Fixes 

55 

56* Fix something. 

57 

58## 0.0.38 (2026-04-02) 

59 

60### Fixes 

61 

62* Previous fix. 

63""" 

64 

65 new_content = update_release_notes( 1456789!#

66 content, "0.0.39", date(2026, 5, 30), Path("docs/release-notes.md") 

67 ) 

68 

69 assert ( 1456789!#

70 new_content 

71 == """# Release Notes 

72 

73## Latest Changes 

74 

75## 0.0.39 (2026-05-30) 

76 

77### Fixes 

78 

79* Fix something. 

80 

81## 0.0.38 (2026-04-02) 

82 

83### Fixes 

84 

85* Previous fix. 

86""" 

87 ) 

88 

89 

90def test_update_release_notes_rejects_existing_version() -> None: 1abcdefgh

91 content = """# Release Notes 1$%'()*+,

92 

93## Latest Changes 

94 

95## 0.0.39 (2026-05-30) 

96""" 

97 

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 ) 

102 

103 

104def test_get_release_notes_body_with_dated_heading() -> None: 1abcdefgh

105 content = """# Release Notes 1-./:;=?@

106 

107## Latest Changes 

108 

109## 0.0.39 (2026-05-30) 

110 

111### Fixes 

112 

113* Fix something. 

114 

115## 0.0.38 (2026-04-02) 

116 

117### Fixes 

118 

119* Previous fix. 

120""" 

121 

122 body = get_release_notes_body(content, "0.0.39", Path("docs/release-notes.md")) 1-./:;=?@

123 

124 assert ( 1-./:;=?@

125 body 

126 == """### Fixes 

127 

128* Fix something. 

129""" 

130 ) 

131 

132 

133def test_get_release_notes_body_with_plain_heading() -> None: 1abcdefgh

134 content = """# Release Notes 1[]^_`{|}

135 

136## Latest Changes 

137 

138## 0.0.39 

139 

140### Fixes 

141 

142* Fix something. 

143""" 

144 

145 body = get_release_notes_body(content, "0.0.39", Path("docs/release-notes.md")) 1[]^_`{|}

146 

147 assert body == "### Fixes\n\n* Fix something.\n" 1[]^_`{|}

148 

149 

150def test_get_release_notes_body_allows_non_version_h2_content() -> None: 1abcdefgh

151 content = """# Release Notes 2~ abbbcbdbebfbgb

152 

153## Latest Changes 

154 

155## 0.0.39 

156 

157## Highlights 

158 

159* Fix something. 

160 

161## 0.0.38 

162 

163* Previous fix. 

164""" 

165 

166 body = get_release_notes_body(content, "0.0.39", Path("docs/release-notes.md")) 2~ abbbcbdbebfbgb

167 

168 assert body == "## Highlights\n\n* Fix something.\n" 2~ abbbcbdbebfbgb

169 

170 

171def test_get_release_notes_body_requires_version_section() -> None: 1abcdefgh

172 content = "# Release Notes\n\n## Latest Changes\n" 2hbibjbkblbmbnbob

173 

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

176 

177 

178def test_get_release_notes_body_requires_non_empty_section() -> None: 1abcdefgh

179 content = """# Release Notes 2pbqbrbsbtbubvbwb

180 

181## Latest Changes 

182 

183## 0.0.39 

184 

185## 0.0.38 

186 

187* Previous fix. 

188""" 

189 

190 with pytest.raises(RuntimeError, match="is empty"): 2pbqbrbsbtbubvbwb

191 get_release_notes_body(content, "0.0.39", Path("docs/release-notes.md")) 2pbqbrbsbtbubvbwb

192 

193 

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 

201 

202## Latest Changes 

203 

204### Fixes 

205 

206* Fix something. 

207""" 

208 ) 

209 

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 ) 

223 

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

228 

229 

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

241 

242 result = runner.invoke(app, ["prepare"]) 1ijklmnop

243 

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

248 

249 

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

254 

255 result = runner.invoke( 1GHIJKLMN

256 app, 

257 [ 

258 "current-version", 

259 "--version-file", 

260 str(version_file), 

261 ], 

262 ) 

263 

264 assert result.exit_code == 0, result.output 1GHIJKLMN

265 assert result.output == "0.0.39\n" 1GHIJKLMN

266 

267 

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 

275 

276## Latest Changes 

277 

278## 0.0.39 (2026-05-30) 

279 

280### Fixes 

281 

282* Fix something. 

283""" 

284 ) 

285 

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 ) 

296 

297 assert result.exit_code == 0, result.output 1yzABCDEF

298 assert result.output == "### Fixes\n\n* Fix something.\n" 1yzABCDEF