File: check-changelog-entries.py

package info (click to toggle)
python-pytest-shell-utilities 1.9.7-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 580 kB
  • sloc: python: 2,998; makefile: 18
file content (127 lines) | stat: -rwxr-xr-x 4,622 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#!/usr/bin/env python3
# Copyright 2021-2024 VMware, Inc.
# SPDX-License-Identifier: Apache-2.0
#
# pylint: disable=invalid-name,missing-module-docstring,missing-function-docstring
import argparse
import pathlib
import re
import sys

CODE_ROOT = pathlib.Path(__file__).resolve().parent.parent
CHANGELOG_ENTRIES_PATH = CODE_ROOT / "changelog"
CHANGELOG_LIKE_RE = re.compile(r"([\d]+)\.([a-z]+)(\.rst)?$")
CHANGELOG_EXTENSIONS = (
    "breaking",
    "deprecation",
    "feature",
    "improvement",
    "bugfix",
    "doc",
    "trivial",
)
CHANGELOG_ENTRY_REREX = r"^[\d]+\.({})\.rst$".format("|".join(CHANGELOG_EXTENSIONS))
CHANGELOG_ENTRY_RE = re.compile(CHANGELOG_ENTRY_REREX)


def check_changelog_entries(files):

    exitcode = 0
    for entry in files:
        path = pathlib.Path(entry).resolve()
        # Is it under changelog/
        try:
            path.relative_to(CHANGELOG_ENTRIES_PATH)
            if path.name in (".gitkeep", ".gitignore", "_template.rst", __name__):
                # These files should be ignored
                continue
            # Is it named properly
            if not CHANGELOG_ENTRY_RE.match(path.name):
                # Does it end in .rst
                if path.suffix != ".rst":
                    exitcode = 1
                    print(
                        "The changelog entry '{}' should have '.rst' as it's file extension".format(
                            path.relative_to(CODE_ROOT),
                        ),
                        file=sys.stderr,
                        flush=True,
                    )
                    continue
                print(
                    "The changelog entry '{}' should have one of the following extensions: {}.".format(
                        path.relative_to(CODE_ROOT),
                        ", ".join(repr(ext) for ext in CHANGELOG_EXTENSIONS),
                    ),
                    file=sys.stderr,
                    flush=True,
                )
                exitcode = 1
                continue
            check_changelog_entry_contents(path)
        except ValueError:
            # Not under changelog/, carry on checking
            # Is it a changelog entry
            if CHANGELOG_ENTRY_RE.match(path.name):
                # So, this IS a changelog entry, but it's misplaced....
                exitcode = 1
                print(
                    "The changelog entry '{}' should be placed under '{}/', not '{}'".format(
                        path.relative_to(CODE_ROOT),
                        CHANGELOG_ENTRIES_PATH.relative_to(CODE_ROOT),
                        path.relative_to(CODE_ROOT).parent,
                    ),
                    file=sys.stderr,
                    flush=True,
                )
                continue
            elif CHANGELOG_LIKE_RE.match(path.name) and not CHANGELOG_ENTRY_RE.match(path.name):
                # Does it look like a changelog entry
                print(
                    "The changelog entry '{}' should have one of the following extensions: {}.".format(
                        path.relative_to(CODE_ROOT),
                        ", ".join(repr(ext) for ext in CHANGELOG_EXTENSIONS),
                    ),
                    file=sys.stderr,
                    flush=True,
                )
                exitcode = 1
                continue

            elif not CHANGELOG_LIKE_RE.match(path.name) and not CHANGELOG_ENTRY_RE.match(path.name):
                # Does not look like, and it's not a changelog entry
                continue
            # Does it end in .rst
            if path.suffix != ".rst":
                exitcode = 1
                print(
                    "The changelog entry '{}' should have '.rst' as it's file extension".format(
                        path.relative_to(CODE_ROOT),
                    ),
                    file=sys.stderr,
                    flush=True,
                )
    return exitcode


def check_changelog_entry_contents(entry):
    contents = entry.read_text().splitlines()
    if len(contents) > 1:
        # More than one line.
        # If the second line starts with '*' it's a bullet list and we need to add an
        # empty line before it.
        if contents[1].strip().startswith("*"):
            contents.insert(1, "")
    entry.write_text("{}\n".format("\n".join(contents)))


def main(argv):
    parser = argparse.ArgumentParser(prog=__name__)
    parser.add_argument("files", nargs="+")

    options = parser.parse_args(argv)
    return check_changelog_entries(options.files)


if __name__ == "__main__":
    sys.exit(main(sys.argv))