2727from resolvelib .reporters import BaseReporter
2828
2929from _packagedcode .pypi import PipRequirementsFileHandler
30+ from _packagedcode .pypi import PypiWheelHandler
3031from _packagedcode .pypi import PythonSdistPkgInfoFile
3132from _packagedcode .pypi import PythonSetupPyHandler
3233from _packagedcode .pypi import SetupCfgHandler
@@ -74,6 +75,7 @@ def __init__(self, environment=None, repos=tuple()):
7475 self .repos = repos or []
7576 self .versions_by_package = {}
7677 self .dependencies_by_purl = {}
78+ self .wheel_or_sdist_by_package = {}
7779
7880 def identify (self , requirement_or_candidate ):
7981 """Given a requirement, return an identifier for it. Overridden."""
@@ -109,17 +111,37 @@ def get_versions_for_package_from_repo(self, name, repo):
109111 """
110112 Return a list of versions for a package name from a repo
111113 """
114+ versions = []
112115 for version , package in repo .get_package_versions (name ).items ():
116+ name = packaging .utils .canonicalize_name (package .name )
117+ purl = PackageURL (type = "pypi" , name = name , version = version )
118+ python_version = packaging .version .parse (
119+ get_python_version_from_env_tag (self .environment .python_version )
120+ )
121+ wheels = list (package .get_supported_wheels (environment = self .environment ))
122+ if wheels :
123+ valid_wheel_present = False
124+ for wheel in wheels :
125+ if wheel .requires_python and python_version in SpecifierSet (
126+ wheel .requires_python
127+ ):
128+ valid_wheel_present = True
129+ if not wheel .requires_python :
130+ valid_wheel_present = True
131+ if valid_wheel_present :
132+ self .wheel_or_sdist_by_package [str (purl )] = "Wheel"
133+ versions .append (version )
134+ continue
113135 if package .sdist :
114- python_version = packaging .version .parse (
115- get_python_version_from_env_tag (self .environment .python_version )
116- )
117136 if package .sdist .requires_python and python_version in SpecifierSet (
118137 package .sdist .requires_python
119138 ):
120- yield version
139+ self .wheel_or_sdist_by_package [str (purl )] = "Sdist"
140+ versions .append (version )
121141 if not package .sdist .requires_python :
122- yield version
142+ self .wheel_or_sdist_by_package [str (purl )] = "Sdist"
143+ versions .append (version )
144+ return versions
123145
124146 def get_versions_for_package_from_pypi_json_api (self , name ):
125147 """
@@ -145,74 +167,98 @@ def get_requirements_for_package(self, purl, candidate):
145167 return self .get_requirements_for_package_from_pypi_json_api (purl )
146168
147169 def get_requirements_for_package_from_pypi_simple (self , candidate ):
148- sdist = utils_pypi .download_sdist (
149- name = candidate .name ,
150- version = str (candidate .version ),
151- repos = self .repos ,
152- )
153170
154- if sdist .endswith (".tar.gz" ):
155- sdist_file = sdist .rstrip (".tar.gz" )
156- file = tarfile .open (os .path .join (utils_pypi .CACHE_THIRDPARTY_DIR , sdist ))
157- file .extractall (
158- os .path .join (utils_pypi .CACHE_THIRDPARTY_DIR , "extracted_sdists" , sdist_file )
171+ purl = PackageURL (type = "pypi" , name = candidate .name , version = str (candidate .version ))
172+
173+ wheel_or_sdist = self .wheel_or_sdist_by_package [str (purl )]
174+
175+ if wheel_or_sdist == "Wheel" :
176+ wheels = utils_pypi .download_wheel (
177+ name = candidate .name ,
178+ version = str (candidate .version ),
179+ environment = self .environment ,
180+ repos = self .repos ,
159181 )
160- file .close ()
161- if sdist .endswith (".zip" ):
162- sdist_file = sdist .rstrip (".zip" )
163- with ZipFile (os .path .join (utils_pypi .CACHE_THIRDPARTY_DIR , sdist ), "r" ) as zip :
164- zip .extractall (
165- os .path .join (utils_pypi .CACHE_THIRDPARTY_DIR , "extracted_sdists" , sdist_file )
182+ for wheel in wheels :
183+ deps = list (
184+ PypiWheelHandler .parse (os .path .join (utils_pypi .CACHE_THIRDPARTY_DIR , wheel ))
166185 )
167- setup_py_path = os .path .join (
168- utils_pypi .CACHE_THIRDPARTY_DIR , "extracted_sdists" , sdist_file , sdist_file , "setup.py"
169- )
170- setup_cfg_path = os .path .join (
171- utils_pypi .CACHE_THIRDPARTY_DIR , "extracted_sdists" , sdist_file , sdist_file , "setup.cfg"
172- )
173- pkg_info_path = os .path .join (
174- utils_pypi .CACHE_THIRDPARTY_DIR , "extracted_sdists" , sdist_file
175- )
176- requirement_path = os .path .join (
177- utils_pypi .CACHE_THIRDPARTY_DIR ,
178- "extracted_sdists" ,
179- sdist_file ,
180- sdist_file ,
181- "requirements.txt" ,
182- )
183- pyproject_path = os .path .join (
184- utils_pypi .CACHE_THIRDPARTY_DIR ,
185- "extracted_sdists" ,
186- sdist_file ,
187- sdist_file ,
188- "pyproject.toml" ,
189- )
190-
191- path_by_format = {
192- "pkginfo" : pkg_info_path ,
193- "setup-py" : setup_py_path ,
194- "setup-cfg" : setup_cfg_path ,
195- "requirement" : requirement_path ,
196- }
197-
198- handler_by_format = {
199- "pkginfo" : PythonSdistPkgInfoFile ,
200- "setup-py" : PythonSetupPyHandler ,
201- "setup-cfg" : SetupCfgHandler ,
202- "requirement" : PipRequirementsFileHandler ,
203- }
204- for format in ["pkginfo" , "setup-py" , "setup-cfg" , "requirement" ]:
205- path = path_by_format [format ]
206- if os .path .exists (path ):
207- handler = handler_by_format [format ]
208- deps = list (handler .parse (path ))
209186 assert len (deps ) == 1
210- dependencies = deps [0 ].dependencies
211- for dep in dependencies :
187+ deps = deps [0 ].dependencies
188+ for dep in deps :
212189 if dep .scope == "install" :
213190 yield packaging .requirements .Requirement (str (dep .extracted_requirement ))
214- if dependencies :
215- break
191+
192+ if wheel_or_sdist == "Sdist" :
193+ sdist = utils_pypi .download_sdist (
194+ name = candidate .name ,
195+ version = str (candidate .version ),
196+ repos = self .repos ,
197+ )
198+
199+ if sdist .endswith (".tar.gz" ):
200+ sdist_file = sdist .rstrip (".tar.gz" )
201+ file = tarfile .open (os .path .join (utils_pypi .CACHE_THIRDPARTY_DIR , sdist ))
202+ file .extractall (
203+ os .path .join (utils_pypi .CACHE_THIRDPARTY_DIR , "extracted_sdists" , sdist_file )
204+ )
205+ file .close ()
206+ if sdist .endswith (".zip" ):
207+ sdist_file = sdist .rstrip (".zip" )
208+ with ZipFile (os .path .join (utils_pypi .CACHE_THIRDPARTY_DIR , sdist ), "r" ) as zip :
209+ zip .extractall (
210+ os .path .join (
211+ utils_pypi .CACHE_THIRDPARTY_DIR , "extracted_sdists" , sdist_file
212+ )
213+ )
214+ setup_py_path = os .path .join (
215+ utils_pypi .CACHE_THIRDPARTY_DIR ,
216+ "extracted_sdists" ,
217+ sdist_file ,
218+ sdist_file ,
219+ "setup.py" ,
220+ )
221+ setup_cfg_path = os .path .join (
222+ utils_pypi .CACHE_THIRDPARTY_DIR ,
223+ "extracted_sdists" ,
224+ sdist_file ,
225+ sdist_file ,
226+ "setup.cfg" ,
227+ )
228+ pkg_info_path = os .path .join (
229+ utils_pypi .CACHE_THIRDPARTY_DIR , "extracted_sdists" , sdist_file
230+ )
231+ requirement_path = os .path .join (
232+ utils_pypi .CACHE_THIRDPARTY_DIR ,
233+ "extracted_sdists" ,
234+ sdist_file ,
235+ sdist_file ,
236+ "requirements.txt" ,
237+ )
238+
239+ path_by_format = {
240+ "pkginfo" : pkg_info_path ,
241+ "setup-py" : setup_py_path ,
242+ "setup-cfg" : setup_cfg_path ,
243+ "requirement" : requirement_path ,
244+ }
245+
246+ handler_by_format = {
247+ "pkginfo" : PythonSdistPkgInfoFile ,
248+ "setup-py" : PythonSetupPyHandler ,
249+ "setup-cfg" : SetupCfgHandler ,
250+ "requirement" : PipRequirementsFileHandler ,
251+ }
252+ for format in ["pkginfo" , "setup-py" , "setup-cfg" , "requirement" ]:
253+ path = path_by_format [format ]
254+ if os .path .exists (path ):
255+ handler = handler_by_format [format ]
256+ deps = list (handler .parse (path ))
257+ assert len (deps ) == 1
258+ dependencies = deps [0 ].dependencies
259+ for dep in dependencies :
260+ if dep .scope == "install" :
261+ yield packaging .requirements .Requirement (str (dep .extracted_requirement ))
216262
217263 def get_requirements_for_package_from_pypi_json_api (self , purl ):
218264
@@ -242,7 +288,7 @@ def _iter_matches(self, identifier, requirements, incompatibilities):
242288 """
243289 Yield candidates for the given identifier, requirements and incompatibilities
244290 """
245- name , _ , _extras = identifier .partition ("[" )
291+ name , _ , _ = identifier .partition ("[" )
246292 bad_versions = {c .version for c in incompatibilities [identifier ]}
247293 extras = {e for r in requirements [identifier ] for e in r .extras }
248294 if not self .repos :
0 commit comments