|
| 1 | +# -*- coding: utf-8 -*- |
| 2 | +"""Which changelog a new one gets compared against. |
| 3 | +
|
| 4 | +`write_changelog` asks `find_previous_version` what the previous release was, |
| 5 | +and the answer comes from the file names in `changelogs/` alone. That made the |
| 6 | +naming of those files load-bearing: the pattern used to be digits and dots, so |
| 7 | +a version carrying a release level -- 3.14.7.1b1 -- matched nothing and the |
| 8 | +comparison skipped straight past it. PEP 440 orders those versions correctly |
| 9 | +already (3.14.7.0 < 3.14.7.1b1 < 3.14.7.1); only the file name pattern did not. |
| 10 | +
|
| 11 | +The layouts here are synthetic: the functions care about names, not contents, |
| 12 | +so an empty file under the right name exercises the real code. |
| 13 | +""" |
| 14 | +from pathlib import Path |
| 15 | + |
| 16 | +import pytest |
| 17 | + |
| 18 | +from wppm.diff import changelog_versions, copy_changelogs, find_previous_version |
| 19 | + |
| 20 | + |
| 21 | +def changelogs(searchdir: Path, *names: str) -> Path: |
| 22 | + """A changelogs directory holding exactly these files.""" |
| 23 | + searchdir.mkdir(parents=True, exist_ok=True) |
| 24 | + for name in names: |
| 25 | + (searchdir / name).write_text("", encoding="utf-8") |
| 26 | + return searchdir |
| 27 | + |
| 28 | + |
| 29 | +class TestFindPreviousVersion: |
| 30 | + def test_picks_the_nearest_earlier_version(self, tmp_path): |
| 31 | + searchdir = changelogs( |
| 32 | + tmp_path, |
| 33 | + "WinPythondot-64bit-3.13.15.0.md", |
| 34 | + "WinPythondot-64bit-3.14.7.0.md", |
| 35 | + "WinPythondot-64bit-3.14.7.1.md", |
| 36 | + ) |
| 37 | + assert find_previous_version("3.14.7.1", searchdir, "dot") == "3.14.7.0" |
| 38 | + |
| 39 | + def test_a_release_level_is_visible_and_ordered(self, tmp_path): |
| 40 | + """The b1 sits between .0 and .1, so it is what .1 compares against. |
| 41 | +
|
| 42 | + This is the case the old digits-and-dots pattern dropped: it would |
| 43 | + have answered 3.14.7.0 and reported a beta's worth of changes twice. |
| 44 | + """ |
| 45 | + searchdir = changelogs( |
| 46 | + tmp_path, |
| 47 | + "WinPythondot-64bit-3.14.7.0.md", |
| 48 | + "WinPythondot-64bit-3.14.7.1b1.md", |
| 49 | + ) |
| 50 | + assert find_previous_version("3.14.7.1", searchdir, "dot") == "3.14.7.1b1" |
| 51 | + |
| 52 | + def test_a_release_level_compares_against_the_release_before_it(self, tmp_path): |
| 53 | + searchdir = changelogs( |
| 54 | + tmp_path, |
| 55 | + "WinPythondot-64bit-3.14.7.0.md", |
| 56 | + "WinPythondot-64bit-3.14.7.1b1.md", |
| 57 | + ) |
| 58 | + assert find_previous_version("3.14.7.1b1", searchdir, "dot") == "3.14.7.0" |
| 59 | + |
| 60 | + @pytest.mark.parametrize("level", ["b1", "b2", "rc1", "a1", "post1"]) |
| 61 | + def test_every_level_winpython_has_used_parses(self, tmp_path, level): |
| 62 | + searchdir = changelogs( |
| 63 | + tmp_path, |
| 64 | + "WinPythondot-64bit-3.14.7.0.md", |
| 65 | + f"WinPythondot-64bit-3.14.7.1{level}.md", |
| 66 | + ) |
| 67 | + assert find_previous_version("3.14.8.0", searchdir, "dot") == f"3.14.7.1{level}" |
| 68 | + |
| 69 | + def test_history_companions_are_never_the_answer(self, tmp_path): |
| 70 | + """`_History.md` sits beside every changelog and is not one.""" |
| 71 | + searchdir = changelogs( |
| 72 | + tmp_path, |
| 73 | + "WinPythondot-64bit-3.14.7.0.md", |
| 74 | + "WinPythondot-64bit-3.14.7.0_History.md", |
| 75 | + ) |
| 76 | + assert find_previous_version("3.14.7.1", searchdir, "dot") == "3.14.7.0" |
| 77 | + |
| 78 | + def test_unrelated_files_are_ignored(self, tmp_path): |
| 79 | + searchdir = changelogs( |
| 80 | + tmp_path, |
| 81 | + "WinPythondot-64bit-3.14.7.0.md", |
| 82 | + "pylock.64-3_14_7_0dot.toml", |
| 83 | + "requir.64-3_14_7_0dot.txt", |
| 84 | + "README.md", |
| 85 | + ) |
| 86 | + assert find_previous_version("3.14.7.1", searchdir, "dot") == "3.14.7.0" |
| 87 | + |
| 88 | + def test_the_old_txt_changelogs_still_count(self, tmp_path): |
| 89 | + searchdir = changelogs(tmp_path, "WinPython-64bit-2.7.10.1.txt") |
| 90 | + assert find_previous_version("2.7.10.2", searchdir, "") == "2.7.10.1" |
| 91 | + |
| 92 | + def test_nothing_earlier_returns_the_target_itself(self, tmp_path): |
| 93 | + """The documented fallback: comparing a version against itself is empty.""" |
| 94 | + searchdir = changelogs(tmp_path, "WinPythondot-64bit-3.14.7.1.md") |
| 95 | + assert find_previous_version("3.14.7.1", searchdir, "dot") == "3.14.7.1" |
| 96 | + |
| 97 | + def test_flavors_do_not_see_each_other(self, tmp_path): |
| 98 | + """dot and slim ship different package sets; a cross-flavor diff is noise.""" |
| 99 | + searchdir = changelogs( |
| 100 | + tmp_path, |
| 101 | + "WinPythondot-64bit-3.14.7.0.md", |
| 102 | + "WinPythonslim-64bit-3.14.7.1.md", |
| 103 | + ) |
| 104 | + assert find_previous_version("3.14.7.2", searchdir, "dot") == "3.14.7.0" |
| 105 | + assert find_previous_version("3.14.7.2", searchdir, "slim") == "3.14.7.1" |
| 106 | + |
| 107 | + def test_a_flavor_is_not_a_prefix_of_another(self, tmp_path): |
| 108 | + """dot must not match dotf: the free-threaded build is a separate line.""" |
| 109 | + searchdir = changelogs( |
| 110 | + tmp_path, |
| 111 | + "WinPythondot-64bit-3.14.7.0.md", |
| 112 | + "WinPythondotf-64bit-3.14.7.1.md", |
| 113 | + ) |
| 114 | + assert find_previous_version("3.14.7.2", searchdir, "dot") == "3.14.7.0" |
| 115 | + assert find_previous_version("3.14.7.2", searchdir, "dotf") == "3.14.7.1" |
| 116 | + |
| 117 | + def test_the_unflavored_name_does_not_match_flavored_files(self, tmp_path): |
| 118 | + searchdir = changelogs( |
| 119 | + tmp_path, |
| 120 | + "WinPython-64bit-3.9.8.0.md", |
| 121 | + "WinPythondot-64bit-3.14.7.0.md", |
| 122 | + ) |
| 123 | + assert find_previous_version("3.15.0.0", searchdir, "") == "3.9.8.0" |
| 124 | + |
| 125 | + def test_architecture_separates_the_lines(self, tmp_path): |
| 126 | + searchdir = changelogs( |
| 127 | + tmp_path, |
| 128 | + "WinPythondot-32bit-3.9.0.0.md", |
| 129 | + "WinPythondot-64bit-3.8.0.0.md", |
| 130 | + ) |
| 131 | + assert find_previous_version("3.14.0.0", searchdir, "dot", 64) == "3.8.0.0" |
| 132 | + assert find_previous_version("3.14.0.0", searchdir, "dot", 32) == "3.9.0.0" |
| 133 | + |
| 134 | + |
| 135 | +class TestChangelogVersions: |
| 136 | + def test_reports_the_file_each_version_came_from(self, tmp_path): |
| 137 | + searchdir = changelogs( |
| 138 | + tmp_path, |
| 139 | + "WinPythondot-64bit-3.14.7.1b1.md", |
| 140 | + "WinPythondot-64bit-3.14.7.0_History.md", |
| 141 | + ) |
| 142 | + found = changelog_versions(searchdir, "dot") |
| 143 | + assert [(raw, name) for _, raw, name in found] == [ |
| 144 | + ("3.14.7.1b1", "WinPythondot-64bit-3.14.7.1b1.md") |
| 145 | + ] |
| 146 | + |
| 147 | + |
| 148 | +class TestCopyChangelogs: |
| 149 | + @pytest.fixture |
| 150 | + def dest(self, tmp_path): |
| 151 | + target = tmp_path / "dest" |
| 152 | + target.mkdir() |
| 153 | + return target |
| 154 | + |
| 155 | + def test_takes_the_whole_major_minor_including_levels(self, tmp_path, dest): |
| 156 | + src = changelogs( |
| 157 | + tmp_path / "src", |
| 158 | + "WinPythondot-64bit-3.14.7.0.md", |
| 159 | + "WinPythondot-64bit-3.14.7.1b1.md", |
| 160 | + "WinPythondot-64bit-3.13.15.0.md", |
| 161 | + ) |
| 162 | + copy_changelogs("3.14.7.1", src, "dot", 64, dest) |
| 163 | + assert sorted(p.name for p in dest.iterdir()) == [ |
| 164 | + "WinPythondot-64bit-3.14.7.0.md", |
| 165 | + "WinPythondot-64bit-3.14.7.1b1.md", |
| 166 | + ] |
| 167 | + |
| 168 | + def test_a_minor_is_not_a_string_prefix(self, tmp_path, dest): |
| 169 | + """Selecting on the parsed version stops 3.1 from dragging in 3.15.""" |
| 170 | + src = changelogs( |
| 171 | + tmp_path / "src", |
| 172 | + "WinPythondot-64bit-3.1.0.0.md", |
| 173 | + "WinPythondot-64bit-3.15.0.5.md", |
| 174 | + ) |
| 175 | + copy_changelogs("3.1.0.0", src, "dot", 64, dest) |
| 176 | + assert [p.name for p in dest.iterdir()] == ["WinPythondot-64bit-3.1.0.0.md"] |
| 177 | + |
| 178 | + def test_history_companions_are_not_copied(self, tmp_path, dest): |
| 179 | + src = changelogs( |
| 180 | + tmp_path / "src", |
| 181 | + "WinPythondot-64bit-3.14.7.0.md", |
| 182 | + "WinPythondot-64bit-3.14.7.0_History.md", |
| 183 | + ) |
| 184 | + copy_changelogs("3.14.7.0", src, "dot", 64, dest) |
| 185 | + assert [p.name for p in dest.iterdir()] == ["WinPythondot-64bit-3.14.7.0.md"] |
0 commit comments