1111from functools import wraps
1212import glob
1313import logging
14+ import json
1415import os
1516from os import environ
1617from os .path import (join , dirname , realpath , exists , expanduser , basename )
4849 max_build_tool_version ,
4950)
5051
52+ from packaging .utils import parse_wheel_filename
53+ from packaging .requirements import Requirement
54+
5155user_dir = dirname (realpath (os .path .curdir ))
5256toolchain_dir = dirname (__file__ )
5357sys .path .insert (0 , join (toolchain_dir , "tools" , "external" ))
@@ -121,6 +125,92 @@ def dist_from_args(ctx, args):
121125 allow_replace_dist = args .allow_replace_dist )
122126
123127
128+ def is_wheel_platform_independent (whl_name ):
129+ name , version , build , tags = parse_wheel_filename (whl_name )
130+ return all (tag .platform == "any" for tag in tags )
131+
132+
133+ def process_python_modules (build_order , modules ):
134+ """
135+ idk what this does
136+ """
137+ modules = list (modules )
138+ build_order = list (build_order )
139+ _requirement_names = []
140+ processed_modules = []
141+
142+ for module in modules + build_order :
143+ try :
144+ _requirement_names .append (Requirement (module ).name )
145+ except Exception :
146+ processed_modules .append (module )
147+ if module in modules :
148+ modules .remove (module )
149+
150+ if len (processed_modules ) > 0 :
151+ warning (f'Ignored by module resolver : { processed_modules } ' )
152+
153+ processed_modules .extend (modules )
154+
155+ # need a tempfile for pip report output
156+ path = os .path .realpath (".pip_report.json" )
157+
158+ if not exists (path ):
159+ shprint (
160+ sh .pip , 'install' , * modules ,
161+ '--dry-run' , '--break-system-packages' , '--ignore-installed' ,
162+ '--report' , path , '-q'
163+ )
164+
165+ with open (path , "r" ) as f :
166+ try :
167+ report = json .load (f )
168+ except Exception :
169+ os .remove (path )
170+ return process_python_modules (modules )
171+
172+ info ('Extra resolved pure python dependencies :' )
173+
174+ ignored_str = " (ignored)"
175+ # did we find any non pure python package?
176+ any_not_pure_python = False
177+
178+ info (" " )
179+ for module in report ["install" ]:
180+
181+ mname = module ["metadata" ]["name" ]
182+ mver = module ["metadata" ]["version" ]
183+ filename = basename (module ["download_info" ]["url" ])
184+ pure_python = True
185+
186+ if (filename .endswith (".whl" ) and not is_wheel_platform_independent (filename )):
187+ any_not_pure_python = True
188+ pure_python = False
189+
190+ # does this module matches any recipe name?
191+ if mname .lower () in _requirement_names :
192+ continue
193+
194+ color = Out_Fore .GREEN if pure_python else Out_Fore .RED
195+ ignored = "" if pure_python else ignored_str
196+
197+ info (
198+ f" { color } { mname } { Out_Fore .WHITE } : "
199+ f"{ Out_Style .BRIGHT } { mver } { Out_Style .RESET_ALL } "
200+ f"{ ignored } "
201+ )
202+
203+ if pure_python :
204+ processed_modules .append (f"{ mname } =={ mver } " )
205+ info (" " )
206+
207+ if any_not_pure_python :
208+ warning ("Some packages were ignored because they are not pure Python." )
209+ warning ("To install the ignored packages, explicitly list them in your requirements file." )
210+
211+ return processed_modules
212+
213+
124214def build_dist_from_args (ctx , dist , args ):
125215 """Parses out any bootstrap related arguments, and uses them to build
126216 a dist."""
@@ -134,8 +224,9 @@ def build_dist_from_args(ctx, dist, args):
134224 blacklist = blacklist
135225 ))
136226 assert set (build_order ).intersection (set (python_modules )) == set ()
227+
137228 ctx .recipe_build_order = build_order
138- ctx .python_modules = python_modules
229+ ctx .python_modules = process_python_modules ( build_order , python_modules )
139230
140231 info ('The selected bootstrap is {}' .format (bs .name ))
141232 info_main ('# Creating dist with {} bootstrap' .format (bs .name ))
0 commit comments