Skip to content

Commit 0deca77

Browse files
committed
Fix linting issues
Signed-off-by: Tushar Goel <[email protected]>
1 parent e33ecee commit 0deca77

File tree

5 files changed

+66
-15
lines changed

5 files changed

+66
-15
lines changed

etc/scripts/generate_validators.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,6 @@
7272
# Visit https://github.com/package-url/packageurl-python for support and
7373
# download.
7474
75-
from packageurl.contrib.route import Router
76-
7775
"""
7876
Validate each type according to the PURL spec type definitions
7977
"""

src/packageurl/__init__.py

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ def normalize_namespace(
133133
"hex",
134134
):
135135
namespace_str = namespace_str.lower()
136-
if ptype in ("cpan"):
136+
if ptype and ptype in ("cpan"):
137137
namespace_str = namespace_str.upper()
138138
segments = [seg for seg in namespace_str.split("/") if seg.strip()]
139139
segments_quoted = map(get_quoter(encode), segments)
@@ -192,6 +192,8 @@ def normalize_name(
192192
name_str = name_str.lower()
193193
if ptype == "pypi":
194194
name_str = name_str.replace("_", "-").lower()
195+
if ptype == "hackage":
196+
name_str = name_str.replace("_", "-")
195197
return name_str or None
196198

197199

@@ -395,7 +397,7 @@ def __new__(
395397
version: AnyStr | None = None,
396398
qualifiers: AnyStr | dict[str, str] | None = None,
397399
subpath: AnyStr | None = None,
398-
normalize_purl=True,
400+
normalize_purl: bool = True,
399401
) -> Self:
400402
required = dict(type=type, name=name)
401403
for key, value in required.items():
@@ -421,6 +423,13 @@ def __new__(
421423
f"Invalid purl: qualifiers argument must be a dict or a string: {qualifiers!r}."
422424
)
423425

426+
type_final: str
427+
namespace_final: Optional[str]
428+
name_final: str
429+
version_final: Optional[str]
430+
qualifiers_final: dict[str, str]
431+
subpath_final: Optional[str]
432+
424433
if normalize_purl:
425434
(
426435
type_final,
@@ -430,14 +439,18 @@ def __new__(
430439
qualifiers_final,
431440
subpath_final,
432441
) = normalize(type, namespace, name, version, qualifiers, subpath, encode=None)
433-
434442
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
443+
from packageurl.utils import ensure_str
444+
445+
type_final = ensure_str(type) or ""
446+
namespace_final = ensure_str(namespace)
447+
name_final = ensure_str(name) or ""
448+
version_final = ensure_str(version)
449+
if isinstance(qualifiers, dict):
450+
qualifiers_final = qualifiers
451+
else:
452+
qualifiers_final = {}
453+
subpath_final = ensure_str(subpath)
441454

442455
return super().__new__(
443456
cls,

src/packageurl/utils.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
# Visit https://github.com/package-url/packageurl-python for support and
2525
# download.
2626

27+
from typing import Optional
28+
from typing import Union
29+
2730
from packageurl import PackageURL
2831

2932

@@ -51,3 +54,11 @@ def get_golang_purl(go_package: str):
5154
name = parts[-1]
5255
namespace = "/".join(parts[:-1])
5356
return PackageURL(type="golang", namespace=namespace, name=name, version=version)
57+
58+
59+
def ensure_str(value: Optional[Union[str, bytes]]) -> Optional[str]:
60+
if value is None:
61+
return None
62+
if isinstance(value, bytes):
63+
return value.decode("utf-8") # or whatever encoding is right
64+
return value

src/packageurl/validate.py

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222
# Visit https://github.com/package-url/packageurl-python for support and
2323
# download.
2424

25-
from packageurl.contrib.route import Router
26-
2725
"""
2826
Validate each type according to the PURL spec type definitions
2927
"""
@@ -41,7 +39,10 @@ def validate(cls, purl, strict=False):
4139
elif cls.namespace_requirement == "required" and not purl.namespace:
4240
yield f"Namespace is required for purl type: {cls.type!r}"
4341

44-
if (
42+
if purl.type == "cpan":
43+
if purl.namespace and purl.namespace != purl.namespace.upper():
44+
yield f"Namespace must be uppercase for purl type: {cls.type!r}"
45+
elif (
4546
not cls.namespace_case_sensitive
4647
and purl.namespace
4748
and purl.namespace.lower() != purl.namespace
@@ -243,6 +244,14 @@ class CpanTypeValidator(TypeValidator):
243244
version_case_sensitive = True
244245
purl_pattern = "pkg:cpan/.*"
245246

247+
@classmethod
248+
def validate_type(cls, purl, strict=False):
249+
if purl.namespace and "::" in purl.name:
250+
yield f"Name must not contain '::' when Namespace is absent for purl type: {cls.type!r}"
251+
if not purl.namespace and "-" in purl.name:
252+
yield f"Name must not contain '-' when Namespace is absent for purl type: {cls.type!r}"
253+
yield from super().validate_type(purl, strict)
254+
246255

247256
class CranTypeValidator(TypeValidator):
248257
type = "cran"
@@ -355,6 +364,12 @@ class HackageTypeValidator(TypeValidator):
355364
version_case_sensitive = True
356365
purl_pattern = "pkg:hackage/.*"
357366

367+
@classmethod
368+
def validate_type(cls, purl, strict=False):
369+
if "_" in purl.name:
370+
yield f"Name contains underscores but should be kebab-case for purl type: {cls.type!r}"
371+
yield from super().validate_type(purl, strict)
372+
358373

359374
class HexTypeValidator(TypeValidator):
360375
type = "hex"
@@ -481,6 +496,14 @@ class PubTypeValidator(TypeValidator):
481496
version_case_sensitive = True
482497
purl_pattern = "pkg:pub/.*"
483498

499+
@classmethod
500+
def validate_type(cls, purl, strict=False):
501+
if any(not (c.islower() or c.isdigit() or c == "_") for c in purl.name):
502+
yield f"Name contains invalid characters but should only contain lowercase letters, digits, or underscores for purl type: {cls.type!r}"
503+
if " " in purl.name:
504+
yield f"Name contains spaces but should use underscores instead for purl type: {cls.type!r}"
505+
yield from super().validate_type(purl, strict)
506+
484507

485508
class PypiTypeValidator(TypeValidator):
486509
type = "pypi"
@@ -495,6 +518,12 @@ class PypiTypeValidator(TypeValidator):
495518
version_case_sensitive = True
496519
purl_pattern = "pkg:pypi/.*"
497520

521+
@classmethod
522+
def validate_type(cls, purl, strict=False):
523+
if "_" in purl.name:
524+
yield f"Name cannot contain `_` for purl type:{cls.type!r}"
525+
yield from super().validate_type(purl, strict)
526+
498527

499528
class QpkgTypeValidator(TypeValidator):
500529
type = "qpkg"

0 commit comments

Comments
 (0)