6
6
import pprint
7
7
import subprocess
8
8
import sys
9
+ import re
10
+ from urllib .request import Request , urlopen
11
+ from urllib .error import HTTPError
12
+ from collections import defaultdict
13
+ import toml
14
+ from contextlib import suppress
9
15
10
16
from .setup import Setup
11
17
from .generator_data import MissingReporter
@@ -256,6 +262,171 @@ def run(self, args):
256
262
pprint .pprint (platforms .get_platform_override_keys (p ))
257
263
258
264
265
+ class MavenParser :
266
+
267
+ after_archs = [
268
+ "static" ,
269
+ "debug" ,
270
+ "staticdebug" ,
271
+ ]
272
+
273
+ @classmethod
274
+ def add_subparser (cls , parent_parser , subparsers ):
275
+ parser = subparsers .add_parser (
276
+ "parse-maven" ,
277
+ help = "Find supported platforms from a pyproject.toml" ,
278
+ parents = [parent_parser ],
279
+ )
280
+ parser .add_argument (
281
+ "toml_link" , help = "Ex: pyproject.toml" ,
282
+ )
283
+ parser .add_argument (
284
+ "-b" ,
285
+ "--brute_force" ,
286
+ action = "store_true" ,
287
+ help = "Try known os and arch combinations instead of parsing html (needed for rev)" ,
288
+ )
289
+ return parser
290
+
291
+ def check_url_exists (self , file_url ):
292
+ with suppress (Exception ):
293
+ if urlopen (Request (file_url )).code == 200 :
294
+ return True
295
+ return False
296
+
297
+ def run (self , args ):
298
+
299
+ self .os_names = set ()
300
+ self .arch_names = set ()
301
+ for plat in platforms ._platforms .values ():
302
+ self .os_names .add (plat .os )
303
+ self .arch_names .add (plat .arch )
304
+
305
+ with open (args .toml_link ) as fp :
306
+ config = toml .load (fp )["tool" ]["robotpy-build" ]
307
+
308
+ wrappers = {}
309
+ if "wrappers" in config :
310
+ wrappers = {
311
+ k : v
312
+ for (k , v ) in config ["wrappers" ].items ()
313
+ if "maven_lib_download" in v
314
+ }
315
+
316
+ static_libs = {}
317
+ if "static_libs" in config :
318
+ static_libs = {
319
+ k : v
320
+ for (k , v ) in config ["static_libs" ].items ()
321
+ if "maven_lib_download" in v
322
+ }
323
+
324
+ if wrappers == {} and static_libs == {}:
325
+ print ("No maven_lib_downloads in pyproject.toml" )
326
+ exit ()
327
+
328
+ for w_name , wrapper in {** wrappers , ** static_libs }.items ():
329
+
330
+ if "maven_lib_download" not in wrapper :
331
+ continue
332
+
333
+ mvl = wrapper ["maven_lib_download" ]
334
+
335
+ repo_url = mvl ["repo_url" ]
336
+ grp = mvl ["group_id" ].replace ("." , "/" )
337
+ art = mvl ["artifact_id" ]
338
+ ver = mvl ["version" ]
339
+
340
+ dir_url = f"{ repo_url } /{ grp } /{ art } /{ ver } /"
341
+
342
+ plats = defaultdict (set )
343
+
344
+ found_source = False
345
+ source_name = None
346
+
347
+ if args .brute_force :
348
+
349
+ for os in self .os_names :
350
+ for arch in self .arch_names :
351
+ for after_arch in self .after_archs + ["" ]:
352
+ classifier = os + arch + after_arch
353
+ file_url = f"{ dir_url } { art } -{ ver } -{ classifier } .zip"
354
+
355
+ if self .check_url_exists (file_url ):
356
+ plats [os ].add (arch )
357
+
358
+ if self .check_url_exists (f"{ dir_url } { art } -{ ver } -source.zip" ):
359
+ found_source = True
360
+ source_name = "source"
361
+
362
+ if self .check_url_exists (f"{ dir_url } { art } -{ ver } -sources.zip" ):
363
+ found_source = True
364
+ source_name = "sources"
365
+
366
+ else :
367
+ try :
368
+ html = str (urlopen (Request (dir_url )).read ())
369
+ except HTTPError as e :
370
+ if e .code != 404 :
371
+ raise e
372
+ else :
373
+ print (
374
+ "The repo url returned a 404 error. Try using the brute_force flag."
375
+ )
376
+ exit ()
377
+
378
+ found_source = False
379
+ source_name = None
380
+
381
+ if "source.zip" in html :
382
+ found_source = True
383
+ source_name = "source"
384
+
385
+ if "sources.zip" in html :
386
+ found_source = True
387
+ source_name = "sources"
388
+
389
+ # matches = re.findall('\.zip">(.*?)\.zip</a>', html, re.I) # match on text
390
+ matches = re .findall ('href="(.*?)">' , html , re .I ) # match on links
391
+ matches = [
392
+ m [:- 4 ] for m in matches if m [- 4 :] == ".zip"
393
+ ] # match on zip files and remove extension
394
+
395
+ for m in matches :
396
+ for os in self .os_names :
397
+ idx = m .find (os )
398
+
399
+ if idx != - 1 :
400
+ arch = m [idx + len (os ) :]
401
+
402
+ for after_arch in self .after_archs :
403
+ arch = arch .replace (after_arch , "" )
404
+
405
+ plats [os ].add (arch )
406
+ break
407
+
408
+ # Formatting
409
+ print ()
410
+ print (f"Wrapper / static_lib :: { w_name } " )
411
+ print (f"Artifact ID :: { art } " )
412
+ print ()
413
+
414
+ if found_source :
415
+ print ("This repo appears to provide sources." )
416
+ print ("The name of the source file is:" , source_name )
417
+ print ()
418
+
419
+ plat_str = "supported_platforms = [\n "
420
+ for os in plats :
421
+ for arch in plats [os ]:
422
+ plat_str += ' {{ os = "{}", arch = "{}" }},\n ' .format (
423
+ os , arch
424
+ )
425
+ plat_str += "]"
426
+
427
+ print (plat_str )
428
+
429
+
259
430
def main ():
260
431
261
432
parser = argparse .ArgumentParser (prog = "robotpy-build" )
@@ -270,6 +441,7 @@ def main():
270
441
ImportCreator ,
271
442
LibraryRelinker ,
272
443
PlatformInfo ,
444
+ MavenParser ,
273
445
):
274
446
cls .add_subparser (parent_parser , subparsers ).set_defaults (cls = cls )
275
447
0 commit comments