ansible-later: 2.0.22 -> 2.0.23
[NixPkgs.git] / maintainers / scripts / remove-old-aliases.py
blobc5629c829594d3d8537cc71581328b06b38331ac
1 #!/usr/bin/env nix-shell
2 #!nix-shell -i python3 -p "python3.withPackages(ps: with ps; [ ])" nix
3 """
4 A program to remove old aliases or convert old aliases to throws
5 Example usage:
6 ./maintainers/scripts/remove-old-aliases.py --year 2018 --file ./pkgs/top-level/aliases.nix
8 Check this file with mypy after every change!
9 $ mypy --strict maintainers/scripts/remove-old-aliases.py
10 """
11 import argparse
12 import shutil
13 import subprocess
14 from datetime import date as datetimedate
15 from datetime import datetime
16 from pathlib import Path
19 def process_args() -> argparse.Namespace:
20 """process args"""
21 arg_parser = argparse.ArgumentParser()
22 arg_parser.add_argument(
23 "--year", required=True, type=int, help="operate on aliases older than $year"
25 arg_parser.add_argument(
26 "--month",
27 type=int,
28 default=1,
29 help="operate on aliases older than $year-$month",
31 arg_parser.add_argument(
32 "--only-throws",
33 action="store_true",
34 help="only operate on throws. e.g remove throws older than $date",
36 arg_parser.add_argument("--file", required=True, type=Path, help="alias file")
37 arg_parser.add_argument(
38 "--dry-run", action="store_true", help="don't modify files, only print results"
40 return arg_parser.parse_args()
43 def get_date_lists(
44 txt: list[str], cutoffdate: datetimedate, only_throws: bool
45 ) -> tuple[list[str], list[str], list[str]]:
46 """get a list of lines in which the date is older than $cutoffdate"""
47 date_older_list: list[str] = []
48 date_older_throw_list: list[str] = []
49 date_sep_line_list: list[str] = []
51 for lineno, line in enumerate(txt, start=1):
52 line = line.rstrip()
53 my_date = None
54 for string in line.split():
55 string = string.strip(":")
56 try:
57 # strip ':' incase there is a string like 2019-11-01:
58 my_date = datetime.strptime(string, "%Y-%m-%d").date()
59 except ValueError:
60 try:
61 my_date = datetime.strptime(string, "%Y-%m").date()
62 except ValueError:
63 continue
65 if (
66 my_date is None
67 or my_date > cutoffdate
68 or "preserve, reason:" in line.lower()
70 continue
72 if "=" not in line:
73 date_sep_line_list.append(f"{lineno} {line}")
74 # 'if' lines could be complicated
75 elif "if " in line and "if =" not in line:
76 print(f"RESOLVE MANUALLY {line}")
77 elif "throw" in line:
78 date_older_throw_list.append(line)
79 elif not only_throws:
80 date_older_list.append(line)
82 return (
83 date_older_list,
84 date_sep_line_list,
85 date_older_throw_list,
89 def convert_to_throw(date_older_list: list[str]) -> list[tuple[str, str]]:
90 """convert a list of lines to throws"""
91 converted_list = []
92 for line in date_older_list.copy():
93 indent: str = " " * (len(line) - len(line.lstrip()))
94 before_equal = ""
95 after_equal = ""
96 try:
97 before_equal, after_equal = (x.strip() for x in line.split("=", maxsplit=2))
98 except ValueError as err:
99 print(err, line, "\n")
100 date_older_list.remove(line)
101 continue
103 alias = before_equal.strip()
104 after_equal_list = [x.strip(";:") for x in after_equal.split()]
106 converted = (
107 f"{indent}{alias} = throw \"'{alias}' has been renamed to/replaced by"
108 f" '{after_equal_list.pop(0)}'\";"
109 f' # Converted to throw {datetime.today().strftime("%Y-%m-%d")}'
111 converted_list.append((line, converted))
113 return converted_list
116 def generate_text_to_write(
117 txt: list[str],
118 date_older_list: list[str],
119 converted_to_throw: list[tuple[str, str]],
120 date_older_throw_list: list[str],
121 ) -> list[str]:
122 """generate a list of text to be written to the aliasfile"""
123 text_to_write: list[str] = []
124 for line in txt:
125 text_to_append: str = ""
126 if converted_to_throw:
127 for tupl in converted_to_throw:
128 if line == tupl[0]:
129 text_to_append = f"{tupl[1]}\n"
130 if line not in date_older_list and line not in date_older_throw_list:
131 text_to_append = f"{line}\n"
132 if text_to_append:
133 text_to_write.append(text_to_append)
135 return text_to_write
138 def write_file(
139 aliasfile: Path,
140 text_to_write: list[str],
141 ) -> None:
142 """write file"""
143 temp_aliasfile = Path(f"{aliasfile}.raliases")
144 with open(temp_aliasfile, "w", encoding="utf-8") as far:
145 for line in text_to_write:
146 far.write(line)
147 print("\nChecking the syntax of the new aliasfile")
148 try:
149 subprocess.run(
150 ["nix-instantiate", "--eval", temp_aliasfile],
151 check=True,
152 stdout=subprocess.DEVNULL,
154 except subprocess.CalledProcessError:
155 print(
156 "\nSyntax check failed,",
157 "there may have been a line which only has\n"
158 'aliasname = "reason why";\n'
159 "when it should have been\n"
160 'aliasname = throw "reason why";',
162 temp_aliasfile.unlink()
163 return
164 shutil.move(f"{aliasfile}.raliases", aliasfile)
165 print(f"{aliasfile} modified! please verify with 'git diff'.")
168 def main() -> None:
169 """main"""
170 args = process_args()
172 only_throws = args.only_throws
173 aliasfile = Path(args.file).absolute()
174 cutoffdate = (datetime.strptime(f"{args.year}-{args.month}-01", "%Y-%m-%d")).date()
176 txt: list[str] = (aliasfile.read_text(encoding="utf-8")).splitlines()
178 date_older_list: list[str] = []
179 date_sep_line_list: list[str] = []
180 date_older_throw_list: list[str] = []
182 date_older_list, date_sep_line_list, date_older_throw_list = get_date_lists(
183 txt, cutoffdate, only_throws
186 converted_to_throw: list[tuple[str, str]] = []
187 if date_older_list:
188 converted_to_throw = convert_to_throw(date_older_list)
189 print(" Will be converted to throws. ".center(100, "-"))
190 for l_n in date_older_list:
191 print(l_n)
193 if date_older_throw_list:
194 print(" Will be removed. ".center(100, "-"))
195 for l_n in date_older_throw_list:
196 print(l_n)
198 if date_sep_line_list:
199 print(" On separate line, resolve manually. ".center(100, "-"))
200 for l_n in date_sep_line_list:
201 print(l_n)
203 if not args.dry_run:
204 text_to_write = generate_text_to_write(
205 txt, date_older_list, converted_to_throw, date_older_throw_list
207 write_file(aliasfile, text_to_write)
210 if __name__ == "__main__":
211 main()