@@ -77,11 +77,13 @@ def unquote(s: AnyStr) -> str:
7777
7878
7979@overload
80- def get_quoter (encode : bool = True ) -> Callable [[AnyStr ], str ]: ...
80+ def get_quoter (encode : bool = True ) -> Callable [[AnyStr ], str ]:
81+ ...
8182
8283
8384@overload
84- def get_quoter (encode : None ) -> Callable [[str ], str ]: ...
85+ def get_quoter (encode : None ) -> Callable [[str ], str ]:
86+ ...
8587
8688
8789def get_quoter (encode : bool | None = True ) -> Callable [[AnyStr ], str ] | Callable [[str ], str ]:
@@ -151,19 +153,22 @@ def normalize_version(version: AnyStr | None, encode: bool | None = True) -> str
151153@overload
152154def normalize_qualifiers (
153155 qualifiers : AnyStr | dict [str , str ] | None , encode : Literal [True ] = ...
154- ) -> str | None : ...
156+ ) -> str | None :
157+ ...
155158
156159
157160@overload
158161def normalize_qualifiers (
159162 qualifiers : AnyStr | dict [str , str ] | None , encode : Literal [False ] | None
160- ) -> dict [str , str ]: ...
163+ ) -> dict [str , str ]:
164+ ...
161165
162166
163167@overload
164168def normalize_qualifiers (
165169 qualifiers : AnyStr | dict [str , str ] | None , encode : bool | None = ...
166- ) -> str | dict [str , str ] | None : ...
170+ ) -> str | dict [str , str ] | None :
171+ ...
167172
168173
169174def normalize_qualifiers (
@@ -251,7 +256,8 @@ def normalize(
251256 qualifiers : AnyStr | dict [str , str ] | None ,
252257 subpath : AnyStr | None ,
253258 encode : Literal [True ] = ...,
254- ) -> tuple [str , str | None , str , str | None , str | None , str | None ]: ...
259+ ) -> tuple [str , str | None , str , str | None , str | None , str | None ]:
260+ ...
255261
256262
257263@overload
@@ -263,7 +269,8 @@ def normalize(
263269 qualifiers : AnyStr | dict [str , str ] | None ,
264270 subpath : AnyStr | None ,
265271 encode : Literal [False ] | None ,
266- ) -> tuple [str , str | None , str , str | None , dict [str , str ], str | None ]: ...
272+ ) -> tuple [str , str | None , str , str | None , dict [str , str ], str | None ]:
273+ ...
267274
268275
269276@overload
@@ -275,7 +282,8 @@ def normalize(
275282 qualifiers : AnyStr | dict [str , str ] | None ,
276283 subpath : AnyStr | None ,
277284 encode : bool | None = ...,
278- ) -> tuple [str , str | None , str , str | None , str | dict [str , str ] | None , str | None ]: ...
285+ ) -> tuple [str , str | None , str , str | None , str | dict [str , str ] | None , str | None ]:
286+ ...
279287
280288
281289def normalize (
@@ -459,12 +467,17 @@ def from_string(cls, purl: str) -> Self:
459467 url = remainder , scheme = "" , allow_fragments = True
460468 )
461469
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 )
470+ # The spec (seems) to allow colons in the name and namespace.
471+ # urllib.urlsplit splits on : considers them parts of scheme
472+ # and authority.
473+ # Other libraries do not care about this.
474+ # See https://github.com/package-url/packageurl-python/issues/152#issuecomment-2637692538
475+ # We do + ":" + to put the colon back that urlsplit removed.
476+ if authority :
477+ path = authority + ":" + path
478+
479+ if scheme :
480+ path = scheme + ":" + path
468481
469482 path = path .lstrip ("/" )
470483
0 commit comments