Skip to content

Commit 0f868a1

Browse files
Do not fail on invalid extracted requirements (#1429)
* Do not fail on invalid extracted requirements * Also add project errors on invalid versions/version ranges as these can be package manifest parsing bugs. Signed-off-by: Ayan Sinha Mahapatra <ayansmahapatra@gmail.com> * Update error descriptions from feedback Signed-off-by: Ayan Sinha Mahapatra <ayansmahapatra@gmail.com> --------- Signed-off-by: Ayan Sinha Mahapatra <ayansmahapatra@gmail.com>
1 parent a087f31 commit 0f868a1

File tree

3 files changed

+48
-6
lines changed

3 files changed

+48
-6
lines changed

scanpipe/pipes/purldb.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
from packageurl import PackageURL
3232
from univers.version_range import RANGE_CLASS_BY_SCHEMES
3333
from univers.version_range import InvalidVersionRange
34+
from univers.versions import InvalidVersion
3435

3536
from aboutcode.pipeline import LoopProgress
3637
from scanpipe.pipes import _clean_package_data
@@ -300,28 +301,43 @@ def get_unique_resolved_purls(project):
300301
def get_unique_unresolved_purls(project):
301302
"""Return PURLs from project's unresolved DiscoveredDependencies."""
302303
packages_unresolved = project.discovereddependencies.filter(
303-
is_pinned=False
304+
is_pinned=False,
304305
).exclude(extracted_requirement="*")
305306

306-
distinct_unresolved_results = packages_unresolved.values(
307+
distinct_unpinned_results = packages_unresolved.values(
307308
"type", "namespace", "name", "extracted_requirement"
308309
)
309310

310-
distinct_unresolved = {tuple(item.values()) for item in distinct_unresolved_results}
311+
distinct_unpinned = {tuple(item.values()) for item in distinct_unpinned_results}
311312

312313
packages = set()
313-
for item in distinct_unresolved:
314+
for item in distinct_unpinned:
314315
pkg_type, namespace, name, extracted_requirement = item
315316
if range_class := RANGE_CLASS_BY_SCHEMES.get(pkg_type):
317+
purl = PackageURL(type=pkg_type, namespace=namespace, name=name)
318+
316319
try:
317320
vers = range_class.from_native(extracted_requirement)
318-
except InvalidVersionRange:
321+
except (InvalidVersionRange, InvalidVersion) as exception:
322+
if exception is InvalidVersionRange:
323+
description = "Version range is invalid or unsupported"
324+
else:
325+
description = "Extracted requirement is not a valid version"
326+
details = {
327+
"purl": purl,
328+
"extracted_requirement": extracted_requirement,
329+
}
330+
project.add_error(
331+
description=description,
332+
model="get_unique_unresolved_purls",
333+
details=details,
334+
exception=exception,
335+
)
319336
continue
320337

321338
if not vers.constraints:
322339
continue
323340

324-
purl = PackageURL(type=pkg_type, namespace=namespace, name=name)
325341
packages.add((str(purl), str(vers)))
326342

327343
return packages

scanpipe/tests/__init__.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,21 @@ def make_dependency(project, **extra):
230230
"datasource_id": "pypi_sdist_pkginfo",
231231
}
232232

233+
dependency_data4 = {
234+
"purl": "pkg:npm/wrap-ansi-cjs",
235+
"package_type": "npm",
236+
"extracted_requirement": "npm:wrap-ansi@^7.0.0",
237+
"scope": "devDependencies",
238+
"is_runtime": False,
239+
"is_optional": True,
240+
"is_pinned": False,
241+
"is_direct": True,
242+
"dependency_uid": "pkg:npm/wrap-ansi-cjs?uuid=e656b571-7d3f-46d1-b95b-8f037aef9692",
243+
"for_package_uid": "",
244+
"datafile_path": "",
245+
"datasource_id": "npm_package_lock_json",
246+
}
247+
233248
license_policies = [
234249
{
235250
"license_key": "apache-2.0",

scanpipe/tests/pipes/test_purldb.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
from scanpipe.pipes import purldb
3737
from scanpipe.tests import dependency_data2
3838
from scanpipe.tests import dependency_data3
39+
from scanpipe.tests import dependency_data4
3940
from scanpipe.tests import make_package
4041
from scanpipe.tests import package_data1
4142

@@ -80,6 +81,16 @@ def test_scanpipe_pipes_purldb_get_unique_unresolved_purls(self):
8081

8182
self.assertEqual(expected, result)
8283

84+
def test_scanpipe_pipes_purldb_get_unique_unresolved_purls_error(self):
85+
DiscoveredDependency.create_from_data(self.project1, dependency_data4)
86+
result = purldb.get_unique_unresolved_purls(self.project1)
87+
88+
self.assertEqual(set(), result)
89+
error_message = self.project1.projectmessages.all()[0]
90+
self.assertEqual(
91+
"Extracted requirement is not a valid version", error_message.description
92+
)
93+
8394
@mock.patch("scanpipe.pipes.purldb.request_post")
8495
@mock.patch("scanpipe.pipes.purldb.is_available")
8596
def test_scanpipe_pipes_purldb_feed_purldb(

0 commit comments

Comments
 (0)