1+ import contextlib
12import json
23import re
34import sys
45
5- from collections import OrderedDict
66from pathlib import Path
7- from urllib .request import Request , urlopen
87
98REPO = Path (__file__ ).absolute ().parent .parent
109sys .path .append (str (REPO / "src" ))
@@ -30,6 +29,7 @@ def usage():
3029 print (" -t/--tag TAG Include only the specified tags (comma-separated)" )
3130 print (" -r/--range RANGE Include only the specified range (comma-separated)" )
3231 print (" --latest-micro Include only the latest x.y.z version" )
32+ print (" --report Write plain-text summary report" )
3333 print ()
3434 print ("An output of 'nul' is permitted to drop entries." )
3535 print ("Providing the same inputs and outputs is permitted, as all inputs are read" )
@@ -93,14 +93,15 @@ def __init__(self):
9393 self .allow_dup = False
9494 self .only_dup = False
9595 self .pre = False
96- self .tag_or_range = None
96+ self .tag_or_range = []
9797 self ._expect_tag_or_range = False
9898 self .latest_micro = False
99+ self .report = False
99100
100101 def add_arg (self , arg ):
101102 if arg [:1 ] != "-" :
102103 if self ._expect_tag_or_range :
103- self .tag_or_range = tag_or_range (arg )
104+ self .tag_or_range . append ( tag_or_range (arg ) )
104105 self ._expect_tag_or_range = False
105106 return False
106107 self .target = arg
@@ -121,9 +122,16 @@ def add_arg(self, arg):
121122 if arg == "--latest-micro" :
122123 self .latest_micro = True
123124 return False
125+ if arg == "--report" :
126+ self .report = True
127+ return False
124128 raise ValueError ("Unknown argument: " + arg )
125129
126130 def execute (self , versions , context ):
131+ if self .report :
132+ if self .target != "nul" :
133+ context .setdefault ("reports" , []).append (self .target )
134+ return
127135 written = context .setdefault ("written" , set ())
128136 written_now = set ()
129137 outputs = context .setdefault ("outputs" , {})
@@ -150,7 +158,8 @@ def execute(self, versions, context):
150158 if not self .pre and v .is_prerelease :
151159 continue
152160 if self .tag_or_range and not any (
153- self .tag_or_range .satisfied_by (CompanyTag (i ["company" ], t ))
161+ r .satisfied_by (CompanyTag (i ["company" ], t ))
162+ for r in self .tag_or_range
154163 for t in i ["install-for" ]
155164 ):
156165 continue
@@ -176,19 +185,56 @@ def add_arg(self, arg):
176185 return False
177186 raise ValueError ("Unknown argument: " + arg )
178187
188+ @contextlib .contextmanager
189+ def open (self , file ):
190+ file = Path (file )
191+ if file .match ("nul" ):
192+ import io
193+ yield io .StringIO ()
194+ elif file .match ("stdout" ):
195+ yield sys .stdout
196+ else :
197+ with open (file , "w" , encoding = "utf-8" ) as f :
198+ yield f
199+
200+ def st_size (self , file ):
201+ file = Path (file )
202+ if file .match ("nul" ):
203+ return "no data written"
204+ if file .match ("stdout" ):
205+ return "n/a"
206+ return f"{ Path (file ).stat ().st_size } bytes"
207+
179208 def execute (self , versions , context ):
180209 outputs = context .get ("outputs" ) or {}
181210 output_order = context .get ("output_order" , [])
211+ report_data = {}
182212 for target , next_target in zip (output_order , [* output_order [1 :], None ]):
183213 data = {
184214 "versions" : outputs [target ]
185215 }
186216 if next_target :
187217 data ["next" ] = next_target
188- with open (target , "w" , encoding = "utf-8" ) as f :
218+ for i in outputs [target ]:
219+ report_data .setdefault (target , {}).setdefault (i ["sort-version" ].casefold (), []).append (i )
220+ with self .open (target ) as f :
189221 json .dump (data , f , indent = self .indent )
190222 print ("Wrote {} ({} entries, {} bytes)" .format (
191- target , len (data ["versions" ]), Path (target ).stat ().st_size
223+ target , len (data ["versions" ]), self .st_size (target )
224+ ))
225+
226+ reports = context .get ("reports" , [])
227+ for target in reports :
228+ with self .open (target ) as f :
229+ for output_target in output_order :
230+ print ("Written to" , output_target , file = f )
231+ data = report_data [output_target ]
232+ for key in data :
233+ ids = ", " .join (i ["id" ] for i in data [key ])
234+ print ("{}: {}" .format (key , ids ), file = f )
235+ print (file = f )
236+ print ("Wrote {} ({} bytes)" .format (
237+ target , self .st_size (target )
192238 ))
193239
194240
@@ -203,14 +249,17 @@ def parse_cli(args):
203249 print ("Using equivalent of: --pre --latest-micro -r >=3.11.0 index-windows.json" )
204250 print (" --pre -r >=3.11.0 index-windows-recent.json" )
205251 print (" index-windows-legacy.json" )
206- plan_split = [SplitToFile (), SplitToFile (), SplitToFile ()]
252+ print (" --report index-windows.txt" )
253+ plan_split = [SplitToFile (), SplitToFile (), SplitToFile (), SplitToFile ()]
207254 plan_split [0 ].target = "index-windows.json"
208255 plan_split [1 ].target = "index-windows-recent.json"
209256 plan_split [2 ].target = "index-windows-legacy.json"
257+ plan_split [3 ].target = "index-windows.txt"
258+ plan_split [3 ].report = True
210259 plan_split [0 ].pre = plan_split [1 ].pre = plan_split [2 ].pre = True
211260 plan_split [0 ].latest_micro = True
212- plan_split [0 ].tag_or_range = tag_or_range (">=3.11.0" )
213- plan_split [1 ].tag_or_range = tag_or_range (">=3.11.0" )
261+ plan_split [0 ].tag_or_range = [ tag_or_range (">=3.11" ), tag_or_range ( ">=3.13t" )]
262+ plan_split [1 ].tag_or_range = [ tag_or_range (">=3.11" ), tag_or_range ( ">=3.13t" )]
214263 elif a == "-i" :
215264 action = ReadFile ()
216265 plan_read .append (action )
@@ -246,4 +295,3 @@ def parse_cli(args):
246295 CONTEXT = {}
247296 for p in plan :
248297 p .execute (VERSIONS , CONTEXT )
249-
0 commit comments