11#!/usr/bin/env python3
2- # audit-and-update-record-for-wheel.py - Update RECORD file for wheels.
2+ # audit-and-update-record-for-wheel.py - Check the lib and license for wheels, and update RECORD file for wheels.
33#
44from __future__ import annotations
55
66import argparse
77import logging
88from os .path import abspath , basename , exists , isfile
99import os
10+ import json
1011
11- from auditwheel .wheeltools import InWheel
12+ from auditwheel .wheeltools import InWheelCtx
1213
1314logger = logging .getLogger (__name__ )
1415
1516def configure_parser (p ):
17+ p .add_argument (
18+ "-L" ,
19+ "--lib-sdir" ,
20+ dest = "LIB_SDIR" ,
21+ help = (
22+ "Subdirectory in packages to store copied libraries." ' (default: ".libs")'
23+ ),
24+ default = ".libs" ,
25+ )
1626 p .add_argument (
1727 "-w" ,
1828 "--wheel-dir" ,
@@ -21,27 +31,115 @@ def configure_parser(p):
2131 help = ("Directory to store delocated wheels (default:" ' "wheelhouse/")' ),
2232 default = "wheelhouse/" ,
2333 )
24- p .add_argument ("WHEEL_FILE" , help = "Path to wheel file." , nargs = "+" )
34+ p .add_argument (
35+ "WHEEL_FILE" ,
36+ type = str ,
37+ help = "Path to wheel file." ,
38+ )
39+ p .add_argument (
40+ "-j" ,
41+ "--json" ,
42+ dest = "LICENSE_JSON" ,
43+ help = "Path to lib-license json." ,
44+ )
45+ p .add_argument (
46+ "-nolib" ,
47+ "--ensure-no-libs" ,
48+ dest = "NO_LIBS" ,
49+ action = "store_true" ,
50+ help = "Ensure there is no libs." ,
51+ default = False ,
52+ )
53+ p .add_argument (
54+ "-clib" ,
55+ "--check-libs" ,
56+ dest = "CHECK_LIBS" ,
57+ action = "store_true" ,
58+ help = (
59+ "Enable checking libs."
60+ ),
61+ default = False ,
62+ )
63+ p .add_argument (
64+ "-clic" ,
65+ "--check-licenses" ,
66+ dest = "CHECK_LICENSES" ,
67+ action = "store_true" ,
68+ help = (
69+ "Enable checking licenses."
70+ ),
71+ default = False ,
72+ )
2573 p .set_defaults (func = execute )
2674
2775
76+ def parse_license_json (filepath ):
77+ libs = set ()
78+ licenses = {}
79+ with open (filepath , "r" ) as fp :
80+ for e in json .load (fp ):
81+ for lib in e ["libs" ]:
82+ libs .add (lib )
83+ for license in e ["licenses" ]:
84+ licenses [license ] = False
85+ return libs , licenses
86+
87+
2888def execute (args , p ):
29- for wheel_file in args .WHEEL_FILE :
30- if not isfile (wheel_file ):
31- p .error ("cannot access %s. No such file" % wheel_file )
89+ wheel_file = args .WHEEL_FILE
90+ if not isfile (wheel_file ):
91+ logger .error ("cannot access %s. No such file" % wheel_file )
92+ exit (1 )
3293
33- if not exists (args .WHEEL_DIR ):
34- os .makedirs (args .WHEEL_DIR )
94+ if not exists (args .WHEEL_DIR ):
95+ os .makedirs (args .WHEEL_DIR )
3596
36- out_wheel = os .path .join ("wheelhouse" , basename (wheel_file ))
37- with InWheel (in_wheel = wheel_file , out_wheel = out_wheel ):
97+ out_wheel = os .path .join (args .WHEEL_DIR , basename (wheel_file ))
98+ with InWheelCtx (in_wheel = wheel_file , out_wheel = out_wheel ) as ctx :
99+ if not args .CHECK_LIBS and not args .CHECK_LICENSES :
38100 logger .info ("Updating RECORD file of %s" , basename (wheel_file ))
101+ return
102+ libs = set ()
103+ licenses = {}
104+ if args .CHECK_LIBS or args .CHECK_LICENSES :
105+ libs , licenses = parse_license_json (args .LICENSE_JSON )
106+ real_libs = set ()
107+ for fn in ctx .iter_files ():
108+ path_split = fn .split (os .sep )
109+ name = path_split [- 1 ]
110+ if f"{ args .LIB_SDIR } /" in fn and ".so" in name :
111+ if args .NO_LIBS :
112+ logger .error (f"found possible .so: { fn } " )
113+ exit (1 )
114+ if args .CHECK_LIBS :
115+ # libxxx-xxxx.so(.xxx)
116+ name = "" .join (name .split (".so" )[:- 1 ])
117+ # libxxx-xxxx
118+ name = "-" .join (name .split ("-" )[:- 1 ])
119+ real_libs .add (name )
120+ if args .CHECK_LICENSES and licenses .get (name , None ) is not None :
121+ licenses [name ] = True
122+ ok = True
123+ if args .CHECK_LIBS :
124+ if libs != real_libs :
125+ ok = False
126+ logger .error (f"libs check failed. libs: { libs } , real_libs: { real_libs } " )
127+ if args .CHECK_LICENSES :
128+ for k , v in licenses .items ():
129+ if v != True :
130+ ok = False
131+ logger .error (f"{ k } is not found" )
132+ if not ok :
133+ logger .error ("check is not passed." )
134+ exit (1 )
135+ logger .info ("check passed." )
136+ logger .info ("Updating RECORD file of %s" , basename (wheel_file ))
39137
40- logger .info ("\n Fixed-up wheel written to %s" , out_wheel )
138+ logger .info ("\n Fixed-up wheel written to %s" , out_wheel )
41139
42140
43141def main ():
44- p = argparse .ArgumentParser (description = "Update RECORD for Python wheels." )
142+ p = argparse .ArgumentParser (description = "Cross-distro Python wheels." )
45143 p .add_argument (
46144 "-v" ,
47145 "--verbose" ,
0 commit comments