Skip to content

Commit abe3806

Browse files
authored
Merge pull request #178 from jkugler/jkugler/properly_handle_colons_in_name_and_namespace
feat: fix parsing of names and namespaces with colons
2 parents 6f38e3e + 1c3baf7 commit abe3806

File tree

2 files changed

+55
-6
lines changed

2 files changed

+55
-6
lines changed

src/packageurl/__init__.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -459,12 +459,17 @@ def from_string(cls, purl: str) -> Self:
459459
url=remainder, scheme="", allow_fragments=True
460460
)
461461

462-
if scheme or authority:
463-
msg = (
464-
f'Invalid purl {purl!r} cannot contain a "user:pass@host:port" '
465-
f"URL Authority component: {authority!r}."
466-
)
467-
raise ValueError(msg)
462+
# The spec (seems) to allow colons in the name and namespace.
463+
# urllib.urlsplit splits on : considers them parts of scheme
464+
# and authority.
465+
# Other libraries do not care about this.
466+
# See https://github.com/package-url/packageurl-python/issues/152#issuecomment-2637692538
467+
# We do + ":" + to put the colon back that urlsplit removed.
468+
if authority:
469+
path = authority + ":" + path
470+
471+
if scheme:
472+
path = scheme + ":" + path
468473

469474
path = path.lstrip("/")
470475

tests/test_packageurl.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,3 +330,47 @@ def test_to_dict_custom_empty_value(self):
330330
def test_purl_is_hashable():
331331
s = {PackageURL(name="hashable", type="pypi")}
332332
assert len(s) == 1
333+
334+
335+
def test_colons_in_name_are_handled_correctly() -> None:
336+
p = PackageURL.from_string(
337+
"pkg:nuget/libiconv:%20character%20set%20conversion%[email protected]?package-id=e11a609df352e292"
338+
)
339+
340+
assert p.type == "nuget"
341+
assert p.namespace is None
342+
assert p.name == "libiconv: character set conversion library"
343+
assert p.version == "1.9"
344+
assert p.qualifiers == {"package-id": "e11a609df352e292"}
345+
assert p.subpath is None
346+
347+
assert PackageURL.from_string(p.to_string()).to_string() == p.to_string()
348+
349+
350+
def test_colons_in_namespace_are_handled_correctly() -> None:
351+
p = PackageURL.from_string(
352+
"pkg:nuget/an:odd:space/libiconv:%20character%20set%20conversion%[email protected]?package-id=e11a609df352e292"
353+
)
354+
355+
assert p.type == "nuget"
356+
assert p.namespace == "an:odd:space"
357+
assert p.name == "libiconv: character set conversion library"
358+
assert p.version == "1.9"
359+
assert p.qualifiers == {"package-id": "e11a609df352e292"}
360+
assert p.subpath is None
361+
362+
assert PackageURL.from_string(p.to_string()).to_string() == p.to_string()
363+
364+
365+
def test_encoding_stuff_with_colons_correctly() -> None:
366+
p = PackageURL(
367+
type="nuget",
368+
namespace="an:odd:space",
369+
name="libiconv: character set conversion library",
370+
version="1.9",
371+
qualifiers={"package-id": "e11a609df352e292"},
372+
)
373+
assert (
374+
p.to_string()
375+
== "pkg:nuget/an:odd:space/libiconv:%20character%20set%20conversion%[email protected]?package-id=e11a609df352e292"
376+
)

0 commit comments

Comments
 (0)