From 702b3a6d6a0876be566d54d55b5d33e587c4d709 Mon Sep 17 00:00:00 2001 From: Tushar Goel Date: Fri, 25 Nov 2022 22:37:00 +0530 Subject: [PATCH 1/5] Fix parsing of npm purls without namespace Signed-off-by: Tushar Goel --- src/packageurl/__init__.py | 30 +++++++++++++++++++++ tests/data/test-suite-data.json | 48 +++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/src/packageurl/__init__.py b/src/packageurl/__init__.py index 9104d0f..41c5175 100644 --- a/src/packageurl/__init__.py +++ b/src/packageurl/__init__.py @@ -374,6 +374,36 @@ def from_string(cls, purl): raise ValueError(msg) path = path.lstrip("/") + + # NPM purl have a namespace in the path + # and the namespace in an npm purl is + # different from others because it starts with `@` + # so we need to handle this case separately + if type=="npm" and path.startswith("@"): + namespace = "" + name = "" + namespace, sep, name_version = path.partition("/") + if not sep: + raise ValueError(f"Invalid purl {purl!r}: {path!r}") + + remainder, sep, version = name_version.rpartition("@") + if not sep: + name = name_version + version = None + else: + name = remainder + version = version + type, namespace, name, version, qualifiers, subpath = normalize( # NOQA + type, + namespace, + name, + version, + qualifiers, + subpath, + encode=False, + ) + return PackageURL(type, namespace, name, version, qualifiers, subpath) + remainder, sep, version = path.rpartition("@") if not sep: remainder = version diff --git a/tests/data/test-suite-data.json b/tests/data/test-suite-data.json index b4641cc..923d12c 100644 --- a/tests/data/test-suite-data.json +++ b/tests/data/test-suite-data.json @@ -298,5 +298,53 @@ "qualifiers": {"in production": "true"}, "subpath": null, "is_invalid": true + }, + { + "description": "valid npm purl without version and with subpath", + "purl": "pkg:npm/@babel/core#/googleapis/api/annotations/", + "canonical_purl": "pkg:npm/%40babel/core#googleapis/api/annotations", + "type": "npm", + "namespace": "@babel", + "name": "core", + "version": null, + "qualifiers": null, + "subpath": "googleapis/api/annotations", + "is_invalid": false + }, + { + "description": "valid npm purl with namespace, version and subpath", + "purl": "pkg:npm/@babel/core@1.0.2#/googleapis/api/annotations/", + "canonical_purl": "pkg:npm/%40babel/core@1.0.2#googleapis/api/annotations", + "type": "npm", + "namespace": "@babel", + "name": "core", + "version": "1.0.2", + "qualifiers": null, + "subpath": "googleapis/api/annotations", + "is_invalid": false + }, + { + "description": "valid npm purl without namespace and with subpath", + "purl": "pkg:npm/core@1.0.2#/googleapis/api/annotations/", + "canonical_purl": "pkg:npm/core@1.0.2#googleapis/api/annotations", + "type": "npm", + "namespace": null, + "name": "core", + "version": "1.0.2", + "qualifiers": null, + "subpath": "googleapis/api/annotations", + "is_invalid": false + }, + { + "description": "valid npm purl without namespace, version and subpath", + "purl": "pkg:npm/core#/googleapis/api/annotations/", + "canonical_purl": "pkg:npm/core#googleapis/api/annotations", + "type": "npm", + "namespace": null, + "name": "core", + "version": null, + "qualifiers": null, + "subpath": "googleapis/api/annotations", + "is_invalid": false } ] From b3f79d8a2195e33990f115eae4af314e8a106d10 Mon Sep 17 00:00:00 2001 From: Tushar Goel Date: Fri, 25 Nov 2022 23:25:52 +0530 Subject: [PATCH 2/5] Drop python 3.6 and add 3.11 from CI Signed-off-by: Tushar Goel --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 785228f..be51885 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,11 +11,11 @@ jobs: matrix: os: [ubuntu-latest, windows-latest, macos-latest] python-version: + - "3.11" - "3.10" - "3.9" - "3.8" - "3.7" - - "3.6" steps: - name: Checkout From bf3af8ec58a237e575a27b277012b2be24664a91 Mon Sep 17 00:00:00 2001 From: Tushar Goel Date: Fri, 25 Nov 2022 23:27:28 +0530 Subject: [PATCH 3/5] Fix formatting tests Signed-off-by: Tushar Goel --- src/packageurl/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/packageurl/__init__.py b/src/packageurl/__init__.py index 41c5175..3ec587c 100644 --- a/src/packageurl/__init__.py +++ b/src/packageurl/__init__.py @@ -376,10 +376,10 @@ def from_string(cls, purl): path = path.lstrip("/") # NPM purl have a namespace in the path - # and the namespace in an npm purl is + # and the namespace in an npm purl is # different from others because it starts with `@` # so we need to handle this case separately - if type=="npm" and path.startswith("@"): + if type == "npm" and path.startswith("@"): namespace = "" name = "" namespace, sep, name_version = path.partition("/") From 58988f73320082cc18caac7909da0e55c88bdda4 Mon Sep 17 00:00:00 2001 From: Tushar Goel Date: Tue, 29 Nov 2022 00:01:45 +0530 Subject: [PATCH 4/5] Address review comments Signed-off-by: Tushar Goel --- src/packageurl/__init__.py | 28 +++------------------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/src/packageurl/__init__.py b/src/packageurl/__init__.py index 3ec587c..d11bf4a 100644 --- a/src/packageurl/__init__.py +++ b/src/packageurl/__init__.py @@ -375,34 +375,13 @@ def from_string(cls, purl): path = path.lstrip("/") + namespace = "" # NPM purl have a namespace in the path # and the namespace in an npm purl is # different from others because it starts with `@` # so we need to handle this case separately if type == "npm" and path.startswith("@"): - namespace = "" - name = "" - namespace, sep, name_version = path.partition("/") - if not sep: - raise ValueError(f"Invalid purl {purl!r}: {path!r}") - - remainder, sep, version = name_version.rpartition("@") - if not sep: - name = name_version - version = None - else: - name = remainder - version = version - type, namespace, name, version, qualifiers, subpath = normalize( # NOQA - type, - namespace, - name, - version, - qualifiers, - subpath, - encode=False, - ) - return PackageURL(type, namespace, name, version, qualifiers, subpath) + namespace, sep, path = path.partition("/") remainder, sep, version = path.rpartition("@") if not sep: @@ -412,9 +391,8 @@ def from_string(cls, purl): ns_name = remainder.strip().strip("/") ns_name = ns_name.split("/") ns_name = [seg for seg in ns_name if seg and seg.strip()] - namespace = "" name = "" - if len(ns_name) > 1: + if not namespace and len(ns_name) > 1: name = ns_name[-1] ns = ns_name[0:-1] namespace = "/".join(ns) From c33429ee887ce74703dbb10db3807d78001073f5 Mon Sep 17 00:00:00 2001 From: Tushar Goel Date: Tue, 29 Nov 2022 00:31:09 +0530 Subject: [PATCH 5/5] Add CHANGELOG. Signed-off-by: Tushar Goel --- CHANGELOG.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 9e74019..865bfe9 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,12 @@ Changelog ========= +0.10.5 (2022-11-29) +------------------- + +- Fixed `PackageURL.from_string` to properly handle npm purls + with namespace. + 0.10.4 (2022-10-17) -------------------