root / autotools / check-news @ 0500f6fd
History | View | Annotate | Download (5.1 kB)
1 | 7385c51d | Michael Hanselmann | #!/usr/bin/python |
---|---|---|---|
2 | 7385c51d | Michael Hanselmann | # |
3 | 7385c51d | Michael Hanselmann | |
4 | 1657353c | Michael Hanselmann | # Copyright (C) 2011, 2012, 2013 Google Inc. |
5 | 7385c51d | Michael Hanselmann | # |
6 | 7385c51d | Michael Hanselmann | # This program is free software; you can redistribute it and/or modify |
7 | 7385c51d | Michael Hanselmann | # it under the terms of the GNU General Public License as published by |
8 | 7385c51d | Michael Hanselmann | # the Free Software Foundation; either version 2 of the License, or |
9 | 7385c51d | Michael Hanselmann | # (at your option) any later version. |
10 | 7385c51d | Michael Hanselmann | # |
11 | 7385c51d | Michael Hanselmann | # This program is distributed in the hope that it will be useful, but |
12 | 7385c51d | Michael Hanselmann | # WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | 7385c51d | Michael Hanselmann | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | 7385c51d | Michael Hanselmann | # General Public License for more details. |
15 | 7385c51d | Michael Hanselmann | # |
16 | 7385c51d | Michael Hanselmann | # You should have received a copy of the GNU General Public License |
17 | 7385c51d | Michael Hanselmann | # along with this program; if not, write to the Free Software |
18 | 7385c51d | Michael Hanselmann | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
19 | 7385c51d | Michael Hanselmann | # 02110-1301, USA. |
20 | 7385c51d | Michael Hanselmann | |
21 | 7385c51d | Michael Hanselmann | |
22 | 7385c51d | Michael Hanselmann | """Script to check NEWS file. |
23 | 7385c51d | Michael Hanselmann | |
24 | 7385c51d | Michael Hanselmann | """ |
25 | 7385c51d | Michael Hanselmann | |
26 | f0fa05ac | Iustin Pop | # pylint: disable=C0103 |
27 | f0fa05ac | Iustin Pop | # [C0103] Invalid name |
28 | f0fa05ac | Iustin Pop | |
29 | 7385c51d | Michael Hanselmann | import sys |
30 | 7385c51d | Michael Hanselmann | import time |
31 | 7385c51d | Michael Hanselmann | import datetime |
32 | 7385c51d | Michael Hanselmann | import locale |
33 | 7385c51d | Michael Hanselmann | import fileinput |
34 | 7385c51d | Michael Hanselmann | import re |
35 | d466fd8b | Guido Trotter | import os |
36 | 7385c51d | Michael Hanselmann | |
37 | 7385c51d | Michael Hanselmann | |
38 | 7385c51d | Michael Hanselmann | DASHES_RE = re.compile(r"^\s*-+\s*$") |
39 | 7385c51d | Michael Hanselmann | RELEASED_RE = re.compile(r"^\*\(Released (?P<day>[A-Z][a-z]{2})," |
40 | 7385c51d | Michael Hanselmann | r" (?P<date>.+)\)\*$") |
41 | 7385c51d | Michael Hanselmann | UNRELEASED_RE = re.compile(r"^\*\(unreleased\)\*$") |
42 | 77721d8b | Michele Tartara | VERSION_RE = re.compile(r"^Version (\d+(\.\d+)+( (alpha|beta|rc)\d+)?)$") |
43 | 7385c51d | Michael Hanselmann | |
44 | 1657353c | Michael Hanselmann | #: How many days release timestamps may be in the future |
45 | 1657353c | Michael Hanselmann | TIMESTAMP_FUTURE_DAYS_MAX = 3 |
46 | 1657353c | Michael Hanselmann | |
47 | f0fa05ac | Iustin Pop | errors = [] |
48 | f0fa05ac | Iustin Pop | |
49 | f0fa05ac | Iustin Pop | |
50 | f0fa05ac | Iustin Pop | def Error(msg): |
51 | f0fa05ac | Iustin Pop | """Log an error for later display. |
52 | f0fa05ac | Iustin Pop | |
53 | f0fa05ac | Iustin Pop | """ |
54 | f0fa05ac | Iustin Pop | errors.append(msg) |
55 | f0fa05ac | Iustin Pop | |
56 | f0fa05ac | Iustin Pop | |
57 | f0fa05ac | Iustin Pop | def ReqNLines(req, count_empty, lineno, line): |
58 | dadc7864 | Michele Tartara | """Check if we have N empty lines before the current one. |
59 | f0fa05ac | Iustin Pop | |
60 | f0fa05ac | Iustin Pop | """ |
61 | f0fa05ac | Iustin Pop | if count_empty < req: |
62 | f0fa05ac | Iustin Pop | Error("Line %s: Missing empty line(s) before %s," |
63 | f0fa05ac | Iustin Pop | " %d needed but got only %d" % |
64 | f0fa05ac | Iustin Pop | (lineno, line, req, count_empty)) |
65 | f0fa05ac | Iustin Pop | if count_empty > req: |
66 | f0fa05ac | Iustin Pop | Error("Line %s: Too many empty lines before %s," |
67 | f0fa05ac | Iustin Pop | " %d needed but got %d" % |
68 | f0fa05ac | Iustin Pop | (lineno, line, req, count_empty)) |
69 | f0fa05ac | Iustin Pop | |
70 | 7385c51d | Michael Hanselmann | |
71 | 77721d8b | Michele Tartara | def IsAlphaVersion(version): |
72 | 77721d8b | Michele Tartara | return "alpha" in version |
73 | 77721d8b | Michele Tartara | |
74 | 77721d8b | Michele Tartara | |
75 | 77721d8b | Michele Tartara | def UpdateAllowUnreleased(allow_unreleased, version_match, release): |
76 | 77721d8b | Michele Tartara | if not allow_unreleased: |
77 | 77721d8b | Michele Tartara | return False |
78 | 77721d8b | Michele Tartara | if IsAlphaVersion(release): |
79 | 77721d8b | Michele Tartara | return True |
80 | 77721d8b | Michele Tartara | version = version_match.group(1) |
81 | 77721d8b | Michele Tartara | if version == release: |
82 | 77721d8b | Michele Tartara | return False |
83 | 77721d8b | Michele Tartara | return True |
84 | 77721d8b | Michele Tartara | |
85 | 77721d8b | Michele Tartara | |
86 | 7385c51d | Michael Hanselmann | def main(): |
87 | 7385c51d | Michael Hanselmann | # Ensure "C" locale is used |
88 | 7385c51d | Michael Hanselmann | curlocale = locale.getlocale() |
89 | 7385c51d | Michael Hanselmann | if curlocale != (None, None): |
90 | f0fa05ac | Iustin Pop | Error("Invalid locale %s" % curlocale) |
91 | 7385c51d | Michael Hanselmann | |
92 | d466fd8b | Guido Trotter | # Get the release version, but replace "~" with " " as the version |
93 | d466fd8b | Guido Trotter | # in the NEWS file uses spaces for beta and rc releases. |
94 | d466fd8b | Guido Trotter | release = os.environ.get('RELEASE', "").replace("~", " ") |
95 | d466fd8b | Guido Trotter | |
96 | 7385c51d | Michael Hanselmann | prevline = None |
97 | 7385c51d | Michael Hanselmann | expect_date = False |
98 | 51ef5fe0 | Guido Trotter | count_empty = 0 |
99 | d466fd8b | Guido Trotter | allow_unreleased = True |
100 | d466fd8b | Guido Trotter | found_versions = set() |
101 | 7385c51d | Michael Hanselmann | |
102 | 7385c51d | Michael Hanselmann | for line in fileinput.input(): |
103 | 7385c51d | Michael Hanselmann | line = line.rstrip("\n") |
104 | 7385c51d | Michael Hanselmann | |
105 | d466fd8b | Guido Trotter | version_match = VERSION_RE.match(line) |
106 | d466fd8b | Guido Trotter | if version_match: |
107 | f0fa05ac | Iustin Pop | ReqNLines(2, count_empty, fileinput.filelineno(), line) |
108 | d466fd8b | Guido Trotter | version = version_match.group(1) |
109 | d466fd8b | Guido Trotter | if version in found_versions: |
110 | d466fd8b | Guido Trotter | Error("Line %s: Duplicate release %s found" % |
111 | d466fd8b | Guido Trotter | (fileinput.filelineno(), version)) |
112 | d466fd8b | Guido Trotter | found_versions.add(version) |
113 | 77721d8b | Michele Tartara | allow_unreleased = UpdateAllowUnreleased(allow_unreleased, version_match, |
114 | 77721d8b | Michele Tartara | release) |
115 | d466fd8b | Guido Trotter | |
116 | d466fd8b | Guido Trotter | unreleased_match = UNRELEASED_RE.match(line) |
117 | d466fd8b | Guido Trotter | if unreleased_match and not allow_unreleased: |
118 | d466fd8b | Guido Trotter | Error("Line %s: Unreleased version after current release %s" % |
119 | d466fd8b | Guido Trotter | (fileinput.filelineno(), release)) |
120 | d466fd8b | Guido Trotter | |
121 | d466fd8b | Guido Trotter | if unreleased_match or RELEASED_RE.match(line): |
122 | f0fa05ac | Iustin Pop | ReqNLines(1, count_empty, fileinput.filelineno(), line) |
123 | 51ef5fe0 | Guido Trotter | |
124 | 51ef5fe0 | Guido Trotter | if line: |
125 | 51ef5fe0 | Guido Trotter | count_empty = 0 |
126 | 51ef5fe0 | Guido Trotter | else: |
127 | 51ef5fe0 | Guido Trotter | count_empty += 1 |
128 | 51ef5fe0 | Guido Trotter | |
129 | 7385c51d | Michael Hanselmann | if DASHES_RE.match(line): |
130 | 51ef5fe0 | Guido Trotter | if not VERSION_RE.match(prevline): |
131 | f0fa05ac | Iustin Pop | Error("Line %s: Invalid title" % |
132 | f0fa05ac | Iustin Pop | (fileinput.filelineno() - 1)) |
133 | 51ef5fe0 | Guido Trotter | if len(line) != len(prevline): |
134 | f0fa05ac | Iustin Pop | Error("Line %s: Invalid dashes length" % |
135 | f0fa05ac | Iustin Pop | (fileinput.filelineno())) |
136 | 7385c51d | Michael Hanselmann | expect_date = True |
137 | 7385c51d | Michael Hanselmann | |
138 | 7385c51d | Michael Hanselmann | elif expect_date: |
139 | 7385c51d | Michael Hanselmann | if not line: |
140 | 7385c51d | Michael Hanselmann | # Ignore empty lines |
141 | 7385c51d | Michael Hanselmann | continue |
142 | 7385c51d | Michael Hanselmann | |
143 | 7385c51d | Michael Hanselmann | if UNRELEASED_RE.match(line): |
144 | 7385c51d | Michael Hanselmann | # Ignore unreleased versions |
145 | 7385c51d | Michael Hanselmann | expect_date = False |
146 | 7385c51d | Michael Hanselmann | continue |
147 | 7385c51d | Michael Hanselmann | |
148 | 7385c51d | Michael Hanselmann | m = RELEASED_RE.match(line) |
149 | 7385c51d | Michael Hanselmann | if not m: |
150 | f0fa05ac | Iustin Pop | Error("Line %s: Invalid release line" % fileinput.filelineno()) |
151 | 9495d2f2 | Guido Trotter | expect_date = False |
152 | 9495d2f2 | Guido Trotter | continue |
153 | 7385c51d | Michael Hanselmann | |
154 | 7385c51d | Michael Hanselmann | # Including the weekday in the date string does not work as time.strptime |
155 | 7385c51d | Michael Hanselmann | # would return an inconsistent result if the weekday is incorrect. |
156 | 7385c51d | Michael Hanselmann | parsed_ts = time.mktime(time.strptime(m.group("date"), "%d %b %Y")) |
157 | 7385c51d | Michael Hanselmann | parsed = datetime.date.fromtimestamp(parsed_ts) |
158 | 1657353c | Michael Hanselmann | today = datetime.date.today() |
159 | 1657353c | Michael Hanselmann | |
160 | 1657353c | Michael Hanselmann | if (parsed - datetime.timedelta(TIMESTAMP_FUTURE_DAYS_MAX)) > today: |
161 | 1657353c | Michael Hanselmann | Error("Line %s: %s is more than %s days in the future (today is %s)" % |
162 | 1657353c | Michael Hanselmann | (fileinput.filelineno(), parsed, TIMESTAMP_FUTURE_DAYS_MAX, |
163 | 1657353c | Michael Hanselmann | today)) |
164 | 1657353c | Michael Hanselmann | |
165 | 7385c51d | Michael Hanselmann | weekday = parsed.strftime("%a") |
166 | 7385c51d | Michael Hanselmann | |
167 | 7385c51d | Michael Hanselmann | # Check weekday |
168 | 7385c51d | Michael Hanselmann | if m.group("day") != weekday: |
169 | f0fa05ac | Iustin Pop | Error("Line %s: %s was/is a %s, not %s" % |
170 | f0fa05ac | Iustin Pop | (fileinput.filelineno(), parsed, weekday, |
171 | f0fa05ac | Iustin Pop | m.group("day"))) |
172 | 7385c51d | Michael Hanselmann | |
173 | 7385c51d | Michael Hanselmann | expect_date = False |
174 | 7385c51d | Michael Hanselmann | |
175 | 7385c51d | Michael Hanselmann | prevline = line |
176 | 7385c51d | Michael Hanselmann | |
177 | f0fa05ac | Iustin Pop | if errors: |
178 | f0fa05ac | Iustin Pop | for msg in errors: |
179 | f0fa05ac | Iustin Pop | print >> sys.stderr, msg |
180 | f0fa05ac | Iustin Pop | sys.exit(1) |
181 | f0fa05ac | Iustin Pop | else: |
182 | f0fa05ac | Iustin Pop | sys.exit(0) |
183 | 7385c51d | Michael Hanselmann | |
184 | 7385c51d | Michael Hanselmann | |
185 | 7385c51d | Michael Hanselmann | if __name__ == "__main__": |
186 | 7385c51d | Michael Hanselmann | main() |