2929from collections .abc import Mapping
3030from typing import TYPE_CHECKING
3131from typing import Any
32+ from typing import Optional
3233from typing import Union
3334from typing import overload
3435from urllib .parse import quote as _percent_quote
@@ -125,7 +126,7 @@ def normalize_namespace(
125126
126127def normalize_name (
127128 name : AnyStr | None ,
128- qualifiers : str | dict | None ,
129+ qualifiers : Union [ Union [ str , bytes ], dict [ str , str ], None ] ,
129130 ptype : str | None ,
130131 encode : bool | None = True ,
131132) -> str | None :
@@ -158,15 +159,15 @@ def normalize_name(
158159
159160
160161def normalize_version (
161- version : AnyStr | None , ptype : str | None , encode : bool | None = True
162+ version : AnyStr | None , ptype : Optional [ Union [ str , bytes ]] , encode : bool | None = True
162163) -> str | None :
163164 if not version :
164165 return None
165166
166167 version_str = version if isinstance (version , str ) else version .decode ("utf-8" )
167168 quoter = get_quoter (encode )
168169 version_str = quoter (version_str .strip ())
169- if ptype and ptype in ("huggingface" ):
170+ if ptype and isinstance ( ptype , str ) and ptype in ("huggingface" ):
170171 return version_str .lower ()
171172 return version_str or None
172173
@@ -498,6 +499,8 @@ def from_string(cls, purl: str) -> Self:
498499
499500 type_ = type_ .lower ()
500501
502+ original_remainder = remainder
503+
501504 scheme , authority , path , qualifiers_str , subpath = _urlsplit (
502505 url = remainder , scheme = "" , allow_fragments = True
503506 )
@@ -512,7 +515,9 @@ def from_string(cls, purl: str) -> Self:
512515 path = authority + ":" + path
513516
514517 if scheme :
515- path = scheme + ":" + path
518+ # This is a way to preserve the casing of the original scheme
519+ original_scheme = original_remainder .split (":" , 1 )[0 ]
520+ path = original_scheme + ":" + path
516521
517522 path = path .lstrip ("/" )
518523
0 commit comments