@@ -12,20 +12,10 @@ def normalize(this):
1212
1313
1414class pipdata :
15- """Wrapper aroud pip inspect"""
15+ """Wrapper around Distribution.discover() or pip inspect"""
1616
1717 def __init__ (self , Target = None ):
1818
19- # get pip_inpsect raw data in json form
20- #os.environ["pythonutf8"] = "1" causes issues in movable, so limit to there
21- if Target == None :
22- #pip_inspect = utils.exec_run_cmd(["pip", "inspect"])
23- pip_inspect = utils .exec_shell_cmd (f'set pythonutf8=1 & python -X utf8=1 -m pip inspect' , sys .prefix )
24- else :
25- #pip_inspect = utils.exec_run_cmd([Target , "-X" ,"utf8=1", "-m", "pip", "inspect"])
26- pip_inspect = utils .exec_shell_cmd (f'set pythonutf8=1 & "{ Target } " -X utf8=1 -m pip inspect' , sys .prefix )
27- pip_json = json .loads (pip_inspect )
28-
2919 # create a distro{} dict of Packages
3020 # key = normalised package name
3121 # string_elements = 'name', 'version', 'summary'
@@ -34,6 +24,7 @@ def __init__(self, Target=None):
3424 # req_extra = extra branch needed of the package_key ('all' or '')
3525 # req_version = version needed
3626 # req_marker = marker of the requirement (if any)
27+ # on current Python, use from importlib.metadata + Distribution.Discover() for 2x speed-up
3728 self .distro = {}
3829 self .raw = {}
3930 replacements = str .maketrans ({" " : "" , "[" : "" , "]" : "" , "'" : "" , '"' : "" })
@@ -53,14 +44,21 @@ def __init__(self, Target=None):
5344 "sys_platform" : sys .platform ,
5445 }
5546
56- for p in pip_json ["installed" ]:
57- meta = p ["metadata" ]
58- name = meta ["name" ]
59- key = normalize (name )
60- requires = []
61- self .raw [key ] = meta
62- if "requires_dist" in meta :
63- for i in meta ["requires_dist" ]:
47+ # get pip_inpsect raw data in json form
48+ if Target == None or sys .executable == Target :
49+ # self-Distro inspection case
50+ # faster then pip_inspect = utils.exec_shell_cmd(f'set pythonutf8=1 & python -X utf8=1 -m pip inspect', sys.prefix)
51+ from importlib .metadata import Distribution
52+ pip_json_installed = Distribution .discover ()
53+ for p in pip_json_installed :
54+ meta = p .metadata
55+ name = p .name
56+ version = p .version
57+ key = normalize (name )
58+ requires = []
59+ self .raw [key ] = meta
60+ if p .requires :
61+ for i in p .requires :
6462 det = (i + ";" ).split (";" )
6563
6664 # req_nameextra is "python-jose[cryptography]"
@@ -83,14 +81,60 @@ def __init__(self, Target=None):
8381 if not req_marker == "" :
8482 req_add ["req_marker" ] = req_marker
8583 requires += [req_add ]
86- self .distro [key ] = {
87- "name" : name ,
88- "version" : meta ["version" ],
89- "summary" : meta ["summary" ] if "summary" in meta else "" ,
90- "requires_dist" : requires ,
91- "wanted_per" : [],
92- "description" : meta ["description" ] if "description" in meta else "" ,
93- }
84+ self .distro [key ] = {
85+ "name" : name ,
86+ "version" : p .version ,
87+ "summary" : meta ["Summary" ] if "Summary" in meta else "" ,
88+ "requires_dist" : requires ,
89+ "wanted_per" : [],
90+ "description" : meta ["Description" ] if "Description" in meta else "" ,
91+ }
92+ else :
93+ # General Any Distro inspection case
94+ # unreliable to utf-8: pip_inspect = utils.exec_run_cmd([Target , "-X" ,"utf8=1", "-m", "pip", "inspect"])
95+ # os.environ["pythonutf8"] = "1" causes issues in movable function, so limit to this moment
96+ pip_inspect = utils .exec_shell_cmd (f'set pythonutf8=1 & "{ Target } " -X utf8=1 -m pip inspect' , sys .prefix )
97+ pip_json = json .loads (pip_inspect )
98+
99+
100+ for p in pip_json ["installed" ]:
101+ meta = p ["metadata" ]
102+ name = meta ["name" ]
103+ key = normalize (name )
104+ requires = []
105+ self .raw [key ] = meta
106+ if "requires_dist" in meta :
107+ for i in meta ["requires_dist" ]:
108+ det = (i + ";" ).split (";" )
109+
110+ # req_nameextra is "python-jose[cryptography]"
111+ # from fastapi "python-jose[cryptography]<4.0.0,>=3.3.0
112+ # req_nameextra is "google-cloud-storage"
113+ # from "google-cloud-storage (<2.0.0,>=1.26.0)
114+ req_nameextra = re .split (" |;|==|!|>|<" , det [0 ] + ";" )[0 ]
115+ req_nameextra = normalize (req_nameextra )
116+ req_key = normalize ((req_nameextra + "[" ).split ("[" )[0 ])
117+ req_key_extra = req_nameextra [len (req_key ) + 1 :].split ("]" )[0 ]
118+ req_version = det [0 ][len (req_nameextra ) :].translate (replacements )
119+ req_marker = det [1 ]
120+
121+ req_add = {
122+ "req_key" : req_key ,
123+ "req_version" : req_version ,
124+ "req_extra" : req_key_extra ,
125+ }
126+ # add the marker of the requirement, if not nothing:
127+ if not req_marker == "" :
128+ req_add ["req_marker" ] = req_marker
129+ requires += [req_add ]
130+ self .distro [key ] = {
131+ "name" : name ,
132+ "version" : meta ["version" ],
133+ "summary" : meta ["summary" ] if "summary" in meta else "" ,
134+ "requires_dist" : requires ,
135+ "wanted_per" : [],
136+ "description" : meta ["description" ] if "description" in meta else "" ,
137+ }
94138 # On a second pass, complement distro in reverse mode with 'wanted-per':
95139 # - get all downward links in 'requires_dist' of each package
96140 # - feed the required packages 'wanted_per' as a reverse dict of dict
0 commit comments