@@ -69,6 +69,35 @@ def get_python_version_from_env_tag(python_version: str):
6969 return python_version
7070
7171
72+ def get_sdist_file (repos , candidate ):
73+ """
74+ Return the sdist file for a candidate.
75+ """
76+ sdist = utils_pypi .download_sdist (
77+ name = candidate .name ,
78+ version = str (candidate .version ),
79+ repos = repos ,
80+ )
81+ sdist_file = None
82+
83+ if sdist .endswith (".tar.gz" ):
84+ sdist_file = sdist .rstrip (".tar.gz" )
85+ with tarfile .open (os .path .join (utils_pypi .CACHE_THIRDPARTY_DIR , sdist )) as file :
86+ file .extractall (
87+ os .path .join (utils_pypi .CACHE_THIRDPARTY_DIR , "extracted_sdists" , sdist_file )
88+ )
89+ if sdist .endswith (".zip" ):
90+ sdist_file = sdist .rstrip (".zip" )
91+ with ZipFile (os .path .join (utils_pypi .CACHE_THIRDPARTY_DIR , sdist )) as zip :
92+ zip .extractall (
93+ os .path .join (utils_pypi .CACHE_THIRDPARTY_DIR , "extracted_sdists" , sdist_file )
94+ )
95+
96+ if not sdist_file :
97+ raise Exception (f"Unable to extract sdist { sdist } " )
98+ return sdist_file
99+
100+
72101class PythonInputProvider (AbstractProvider ):
73102 def __init__ (self , environment = None , repos = tuple (), resolved_requirements = []):
74103 self .environment = environment
@@ -170,7 +199,9 @@ def get_requirements_for_package(self, purl, candidate):
170199 return self .get_requirements_for_package_from_pypi_json_api (purl )
171200
172201 def get_requirements_for_package_from_pypi_simple (self , candidate ):
173-
202+ """
203+ Return requirements for a package from the simple repositories.
204+ """
174205 purl = PackageURL (type = "pypi" , name = candidate .name , version = str (candidate .version ))
175206
176207 formats = self .wheel_or_sdist_by_package [str (purl )]
@@ -194,28 +225,7 @@ def get_requirements_for_package_from_pypi_simple(self, candidate):
194225 yield packaging .requirements .Requirement (str (dep .extracted_requirement ))
195226
196227 if format == "Sdist" :
197- sdist = utils_pypi .download_sdist (
198- name = candidate .name ,
199- version = str (candidate .version ),
200- repos = self .repos ,
201- )
202- if sdist .endswith (".tar.gz" ):
203- sdist_file = sdist .rstrip (".tar.gz" )
204- file = tarfile .open (os .path .join (utils_pypi .CACHE_THIRDPARTY_DIR , sdist ))
205- file .extractall (
206- os .path .join (
207- utils_pypi .CACHE_THIRDPARTY_DIR , "extracted_sdists" , sdist_file
208- )
209- )
210- file .close ()
211- if sdist .endswith (".zip" ):
212- sdist_file = sdist .rstrip (".zip" )
213- with ZipFile (os .path .join (utils_pypi .CACHE_THIRDPARTY_DIR , sdist ), "r" ) as zip :
214- zip .extractall (
215- os .path .join (
216- utils_pypi .CACHE_THIRDPARTY_DIR , "extracted_sdists" , sdist_file
217- )
218- )
228+ sdist_file = get_sdist_file (repos = self .repos , candidate = candidate )
219229 setup_py_path = os .path .join (
220230 utils_pypi .CACHE_THIRDPARTY_DIR ,
221231 "extracted_sdists" ,
@@ -241,48 +251,47 @@ def get_requirements_for_package_from_pypi_simple(self, candidate):
241251 "requirements.txt" ,
242252 )
243253
244- path_by_format = {
245- "pkginfo" : pkg_info_path ,
246- "setup-py" : setup_py_path ,
247- "setup-cfg" : setup_cfg_path ,
248- "requirement" : requirement_path ,
254+ path_by_sdist_parser = {
255+ PythonSdistPkgInfoFile : pkg_info_path ,
256+ PythonSetupPyHandler : setup_py_path ,
257+ SetupCfgHandler : setup_cfg_path ,
258+ PipRequirementsFileHandler : requirement_path ,
249259 }
250260
251- handler_by_format = {
252- "pkginfo" : PythonSdistPkgInfoFile ,
253- "setup-py" : PythonSetupPyHandler ,
254- "setup-cfg" : SetupCfgHandler ,
255- "requirement" : PipRequirementsFileHandler ,
256- }
257- for format in ["pkginfo" , "setup-py" , "setup-cfg" , "requirement" ]:
258- path = path_by_format [format ]
259- if os .path .exists (path ):
260- handler = handler_by_format [format ]
261- deps = list (handler .parse (path ))
262- assert len (deps ) == 1
263- dependencies = deps [0 ].dependencies
264- for dep in dependencies :
265- # skip if no purl can be extracted for dependency
266- if dep .purl :
267- dep_purl = PackageURL .from_string (dep .purl )
268- if dep .scope == "install" and (
269- not (dep .is_resolved )
270- or (
271- dep .is_resolved
272- and dep_purl .name not in self .resolved_requirements
273- )
274- ):
275- if dep .is_resolved :
276- self .resolved_requirements .append (dep_purl )
277- # skip the requirement starting with -- like
278- # --editable, --requirement
279- if not dep .extracted_requirement .startswith ("--" ):
280- yield packaging .requirements .Requirement (
281- str (dep .extracted_requirement )
282- )
261+ for handler , path in path_by_sdist_parser .items ():
262+ if not os .path .exists (path ):
263+ continue
283264
284- def get_requirements_for_package_from_pypi_json_api (self , purl ):
265+ deps = list (handler .parse (path ))
266+ assert len (deps ) == 1
267+ dependencies = deps [0 ].dependencies
268+ for dep in dependencies :
269+ if not dep .purl :
270+ continue
271+
272+ dep_purl = PackageURL .from_string (dep .purl )
273+ if not (
274+ dep .scope == "install"
275+ and (
276+ not (dep .is_resolved )
277+ or (
278+ dep .is_resolved
279+ and dep_purl .name not in self .resolved_requirements
280+ )
281+ )
282+ ):
283+ continue
284+ if dep .is_resolved :
285+ self .resolved_requirements .append (dep_purl )
286+ # skip the requirement starting with -- like
287+ # --editable, --requirement
288+ if not dep .extracted_requirement .startswith ("--" ):
289+ yield packaging .requirements .Requirement (str (dep .extracted_requirement ))
285290
291+ def get_requirements_for_package_from_pypi_json_api (self , purl ):
292+ """
293+ Return requirements for a package from the PyPI.org JSON API
294+ """
286295 # if no repos are provided use the incorrect but fast JSON API
287296 if str (purl ) not in self .dependencies_by_purl :
288297 api_url = f"https://pypi.org/pypi/{ purl .name } /{ purl .version } /json"
@@ -455,11 +464,10 @@ def get_resolved_dependencies(
455464 If empty, use instead the PyPI.org JSON API exclusively instead
456465 """
457466 resolved_requirements = [
458- packaging .utils .canonicalize_name (r [ "requirement" ] .name )
467+ packaging .utils .canonicalize_name (r .name )
459468 for r in requirements
460- if r [ "is_requirement_resolved" ]
469+ if getattr ( r , "is_requirement_resolved" , False )
461470 ]
462- requirements = [r ["requirement" ] for r in requirements ]
463471 resolver = Resolver (
464472 provider = PythonInputProvider (
465473 environment = environment , repos = repos , resolved_requirements = resolved_requirements
0 commit comments