forked from pandas-dev/pandas
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsort_whatsnew_note.py
81 lines (63 loc) · 2.34 KB
/
sort_whatsnew_note.py
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
"""
Sort whatsnew note blocks by issue number.
NOTE: this assumes that each entry is on its own line, and ends with an issue number.
If that's not the case, then an entry might not get sorted. However, virtually all
recent-enough whatsnew entries follow this pattern. So, although not perfect, this
script should be good enough to significantly reduce merge conflicts.
For example:
- Fixed bug in resample (:issue:`321`)
- Fixed bug in groupby (:issue:`123`)
would become
- Fixed bug in groupby (:issue:`123`)
- Fixed bug in resample (:issue:`321`)
The motivation is to reduce merge conflicts by reducing the chances that multiple
contributors will edit the same line of code.
You can run this manually with
pre-commit run sort-whatsnew-items --all-files
"""
from __future__ import annotations
import argparse
import re
import sys
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from collections.abc import Sequence
# Check line starts with `-` and ends with e.g. `(:issue:`12345`)`,
# possibly with a trailing full stop.
pattern = re.compile(r"-.*\(:issue:`(\d+)`\)\.?$")
def sort_whatsnew_note(content: str) -> int:
new_lines = []
block: list[str] = []
lines = content.splitlines(keepends=True)
for line in lines:
if line.startswith("- ") and pattern.search(line) is not None:
block.append(line)
else:
block = sorted(block)
new_lines.extend(block)
new_lines.append(line)
block = []
if sorted(new_lines) != sorted(lines): # pragma: no cover
# Defensive check - this script should only reorder lines, not modify any
# content.
raise AssertionError(
"Script modified content of file. Something is wrong, please don't "
"trust it."
)
return "".join(new_lines)
def main(argv: Sequence[str] | None = None) -> int:
parser = argparse.ArgumentParser()
parser.add_argument("paths", nargs="*")
args = parser.parse_args(argv)
ret = 0
for path in args.paths:
with open(path, encoding="utf-8") as fd:
content = fd.read()
new_content = sort_whatsnew_note(content)
if content != new_content:
ret |= 1
with open(path, "w", encoding="utf-8") as fd:
fd.write(new_content)
return ret
if __name__ == "__main__":
sys.exit(main())