4343
4444def info (url ):
4545 """
46- Return data according to the `url` string
47- `url` string can be purl too
46+ Return package metadata for a URL or PURL.
47+ Return None if there is no URL, or the URL or PURL is not supported.
4848 """
4949 if url :
5050 try :
@@ -86,13 +86,7 @@ def get_cargo_data_from_purl(purl):
8686 crate = response .get ("crate" ) or {}
8787 homepage_url = crate .get ("homepage" )
8888 code_view_url = crate .get ("repository" )
89- yield Package (
90- homepage_url = homepage_url ,
91- api_url = api_url ,
92- code_view_url = code_view_url ,
93- download_url = download_url ,
94- ** purl .to_dict (),
95- )
89+
9690 versions = response .get ("versions" , [])
9791 for version in versions :
9892 version_purl = PackageURL (type = purl .type , name = name , version = version .get ("num" ))
@@ -103,6 +97,9 @@ def get_cargo_data_from_purl(purl):
10397 download_url = None
10498 declared_license = version .get ("license" )
10599
100+ if purl .version and version_purl .version != purl .version :
101+ continue
102+
106103 yield Package (
107104 homepage_url = homepage_url ,
108105 api_url = api_url ,
@@ -112,6 +109,9 @@ def get_cargo_data_from_purl(purl):
112109 ** version_purl .to_dict (),
113110 )
114111
112+ if purl .version :
113+ break
114+
115115
116116@router .route ("pkg:npm/.*" )
117117def get_npm_data_from_purl (purl ):
@@ -123,28 +123,17 @@ def get_npm_data_from_purl(purl):
123123 name = purl .name
124124 version = purl .version
125125 api_url = f"{ base_path } /{ name } "
126+
126127 response = get_response (api_url )
127128 vcs_data = response .get ("repository" ) or {}
128129 bugs = response .get ("bugs" ) or {}
129-
130130 download_url = f"{ base_path } /{ name } /-/{ name } -{ version } .tgz" if version else None
131131 vcs_url = vcs_data .get ("url" )
132132 bug_tracking_url = bugs .get ("url" )
133133 license = response .get ("license" )
134134 homepage_url = response .get ("homepage" )
135135
136- yield Package (
137- homepage_url = homepage_url ,
138- api_url = api_url ,
139- vcs_url = vcs_url ,
140- bug_tracking_url = bug_tracking_url ,
141- download_url = download_url ,
142- declared_license = license ,
143- ** purl .to_dict (),
144- )
145-
146136 versions = response .get ("versions" , [])
147- tags = []
148137 for num in versions :
149138 version = versions [num ]
150139 version_purl = PackageURL (
@@ -153,11 +142,13 @@ def get_npm_data_from_purl(purl):
153142 repository = version .get ("repository" ) or {}
154143 bugs = response .get ("bugs" ) or {}
155144 dist = version .get ("dist" ) or {}
156- licenses = version .get ("licenses" ) or [{}]
157145 vcs_url = repository .get ("url" )
158146 download_url = dist .get ("tarball" )
159147 bug_tracking_url = bugs .get ("url" )
160- declared_license = licenses [0 ].get ("type" )
148+ declared_license = license
149+
150+ if purl .version and version_purl .version != purl .version :
151+ continue
161152
162153 yield Package (
163154 homepage_url = homepage_url ,
@@ -169,6 +160,9 @@ def get_npm_data_from_purl(purl):
169160 ** version_purl .to_dict (),
170161 )
171162
163+ if purl .version :
164+ break
165+
172166
173167@router .route ("pkg:pypi/.*" )
174168def get_pypi_data_from_purl (purl ):
@@ -177,6 +171,7 @@ def get_pypi_data_from_purl(purl):
177171 """
178172 purl = PackageURL .from_string (purl )
179173 name = purl .name
174+
180175 base_path = "https://pypi.org/pypi"
181176 api_url = f"{ base_path } /{ name } /json"
182177 response = get_response (api_url )
@@ -187,19 +182,14 @@ def get_pypi_data_from_purl(purl):
187182 project_urls = info .get ("project_urls" ) or {}
188183 code_view_url = get_pypi_codeview_url (project_urls )
189184 bug_tracking_url = get_pypi_bugtracker_url (project_urls )
190- yield Package (
191- homepage_url = homepage_url ,
192- api_url = api_url ,
193- bug_tracking_url = bug_tracking_url ,
194- code_view_url = code_view_url ,
195- declared_license = license ,
196- ** purl .to_dict (),
197- )
185+
198186 for num in releases :
199187 version_purl = PackageURL (type = purl .type , name = name , version = num )
200188 release = releases .get (num ) or [{}]
201189 release = release [0 ]
202190 download_url = release .get ("url" )
191+ if purl .version and version_purl .version != purl .version :
192+ continue
203193 yield Package (
204194 homepage_url = homepage_url ,
205195 api_url = api_url ,
@@ -210,6 +200,9 @@ def get_pypi_data_from_purl(purl):
210200 ** version_purl .to_dict (),
211201 )
212202
203+ if purl .version :
204+ break
205+
213206
214207@router .route ("pkg:github/.*" )
215208def get_github_data_from_purl (purl ):
@@ -296,19 +289,15 @@ def get_bitbucket_data_from_purl(purl):
296289 bitbucket_url = "https://bitbucket.org"
297290 bug_tracking_url = f"{ bitbucket_url } /{ namespace } /{ name } /issues"
298291 code_view_url = f"{ bitbucket_url } /{ namespace } /{ name } "
299- yield Package (
300- api_url = api_url ,
301- bug_tracking_url = bug_tracking_url ,
302- code_view_url = code_view_url ,
303- ** purl .to_dict (),
304- )
292+
305293 links = response .get ("links" ) or {}
306294 tags_url = links .get ("tags" ) or {}
307295 tags_url = tags_url .get ("href" )
308296 if not tags_url :
309297 return []
310298 tags_data = get_response (tags_url )
311299 tags = tags_data .get ("values" ) or {}
300+
312301 for tag in tags :
313302 version = tag .get ("name" ) or ""
314303 version_purl = PackageURL (
@@ -318,6 +307,10 @@ def get_bitbucket_data_from_purl(purl):
318307 f"{ base_path } /{ namespace } /{ name } /downloads/{ name } -{ version } .tar.gz"
319308 )
320309 code_view_url = f"{ bitbucket_url } /{ namespace } /{ name } /src/{ version } "
310+
311+ if purl .version and version_purl .version != purl .version :
312+ continue
313+
321314 yield Package (
322315 api_url = api_url ,
323316 bug_tracking_url = bug_tracking_url ,
@@ -326,6 +319,9 @@ def get_bitbucket_data_from_purl(purl):
326319 ** version_purl .to_dict (),
327320 )
328321
322+ if purl .version :
323+ break
324+
329325
330326@router .route ("pkg:rubygems/.*" )
331327def get_rubygems_data_from_purl (purl ):
@@ -334,22 +330,38 @@ def get_rubygems_data_from_purl(purl):
334330 """
335331 purl = PackageURL .from_string (purl )
336332 name = purl .name
337- api_url = f"https://rubygems.org/api/v1/gems/{ name } .json"
338- response = get_response (api_url )
339- declared_license = response .get ("licenses" ) or None
340- homepage_url = response .get ("homepage_uri" )
341- code_view_url = response .get ("source_code_uri" )
342- bug_tracking_url = response .get ("bug_tracker_uri" )
343- download_url = response .get ("gem_uri" )
344- yield Package (
345- homepage_url = homepage_url ,
346- api_url = api_url ,
347- bug_tracking_url = bug_tracking_url ,
348- code_view_url = code_view_url ,
349- declared_license = declared_license ,
350- download_url = download_url ,
351- ** purl .to_dict (),
352- )
333+ all_versions_url = f"https://rubygems.org/api/v1/versions/{ name } .json"
334+ all_versions = get_response (all_versions_url )
335+
336+ for vers in all_versions :
337+ version_purl = PackageURL (type = purl .type , name = name , version = vers .get ("number" ))
338+
339+ if purl .version and version_purl .version != purl .version :
340+ continue
341+
342+ number = vers .get ("number" )
343+ version_api = f"https://rubygems.org/api/v2/rubygems/{ name } /versions/{ number } .json"
344+ version_api_response = get_response (version_api )
345+ declared_license = version_api_response .get ("licenses" ) or None
346+ homepage_url = version_api_response .get ("homepage_uri" )
347+ code_view_url = version_api_response .get ("source_code_uri" )
348+ bug_tracking_url = version_api_response .get ("bug_tracker_uri" )
349+ download_url = version_api_response .get ("gem_uri" )
350+ repository_homepage_url = version_api_response .get ("project_uri" )
351+
352+ yield Package (
353+ homepage_url = homepage_url ,
354+ api_url = version_api ,
355+ bug_tracking_url = bug_tracking_url ,
356+ code_view_url = code_view_url ,
357+ declared_license = declared_license ,
358+ download_url = download_url ,
359+ repository_homepage_url = repository_homepage_url ,
360+ ** version_purl .to_dict (),
361+ )
362+
363+ if purl .version :
364+ break
353365
354366
355367@router .route ("pkg:gnu/.*" )
@@ -378,7 +390,8 @@ def get_cocoapods_data_from_purl(purl):
378390 data_list = get_cocoapod_tags (spec , name )
379391
380392 for tag in data_list :
381- if purl .version and tag != purl .version :
393+ version_purl = PackageURL (type = purl .type , name = name , version = tag )
394+ if purl .version and version_purl .version != purl .version :
382395 continue
383396
384397 gh_repo_owner = None
@@ -394,7 +407,7 @@ def get_cocoapods_data_from_purl(purl):
394407 gh_repo_name = podspec_homepage_split [- 1 ]
395408
396409 tag_pkg = construct_cocoapods_package (
397- purl ,
410+ version_purl ,
398411 name ,
399412 hashed_path ,
400413 cocoapods_org_url ,
0 commit comments