Skip to content

Commit 44af984

Browse files
committed
Add failing tests
Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com>
1 parent 4ed4256 commit 44af984

File tree

5 files changed

+112
-73
lines changed

5 files changed

+112
-73
lines changed

etc/scripts/generate_validators.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,13 @@ def validate(cls, purl, strict=False):
9191
yield f"Namespace is required for purl type: {cls.type!r}"
9292
9393
if (
94-
cls.namespace_case_sensitive
94+
not cls.namespace_case_sensitive
9595
and purl.namespace
9696
and purl.namespace.lower() != purl.namespace
9797
):
9898
yield f"Namespace is not lowercased for purl type: {cls.type!r}"
9999
100-
if cls.name_case_sensitive and purl.name and purl.name.lower() != purl.name:
100+
if not cls.name_case_sensitive and purl.name and purl.name.lower() != purl.name:
101101
yield f"Name is not lowercased for purl type: {cls.type!r}"
102102
103103
if not cls.version_case_sensitive and purl.version and purl.version.lower() != purl.version:
@@ -148,8 +148,8 @@ def validate_qualifiers(cls, purl):
148148
149149
if disallowed:
150150
yield (
151-
f"Invalid qualifiers found: {', '.join(disallowed)}. "
152-
f"Allowed qualifiers are: {', '.join(allowed_qualifiers_set)}"
151+
f"Invalid qualifiers found: {', '.join(sorted(disallowed))}. "
152+
f"Allowed qualifiers are: {', '.join(sorted(allowed_qualifiers_set))}"
153153
)
154154
'''
155155

@@ -197,7 +197,7 @@ def generate_validators():
197197
namespace_case_sensitive = type_def["namespace_definition"].get("case_sensitive") or False
198198
name_case_sensitive = type_def["name_definition"].get("case_sensitive") or False
199199
version_definition = type_def.get("version_definition") or {}
200-
version_case_sensitive = version_definition.get("case_sensitive") or False
200+
version_case_sensitive = version_definition.get("case_sensitive") or True
201201
repository = type_def.get("repository")
202202
use_repository_url = repository.get("use_repository") or False
203203

src/packageurl/__init__.py

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,21 @@ def normalize_namespace(
120120

121121
namespace_str = namespace if isinstance(namespace, str) else namespace.decode("utf-8")
122122
namespace_str = namespace_str.strip().strip("/")
123-
if ptype in ("bitbucket", "github", "pypi", "gitlab", "composer"):
123+
if ptype in (
124+
"bitbucket",
125+
"github",
126+
"pypi",
127+
"gitlab",
128+
"composer",
129+
"luarocks",
130+
"qpkg",
131+
"alpm",
132+
"apk",
133+
"hex",
134+
):
124135
namespace_str = namespace_str.lower()
136+
if ptype in ("cpan"):
137+
namespace_str = namespace_str.upper()
125138
segments = [seg for seg in namespace_str.split("/") if seg.strip()]
126139
segments_quoted = map(get_quoter(encode), segments)
127140
return "/".join(segments_quoted) or None
@@ -162,10 +175,23 @@ def normalize_name(
162175
name_str = name_str.strip().strip("/")
163176
if ptype and ptype in ("mlflow"):
164177
return normalize_mlflow_name(name_str, qualifiers)
165-
if ptype in ("bitbucket", "github", "pypi", "gitlab", "composer"):
178+
if ptype in (
179+
"bitbucket",
180+
"github",
181+
"pypi",
182+
"gitlab",
183+
"composer",
184+
"luarocks",
185+
"oci",
186+
"npm",
187+
"alpm",
188+
"apk",
189+
"bitnami",
190+
"hex",
191+
):
166192
name_str = name_str.lower()
167193
if ptype == "pypi":
168-
name_str = name_str.replace("_", "-")
194+
name_str = name_str.replace("_", "-").lower()
169195
return name_str or None
170196

171197

@@ -178,7 +204,7 @@ def normalize_version(
178204
version_str = version if isinstance(version, str) else version.decode("utf-8")
179205
quoter = get_quoter(encode)
180206
version_str = quoter(version_str.strip())
181-
if ptype and isinstance(ptype, str) and ptype in ("huggingface"):
207+
if ptype and isinstance(ptype, str) and ptype in ("huggingface", "oci"):
182208
return version_str.lower()
183209
return version_str or None
184210

@@ -369,6 +395,7 @@ def __new__(
369395
version: AnyStr | None = None,
370396
qualifiers: AnyStr | dict[str, str] | None = None,
371397
subpath: AnyStr | None = None,
398+
normalize_purl=True,
372399
) -> Self:
373400
required = dict(type=type, name=name)
374401
for key, value in required.items():
@@ -394,23 +421,32 @@ def __new__(
394421
f"Invalid purl: qualifiers argument must be a dict or a string: {qualifiers!r}."
395422
)
396423

397-
(
398-
type_norm,
399-
namespace_norm,
400-
name_norm,
401-
version_norm,
402-
qualifiers_norm,
403-
subpath_norm,
404-
) = normalize(type, namespace, name, version, qualifiers, subpath, encode=None)
424+
if normalize_purl:
425+
(
426+
type_final,
427+
namespace_final,
428+
name_final,
429+
version_final,
430+
qualifiers_final,
431+
subpath_final,
432+
) = normalize(type, namespace, name, version, qualifiers, subpath, encode=None)
433+
434+
else:
435+
type_final = type
436+
namespace_final = namespace
437+
name_final = name
438+
version_final = version
439+
qualifiers_final = qualifiers
440+
subpath_final = subpath
405441

406442
return super().__new__(
407443
cls,
408-
type=type_norm,
409-
namespace=namespace_norm,
410-
name=name_norm,
411-
version=version_norm,
412-
qualifiers=qualifiers_norm,
413-
subpath=subpath_norm,
444+
type=type_final,
445+
namespace=namespace_final,
446+
name=name_final,
447+
version=version_final,
448+
qualifiers=qualifiers_final,
449+
subpath=subpath_final,
414450
)
415451

416452
def __str__(self, *args: Any, **kwargs: Any) -> str:

0 commit comments

Comments
 (0)