6
6
import logging
7
7
import shutil
8
8
import textwrap
9
+ from dataclasses import dataclass
9
10
from pathlib import Path
10
11
11
12
import plumbum
12
13
import tabulate
13
14
from dateutil import relativedelta
14
15
16
+ from wiki .config import Config
17
+ from wiki .manifest_time import get_manifest_timestamp , get_manifest_year_month
18
+
15
19
git = plumbum .local ["git" ]
16
20
17
21
LOGGER = logging .getLogger (__name__ )
18
22
THIS_DIR = Path (__file__ ).parent .resolve ()
19
23
20
24
21
- def calculate_monthly_stat (
22
- year_month_file : Path , year_month_date : datetime .date
23
- ) -> tuple [int , int , int ]:
24
- year_month_file_content = year_month_file .read_text ()
25
+ @dataclass
26
+ class YearMonthFile :
27
+ month : int
28
+ content : str
29
+
25
30
31
+ @dataclass
32
+ class Statistics :
33
+ builds : int
34
+ images : int
35
+ commits : int
36
+
37
+
38
+ def calculate_monthly_stat (
39
+ year_month_file : YearMonthFile , year_month_date : datetime .date
40
+ ) -> Statistics :
26
41
builds = sum (
27
42
"jupyter/base-notebook" in line and "aarch64" not in line
28
- for line in year_month_file_content .split ("\n " )
43
+ for line in year_month_file . content .split ("\n " )
29
44
)
30
45
31
- images = year_month_file_content .count ("Build manifest" )
46
+ images = year_month_file . content .count ("Build manifest" )
32
47
33
48
with plumbum .local .env (TZ = "UTC" ):
34
49
future = (
@@ -46,69 +61,102 @@ def calculate_monthly_stat(
46
61
future .wait ()
47
62
commits = len (future .stdout .splitlines ())
48
63
49
- return builds , images , commits
64
+ return Statistics ( builds = builds , images = images , commits = commits )
50
65
51
66
52
- def generate_home_wiki_page (wiki_dir : Path , repository : str ) -> None :
53
- YEAR_MONTHLY_TABLES = "<!-- YEAR_MONTHLY_TABLES -->"
67
+ @dataclass
68
+ class YearFiles :
69
+ year : int
70
+ files : list [YearMonthFile ]
54
71
55
- wiki_home_content = (THIS_DIR / "Home.md" ).read_text ()
56
72
57
- assert YEAR_MONTHLY_TABLES in wiki_home_content
58
- wiki_home_content = wiki_home_content [
59
- : wiki_home_content .find (YEAR_MONTHLY_TABLES ) + len (YEAR_MONTHLY_TABLES )
60
- ]
61
- wiki_home_content = wiki_home_content .format (REPOSITORY = repository )
73
+ def generate_home_wiki_tables (repository : str , all_years : list [YearFiles ]) -> str :
74
+ tables = ""
62
75
63
76
GITHUB_COMMITS_URL = (
64
77
f"[{{}}](https://github.com/{ repository } /commits/main/?since={{}}&until={{}})"
65
78
)
66
79
67
80
YEAR_TABLE_HEADERS = ["Month" , "Builds" , "Images" , "Commits" ]
68
81
69
- for year_dir in sorted ((wiki_dir / "monthly-files" ).glob ("*" ), reverse = True ):
70
- year = int (year_dir .name )
71
- wiki_home_content += f"\n \n ## { year } \n \n "
82
+ for year_files in all_years :
83
+ year = year_files .year
84
+
85
+ tables += f"\n \n ## { year } \n \n "
72
86
year_table_rows = []
73
87
74
- year_builds , year_images , year_commits = 0 , 0 , 0
75
- for year_month_file in sorted ( year_dir . glob ( "*.md" ), reverse = True ) :
76
- year_month = year_month_file .stem
77
- year_month_date = datetime .date (year = year , month = int ( year_month [ 5 :]) , day = 1 )
78
- builds , images , commits = calculate_monthly_stat (
79
- year_month_file , year_month_date
80
- )
81
- year_builds += builds
82
- year_images += images
83
- year_commits += commits
88
+ year_stat = Statistics ( builds = 0 , images = 0 , commits = 0 )
89
+ for year_month_file in year_files . files :
90
+ month = year_month_file .month
91
+ year_month_date = datetime .date (year = year , month = month , day = 1 )
92
+ month_stat = calculate_monthly_stat (year_month_file , year_month_date )
93
+
94
+ year_stat . builds += month_stat . builds
95
+ year_stat . images += month_stat . images
96
+ year_stat . commits += month_stat . commits
97
+
84
98
commits_url = GITHUB_COMMITS_URL .format (
85
- commits ,
99
+ month_stat . commits ,
86
100
year_month_date ,
87
101
year_month_date + relativedelta .relativedelta (day = 31 ),
88
102
)
103
+ year_month = f"{ year } -{ month :0>2} "
89
104
year_table_rows .append (
90
- [f"[`{ year_month } `](./{ year_month } )" , builds , images , commits_url ]
105
+ [
106
+ f"[`{ year_month } `](./{ year_month } )" ,
107
+ month_stat .builds ,
108
+ month_stat .images ,
109
+ commits_url ,
110
+ ]
91
111
)
92
112
93
113
year_commits_url = GITHUB_COMMITS_URL .format (
94
- year_commits , f"{ year } -01-01" , f"{ year } -12-31"
114
+ year_stat . commits , f"{ year } -01-01" , f"{ year } -12-31"
95
115
)
96
116
year_table_rows .append (
97
- ["**Total**" , year_builds , year_images , year_commits_url ]
117
+ ["**Total**" , year_stat . builds , year_stat . images , year_commits_url ]
98
118
)
99
119
100
- wiki_home_content += tabulate .tabulate (
120
+ tables += tabulate .tabulate (
101
121
year_table_rows , YEAR_TABLE_HEADERS , tablefmt = "github"
102
122
)
103
- wiki_home_content += "\n "
123
+ LOGGER .info ("Generated home wiki tables" )
124
+ return tables
125
+
126
+
127
+ def write_home_wiki_page (wiki_dir : Path , repository : str ) -> None :
128
+ all_years = []
129
+ for year_dir in sorted ((wiki_dir / "monthly-files" ).glob ("*" ), reverse = True ):
130
+ files = sorted (year_dir .glob ("*.md" ), reverse = True )
131
+ all_years .append (
132
+ YearFiles (
133
+ int (year_dir .name ),
134
+ [
135
+ YearMonthFile (month = int (f .stem [5 :]), content = f .read_text ())
136
+ for f in files
137
+ ],
138
+ )
139
+ )
140
+ wiki_home_tables = generate_home_wiki_tables (repository , all_years )
141
+
142
+ wiki_home_content = (THIS_DIR / "Home.md" ).read_text ()
143
+ YEAR_MONTHLY_TABLES = "<!-- YEAR_MONTHLY_TABLES -->"
144
+
145
+ assert YEAR_MONTHLY_TABLES in wiki_home_content
146
+ wiki_home_content = wiki_home_content [
147
+ : wiki_home_content .find (YEAR_MONTHLY_TABLES ) + len (YEAR_MONTHLY_TABLES )
148
+ ]
149
+ wiki_home_content = wiki_home_content .format (REPOSITORY = repository )
150
+ wiki_home_content += wiki_home_tables + "\n "
104
151
105
152
(wiki_dir / "Home.md" ).write_text (wiki_home_content )
106
153
LOGGER .info ("Updated Home page" )
107
154
108
155
109
- def update_monthly_wiki_page (
110
- wiki_dir : Path , year_month : str , build_history_line : str
111
- ) -> None :
156
+ def update_monthly_wiki_page (wiki_dir : Path , build_history_line : str ) -> None :
157
+ assert build_history_line .startswith ("| `" )
158
+ year_month = build_history_line [3 :10 ]
159
+
112
160
MONTHLY_PAGE_HEADER = textwrap .dedent (
113
161
f"""\
114
162
# Images built during { year_month }
@@ -133,23 +181,6 @@ def update_monthly_wiki_page(
133
181
LOGGER .info (f"Updated monthly page: { monthly_page .relative_to (wiki_dir )} " )
134
182
135
183
136
- def get_manifest_timestamp (manifest_file : Path ) -> str :
137
- file_content = manifest_file .read_text ()
138
- TIMESTAMP_PREFIX = "Build timestamp: "
139
- TIMESTAMP_LENGTH = 20
140
- timestamp = file_content [
141
- file_content .find (TIMESTAMP_PREFIX ) + len (TIMESTAMP_PREFIX ) :
142
- ][:TIMESTAMP_LENGTH ]
143
- # Should be good enough till year 2100
144
- assert timestamp .startswith ("20" ), timestamp
145
- assert timestamp .endswith ("Z" ), timestamp
146
- return timestamp
147
-
148
-
149
- def get_manifest_year_month (manifest_file : Path ) -> str :
150
- return get_manifest_timestamp (manifest_file )[:7 ]
151
-
152
-
153
184
def remove_old_manifests (wiki_dir : Path ) -> None :
154
185
MAX_NUMBER_OF_MANIFESTS = 4500
155
186
@@ -163,40 +194,37 @@ def remove_old_manifests(wiki_dir: Path) -> None:
163
194
LOGGER .info (f"Removed manifest: { file .relative_to (wiki_dir )} " )
164
195
165
196
166
- def update_wiki (
167
- * ,
168
- wiki_dir : Path ,
169
- hist_lines_dir : Path ,
170
- manifests_dir : Path ,
171
- repository : str ,
172
- allow_no_files : bool ,
173
- ) -> None :
174
- LOGGER .info ("Updating wiki" )
175
-
176
- manifest_files = list (manifests_dir .rglob ("*.md" ))
177
- if not allow_no_files :
197
+ def copy_manifest_files (config : Config ) -> None :
198
+ manifest_files = list (config .manifests_dir .rglob ("*.md" ))
199
+ if not config .allow_no_files :
178
200
assert manifest_files , "expected to have some manifest files"
179
201
for manifest_file in manifest_files :
180
202
year_month = get_manifest_year_month (manifest_file )
181
203
year = year_month [:4 ]
182
- copy_to = wiki_dir / "manifests" / year / year_month / manifest_file .name
204
+ copy_to = config . wiki_dir / "manifests" / year / year_month / manifest_file .name
183
205
copy_to .parent .mkdir (parents = True , exist_ok = True )
184
206
shutil .copy (manifest_file , copy_to )
185
- LOGGER .info (f"Added manifest file: { copy_to .relative_to (wiki_dir )} " )
207
+ LOGGER .info (f"Added manifest file: { copy_to .relative_to (config . wiki_dir )} " )
186
208
187
- build_history_line_files = sorted (hist_lines_dir .rglob ("*.txt" ))
188
- if not allow_no_files :
209
+
210
+ def update_wiki (config : Config ) -> None :
211
+ LOGGER .info ("Updating wiki" )
212
+
213
+ copy_manifest_files (config )
214
+
215
+ build_history_line_files = sorted (config .hist_lines_dir .rglob ("*.txt" ))
216
+ if not config .allow_no_files :
189
217
assert (
190
218
build_history_line_files
191
219
), "expected to have some build history line files"
192
220
for build_history_line_file in build_history_line_files :
193
221
build_history_line = build_history_line_file .read_text ()
194
- assert build_history_line .startswith ("| `" )
195
- year_month = build_history_line [3 :10 ]
196
- update_monthly_wiki_page (wiki_dir , year_month , build_history_line )
222
+ update_monthly_wiki_page (config .wiki_dir , build_history_line )
223
+
224
+ write_home_wiki_page (config .wiki_dir , config .repository )
225
+ remove_old_manifests (config .wiki_dir )
197
226
198
- generate_home_wiki_page (wiki_dir , repository )
199
- remove_old_manifests (wiki_dir )
227
+ LOGGER .info ("Uncyclo updated" )
200
228
201
229
202
230
if __name__ == "__main__" :
@@ -233,4 +261,5 @@ def update_wiki(
233
261
)
234
262
args = arg_parser .parse_args ()
235
263
236
- update_wiki (** vars (args ))
264
+ config = Config (** vars (args ))
265
+ update_wiki (config )
0 commit comments